svelte-product-mockup 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +138 -0
- package/dist/assets/render.worker-CozETkb6.js +1 -0
- package/dist/index.css +1 -0
- package/dist/index.js +2474 -0
- package/package.json +43 -0
- package/src/app.d.ts +13 -0
- package/src/app.html +11 -0
- package/src/index.ts +16 -0
- package/src/lib/assets/carshotools.svg +15 -0
- package/src/lib/assets/favicon.svg +9 -0
- package/src/lib/components/CarshoToolsLogo.svelte +23 -0
- package/src/lib/components/ImageAdder.svelte +148 -0
- package/src/lib/components/InfoSections.svelte +152 -0
- package/src/lib/components/LayerControls.svelte +229 -0
- package/src/lib/components/MockupEditor.svelte +914 -0
- package/src/lib/components/MockupEditorRenderer.svelte +178 -0
- package/src/lib/components/MockupListModal.svelte +333 -0
- package/src/lib/components/MockupRenderer.svelte +64 -0
- package/src/lib/components/Modal.svelte +121 -0
- package/src/lib/components/ZoomableCanvas.svelte +126 -0
- package/src/lib/components/sections/ControlGroup.svelte +82 -0
- package/src/lib/components/sections/RestyleSection.svelte +356 -0
- package/src/lib/components/sections/Section.svelte +65 -0
- package/src/lib/components/sections/SizingSection.svelte +233 -0
- package/src/lib/components/sections/TransformSection.svelte +229 -0
- package/src/lib/components/sections/WarpSection.svelte +505 -0
- package/src/lib/components/sections/types.ts +13 -0
- package/src/lib/config.ts +2 -0
- package/src/lib/icons/ChevronIcon.svelte +23 -0
- package/src/lib/icons/EyeClosedIcon.svelte +23 -0
- package/src/lib/icons/EyeOpenIcon.svelte +23 -0
- package/src/lib/icons/ImageIcon.svelte +23 -0
- package/src/lib/icons/PlusIcon.svelte +20 -0
- package/src/lib/icons/ResetIcon.svelte +23 -0
- package/src/lib/icons/TrashIcon.svelte +20 -0
- package/src/lib/image-transformations/index.ts +89 -0
- package/src/lib/image-transformations/resize.ts +125 -0
- package/src/lib/image-transformations/restyle.ts +142 -0
- package/src/lib/image-transformations/types.ts +79 -0
- package/src/lib/image-transformations/warp/custom.ts +13 -0
- package/src/lib/image-transformations/warp/cylinder.ts +239 -0
- package/src/lib/image-transformations/warp/helpers.ts +303 -0
- package/src/lib/image-transformations/warp/index.ts +65 -0
- package/src/lib/image-transformations/warp/plane.ts +184 -0
- package/src/lib/image-transformations/warp/sphere.ts +145 -0
- package/src/lib/image-transformations/warp/types.ts +122 -0
- package/src/lib/image-transformations/warp.ts +1 -0
- package/src/lib/renderMockupCanvas.ts +454 -0
- package/src/lib/renderMockupCanvasEditor.ts +48 -0
- package/src/lib/storage.ts +99 -0
- package/src/lib/stores/mockupStore.ts +161 -0
- package/src/lib/types.ts +67 -0
- package/src/lib/workers/InputBatcher.ts +65 -0
- package/src/lib/workers/RenderScheduler.ts +123 -0
- package/src/lib/workers/index.ts +3 -0
- package/src/lib/workers/render.worker.ts +86 -0
- package/src/lib/workers/types.ts +34 -0
- package/src/mockup.css +32 -0
- package/src/routes/+layout.js +1 -0
- package/src/routes/+layout.svelte +13 -0
- package/src/routes/+page.svelte +83 -0
- package/src/routes/test/+page.svelte +815 -0
package/README.md
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Product Mockups
|
|
2
|
+
|
|
3
|
+
A powerful mockup rendering and editing library built with Svelte 5.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install product-mockups
|
|
9
|
+
# or
|
|
10
|
+
pnpm add product-mockups
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
### Basic Renderer
|
|
16
|
+
|
|
17
|
+
```svelte
|
|
18
|
+
<script>
|
|
19
|
+
import { MockupRenderer } from 'product-mockups';
|
|
20
|
+
import type { Mockup } from 'product-mockups';
|
|
21
|
+
|
|
22
|
+
const mockup: Mockup = {
|
|
23
|
+
id: '1',
|
|
24
|
+
name: 'My Mockup',
|
|
25
|
+
composition: {
|
|
26
|
+
width: 800,
|
|
27
|
+
height: 600,
|
|
28
|
+
layers: [
|
|
29
|
+
{
|
|
30
|
+
id: 'layer1',
|
|
31
|
+
src: 'https://example.com/image.jpg',
|
|
32
|
+
transform: { x: 400, y: 300, scale: 1, rotation: 0 },
|
|
33
|
+
opacity: 1,
|
|
34
|
+
visible: true,
|
|
35
|
+
effects: []
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
view: { zoom: 1, panX: 0, panY: 0 },
|
|
40
|
+
createdAt: Date.now(),
|
|
41
|
+
updatedAt: Date.now()
|
|
42
|
+
};
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<MockupRenderer mockup={mockup} />
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Editor Component
|
|
49
|
+
|
|
50
|
+
```svelte
|
|
51
|
+
<script>
|
|
52
|
+
import { MockupEditor, STORAGE_KEY, CURRENT_MOCKUP_KEY } from 'product-mockups';
|
|
53
|
+
import { createNewMockup } from 'product-mockups';
|
|
54
|
+
import type { Mockup } from 'product-mockups';
|
|
55
|
+
|
|
56
|
+
let mockup: Mockup = $state(createNewMockup());
|
|
57
|
+
let mockupName = $state('');
|
|
58
|
+
|
|
59
|
+
function handleMockupChange(updatedMockup: Mockup) {
|
|
60
|
+
mockup = updatedMockup;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function handleMockupNameChange(name: string) {
|
|
64
|
+
mockupName = name;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function handleCopyConfig() {
|
|
68
|
+
await navigator.clipboard.writeText(JSON.stringify(mockup, null, 2));
|
|
69
|
+
}
|
|
70
|
+
</script>
|
|
71
|
+
|
|
72
|
+
<MockupEditor
|
|
73
|
+
mockup={mockup}
|
|
74
|
+
mockupName={mockupName}
|
|
75
|
+
onMockupChange={handleMockupChange}
|
|
76
|
+
onMockupNameChange={handleMockupNameChange}
|
|
77
|
+
onCopyConfig={handleCopyConfig}
|
|
78
|
+
storageKey={STORAGE_KEY}
|
|
79
|
+
currentMockupKey={CURRENT_MOCKUP_KEY}
|
|
80
|
+
>
|
|
81
|
+
<h1>My Mockup Editor</h1>
|
|
82
|
+
</MockupEditor>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Programmatic Rendering
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
import { renderMockupCanvas } from 'product-mockups';
|
|
89
|
+
import type { Composition } from 'product-mockups';
|
|
90
|
+
|
|
91
|
+
const canvas = document.getElementById('my-canvas') as HTMLCanvasElement;
|
|
92
|
+
const composition: Composition = {
|
|
93
|
+
width: 800,
|
|
94
|
+
height: 600,
|
|
95
|
+
layers: [/* ... */]
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const cleanup = renderMockupCanvas(canvas, composition);
|
|
99
|
+
// Later: cleanup();
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## API
|
|
103
|
+
|
|
104
|
+
### Components
|
|
105
|
+
|
|
106
|
+
- `MockupEditor` - Full-featured editor component
|
|
107
|
+
- `MockupRenderer` - Simple renderer component
|
|
108
|
+
- `MockupEditorRenderer` - Renderer with editor features
|
|
109
|
+
- `ZoomableCanvas` - Canvas wrapper with zoom/pan
|
|
110
|
+
- `LayerControls` - Layer editing controls
|
|
111
|
+
- `MockupListModal` - Modal for selecting mockups
|
|
112
|
+
|
|
113
|
+
### Functions
|
|
114
|
+
|
|
115
|
+
- `renderMockupCanvas(canvas, composition, overrides?, onRenderTime?)` - Render to canvas
|
|
116
|
+
- `renderMockupCanvasEditor(canvas, composition, overrides?, onRenderTime?)` - Editor renderer
|
|
117
|
+
- `saveMockup(mockup, storageKey?)` - Save mockup to localStorage
|
|
118
|
+
- `loadMockup(id, storageKey?)` - Load mockup from localStorage
|
|
119
|
+
- `loadAllMockups(storageKey?)` - Load all mockups
|
|
120
|
+
- `createNewMockup(name?)` - Create a new mockup
|
|
121
|
+
|
|
122
|
+
### Types
|
|
123
|
+
|
|
124
|
+
- `Mockup` - Main mockup type
|
|
125
|
+
- `Composition` - Canvas composition
|
|
126
|
+
- `Layer` - Layer definition
|
|
127
|
+
- `LayerEffect` - Effect configuration
|
|
128
|
+
- `WarpEffect` - Warp effect configuration
|
|
129
|
+
- `RestyleEffect` - Image adjustment effect
|
|
130
|
+
|
|
131
|
+
### Configuration
|
|
132
|
+
|
|
133
|
+
- `STORAGE_KEY` - Default localStorage key for mockups (default: `'product-mockups'`)
|
|
134
|
+
- `CURRENT_MOCKUP_KEY` - Default localStorage key for current mockup (default: `'product-mockups-current'`)
|
|
135
|
+
|
|
136
|
+
## License
|
|
137
|
+
|
|
138
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(){"use strict";const ot={scale:1,translateX:0,translateY:0},at={showBounds:!1,showDepthVis:!1,showCrosshair:!1};({...ot});function et(c){const n=new OffscreenCanvas(c.width,c.height).getContext("2d");if(!n)throw new Error("Failed to create canvas context");return n.drawImage(c,0,0),n.getImageData(0,0,c.width,c.height)}function ct(c,e,n){const s=c.width,o=c.height,t=c.data;if(e<0||e>=s||n<0||n>=o)return null;const a=Math.floor(e),u=Math.floor(n),r=Math.min(a+1,s-1),M=Math.min(u+1,o-1),l=e-a,m=n-u,f=(Y,z)=>{const d=(z*s+Y)*4;return{r:t[d],g:t[d+1],b:t[d+2],a:t[d+3]}},g=f(a,u),i=f(r,u),p=f(a,M),h=f(r,M),S=(Y,z,d)=>Y+(z-Y)*d,X=S(S(g.r,i.r,l),S(p.r,h.r,l),m),v=S(S(g.g,i.g,l),S(p.g,h.g,l),m),V=S(S(g.b,i.b,l),S(p.b,h.b,l),m),B=S(S(g.a,i.a,l),S(p.a,h.a,l),m);return{r:X,g:v,b:V,a:B}}function J(c,e,n,s,o,t,a,u,r,M){const l=et(e),m=M?.showDepthVis??!1,f=M?.maxZ??500,g=r??{minX:-o/2,minY:-t/2,maxX:o/2,maxY:t/2},i=g.maxX-g.minX,p=g.maxY-g.minY,h=Math.floor(i*a),S=Math.floor(p*a);if(h<=0||S<=0)return;const X=new ImageData(h,S),v=X.data;for(let d=0;d<S;d++)for(let P=0;P<h;P++){const T=g.minX+P/a,b=g.minY+d/a,I=u(T,b);if(!I||I.z<=0)continue;const y=(d*h+P)*4;if(m){const Z=Math.min(1,Math.max(0,I.z/f)),x=Math.floor(Z*200+55);v[y]=Math.floor(x*.3),v[y+1]=Math.floor(x*.6),v[y+2]=x,v[y+3]=200}else{const{u:Z,v:x}=I,w=ct(l,Z,x);w&&(v[y]=Math.round(w.r),v[y+1]=Math.round(w.g),v[y+2]=Math.round(w.b),v[y+3]=Math.round(w.a))}}const V=new OffscreenCanvas(h,S),B=V.getContext("2d");if(!B)return;B.putImageData(X,0,0);const Y=n+g.minX,z=s+g.minY;a!==1?c.drawImage(V,Y,z,i,p):c.drawImage(V,Y,z)}function K(c,e,n,s=20){if(!("save"in c))return;const o=c;o.save(),o.strokeStyle="#00ff00",o.lineWidth=2,o.beginPath(),o.moveTo(e-s,n),o.lineTo(e+s,n),o.stroke(),o.beginPath(),o.moveTo(e,n-s),o.lineTo(e,n+s),o.stroke(),o.fillStyle="#00ff00",o.beginPath(),o.arc(e,n,3,0,Math.PI*2),o.fill(),o.restore()}function U(c,e,n,s,o,t){const a=Math.cos(s),u=Math.sin(s),r=Math.cos(o),M=Math.sin(o),l=Math.cos(t),m=Math.sin(t);let f=c,g=e,i=n;if(t!==0){const p=f,h=g;f=p*l-h*m,g=p*m+h*l}if(o!==0){const p=f,h=i;f=p*r+h*M,i=-p*M+h*r}if(s!==0){const p=g,h=i;g=p*a-h*u,i=p*u+h*a}return[f,g,i]}function it(c,e,n,s,o,t){const a=Math.cos(s),u=Math.sin(s),r=Math.cos(o),M=Math.sin(o),l=Math.cos(t),m=Math.sin(t);let f=c,g=e,i=n;if(s!==0){const p=g,h=i;g=p*a+h*u,i=-p*u+h*a}if(o!==0){const p=f,h=i;f=p*r-h*M,i=p*M+h*r}if(t!==0){const p=f,h=g;f=p*l+h*m,g=-p*m+h*l}return[f,g,i]}function rt(c,e,n,s,o,t){if(!("save"in c))return;const a=c;a.save(),a.strokeStyle="#ff6600",a.lineWidth=1.5,a.setLineDash([4,6]);const u=50,r=3;for(let M=-r;M<=r;M++){const l=M*u,m=[];for(let f=-10;f<=10;f++){const g=f*u,i=t(l,g);i&&m.push({x:e+i.x,y:n+i.y})}if(m.length>1){a.beginPath(),a.moveTo(m[0].x,m[0].y);for(let f=1;f<m.length;f++)a.lineTo(m[f].x,m[f].y);a.stroke()}}for(let M=-r;M<=r;M++){const l=M*u,m=[];for(let f=-10;f<=10;f++){const g=f*u,i=t(g,l);i&&m.push({x:e+i.x,y:n+i.y})}if(m.length>1){a.beginPath(),a.moveTo(m[0].x,m[0].y);for(let f=1;f<m.length;f++)a.lineTo(m[f].x,m[f].y);a.stroke()}}a.restore()}function lt(c,e,n,s,o,t,a,u){if(!("save"in c))return;const r=c;r.save(),r.lineWidth=2,r.setLineDash([6,4]);const M=Math.sin(t);let l=1/0,m=-1/0;const f=(d,P,T)=>{const b=P*M,I=u/(u+b);return{x:e+d*I,y:n+P*I,z:T}},g=(d,P,T)=>{const b=T-P;if(b<.001)return"#ff6600";const I=(d-P)/b,y=Math.round(100+I*155),Z=Math.round(30+I*70),x=Math.round(0+I*0);return`rgb(${y},${Z},${x})`},i=32,p=[],h=[],S=[],X=[],v=t>.01?-Math.PI/2:0,V=t>.01?Math.PI/2:Math.PI*2,B=t<-.01?-Math.PI/2:0,Y=t<-.01?Math.PI/2:Math.PI*2;for(let d=0;d<=i;d++){const P=d/i,T=v+P*(V-v),b=Math.sin(T)*s,I=Math.cos(T)*s,y=-o/2,[Z,x,w]=U(b,y,I,t,0,a),k=f(Z,x,w);p.push(k),l=Math.min(l,w),m=Math.max(m,w)}for(let d=0;d<=i;d++){const P=d/i,T=B+P*(Y-B),b=Math.sin(T)*s,I=Math.cos(T)*s,y=o/2,[Z,x,w]=U(b,y,I,t,0,a),k=f(Z,x,w);h.push(k),l=Math.min(l,w),m=Math.max(m,w)}for(let d=0;d<=10;d++){const P=d/10,T=-o/2+P*o,[b,I,y]=U(-s,T,0,t,0,a);S.push(f(b,I,y)),l=Math.min(l,y),m=Math.max(m,y);const[Z,x,w]=U(s,T,0,t,0,a);X.push(f(Z,x,w)),l=Math.min(l,w),m=Math.max(m,w)}const z=d=>{for(let P=0;P<d.length-1;P++){const T=d[P],b=d[P+1],I=(T.z+b.z)/2;r.strokeStyle=g(I,l,m),r.beginPath(),r.moveTo(T.x,T.y),r.lineTo(b.x,b.y),r.stroke()}};z(p),z(h),z(S),z(X),r.restore()}function ft(c,e,n,s,o,t,a,u,r,M){const{diameter:l,perspective:m,rotationX:f,rotationZ:g}=a,i=l/2,p=f*Math.PI/180,h=g*Math.PI/180,S=Math.abs(p)>.001,X=m??1,v=X>.01?i*(10/X):i*1e3,V=u.scale,B=u.translateX,Y=u.translateY;let z={minX:-i,minY:-t/2,maxX:i,maxY:t/2};if(S){const T=[{x:-i,y:-t/2},{x:i,y:-t/2},{x:i,y:t/2},{x:-i,y:t/2}],b=[];for(const y of T){const[Z,x,w]=U(y.x,y.y,i,p,0,h),k=v/(v+w);b.push({x:Z*k,y:x*k});const[j,W,C]=U(y.x,y.y,0,p,0,h),D=v/(v+C);b.push({x:j*D,y:W*D})}const I=i*Math.abs(Math.sin(p));b.length>0&&(z={minX:Math.min(...b.map(y=>y.x))-2,minY:Math.min(...b.map(y=>y.y))-I-2,maxX:Math.max(...b.map(y=>y.x))+2,maxY:Math.max(...b.map(y=>y.y))+I+2})}const d=(T,b)=>{const I=Math.cos(h),y=Math.sin(h),Z=T*I+b*y,x=-T*y+b*I,w=Math.cos(p),k=Math.sin(p),j=x*k,W=v/(v+j),C=Z/W,D=x/W;if(Math.abs(C)>i)return null;const E=Math.sqrt(i*i-C*C);if(Math.abs(w)<.01)return null;const L=(D+E*k)/w,O=L*k+E*w;if(O<0)return null;const F=Math.asin(C/i)*i/o+.5,$=L/t+.5,q=(F-.5-B)/V+.5,A=($-.5-Y)/V+.5;return q>=0&&q<=1&&A>=0&&A<=1?{u:q*e.width,v:A*e.height,z:O}:null},P=M.showDepthVis?{showDepthVis:!0,maxZ:i}:void 0;M.showBounds&<(c,n,s,i,t,p,h,v),J(c,e,n,s,o,t,r,d,z,P),M.showCrosshair&&K(c,n,s)}function ht(c,e,n,s,o,t,a,u,r,M){const{rotationX:l,rotationY:m,rotationZ:f,depthScale:g}=a,i=l*(Math.PI/180),p=m*(Math.PI/180),h=f*(Math.PI/180),S=Math.abs(i)>.001||Math.abs(p)>.001||Math.abs(h)>.001,X=u.scale,v=u.translateX,V=u.translateY,B=g*.001,Y=B>1e-4?1/B:1e4,z=(x,w)=>{const[k,j,W]=U(x,w,0,i,p,h),C=W+Y;if(C<=0)return null;const D=Y/C,E=k*D,L=j*D;return{x:E,y:L,z:W}};let d=-o/2,P=o/2,T=-t/2,b=t/2;if(S){const x=[];for(let k=0;k<=10;k++){const j=k/10,W=-o/2+j*o,C=z(W,-t/2);C&&x.push({x:C.x,y:C.y});const D=z(W,t/2);D&&x.push({x:D.x,y:D.y});const E=-t/2+j*t,L=z(-o/2,E);L&&x.push({x:L.x,y:L.y});const O=z(o/2,E);O&&x.push({x:O.x,y:O.y})}if(x.length>0){d=Math.min(...x.map(D=>D.x)),P=Math.max(...x.map(D=>D.x)),T=Math.min(...x.map(D=>D.y)),b=Math.max(...x.map(D=>D.y));const k=Math.sqrt(i*i+p*p+h*h),j=2,W=k*Math.max(o,t)*.1,C=j+W;d-=C,P+=C,T-=C,b+=C}}const I={minX:d,minY:T,maxX:P,maxY:b},y=(x,w)=>{if(!S){const wt=x/o+.5,St=w/t+.5,tt=(wt-.5-v)/X+.5,nt=(St-.5-V)/X+.5;return tt>=0&&tt<=1&&nt>=0&&nt<=1?{u:tt*e.width,v:nt*e.height,z:1}:null}const[k,j,W]=U(0,0,1,i,p,h),C=0,D=0,E=0,L=-Y,O=x-D,R=w-E,H=0-L,F=Math.sqrt(O*O+R*R+H*H),$=O/F,q=R/F,A=H/F,st=$*k+q*j+A*W;if(Math.abs(st)<1e-4)return null;const G=-(D*k+E*j+L*W+C)/st;if(G<0)return null;const yt=D+$*G,xt=E+q*G,N=L+A*G;if(N<L)return null;const[bt,vt]=it(yt,xt,N,i,p,h),Pt=bt/o+.5,Tt=vt/t+.5,It=N+Y,Q=(Pt-.5-v)/X+.5,_=(Tt-.5-V)/X+.5;return Q>=0&&Q<=1&&_>=0&&_<=1?{u:Q*e.width,v:_*e.height,z:It}:null},Z=M.showDepthVis?{showDepthVis:!0,maxZ:Y*.5}:void 0;M.showBounds&&rt(c,n,s,o,t,z),J(c,e,n,s,o,t,r,y,I,Z),M.showCrosshair&&K(c,n,s)}function pt(c,e,n,s,o){if(!("save"in c))return;const t=c;if(t.save(),t.strokeStyle="#ff6600",t.lineWidth=2,t.setLineDash([6,4]),t.beginPath(),t.arc(e,n,s,0,Math.PI*2),t.stroke(),t.beginPath(),t.moveTo(e-s,n),t.lineTo(e+s,n),t.stroke(),t.beginPath(),t.moveTo(e,n-s),t.lineTo(e,n+s),t.stroke(),t.beginPath(),t.moveTo(e-s,n-s),t.lineTo(e-s,n+s),t.stroke(),t.beginPath(),t.moveTo(e+s,n-s),t.lineTo(e+s,n+s),t.stroke(),Math.abs(o)>.001){t.strokeStyle="#ffaa00";const a=Math.cos(o),u=Math.sin(o),r=s*.7;t.beginPath(),t.moveTo(e+a*r,n+u*r),t.lineTo(e-a*r,n-u*r),t.stroke(),t.beginPath(),t.moveTo(e-u*r,n+a*r),t.lineTo(e+u*r,n-a*r),t.stroke()}t.restore()}function mt(c,e,n,s,o,t,a,u,r,M){const{radius:l,rotationZ:m}=a,f=m*(Math.PI/180),g=u.scale,i=u.translateX,p=u.translateY,h={minX:-l,minY:-l,maxX:l,maxY:l},S=(v,V)=>{const B=Math.sqrt(v*v+V*V);if(B>l)return null;const Y=Math.sqrt(l*l-v*v-V*V),d=Math.asin(B/l)*l,P=Math.atan2(V,v)-f,T=d*Math.cos(P),b=d*Math.sin(P),I=T/o+.5,y=b/t+.5,Z=(I-.5-i)/g+.5,x=(y-.5-p)/g+.5;return Z>=0&&Z<=1&&x>=0&&x<=1?{u:Z*e.width,v:x*e.height,z:Y}:null},X=M.showDepthVis?{showDepthVis:!0,maxZ:l}:void 0;M.showBounds&&pt(c,n,s,l,f),J(c,e,n,s,o,t,r,S,h,X),M.showCrosshair&&K(c,n,s)}function ut(c,e,n,s,o,t,a){c.drawImage(e,n-o/2,s-t/2,o,t)}function dt(c,e,n,s,o,t,a){if(!a.enabled||a.shape==="none"){c.drawImage(e,n-o/2,s-t/2,o,t);return}const u=a.quality??1,r=a.image??ot,M=a.debug??at;switch(a.shape){case"cylinder":a.cylinder&&ft(c,e,n,s,o,t,a.cylinder,r,u,M);break;case"plane":a.plane&&ht(c,e,n,s,o,t,a.plane,r,u,M);break;case"sphere":a.sphere&&mt(c,e,n,s,o,t,a.sphere,r,u,M);break;case"custom":a.custom&&ut(c,e,n,s,o,t,a.custom);break;default:c.drawImage(e,n-o/2,s-t/2,o,t)}}self.onmessage=async c=>{const{type:e,payload:n}=c.data;if(e==="render"){const s=performance.now();try{const o=await Mt(n),t=performance.now()-s,a={type:"complete",payload:{id:n.id,result:o,frameTime:t}};self.postMessage(a,[o])}catch(o){const t={type:"error",payload:{id:n.id,error:o instanceof Error?o.message:String(o)}};self.postMessage(t)}}};async function Mt(c){const{canvasWidth:e,canvasHeight:n,layers:s,images:o}=c;performance.now();const t=new OffscreenCanvas(e,n),a=t.getContext("2d");if(!a)throw new Error("Failed to get 2d context");a.fillStyle="#ffffff",a.fillRect(0,0,e,n);for(let r=0;r<s.length;r++){const M=s[r],l=o[r];l&>(a,l,M)}return await createImageBitmap(t)}function gt(c,e,n){c.save(),c.globalAlpha=n.opacity;const s=n.x,o=n.y;c.translate(s,o),c.rotate(n.rotation*Math.PI/180),n.warp&&n.warp.enabled&&n.warp.shape!=="none"?dt(c,e,0,0,n.width,n.height,n.warp):c.drawImage(e,-n.width/2,-n.height/2,n.width,n.height),c.restore()}})();
|
package/dist/index.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.mockup-renderer.svelte-1xdpk2w{position:relative;display:flex;align-items:center;justify-content:center;width:100%;height:100%;overflow:hidden}.canvas.svelte-1xdpk2w{display:block;max-width:100%;max-height:100%}.mockup-renderer.contain.svelte-1xdpk2w .canvas:where(.svelte-1xdpk2w){width:auto;height:auto;max-width:100%;max-height:100%;object-fit:contain}.mockup-renderer.cover.svelte-1xdpk2w .canvas:where(.svelte-1xdpk2w){width:100%;height:100%;object-fit:cover}.zoomable-canvas.svelte-zjsyu1{width:100%;height:100%;display:flex;align-items:center;justify-content:center;background:var(--color-bg, #f5f5f5);overflow:hidden;cursor:grab;position:relative}.zoomable-canvas.svelte-zjsyu1:active{cursor:grabbing}.canvas-frame.svelte-zjsyu1{transform-origin:center center;box-shadow:0 4px 16px #0000001a}.view-controls.svelte-zjsyu1{position:absolute;bottom:1rem;right:1rem;display:flex;align-items:center;gap:.5rem;background:#000000b3;padding:.3rem .5rem;border-radius:4px}.zoom-indicator.svelte-zjsyu1{color:#fff;font-size:.75rem;font-family:monospace;min-width:2.5rem;text-align:center}.reset-btn.svelte-zjsyu1{background:transparent;border:1px solid rgba(255,255,255,.3);color:#fffc;padding:.2rem .5rem;border-radius:3px;font-size:.75rem;cursor:pointer;transition:all .2s}.reset-btn.svelte-zjsyu1:hover{border-color:#fff9;color:#fff}.mockup-renderer.svelte-1p1rf8j{position:relative;display:flex;align-items:center;justify-content:center;width:100%;height:100%;overflow:hidden}.canvas.svelte-1p1rf8j{display:block;max-width:100%;max-height:100%}.mockup-renderer.contain.svelte-1p1rf8j .canvas:where(.svelte-1p1rf8j){width:auto;height:auto;max-width:100%;max-height:100%;object-fit:contain}.mockup-renderer.cover.svelte-1p1rf8j .canvas:where(.svelte-1p1rf8j){width:100%;height:100%;object-fit:cover}.render-time.svelte-1p1rf8j{position:absolute;top:8px;right:8px;background:#000000b3;color:#fff;padding:4px 8px;border-radius:4px;font-size:12px;font-family:monospace;pointer-events:none;z-index:10}.control-row.svelte-18gpljp{display:flex;align-items:center;gap:.25rem;min-width:0;max-width:100%}.reset-btn.svelte-18gpljp{display:flex;align-items:center;justify-content:center;padding:.25rem;background:transparent;border:none;border-radius:4px;color:var(--color-text-muted, #666);cursor:pointer;opacity:.5;transition:opacity .15s,color .15s}.reset-btn.svelte-18gpljp:hover{opacity:1;color:var(--color-primary, #007bff)}.control-label.svelte-18gpljp{display:flex;align-items:center;gap:.5rem;flex:1;min-width:0}.label-text.svelte-18gpljp{width:80px;flex-shrink:0;font-size:.875rem;color:var(--color-text-muted, #666)}.control-content.svelte-18gpljp{flex:1;display:flex;align-items:center;gap:.5rem;min-width:0;max-width:100%;overflow:hidden}.section.svelte-efcks6{border-top:1px solid var(--color-border, #ccc);border-bottom:1px solid var(--color-border, #ccc);background:var(--color-surface, #fff);min-width:0}.section-title.svelte-efcks6{padding:.75rem 0;font-size:.875rem;font-weight:600;text-transform:uppercase;color:var(--color-text-muted, #666);cursor:pointer;list-style:none;display:flex;align-items:center;gap:.5rem;border-bottom:1px solid var(--color-border, #eee)}.section-title.svelte-efcks6::-webkit-details-marker{display:none}.section-title.svelte-efcks6:before{content:"▶";font-size:.625rem;transition:transform .15s ease}.section[open].svelte-efcks6>.section-title:where(.svelte-efcks6):before{transform:rotate(90deg)}.section-content.svelte-efcks6{padding:.75rem 0;display:flex;flex-direction:column;gap:.75rem}.manual-input.svelte-efcks6{width:60px;padding:.375rem .5rem;border:1px solid var(--color-border, #ccc);border-radius:4px;font-size:.875rem}input[type=range].svelte-efcks6{flex:1;min-width:0;max-width:100%}.subsection.svelte-efcks6{margin-top:.75rem;border-top:1px solid var(--color-border, #e0e0e0)}.subsection.svelte-efcks6:first-child{margin-top:0;border-top:none}.subsection-title.svelte-efcks6{padding:.5rem 0;font-size:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--color-text-muted, #666);cursor:pointer;list-style:none;display:flex;align-items:center;gap:.5rem}.subsection-title.svelte-efcks6::-webkit-details-marker{display:none}.subsection-title.svelte-efcks6:before{content:"▶";font-size:.625rem;transition:transform .15s ease}.subsection[open].svelte-efcks6>.subsection-title:where(.svelte-efcks6):before{transform:rotate(90deg)}.subsection-content.svelte-efcks6{padding-bottom:.25rem}.section.svelte-1qmrgom{border-top:1px solid var(--color-border, #ccc);border-bottom:1px solid var(--color-border, #ccc);background:var(--color-surface, #fff);min-width:0}.section-title.svelte-1qmrgom{padding:.75rem 0;font-size:.875rem;font-weight:600;text-transform:uppercase;color:var(--color-text-muted, #666);cursor:pointer;list-style:none;display:flex;align-items:center;gap:.5rem;border-bottom:1px solid var(--color-border, #eee)}.section-title.svelte-1qmrgom::-webkit-details-marker{display:none}.section-title.svelte-1qmrgom:before{content:"▶";font-size:.625rem;transition:transform .15s ease}.section[open].svelte-1qmrgom>.section-title:where(.svelte-1qmrgom):before{transform:rotate(90deg)}.section-content.svelte-1qmrgom{padding:.75rem 0;display:flex;flex-direction:column;gap:.75rem}.mode-select.svelte-1qmrgom{padding:.375rem .5rem;border:1px solid var(--color-border, #ccc);border-radius:4px;font-size:.875rem;background:var(--color-surface, #fff)}.px-input.svelte-1qmrgom{width:50px;padding:.375rem .5rem;border:1px solid var(--color-border, #ccc);border-radius:4px;font-size:.875rem;appearance:textfield;-moz-appearance:textfield}.px-input.svelte-1qmrgom::-webkit-outer-spin-button,.px-input.svelte-1qmrgom::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.constraint-select.svelte-1qmrgom{width:70px;flex-shrink:0;padding:.375rem .5rem;border:1px solid var(--color-border, #ccc);border-radius:4px;font-size:.875rem}.manual-input.svelte-1qmrgom{width:60px;padding:.375rem .5rem;border:1px solid var(--color-border, #ccc);border-radius:4px;font-size:.875rem}input[type=range].svelte-1qmrgom{flex:1;min-width:0;max-width:100%}.section.svelte-1h62jm0{border-top:1px solid var(--color-border, #ccc);border-bottom:1px solid var(--color-border, #ccc);background:var(--color-surface, #fff);min-width:0}.section-header.svelte-1h62jm0{display:flex;align-items:center;justify-content:space-between;padding:.75rem 0;border-bottom:1px solid var(--color-border, #eee);cursor:pointer}.section-title.svelte-1h62jm0{margin:0;font-size:.875rem;font-weight:600;text-transform:uppercase;color:var(--color-text-muted, #666)}.section-toggle.svelte-1h62jm0{font-size:.75rem;color:var(--color-text-muted, #666)}.section-content.svelte-1h62jm0{padding:.75rem 0;display:flex;flex-direction:column;gap:.75rem}.shape-select.svelte-1ani6pi{padding:.375rem .5rem;border:1px solid var(--color-border, #ccc);border-radius:4px;font-size:.875rem;background:var(--color-surface, #fff)}.manual-input.svelte-1ani6pi{width:60px;padding:.375rem .5rem;border:1px solid var(--color-border, #ccc);border-radius:4px;font-size:.875rem}input[type=range].svelte-1ani6pi{flex:1;min-width:0;max-width:100%}.subsection.svelte-1ani6pi{margin-top:.75rem;border-top:1px solid var(--color-border, #e0e0e0)}.subsection-title.svelte-1ani6pi{padding:.5rem 0;font-size:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--color-text-muted, #666);cursor:pointer;list-style:none;display:flex;align-items:center;gap:.5rem}.subsection-title.svelte-1ani6pi::-webkit-details-marker{display:none}.subsection-title.svelte-1ani6pi:before{content:"▶";font-size:.625rem;transition:transform .15s ease}.subsection[open].svelte-1ani6pi>.subsection-title:where(.svelte-1ani6pi):before{transform:rotate(90deg)}.subsection-content.svelte-1ani6pi{padding-bottom:.25rem}.section.svelte-1f6utug{border-top:1px solid var(--color-border, #ccc);border-bottom:1px solid var(--color-border, #ccc);background:var(--color-surface, #fff);min-width:0}.section-title.svelte-1f6utug{padding:.75rem 0;font-size:.875rem;font-weight:600;text-transform:uppercase;color:var(--color-text-muted, #666);cursor:pointer;list-style:none;display:flex;align-items:center;gap:.5rem;border-bottom:1px solid var(--color-border, #eee)}.section-title.svelte-1f6utug::-webkit-details-marker{display:none}.section-title.svelte-1f6utug:before{content:"▶";font-size:.625rem;transition:transform .15s ease}.section[open].svelte-1f6utug>.section-title:where(.svelte-1f6utug):before{transform:rotate(90deg)}.section-content.svelte-1f6utug{padding:.75rem 0;display:flex;flex-direction:column;gap:.75rem}.manual-input.svelte-1f6utug{width:60px;padding:.375rem .5rem;border:1px solid var(--color-border, #ccc);border-radius:4px;font-size:.875rem}input[type=range].svelte-1f6utug{flex:1;min-width:0;max-width:100%}.subsection.svelte-1f6utug{margin-top:.75rem;border-top:1px solid var(--color-border, #e0e0e0)}.subsection.svelte-1f6utug:first-child{margin-top:0;border-top:none}.subsection-title.svelte-1f6utug{padding:.5rem 0;font-size:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--color-text-muted, #666);cursor:pointer;list-style:none;display:flex;align-items:center;gap:.5rem}.subsection-title.svelte-1f6utug::-webkit-details-marker{display:none}.subsection-title.svelte-1f6utug:before{content:"▶";font-size:.625rem;transition:transform .15s ease}.subsection[open].svelte-1f6utug>.subsection-title:where(.svelte-1f6utug):before{transform:rotate(90deg)}.subsection-content.svelte-1f6utug{padding-bottom:.25rem}.layer-controls.svelte-et76o3{border-radius:4px;padding-top:.75rem;padding-bottom:.75rem;margin-bottom:.5rem;background:var(--color-surface, #fff)}.layer-header.svelte-et76o3{display:flex;align-items:center;gap:.5rem;margin-bottom:.75rem;padding-bottom:.75rem;border-bottom:1px solid var(--color-border, #eee)}.visibility-toggle.svelte-et76o3{background:none;border:none;cursor:pointer;padding:.25rem;display:flex;align-items:center;justify-content:center;color:var(--color-text, #000)}.layer-preview.svelte-et76o3{flex:1;display:flex;align-items:center;justify-content:center;height:40px;overflow:hidden;border-radius:4px;background:#f5f5f5}.layer-preview.svelte-et76o3 img:where(.svelte-et76o3){max-width:100%;max-height:100%;object-fit:contain}.delete-btn.svelte-et76o3{background:#ef4444;color:#fff;border:none;border-radius:4px;width:24px;height:24px;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0}.delete-btn.svelte-et76o3:hover{background:#dc2626}.layer-name-section.svelte-et76o3{padding:0 .75rem;margin-bottom:.75rem}.layer-name-section.svelte-et76o3 .form-label:where(.svelte-et76o3){display:block;font-size:.75rem;font-weight:500;color:var(--color-text-muted, #666);margin-bottom:.25rem;text-transform:uppercase;letter-spacing:.5px}.layer-name-section.svelte-et76o3 .form-input:where(.svelte-et76o3){width:100%;padding:.375rem .5rem;border:1px solid var(--color-border, #ccc);border-radius:4px;font-size:.875rem;font-family:inherit}.layer-name-section.svelte-et76o3 .form-input:where(.svelte-et76o3):focus{outline:none;border-color:var(--color-primary, #3b82f6)}.form-hint.svelte-et76o3{font-size:.75rem;color:var(--color-text-muted, #666);margin:.25rem 0 0}.sections.svelte-et76o3{display:flex;flex-direction:column;gap:0;overflow:hidden;min-width:0}.modal-backdrop.svelte-ta60gp{position:fixed;inset:0;z-index:10000;background:var(--color-overlay-darker);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);border:none;padding:0;margin:0;cursor:pointer;border-radius:unset}.modal-backdrop.svelte-ta60gp:hover{background:var(--color-overlay-darker)!important}.modal-content.svelte-ta60gp{position:fixed;top:0;left:0;right:0;height:100dvh;z-index:10001;overflow-y:auto;-webkit-overflow-scrolling:touch;pointer-events:none;padding:env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)}.modal-content.ios-safari.svelte-ta60gp{height:100dvh;overflow-y:auto}.modal-content.svelte-ta60gp>*{pointer-events:auto;margin:0 auto}.mockup-list-container.svelte-33nadc{background:var(--color-surface, #fff);border-radius:8px;padding:2rem;max-width:900px;width:100%;margin:2rem auto;max-height:calc(100dvh - 4rem);overflow-y:auto;box-shadow:0 10px 40px #0003}.mockup-list-header.svelte-33nadc{display:flex;align-items:center;justify-content:space-between;margin-bottom:2rem;gap:1rem}.mockup-list-header.svelte-33nadc h2:where(.svelte-33nadc){font-size:1.5rem;font-weight:600;color:var(--color-text, #111);margin:0}.new-mockup-btn.svelte-33nadc{display:flex;align-items:center;gap:.5rem;padding:.5rem 1rem;background:var(--color-primary, #3b82f6);color:#fff;border:none;border-radius:6px;cursor:pointer;font-size:.875rem;font-weight:500;transition:background .2s}.new-mockup-btn.svelte-33nadc:hover{background:var(--color-primary-dark, #2563eb)}.new-mockup-btn.primary.svelte-33nadc{margin-top:1rem}.empty-state.svelte-33nadc{text-align:center;padding:4rem 2rem;color:var(--color-text-muted, #666)}.empty-state.svelte-33nadc p:where(.svelte-33nadc){font-size:1rem;margin-bottom:1.5rem}.mockup-grid.svelte-33nadc{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:1rem}.mockup-card.svelte-33nadc{background:var(--color-surface-alt, #f5f5f5);border:2px solid var(--color-border, #ccc);border-radius:8px;padding:1rem;cursor:pointer;transition:all .2s;display:flex;flex-direction:column;gap:.75rem}.mockup-card.svelte-33nadc:hover{border-color:var(--color-primary, #3b82f6);background:var(--color-surface, #fff);transform:translateY(-2px);box-shadow:0 4px 12px #0000001a}.mockup-card.current.svelte-33nadc{border-color:var(--color-primary, #3b82f6);background:var(--color-primary-light, #eff6ff)}.mockup-card-header.svelte-33nadc{display:flex;align-items:flex-start;justify-content:space-between;gap:.5rem}.mockup-card-title.svelte-33nadc{font-size:1rem;font-weight:600;color:var(--color-text, #111);margin:0;flex:1;word-break:break-word}.mockup-card-actions.svelte-33nadc{display:flex;align-items:center;gap:.5rem;flex-shrink:0}.copy-btn.svelte-33nadc{background:transparent;border:1px solid var(--color-primary, #3b82f6);color:var(--color-primary, #3b82f6);cursor:pointer;padding:.25rem .5rem;border-radius:4px;font-size:.75rem;transition:all .2s;display:flex;align-items:center;justify-content:center}.copy-btn.svelte-33nadc:hover{background:var(--color-primary, #3b82f6);color:#fff}.delete-btn.svelte-33nadc{background:transparent;border:none;color:var(--color-text-muted, #666);cursor:pointer;padding:.25rem;border-radius:4px;display:flex;align-items:center;justify-content:center;transition:all .2s;flex-shrink:0}.delete-btn.svelte-33nadc:hover{background:#ef4444;color:#fff}.mockup-card-info.svelte-33nadc{display:flex;gap:1rem;font-size:.875rem}.mockup-card-stat.svelte-33nadc{display:flex;flex-direction:column;gap:.25rem}.stat-label.svelte-33nadc{color:var(--color-text-muted, #666);font-size:.75rem;text-transform:uppercase}.stat-value.svelte-33nadc{color:var(--color-text, #111);font-weight:500}.mockup-card-footer.svelte-33nadc{margin-top:auto;padding-top:.75rem;border-top:1px solid var(--color-border, #ccc)}.mockup-card-date.svelte-33nadc{display:flex;flex-direction:column;gap:.25rem;font-size:.75rem}.date-label.svelte-33nadc{color:var(--color-text-muted, #666);text-transform:uppercase}.date-value.svelte-33nadc{color:var(--color-text, #111)}.processor-container.svelte-w47swm{display:flex;height:100%;overflow:hidden}sidebar.svelte-w47swm{min-width:360px;flex-shrink:0;background:var(--color-surface, #fff);border-right:1px solid var(--color-border, #ccc);display:flex;flex-direction:column;overflow-y:auto;overflow-x:hidden;padding-left:1rem}.header-logos.svelte-w47swm{display:flex;gap:1rem;font-size:1.5rem;padding:.5rem 1rem .5rem .5rem;border-bottom:1px solid var(--color-border, #ccc);align-items:center;flex-wrap:wrap}.editor-items.svelte-w47swm{flex:1;overflow-y:auto;padding:0;padding-right:.5rem;display:flex;flex-direction:column}.editor-section.svelte-w47swm{border-bottom:1px solid var(--color-border, #ccc);padding:.25rem 0 .75rem}.output-canvas.svelte-w47swm{flex:1;display:flex;min-width:0;background:var(--color-bg, #f5f5f5);overflow:hidden;position:relative;flex-shrink:0}.canvas-header.svelte-w47swm{display:none}.sidebar-title-2.svelte-w47swm{font-size:.875rem;font-weight:600;text-transform:uppercase;color:var(--color-text-muted, #666);padding:.75rem 0 .25rem;margin-bottom:.5rem}.layers-header.svelte-w47swm{display:flex;align-items:center;justify-content:space-between;gap:.5rem;margin-bottom:.5rem}.layers-title.svelte-w47swm{font-size:.875rem;font-weight:600;text-transform:uppercase;color:var(--color-text-muted, #666);flex:1}.add-layer-buttons.svelte-w47swm{display:flex;gap:.25rem}.add-layer-btn.svelte-w47swm{padding:.375rem .75rem;background:var(--color-primary, #3b82f6);color:#fff;border:none;border-radius:4px;cursor:pointer;font-size:.875rem;transition:background .2s;display:flex;align-items:center;gap:.375rem}.add-layer-btn.svelte-w47swm:hover{background:var(--color-primary-dark, #2563eb)}.add-layer-btn.secondary.svelte-w47swm{background:transparent;color:var(--color-text, #111);border:1px solid var(--color-border, #ccc)}.add-layer-btn.secondary.svelte-w47swm:hover{background:var(--color-bg, #f5f5f5)}.url-input-group.svelte-w47swm{display:flex;gap:.5rem;margin-top:.5rem;padding:.75rem;background:var(--color-surface-alt, #f5f5f5);border-radius:4px}.url-input-group.svelte-w47swm input:where(.svelte-w47swm){flex:1;padding-top:.375rem;padding-bottom:.375rem;border:1px solid var(--color-border, #ccc);border-radius:4px;font-size:.875rem}.url-input-group.svelte-w47swm button:where(.svelte-w47swm){padding:.375rem .75rem;background:var(--color-primary, #3b82f6);color:#fff;border:none;border-radius:4px;cursor:pointer;font-size:.875rem;transition:background .2s}.url-input-group.svelte-w47swm button:where(.svelte-w47swm):hover{background:var(--color-primary-dark, #2563eb)}.canvas-size-controls.svelte-w47swm{display:grid;grid-template-columns:1fr 1fr;gap:.5rem;margin-bottom:1rem;margin-top:0}.form-input-group.svelte-w47swm{display:flex;flex-direction:column}.no-layers.svelte-w47swm{padding:1rem;text-align:center;color:var(--color-text-muted, #666);font-size:.875rem}.layers-list.svelte-w47swm{display:flex;flex-direction:column;gap:.5rem}.layer-item.svelte-w47swm{display:flex;align-items:center;gap:.5rem;padding:.5rem;border:1px solid var(--color-border, #ccc);border-radius:4px;cursor:pointer;transition:all .2s;background:var(--color-surface, #fff)}.layer-item.svelte-w47swm:hover{border-color:var(--color-primary, #3b82f6);background:var(--color-surface-alt, #f5f5f5)}.layer-item.selected.svelte-w47swm{border-color:var(--color-primary, #3b82f6);background:var(--color-primary-light, #eff6ff)}.layer-item-preview.svelte-w47swm{width:40px;height:40px;flex-shrink:0;border-radius:4px;overflow:hidden;background:#f5f5f5;display:flex;align-items:center;justify-content:center}.layer-item-preview.svelte-w47swm img:where(.svelte-w47swm){width:100%;height:100%;object-fit:cover}.layer-item-info.svelte-w47swm{flex:1;display:flex;align-items:center;justify-content:space-between;gap:.5rem}.layer-item-name.svelte-w47swm{font-size:.875rem;color:var(--color-text, #111);display:flex;flex-direction:column;gap:.25rem}.layer-key-badge.svelte-w47swm{font-size:.7rem;font-family:monospace;background:var(--color-primary-light, #eff6ff);color:var(--color-primary, #3b82f6);padding:.125rem .375rem;border-radius:3px;font-weight:500}.layer-item-actions.svelte-w47swm{display:flex;gap:.25rem;align-items:center}.layer-order-btn.svelte-w47swm{background:transparent;border:1px solid var(--color-border, #ccc);border-radius:3px;width:24px;height:24px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s;color:var(--color-text, #000);padding:0}.layer-order-btn.svelte-w47swm:hover:not(:disabled){background:var(--color-primary, #3b82f6);border-color:var(--color-primary, #3b82f6);color:#fff}.layer-order-btn.svelte-w47swm:disabled{opacity:.3;cursor:not-allowed}.layer-delete-btn.svelte-w47swm{background:#ef4444;color:#fff;border:none;border-radius:3px;display:flex;align-items:center;justify-content:center;padding:0;width:24px;height:24px;cursor:pointer;font-size:1rem;line-height:1;transition:background .2s}.layer-delete-btn.svelte-w47swm:hover{background:#dc2626}.mockup-name-header.svelte-w47swm{display:flex;align-items:center;justify-content:space-between;margin-bottom:.5rem}.mockup-title-group.svelte-w47swm,.mockup-buttons-group.svelte-w47swm{display:flex;align-items:center;gap:.5rem}.new-mockup-btn.svelte-w47swm{padding:.375rem .75rem;background:var(--color-primary, #3b82f6);color:#fff;border:none;border-radius:4px;cursor:pointer;font-size:.875rem;transition:background .2s;display:flex;align-items:center;gap:.375rem}.new-mockup-btn.svelte-w47swm:hover{background:var(--color-primary-dark, #2563eb)}.mockup-name-title.svelte-w47swm{font-size:.875rem;font-weight:600;text-transform:uppercase;color:var(--color-text-muted, #666);margin:0}.view-all-btn.svelte-w47swm{padding:.375rem .75rem;background:transparent;color:var(--color-primary, #3b82f6);border:1px solid var(--color-primary, #3b82f6);border-radius:4px;cursor:pointer;font-size:.875rem;transition:all .2s}.view-all-btn.svelte-w47swm:hover{background:var(--color-primary, #3b82f6);color:#fff}.form-label.svelte-w47swm{display:block;font-size:.875rem;font-weight:500;color:var(--color-text, #111);margin-bottom:.25rem}.form-input.svelte-w47swm{width:100%;padding:.5rem;border:1px solid var(--color-border, #ccc);border-radius:4px;font-size:.875rem;margin-bottom:.75rem}.name-input-group.svelte-w47swm{display:flex;gap:.5rem;align-items:stretch}.name-input.svelte-w47swm{flex:1;margin-bottom:0;min-width:0}.copy-config-btn.svelte-w47swm{padding:.375rem .75rem;background:transparent;color:var(--color-primary, #3b82f6);border:1px solid var(--color-primary, #3b82f6);border-radius:4px;cursor:pointer;font-size:.875rem;transition:all .2s;white-space:nowrap;flex-shrink:0}.copy-config-btn.svelte-w47swm:hover{background:var(--color-primary, #3b82f6);color:#fff}.no-layers.svelte-w47swm{text-align:center;color:var(--color-text-muted, #666);font-size:.875rem;padding:2rem}@media(max-width:768px){.processor-container.svelte-w47swm{flex-direction:column;height:100%}sidebar.svelte-w47swm{min-width:unset;width:100%;border-right:none;border-top:1px solid var(--color-border, #ccc);order:2;flex-shrink:1;overflow-y:auto}sidebar.svelte-w47swm .header-logos:where(.svelte-w47swm){display:none}.output-canvas.svelte-w47swm{order:1;flex:0 0 50vh;height:50vh;min-height:50vh}.canvas-header.svelte-w47swm{display:flex;position:absolute;top:0;left:0;right:0;z-index:10;gap:1rem;font-size:1.5rem;padding:.5rem 1rem;align-items:center;flex-wrap:wrap}}
|