@cevek/screentest 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ ._viewport_1obvw_1{z-index:1000;outline:none;flex-direction:column;gap:8px;width:360px;max-width:calc(100vw - 32px);margin:0;padding:0;list-style:none;display:flex;position:fixed;bottom:16px;right:16px}._toast_1obvw_17{background:var(--bg-elev-2);border:1px solid var(--border-strong);border-left:3px solid var(--accent);box-shadow:var(--shadow);border-radius:6px;padding:10px 14px}._toast_1obvw_17[data-state=open]{animation:.16s ease-out _slideIn_1obvw_1}._toast_1obvw_17[data-state=closed]{animation:.12s ease-in forwards _fadeOut_1obvw_1}._toast_1obvw_17._error_1obvw_32{border-left-color:var(--red)}._toast_1obvw_17._success_1obvw_36{border-left-color:var(--green)}._toast_1obvw_17._info_1obvw_40{border-left-color:var(--accent)}._title_1obvw_44{margin:0 0 2px;font-size:13px;font-weight:600}._desc_1obvw_50{color:var(--text-dim);white-space:pre-wrap;overflow-wrap:anywhere;margin:0;font-size:12px}@keyframes _slideIn_1obvw_1{0%{opacity:0;transform:translate(8px)}to{opacity:1;transform:translate(0)}}@keyframes _fadeOut_1obvw_1{0%{opacity:1}to{opacity:0}}._tree_4auq3_1{margin:0;padding:0;list-style:none}._groupLi_4auq3_7,._leafLi_4auq3_8{list-style:none}._group_4auq3_7,._leaf_4auq3_8{width:100%;color:var(--text);text-align:left;border-radius:4px;align-items:center;gap:6px;min-width:0;padding:4px 8px 4px 6px;font-size:12.5px;display:flex}._group_4auq3_7:hover,._leaf_4auq3_8:hover{background:var(--bg-elev-2)}._chevron_4auq3_31{color:var(--text-faint);flex:none;transition:transform .12s}._chevronOpen_4auq3_37{transform:rotate(90deg)}._groupName_4auq3_41,._leafName_4auq3_42{white-space:nowrap;text-overflow:ellipsis;flex:auto;min-width:0;overflow:hidden}._groupName_4auq3_41{color:var(--text-dim);font-weight:500}._staleBadge_4auq3_55{background:var(--orange);color:#1a1408;border-radius:8px;flex:none;padding:1px 6px;font-size:10px;font-weight:700;line-height:1.4}._leaf_4auq3_8{cursor:pointer}._leafSelected_4auq3_70{background:#6ea8ff29}._leafSelected_4auq3_70:hover{background:#6ea8ff38}._icon_4auq3_78{flex:none}._acceptInline_4auq3_82{opacity:0;width:18px;height:18px;color:var(--text-dim);border-radius:3px;flex:none;justify-content:center;align-items:center;display:inline-flex}._leaf_4auq3_8:hover ._acceptInline_4auq3_82{opacity:1}._acceptInline_4auq3_82:hover{background:var(--bg);color:var(--green)}._toneGreen_4auq3_103{color:var(--green)}._toneYellow_4auq3_107{color:var(--yellow)}._toneOrange_4auq3_111{color:var(--orange)}._toneRed_4auq3_115{color:var(--red)}._toneRedDim_4auq3_119{color:var(--red-dim)}._toneBlueGrey_4auq3_123{color:var(--blue-grey)}._toneAccent_4auq3_127{color:var(--accent)}._spin_4auq3_131{animation:.9s linear infinite _spin_4auq3_131}@keyframes _spin_4auq3_131{to{transform:rotate(360deg)}}._root_12w7q_1{border-bottom:1px solid var(--border);background:var(--bg-elev);flex-direction:column;gap:8px;padding:10px 12px;display:flex}._row_12w7q_10{align-items:center;gap:6px;display:flex}._action_12w7q_16{border:1px solid var(--border-strong);background:var(--bg-elev-2);color:var(--text);border-radius:4px;align-items:center;gap:6px;padding:5px 10px;font-size:12px;display:inline-flex}._action_12w7q_16:hover:not(:disabled){background:var(--bg);border-color:var(--accent)}._actionCount_12w7q_33{background:var(--border-strong);color:var(--text-dim);border-radius:8px;padding:1px 6px;font-size:10px}._stop_12w7q_41{border:1px solid var(--red-dim);color:var(--red);background:0 0;border-radius:4px;align-items:center;gap:6px;padding:5px 10px;font-size:12px;display:inline-flex}._stop_12w7q_41:hover{background:#e35d5d1a}._progressOuter_12w7q_57{background:var(--bg);border-radius:4px;width:100%;height:8px;position:relative;overflow:hidden}._progressInner_12w7q_66{background:var(--accent);transition:width 80ms;position:absolute;inset:0 auto 0 0}._progressLabel_12w7q_73{color:var(--text-dim);font-size:10px;position:absolute;top:-18px;right:4px}._counts_12w7q_81{color:var(--text-dim);font-size:11px}._tip_12w7q_86{background:var(--bg-elev-2);border:1px solid var(--border-strong);color:var(--text);max-width:260px;box-shadow:var(--shadow);z-index:1000;border-radius:4px;padding:6px 10px;font-size:11px}._root_1x09j_1{flex-direction:column;min-width:0;height:100%;display:flex}._scroll_1x09j_8{flex:auto;padding:4px 0 24px;overflow:hidden auto}._section_1x09j_15{margin:6px 0 4px}._sectionTitle_1x09j_19{text-transform:uppercase;letter-spacing:.06em;color:var(--text-faint);padding:8px 12px 4px;font-size:11px;font-weight:600}._sectionEmpty_1x09j_28{color:var(--text-faint);padding:4px 12px 8px;font-size:12px;font-style:italic}._sectionBody_1x09j_35{padding:0 4px}._shell_wtjyy_1{background:var(--bg);grid-template-columns:320px 1fr;height:100vh;display:grid}._aside_wtjyy_8{background:var(--bg-elev);border-right:1px solid var(--border);flex-direction:column;min-width:0;height:100vh;display:flex;overflow:hidden}._main_wtjyy_18{flex-direction:column;min-width:0;height:100vh;display:flex;overflow:hidden}._splash_wtjyy_26{background:var(--bg);height:100vh;color:var(--text-dim);flex-direction:column;justify-content:center;align-items:center;gap:12px;display:flex}._spinner_wtjyy_37{border:3px solid var(--border-strong);border-top-color:var(--accent);border-radius:50%;width:28px;height:28px;animation:.9s linear infinite _spin_wtjyy_37}._errorTitle_wtjyy_46{color:var(--text);font-weight:600}._errorMsg_wtjyy_51{color:var(--red);text-align:center;max-width:600px}._retry_wtjyy_57{border:1px solid var(--border-strong);background:var(--bg-elev);color:var(--text);border-radius:4px;margin-top:8px;padding:6px 14px}._retry_wtjyy_57:hover{background:var(--bg-elev-2)}@keyframes _spin_wtjyy_37{to{transform:rotate(360deg)}}._stageWrap_1ppm4_1{background-color:#14171e;background-image:linear-gradient(45deg,#1a1d27 25%,#0000 25%),linear-gradient(-45deg,#1a1d27 25%,#0000 25%),linear-gradient(45deg,#0000 75%,#1a1d27 75%),linear-gradient(-45deg,#0000 75%,#1a1d27 75%);background-position:0 0,0 10px,10px -10px,-10px 0;background-repeat:repeat,repeat,repeat,repeat;background-size:20px 20px;background-attachment:scroll,scroll,scroll,scroll;background-origin:padding-box,padding-box,padding-box,padding-box;background-clip:border-box,border-box,border-box,border-box;flex:auto;justify-content:center;align-items:center;min-width:0;min-height:0;display:flex;position:relative;overflow:auto}._canvas_1ppm4_17{min-width:1px;min-height:1px;image-rendering:pixelated;flex:none;margin:auto;position:relative}._canvasInteractive_1ppm4_27{cursor:col-resize}._canvasDragging_1ppm4_31{cursor:col-resize;-webkit-user-select:none;user-select:none}._layer_1ppm4_36{-webkit-user-select:none;user-select:none;pointer-events:none;image-rendering:pixelated;background:0 0;position:absolute;top:0;left:0}._hiddenProbe_1ppm4_46{opacity:0;pointer-events:none;width:1px;height:1px;position:absolute}._diffLayer_1ppm4_54{image-rendering:pixelated;pointer-events:none;position:absolute;top:0;left:0}._sliderLine_1ppm4_62{background:var(--accent);pointer-events:none;width:1px;position:absolute;top:0;bottom:0;box-shadow:0 0 0 1px #0006}._sliderHandle_1ppm4_72{background:var(--accent);border:2px solid var(--bg);width:12px;height:12px;box-shadow:0 0 0 1px var(--accent);border-radius:50%;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}._plate_1ppm4_85{border:1px solid var(--border-strong);color:var(--text);z-index:5;pointer-events:none;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);background:#0f1115d9;border-radius:4px;padding:6px 10px;font-size:11.5px;position:absolute;top:12px;left:50%;transform:translate(-50%)}._root_j601s_1{flex-direction:column;min-width:0;height:100%;display:flex}._header_j601s_8{border-bottom:1px solid var(--border);background:var(--bg-elev);flex-shrink:0;align-items:center;gap:8px;padding:8px 14px;display:flex}._spacer_j601s_18{flex:auto}._badges_j601s_22{align-items:center;gap:6px;display:flex}._badge_j601s_22{letter-spacing:.06em;border:1px solid #0000;border-radius:4px;align-items:center;padding:2px 8px;font-size:10.5px;font-weight:700;display:inline-flex}._badgeNew_j601s_39{color:var(--green);background:#5fd27326;border-color:#5fd27366}._badgeChange_j601s_45{color:var(--yellow);background:#e5c45426;border-color:#e5c45466}._badgeStale_j601s_51{color:var(--orange);background:#f08b4a26;border-color:#f08b4a66}._badgeDeleted_j601s_57{color:var(--red);background:#e35d5d26;border-color:#e35d5d66}._badgeDeletedStale_j601s_63{color:var(--red-dim);background:#8b48482e;border-color:#8b484866}._badgeAccepted_j601s_69{color:var(--blue-grey);background:#8aa0c026;border-color:#8aa0c066}._headerBtn_j601s_75{border:1px solid var(--border-strong);background:var(--bg-elev-2);color:var(--text);border-radius:4px;align-items:center;gap:6px;padding:5px 10px;font-size:12px;display:inline-flex}._headerBtn_j601s_75:hover:not(:disabled){background:var(--bg);border-color:var(--accent)}._acceptBtn_j601s_92:not(:disabled){color:var(--green);border-color:#5fd27380}._acceptBtn_j601s_92:not(:disabled):hover{background:#5fd2731a}._tip_j601s_101{background:var(--bg-elev-2);border:1px solid var(--border-strong);color:var(--text);max-width:280px;box-shadow:var(--shadow);z-index:1000;border-radius:4px;padding:6px 10px;font-size:11px}._spin_j601s_113{animation:.9s linear infinite _spin_j601s_113}@keyframes _spin_j601s_113{to{transform:rotate(360deg)}}._notFound_15r13_1{height:100%;color:var(--text-dim);justify-content:center;align-items:center;display:flex}._empty_19hhh_1{height:100%;color:var(--text-dim);justify-content:center;align-items:center;font-size:14px;display:flex}:root{--bg:#0f1115;--bg-elev:#161922;--bg-elev-2:#1d2230;--border:#262b38;--border-strong:#353c4f;--text:#e6e8ee;--text-dim:#9099b0;--text-faint:#5f6679;--accent:#6ea8ff;--accent-hover:#8ab8ff;--green:#5fd273;--yellow:#e5c454;--orange:#f08b4a;--red:#e35d5d;--red-dim:#8b4848;--blue-grey:#8aa0c0;--purple:#a855f7;--shadow:0 4px 16px #00000059;--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark}*,:before,:after{box-sizing:border-box}html,body,#root{background:var(--bg);height:100%;color:var(--text);margin:0;padding:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;font-size:13px;line-height:1.4}button{font:inherit;color:inherit;cursor:pointer;background:0 0;border:0;padding:0}button:disabled{cursor:not-allowed;opacity:.5}a{color:var(--accent)}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:var(--border-strong);border-radius:5px}::-webkit-scrollbar-thumb:hover{background:#4a5266}
@@ -0,0 +1 @@
1
+ function e(e,r,a,c,l,u={}){let{threshold:d=.1,alpha:f=.1,aaColor:p=[255,255,0],diffColor:m=[255,0,0],checkerboard:h=!0,includeAA:g,diffColorAlt:_,diffMask:v}=u;if(!t(e)||!t(r)||a&&!t(a))throw Error(`Image data: Uint8Array, Uint8ClampedArray or Buffer expected.`);if(e.length!==r.length||a&&a.length!==e.length)throw Error(`Image sizes do not match. Image 1 size: ${e.length}, image 2 size: ${r.length}`);if(e.length!==c*l*4)throw Error(`Image data size does not match width/height. Expecting ${c*l*4}. Got ${e.length}`);let y=c*l,b=new Uint32Array(e.buffer,e.byteOffset,y),x=new Uint32Array(r.buffer,r.byteOffset,y),S=!0;for(let e=0;e<y;e++)if(b[e]!==x[e]){S=!1;break}if(S){if(a&&!v)for(let t=0,n=0;t<y;t++,n+=4)s(e,n,f,a);return 0}let C=35215*d*d,[w,T,E]=p,[D,O,k]=m,[A,j,M]=_||m,N=0;for(let t=0,u=0;t<y;t++,u+=4){let d=b[t]===x[t]?0:i(e,r,u,u,h);if(Math.abs(d)>C){let i=t%c,s=t/c|0;!g&&(n(e,i,s,c,l,b,x,h)||n(r,i,s,c,l,x,b,h))?a&&!v&&o(a,u,w,T,E):(a&&(d<0?o(a,u,A,j,M):o(a,u,D,O,k)),N++)}else a&&!v&&s(e,u,f,a)}return N}function t(e){return ArrayBuffer.isView(e)&&e.BYTES_PER_ELEMENT===1}function n(e,t,n,i,o,s,c,l){let u=Math.max(t-1,0),d=Math.max(n-1,0),f=Math.min(t+1,i-1),p=Math.min(n+1,o-1),m=(n*i+t)*4,h=e[m],g=e[m+1],_=e[m+2],v=e[m+3],y=+(t===u||t===f||n===d||n===p),b=0,x=0,S=0,C=0,w=0,T=0;for(let r=u;r<=f;r++)for(let o=d;o<=p;o++){if(r===t&&o===n)continue;let s=a(e,m,(o*i+r)*4,h,g,_,v,l);if(s===0){if(y++,y>2)return!1}else s<b?(b=s,S=r,C=o):s>x&&(x=s,w=r,T=o)}return b===0||x===0?!1:r(s,S,C,i,o)&&r(c,S,C,i,o)||r(s,w,T,i,o)&&r(c,w,T,i,o)}function r(e,t,n,r,i){let a=Math.max(t-1,0),o=Math.max(n-1,0),s=Math.min(t+1,r-1),c=Math.min(n+1,i-1),l=e[n*r+t],u=+(t===a||t===s||n===o||n===c);for(let i=a;i<=s;i++)for(let a=o;a<=c;a++)if(!(i===t&&a===n)&&(u+=+(l===e[a*r+i]),u>2))return!0;return!1}function i(e,t,n,r,i){let a=e[n],o=e[n+1],s=e[n+2],c=e[n+3],l=t[r],u=t[r+1],d=t[r+2],f=t[r+3],p=a-l,m=o-u,h=s-d,g=c-f;if(c<255||f<255){let e=255,t=255,r=255;i&&(e=48+n%2*159,t=48+159*((n/1.618033988749895|0)%2),r=48+159*((n/2.618033988749895|0)%2)),p=(a*c-l*f-e*g)/255,m=(o*c-u*f-t*g)/255,h=(s*c-d*f-r*g)/255}let _=p*.29889531+m*.58662247+h*.11448223,v=p*.59597799-m*.2741761-h*.32180189,y=p*.21147017-m*.52261711+h*.31114694,b=.5053*_*_+.299*v*v+.1957*y*y;return _>0?-b:b}function a(e,t,n,r,i,a,o,s){let c=e[n],l=e[n+1],u=e[n+2],d=e[n+3],f=r-c,p=i-l,m=a-u,h=o-d;if(!f&&!p&&!m&&!h)return 0;if(o<255||d<255){let e=255,n=255,g=255;s&&(e=48+t%2*159,n=48+159*((t/1.618033988749895|0)%2),g=48+159*((t/2.618033988749895|0)%2)),f=(r*o-c*d-e*h)/255,p=(i*o-l*d-n*h)/255,m=(a*o-u*d-g*h)/255}return f*.29889531+p*.58662247+m*.11448223}function o(e,t,n,r,i){e[t]=n,e[t+1]=r,e[t+2]=i,e[t+3]=255}function s(e,t,n,r){let i=255+(e[t]*.29889531+e[t+1]*.58662247+e[t+2]*.11448223-255)*n*e[t+3]/255;o(r,t,i,i,i)}function c(e,t,n){let r=new OffscreenCanvas(t,n).getContext(`2d`,{colorSpace:`srgb`});if(!r)throw Error(`OffscreenCanvas 2d context unavailable`);return r.clearRect(0,0,t,n),r.drawImage(e,0,0),r.getImageData(0,0,t,n,{colorSpace:`srgb`}).data}self.addEventListener(`message`,async t=>{let n=t.data;try{let t=n.expected?.width??0,r=n.expected?.height??0,i=n.actual?.width??0,a=n.actual?.height??0,o=Math.max(t,i),s=Math.max(r,a);if(o===0||s===0){let e=new Uint8ClampedArray,t={id:n.id,width:0,height:0,buffer:e.buffer};self.postMessage(t,[e.buffer]);return}let l=n.expected?c(n.expected,o,s):new Uint8ClampedArray(o*s*4),u=n.actual?c(n.actual,o,s):new Uint8ClampedArray(o*s*4),d=new Uint8ClampedArray(o*s*4);e(l,u,d,o,s,{threshold:.1,includeAA:!1,diffColor:[255,0,255],alpha:0});let f=Math.min(t||o,i||o),p=Math.min(r||s,a||s);for(let e=0;e<s;e++){let n=e<p;for(let r=0;r<o;r++){let a=(e*o+r)*4,s=n&&r<f&&t>0&&i>0,c=!1;s?d[a]===255&&d[a+1]===0&&d[a+2]===255&&(c=!0):c=!0,c?(d[a]=168,d[a+1]=85,d[a+2]=247,d[a+3]=255):(d[a]=0,d[a+1]=0,d[a+2]=0,d[a+3]=0)}}let m={id:n.id,width:o,height:s,buffer:d.buffer};self.postMessage(m,[d.buffer])}catch(e){let t={id:n.id,error:e instanceof Error?e.message:String(e)};self.postMessage(t)}});
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
6
+ <title>screentest</title>
7
+ <script type="module" crossorigin src="/assets/index-DIlEhyib.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-DMJ0v7v-.css">
9
+ </head>
10
+ <body>
11
+ <div id="root"></div>
12
+ </body>
13
+ </html>
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@cevek/screentest",
3
+ "publishConfig": {
4
+ "access": "public"
5
+ },
6
+ "version": "0.1.0",
7
+ "description": "Local desktop tool for visual screenshot-test review — Express + React UI shipped as a single CLI.",
8
+ "license": "MIT",
9
+ "type": "module",
10
+ "bin": {
11
+ "screentest": "dist/index.js"
12
+ },
13
+ "files": [
14
+ "dist",
15
+ "README.md"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsup && node scripts/copy-web.mjs",
19
+ "start": "node dist/index.js",
20
+ "typecheck": "tsc --noEmit"
21
+ },
22
+ "dependencies": {
23
+ "express": "^5.2.1",
24
+ "open": "^11.0.0"
25
+ },
26
+ "devDependencies": {
27
+ "@screentest/shared": "workspace:*",
28
+ "@types/express": "^5.0.6",
29
+ "@types/node": "^25.9.1",
30
+ "tsup": "^8.5.1",
31
+ "tsx": "^4.22.4",
32
+ "typescript": "^6.0.3"
33
+ }
34
+ }