screengraft 0.63.3 → 0.63.5
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/package.json +1 -1
- package/ui/index.html +35 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "screengraft",
|
|
3
|
-
"version": "0.63.
|
|
3
|
+
"version": "0.63.5",
|
|
4
4
|
"description": "Put a UI screenshot or screen recording onto a photographed device screen with the perspective exactly right \u2014 a homography you confirm by hand, not a generative guess.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mockup",
|
package/ui/index.html
CHANGED
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
stroke in the system; it sits over the photograph, so it has to read on
|
|
90
90
|
any tone. The two shadows are the Button Group's and the Status pill's. */
|
|
91
91
|
/* Button Group 145:372, read from the node's own paints on 14 Sep 2026:
|
|
92
|
-
the stroke is
|
|
92
|
+
the stroke is four paints, 0.75px OUTSIDE the box, each with a blend
|
|
93
93
|
mode, so the hairline takes its look from the photograph under it —
|
|
94
94
|
lighter on a dark backdrop, darker on a light one, a touch desaturated.
|
|
95
95
|
The MCP's code export had flattened it to one colour twice over.
|
|
@@ -105,6 +105,8 @@
|
|
|
105
105
|
--group-edge-lum:rgba(255,70,70,.15);
|
|
106
106
|
--group-edge-hue:rgba(126,126,126,.2);
|
|
107
107
|
--group-edge-lift:rgba(255,255,255,.4);
|
|
108
|
+
/* The Button Group's stroke weight (0.75, set 14 Sep); the pills keep 1px. */
|
|
109
|
+
--group-bw:.75px;
|
|
108
110
|
--group-shadow:0 2px 4px rgba(0,0,0,.08), 0 3px 10px rgba(0,0,0,.12), 0 4px 24px rgba(0,0,0,.25);
|
|
109
111
|
--pill-shadow:0 2px 2px rgba(0,0,0,.03), 0 3px 5px rgba(0,0,0,.08), 0 4px 12px rgba(0,0,0,.25);
|
|
110
112
|
|
|
@@ -556,6 +558,11 @@
|
|
|
556
558
|
.pane{min-width:0;min-height:0;display:grid;grid-template-rows:minmax(0,1fr);
|
|
557
559
|
grid-template-columns:minmax(0,1fr);
|
|
558
560
|
position:relative; /* the frame the rails are anchored to */
|
|
561
|
+
/* An isolated group: the blend rings on the rails and pills composite
|
|
562
|
+
against THIS pane's content -- the well, the canvas, the result
|
|
563
|
+
image -- as one unit, rather than against whatever layer the
|
|
564
|
+
compositor happened to have on hand at first paint. */
|
|
565
|
+
isolation:isolate;
|
|
559
566
|
border-right:1px solid var(--line)}
|
|
560
567
|
.panehead{display:flex;align-items:center;gap:var(--s2);padding:var(--s2) var(--s4);background:var(--card);
|
|
561
568
|
box-shadow:inset 0 -1px 0 var(--line);font-size:12px;flex-wrap:wrap;min-height:48px}
|
|
@@ -587,13 +594,17 @@
|
|
|
587
594
|
.bgroup{position:relative;display:inline-flex;flex-direction:column;align-items:stretch;flex:none;
|
|
588
595
|
background:var(--raise);border:0;
|
|
589
596
|
border-radius:var(--r-sm);box-shadow:var(--group-shadow)}
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
.bgroup::after{
|
|
595
|
-
|
|
596
|
-
|
|
597
|
+
/* A ring is a SPREAD SHADOW, not a border: Chrome snaps a border to whole
|
|
598
|
+
device pixels, so 0.75px painted as 0.5 (one of two); a shadow's spread is
|
|
599
|
+
antialiased and renders the true 1.5 device pixels. Same outside-the-box
|
|
600
|
+
placement, the ring's colour is the shadow's. */
|
|
601
|
+
.bgroup::before,.bgroup::after,.bgroup > .ring{content:"";position:absolute;inset:0;
|
|
602
|
+
border-radius:var(--r-sm);pointer-events:none;
|
|
603
|
+
box-shadow:0 0 0 var(--group-bw) var(--ring)}
|
|
604
|
+
.bgroup::before{--ring:var(--group-edge-sat);mix-blend-mode:saturation;z-index:1}
|
|
605
|
+
.bgroup::after{--ring:var(--group-edge-lum);mix-blend-mode:luminosity;z-index:2}
|
|
606
|
+
.bgroup > .ring{--ring:var(--group-edge-hue);mix-blend-mode:hue;z-index:3}
|
|
607
|
+
.bgroup > .ring.lift{--ring:var(--group-edge-lift);mix-blend-mode:soft-light;z-index:4}
|
|
597
608
|
.bgroup.row{flex-direction:row}
|
|
598
609
|
.bgroup > .segbtn:first-of-type{border-top-left-radius:var(--r-sm);border-top-right-radius:var(--r-sm)}
|
|
599
610
|
.bgroup > .segbtn:last-of-type{border-bottom-left-radius:var(--r-sm);border-bottom-right-radius:var(--r-sm)}
|
|
@@ -2115,6 +2126,7 @@ async function maybeStart(){
|
|
|
2115
2126
|
const ready = !!st.shot; // the screenshot gates the fit, not the photo
|
|
2116
2127
|
img.onload = () => {
|
|
2117
2128
|
computeFit(); setCanvasZoom(fitScale);
|
|
2129
|
+
refreshRings();
|
|
2118
2130
|
if (!ready){
|
|
2119
2131
|
// Photo only: show it immediately so choosing one visibly does
|
|
2120
2132
|
// something. No quad yet — there is nothing to fit into it.
|
|
@@ -2496,6 +2508,20 @@ $('#resetquad').onclick = () => {
|
|
|
2496
2508
|
draw(); drawStrip(); autoPreview();
|
|
2497
2509
|
};
|
|
2498
2510
|
|
|
2511
|
+
// The blend rings on the rails and pills are painted against what is under
|
|
2512
|
+
// them at the time; when a NEW picture lands in the canvas or the result pane
|
|
2513
|
+
// they can keep a result blended against the empty well until something else
|
|
2514
|
+
// invalidates them (reported 14 Sep 2026: the stroke appeared only after the
|
|
2515
|
+
// picture was moved). Toggling display forces a fresh paint of each ring.
|
|
2516
|
+
function refreshRings(){
|
|
2517
|
+
document.querySelectorAll('.bgroup > .ring, .pillwrap > .ring').forEach(r => {
|
|
2518
|
+
r.style.display = 'none'; void r.offsetHeight; r.style.display = '';
|
|
2519
|
+
});
|
|
2520
|
+
// ::before / ::after rings ride on the group; nudge the group itself.
|
|
2521
|
+
document.querySelectorAll('.bgroup').forEach(g => {
|
|
2522
|
+
g.style.willChange = 'transform'; void g.offsetHeight; g.style.willChange = '';
|
|
2523
|
+
});
|
|
2524
|
+
}
|
|
2499
2525
|
function syncCornerRail(){
|
|
2500
2526
|
const i = pick && pick.kind === 'corner' ? pick.i : -1;
|
|
2501
2527
|
document.querySelectorAll('#lrail [data-jump]').forEach(b => {
|
|
@@ -3592,6 +3618,7 @@ async function renderPreview(){
|
|
|
3592
3618
|
const im = $('#outImg');
|
|
3593
3619
|
im.onload = () => {
|
|
3594
3620
|
outNat = im.naturalWidth;
|
|
3621
|
+
refreshRings();
|
|
3595
3622
|
// autoPreview runs on every drag, and it must not yank the pane away from
|
|
3596
3623
|
// a clip that is playing. The still is still rendered and waiting behind.
|
|
3597
3624
|
if ($('#liveWrap').hidden) showResult('still');
|