@qwertybit/pr-preview 0.1.3 → 0.1.4
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/CHANGELOG.md +71 -0
- package/README.md +84 -27
- package/dist/cli/index.js +1029 -131
- package/dist/cli/index.js.map +1 -1
- package/dist/inpage/recorder.global.js +79 -14
- package/package.json +2 -1
|
@@ -257,27 +257,40 @@
|
|
|
257
257
|
}
|
|
258
258
|
|
|
259
259
|
// src/recorder/inpage/cursor.ts
|
|
260
|
-
var CURSOR_SVG = `<svg width="
|
|
260
|
+
var CURSOR_SVG = `<svg width="100%" height="100%" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M5.5 3.21V20.8c0 .45.54.67.85.35l4.86-4.86a.5.5 0 0 1 .35-.15h6.87a.5.5 0 0 0 .35-.85L6.35 2.85a.5.5 0 0 0-.85.36Z" fill="#1a1a2e" stroke="#fff" stroke-width="1.5"/></svg>`;
|
|
261
261
|
function ease(t) {
|
|
262
262
|
return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
|
|
263
263
|
}
|
|
264
|
+
function easeOut(t) {
|
|
265
|
+
return 1 - Math.pow(1 - t, 3);
|
|
266
|
+
}
|
|
264
267
|
function installCursor() {
|
|
265
268
|
if (window.__prPreviewCursor) return;
|
|
266
269
|
let el = null;
|
|
267
270
|
let pos = { x: (window.innerWidth || 1280) / 2, y: (window.innerHeight || 800) / 2 };
|
|
271
|
+
let scale = 1;
|
|
268
272
|
function ensure() {
|
|
269
273
|
if (el && document.body.contains(el)) return el;
|
|
270
274
|
el = document.createElement("div");
|
|
271
275
|
el.id = "__pr-preview-cursor";
|
|
272
|
-
el.style.cssText = "position:fixed;z-index:2147483647;pointer-events:none;
|
|
273
|
-
|
|
276
|
+
el.style.cssText = "position:fixed;left:0;top:0;width:0;height:0;z-index:2147483647;pointer-events:none;transform-origin:0 0;transition:none;will-change:transform;display:none;";
|
|
277
|
+
const halo = document.createElement("div");
|
|
278
|
+
halo.style.cssText = "position:absolute;left:-26px;top:-26px;width:52px;height:52px;border-radius:50%;background:radial-gradient(circle,rgba(79,142,247,.45) 0%,rgba(79,142,247,.18) 42%,rgba(79,142,247,0) 70%);";
|
|
279
|
+
const arrow = document.createElement("div");
|
|
280
|
+
arrow.style.cssText = "position:absolute;left:-6px;top:-5px;width:40px;height:40px;filter:drop-shadow(0 2px 3px rgba(0,0,0,.5));";
|
|
281
|
+
arrow.innerHTML = CURSOR_SVG;
|
|
282
|
+
el.appendChild(halo);
|
|
283
|
+
el.appendChild(arrow);
|
|
274
284
|
document.body.appendChild(el);
|
|
275
285
|
return el;
|
|
276
286
|
}
|
|
287
|
+
function apply() {
|
|
288
|
+
const node = ensure();
|
|
289
|
+
node.style.transform = `translate(${pos.x}px, ${pos.y}px) scale(${scale})`;
|
|
290
|
+
}
|
|
277
291
|
function place(x, y) {
|
|
278
292
|
pos = { x, y };
|
|
279
|
-
|
|
280
|
-
node.style.transform = `translate(${x}px, ${y}px)`;
|
|
293
|
+
apply();
|
|
281
294
|
}
|
|
282
295
|
window.__prPreviewCursor = {
|
|
283
296
|
show(x, y) {
|
|
@@ -290,28 +303,80 @@
|
|
|
290
303
|
const node = ensure();
|
|
291
304
|
node.style.display = "block";
|
|
292
305
|
const from = { ...pos };
|
|
293
|
-
const
|
|
294
|
-
const
|
|
306
|
+
const dx = x - from.x;
|
|
307
|
+
const dy = y - from.y;
|
|
308
|
+
const dist = Math.hypot(dx, dy);
|
|
295
309
|
if (dist < 1) {
|
|
310
|
+
place(x, y);
|
|
296
311
|
resolve();
|
|
297
312
|
return;
|
|
298
313
|
}
|
|
314
|
+
const dur = Math.max(280, Math.min(durationMs, dist * 0.9));
|
|
315
|
+
const ux = dx / dist;
|
|
316
|
+
const uy = dy / dist;
|
|
317
|
+
const nx = -uy;
|
|
318
|
+
const ny = ux;
|
|
319
|
+
const overshoot = dist > 70 ? Math.min(dist * 0.08, 14) : 0;
|
|
320
|
+
const aim = { x: x + ux * overshoot, y: y + uy * overshoot };
|
|
321
|
+
const adx = aim.x - from.x;
|
|
322
|
+
const ady = aim.y - from.y;
|
|
323
|
+
const arc = Math.min(dist * 0.16, 55) * (Math.random() < 0.5 ? -1 : 1);
|
|
324
|
+
const cx = from.x + adx * 0.5 + nx * arc;
|
|
325
|
+
const cy = from.y + ady * 0.5 + ny * arc;
|
|
326
|
+
const jitter = Math.min(dist * 0.02, 3.5);
|
|
327
|
+
const ballisticDur = overshoot ? dur * 0.82 : dur;
|
|
328
|
+
const correctDur = 150;
|
|
329
|
+
const correct = (from2, c0) => {
|
|
330
|
+
const t = Math.min(1, (performance.now() - c0) / correctDur);
|
|
331
|
+
const k = easeOut(t);
|
|
332
|
+
place(from2.x + (x - from2.x) * k, from2.y + (y - from2.y) * k);
|
|
333
|
+
if (t < 1) requestAnimationFrame(() => correct(from2, c0));
|
|
334
|
+
else {
|
|
335
|
+
place(x, y);
|
|
336
|
+
resolve();
|
|
337
|
+
}
|
|
338
|
+
};
|
|
299
339
|
const t0 = performance.now();
|
|
300
|
-
const
|
|
301
|
-
const t = Math.min(1, (now - t0) /
|
|
340
|
+
const ballistic = (now) => {
|
|
341
|
+
const t = Math.min(1, (now - t0) / ballisticDur);
|
|
302
342
|
const k = ease(t);
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
343
|
+
const mt = 1 - k;
|
|
344
|
+
let px = mt * mt * from.x + 2 * mt * k * cx + k * k * aim.x;
|
|
345
|
+
let py = mt * mt * from.y + 2 * mt * k * cy + k * k * aim.y;
|
|
346
|
+
if (t < 0.9) {
|
|
347
|
+
const fade = 1 - t / 0.9;
|
|
348
|
+
px += (Math.random() * 2 - 1) * jitter * fade;
|
|
349
|
+
py += (Math.random() * 2 - 1) * jitter * fade;
|
|
350
|
+
}
|
|
351
|
+
place(px, py);
|
|
352
|
+
if (t < 1) requestAnimationFrame(ballistic);
|
|
353
|
+
else if (overshoot) correct({ x: aim.x, y: aim.y }, performance.now());
|
|
354
|
+
else {
|
|
355
|
+
place(x, y);
|
|
356
|
+
resolve();
|
|
357
|
+
}
|
|
306
358
|
};
|
|
307
|
-
requestAnimationFrame(
|
|
359
|
+
requestAnimationFrame(ballistic);
|
|
308
360
|
});
|
|
309
361
|
},
|
|
310
362
|
clickPulse() {
|
|
311
363
|
return new Promise((resolve) => {
|
|
312
364
|
const ring = document.createElement("div");
|
|
313
|
-
ring.style.cssText = `position:fixed;z-index:2147483646;pointer-events:none;left:${pos.x -
|
|
365
|
+
ring.style.cssText = `position:fixed;z-index:2147483646;pointer-events:none;left:${pos.x - 22}px;top:${pos.y - 22}px;width:44px;height:44px;border-radius:50%;border:3px solid #4f8ef7;opacity:.9;transform:scale(.4);transition:transform .3s ease-out,opacity .3s ease-out;`;
|
|
314
366
|
document.body.appendChild(ring);
|
|
367
|
+
const pressT0 = performance.now();
|
|
368
|
+
const PRESS_MS = 200;
|
|
369
|
+
const press = (now) => {
|
|
370
|
+
const p = Math.min(1, (now - pressT0) / PRESS_MS);
|
|
371
|
+
scale = 1 - 0.18 * Math.sin(p * Math.PI);
|
|
372
|
+
apply();
|
|
373
|
+
if (p < 1) requestAnimationFrame(press);
|
|
374
|
+
else {
|
|
375
|
+
scale = 1;
|
|
376
|
+
apply();
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
requestAnimationFrame(press);
|
|
315
380
|
requestAnimationFrame(() => {
|
|
316
381
|
ring.style.transform = "scale(1.4)";
|
|
317
382
|
ring.style.opacity = "0";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qwertybit/pr-preview",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Record a UI journey once, get polished before/after MP4 clips of every pull request — automatically.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "QwertyBit <vlad@flowpoint.ai>",
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
"frontend"
|
|
58
58
|
],
|
|
59
59
|
"dependencies": {
|
|
60
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
60
61
|
"commander": "^12.1.0",
|
|
61
62
|
"get-port": "^7.1.0",
|
|
62
63
|
"gifenc": "^1.0.3",
|