screengraft 0.54.7 → 0.54.8

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/ui/index.html +44 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "screengraft",
3
- "version": "0.54.7",
3
+ "version": "0.54.8",
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
@@ -2920,9 +2920,38 @@ function swingText(mode){
2920
2920
  if (mode === 'rotB') return 'the left end swings, pivot on the right';
2921
2921
  return 'flat on the rule means aligned';
2922
2922
  }
2923
+ /* A corner under the pointer gets a plain magnified view instead of the
2924
+ rectified strip: the strip straightens ONE edge, and a corner is where two
2925
+ meet, so straightening either would bend the other. Same magnification as
2926
+ the strip (H / 2·stripHalf, so the ± buttons work here too), centred on the
2927
+ corner, unrotated, with both edges drawn through it and the ring at the
2928
+ centre. Requested 13 Sep 2026; edges keep the strip as it is. */
2929
+ function paintCorner(c, W, H, i){
2930
+ c.setTransform(1,0,0,1,0,0);
2931
+ c.fillStyle = '#0c0c0b'; c.fillRect(0,0,W,H);
2932
+ const P = st.corners[i], M = H / (2*stripHalf);
2933
+ c.save();
2934
+ c.setTransform(M, 0, 0, M, W/2 - P[0]*M, H/2 - P[1]*M);
2935
+ c.imageSmoothingEnabled = true;
2936
+ c.drawImage(img, 0, 0);
2937
+ c.restore();
2938
+ if (stripHC) stretchContrast(c, W, H);
2939
+ const toS = q => [W/2 + (q[0]-P[0])*M, H/2 + (q[1]-P[1])*M];
2940
+ const prev = st.corners[(i+3)%4], next = st.corners[(i+1)%4];
2941
+ for (const q of [prev, next]){
2942
+ const e = toS(q), d = unit(sub(e, [W/2, H/2]));
2943
+ const s0 = add([W/2, H/2], mul(d, HANDLE_GAP_S)), s1 = add([W/2, H/2], mul(d, 4000));
2944
+ cased(c, () => { c.beginPath(); c.moveTo(s0[0], s0[1]); c.lineTo(s1[0], s1[1]); }, QUAD_W, CORE_QUAD);
2945
+ }
2946
+ casedRing(c, W/2, H/2, 4, CORE_QUAD);
2947
+ c.font = '600 11px system-ui'; c.textBaseline = 'middle';
2948
+ casedText(c, LBL[i], W/2 + 12, H/2 - 12, 'rgba(255,255,255,.95)');
2949
+ }
2950
+ const HANDLE_GAP_S = 4 + 1 + CASE_PAD/2 + 1; // the same break the canvas leaves around a ring
2923
2951
  function drawStrip(){
2924
2952
  const a = drag || hover || pick;
2925
- const has = !!(st.corners && a && a.kind === 'edge' && img.naturalWidth);
2953
+ const has = !!(st.corners && a && (a.kind === 'edge' || a.kind === 'corner') && img.naturalWidth);
2954
+ const corner = has && a.kind === 'corner';
2926
2955
  $('#stripZ').textContent = '±' + stripHalf + 'px';
2927
2956
  if (loupeMode === 'dock'){
2928
2957
  $('#floatLoupe').classList.remove('on');
@@ -2932,13 +2961,23 @@ function drawStrip(){
2932
2961
  $('#stripSt').textContent = 'Hover or drag an edge — this straightens it, so misalignment shows as a wedge.';
2933
2962
  return;
2934
2963
  }
2935
- paintStrip(sctx, W, H, a.i, a.mode);
2936
- $('#stripSt').textContent = `${EDGE_LBL[a.i]} edge · ±${stripHalf}px · ${(H/(2*stripHalf)).toFixed(1)}× across the boundary — ${swingText(a.mode)}`;
2964
+ if (corner){
2965
+ paintCorner(sctx, W, H, a.i);
2966
+ $('#stripSt').textContent = `${LBL[a.i]} corner · ${(H/(2*stripHalf)).toFixed(1)}× — where the two edges meet`;
2967
+ } else {
2968
+ paintStrip(sctx, W, H, a.i, a.mode);
2969
+ $('#stripSt').textContent = `${EDGE_LBL[a.i]} edge · ±${stripHalf}px · ${(H/(2*stripHalf)).toFixed(1)}× across the boundary — ${swingText(a.mode)}`;
2970
+ }
2937
2971
  } else {
2938
2972
  const fl = $('#floatLoupe');
2939
2973
  if (!has){ fl.classList.remove('on'); return; }
2940
- paintStrip(fctx, stripF.width, stripF.height, a.i, a.mode);
2941
- $('#stripFCap').textContent = `${EDGE_LBL[a.i]} edge · ±${stripHalf}px — ${swingText(a.mode)}`;
2974
+ if (corner){
2975
+ paintCorner(fctx, stripF.width, stripF.height, a.i);
2976
+ $('#stripFCap').textContent = `${LBL[a.i]} corner · ${(stripF.height/(2*stripHalf)).toFixed(1)}× — where the two edges meet`;
2977
+ } else {
2978
+ paintStrip(fctx, stripF.width, stripF.height, a.i, a.mode);
2979
+ $('#stripFCap').textContent = `${EDGE_LBL[a.i]} edge · ±${stripHalf}px — ${swingText(a.mode)}`;
2980
+ }
2942
2981
  fl.classList.add('on');
2943
2982
  const w = fl.offsetWidth || 356, h = fl.offsetHeight || 130;
2944
2983
  let x = lastPointer[0] + 26, y = lastPointer[1] - h - 18;