@autono/pinbox-toolbar 0.8.0 → 0.10.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.
- package/dist/index-DK_kVd2Z.d.ts +240 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/{src-D1qn1iet.js → src-ChTPrRo5.js} +567 -6
- package/dist/svelte.d.ts +1 -1
- package/dist/svelte.js +1 -1
- package/dist/toolbar.iife.js +567 -6
- package/dist/vue.d.ts +1 -1
- package/dist/vue.js +1 -1
- package/package.json +2 -2
- package/dist/index-BAoi0bRT.d.ts +0 -2633
package/dist/toolbar.iife.js
CHANGED
|
@@ -289,6 +289,448 @@ var Pinbox = (function(exports) {
|
|
|
289
289
|
return `${open.map((p) => block(p, threads.get(p.id) ?? [])).join("\n\n")}\n`;
|
|
290
290
|
}
|
|
291
291
|
//#endregion
|
|
292
|
+
//#region src/motion/spring.ts
|
|
293
|
+
/** Bar ⇄ puck morphs and the post-drag settle. */
|
|
294
|
+
const MORPH_SPRING = {
|
|
295
|
+
k: 300,
|
|
296
|
+
c: 30
|
|
297
|
+
};
|
|
298
|
+
/** The morph surface chasing the pointer mid-drag. */
|
|
299
|
+
const FOLLOW_SPRING = {
|
|
300
|
+
k: 600,
|
|
301
|
+
c: 38
|
|
302
|
+
};
|
|
303
|
+
/** Integration substep — small enough that MORPH/FOLLOW stay stable at any dt. */
|
|
304
|
+
const SUBSTEP = 1 / 240;
|
|
305
|
+
/** A property this close to target, moving this slowly, counts as settled. */
|
|
306
|
+
const SETTLE = .5;
|
|
307
|
+
function mkSpring(init) {
|
|
308
|
+
const cur = { ...init };
|
|
309
|
+
const tgt = { ...init };
|
|
310
|
+
const keys = Object.keys(init);
|
|
311
|
+
const vel = {};
|
|
312
|
+
for (const key of keys) vel[key] = 0;
|
|
313
|
+
let cfg = { ...MORPH_SPRING };
|
|
314
|
+
const curN = cur;
|
|
315
|
+
const tgtN = tgt;
|
|
316
|
+
function integrate(h) {
|
|
317
|
+
for (const key of keys) {
|
|
318
|
+
const x = curN[key] ?? 0;
|
|
319
|
+
const v = vel[key] ?? 0;
|
|
320
|
+
const nextV = v + (-cfg.k * (x - (tgtN[key] ?? 0)) - cfg.c * v) * h;
|
|
321
|
+
vel[key] = nextV;
|
|
322
|
+
curN[key] = x + nextV * h;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
return {
|
|
326
|
+
cur,
|
|
327
|
+
tgt,
|
|
328
|
+
snap(values) {
|
|
329
|
+
Object.assign(cur, values);
|
|
330
|
+
Object.assign(tgt, values);
|
|
331
|
+
for (const key of Object.keys(vel)) vel[key] = 0;
|
|
332
|
+
},
|
|
333
|
+
to(values, nextCfg) {
|
|
334
|
+
Object.assign(tgt, values);
|
|
335
|
+
if (nextCfg) cfg = { ...nextCfg };
|
|
336
|
+
},
|
|
337
|
+
step(dt) {
|
|
338
|
+
let remaining = dt;
|
|
339
|
+
while (remaining > 1e-6) {
|
|
340
|
+
const h = Math.min(SUBSTEP, remaining);
|
|
341
|
+
remaining -= h;
|
|
342
|
+
integrate(h);
|
|
343
|
+
}
|
|
344
|
+
for (const key of keys) {
|
|
345
|
+
const v = vel[key] ?? 0;
|
|
346
|
+
const gap = (curN[key] ?? 0) - (tgtN[key] ?? 0);
|
|
347
|
+
if (Math.abs(v) > SETTLE || Math.abs(gap) > SETTLE) return false;
|
|
348
|
+
}
|
|
349
|
+
this.snap({ ...tgt });
|
|
350
|
+
return true;
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
//#endregion
|
|
355
|
+
//#region src/minimize.ts
|
|
356
|
+
const PUCK = 48;
|
|
357
|
+
const MARGIN = 16;
|
|
358
|
+
/** Movement that begins a drag… */
|
|
359
|
+
const DRAG_START = 8;
|
|
360
|
+
/** …but a release under this much TOTAL travel is still a tap. */
|
|
361
|
+
const TAP_MAX = 12;
|
|
362
|
+
/** Spring hold while the surface swap crossfades (ms). */
|
|
363
|
+
const HOLD_MINIMIZE = 90;
|
|
364
|
+
const HOLD_RESTORE = 70;
|
|
365
|
+
/** Arrival: real element fades in first, morph layer fades this much later. */
|
|
366
|
+
const SWAP_FADE = 100;
|
|
367
|
+
/** …and is display:none'd once its own fade has finished. */
|
|
368
|
+
const LAYER_HIDE = 140;
|
|
369
|
+
const BAR_RADIUS = 4;
|
|
370
|
+
/** The carrier icon rides the surface only while it is puck-like (< this width). */
|
|
371
|
+
const CARRIER_MAX_W = 260;
|
|
372
|
+
function createMinimize(host) {
|
|
373
|
+
const { win, bar, ui } = host;
|
|
374
|
+
const main = mkSpring({
|
|
375
|
+
x: 0,
|
|
376
|
+
y: 0,
|
|
377
|
+
w: 0,
|
|
378
|
+
h: 0,
|
|
379
|
+
r: 0
|
|
380
|
+
});
|
|
381
|
+
let mode = "bar";
|
|
382
|
+
let puckPos = null;
|
|
383
|
+
let dock = loadDock();
|
|
384
|
+
let pdown = null;
|
|
385
|
+
let keyboardToggle = false;
|
|
386
|
+
let raf = 0;
|
|
387
|
+
let last = 0;
|
|
388
|
+
let holdTimer = 0;
|
|
389
|
+
let fadeTimer = 0;
|
|
390
|
+
let hideTimer = 0;
|
|
391
|
+
function loadDock() {
|
|
392
|
+
try {
|
|
393
|
+
const raw = host.storage?.getItem(`${host.storagePrefix}:dock`);
|
|
394
|
+
if (raw == null) return null;
|
|
395
|
+
const parsed = JSON.parse(raw);
|
|
396
|
+
if (typeof parsed.x !== "number" || typeof parsed.y !== "number") return null;
|
|
397
|
+
return {
|
|
398
|
+
x: parsed.x,
|
|
399
|
+
y: parsed.y
|
|
400
|
+
};
|
|
401
|
+
} catch {
|
|
402
|
+
return null;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
function persist() {
|
|
406
|
+
try {
|
|
407
|
+
if (dock) host.storage?.setItem(`${host.storagePrefix}:dock`, JSON.stringify(dock));
|
|
408
|
+
host.storage?.setItem(`${host.storagePrefix}:minimized`, mode === "bar" ? "0" : "1");
|
|
409
|
+
} catch {}
|
|
410
|
+
}
|
|
411
|
+
function loadMinimized() {
|
|
412
|
+
try {
|
|
413
|
+
const raw = host.storage?.getItem(`${host.storagePrefix}:minimized`);
|
|
414
|
+
return raw == null ? host.initialMinimized : raw === "1";
|
|
415
|
+
} catch {
|
|
416
|
+
return host.initialMinimized;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
const clamp = (v, lo, hi) => Math.min(Math.max(v, lo), hi);
|
|
420
|
+
function clampPos(p) {
|
|
421
|
+
return {
|
|
422
|
+
x: clamp(p.x, MARGIN, win.innerWidth - MARGIN - PUCK),
|
|
423
|
+
y: clamp(p.y, MARGIN, win.innerHeight - MARGIN - PUCK)
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
function defaultDock() {
|
|
427
|
+
const r = bar.getBoundingClientRect();
|
|
428
|
+
return {
|
|
429
|
+
x: r.left + r.width / 2 - PUCK / 2,
|
|
430
|
+
y: r.top + (r.height - PUCK) / 2
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
function placePuck(x, y) {
|
|
434
|
+
puckPos = {
|
|
435
|
+
x,
|
|
436
|
+
y
|
|
437
|
+
};
|
|
438
|
+
ui.puck.style.transform = `translate(${x}px, ${y}px)`;
|
|
439
|
+
}
|
|
440
|
+
function render() {
|
|
441
|
+
const m = main.cur;
|
|
442
|
+
ui.surface.style.width = `${m.w}px`;
|
|
443
|
+
ui.surface.style.height = `${m.h}px`;
|
|
444
|
+
ui.surface.style.borderRadius = `${m.r}px`;
|
|
445
|
+
ui.surface.style.transform = `translate(${m.x}px, ${m.y}px)`;
|
|
446
|
+
ui.carrier.style.transform = `translate(${m.x + m.w / 2 - PUCK / 2}px, ${m.y + m.h / 2 - PUCK / 2}px)`;
|
|
447
|
+
const iconOn = mode === "drag" || mode === "settle" || (mode === "toPuck" || mode === "toBar") && m.w < CARRIER_MAX_W;
|
|
448
|
+
ui.carrier.classList.toggle("show", iconOn);
|
|
449
|
+
}
|
|
450
|
+
function showMorph() {
|
|
451
|
+
win.clearTimeout(hideTimer);
|
|
452
|
+
win.clearTimeout(fadeTimer);
|
|
453
|
+
ui.morphWrap.hidden = false;
|
|
454
|
+
ui.morphWrap.offsetWidth;
|
|
455
|
+
ui.morphWrap.classList.add("on");
|
|
456
|
+
}
|
|
457
|
+
function hideMorph() {
|
|
458
|
+
ui.morphWrap.classList.remove("on");
|
|
459
|
+
ui.carrier.classList.remove("show");
|
|
460
|
+
win.clearTimeout(hideTimer);
|
|
461
|
+
hideTimer = win.setTimeout(() => {
|
|
462
|
+
ui.morphWrap.hidden = true;
|
|
463
|
+
}, LAYER_HIDE);
|
|
464
|
+
}
|
|
465
|
+
function tick(now) {
|
|
466
|
+
const dt = Math.min((now - last) / 1e3, 1 / 30);
|
|
467
|
+
last = now;
|
|
468
|
+
const done = main.step(dt);
|
|
469
|
+
render();
|
|
470
|
+
if (done && mode !== "drag") {
|
|
471
|
+
raf = 0;
|
|
472
|
+
if (mode === "toPuck" || mode === "settle") finishPuck();
|
|
473
|
+
else if (mode === "toBar") finishBar();
|
|
474
|
+
} else raf = win.requestAnimationFrame(tick);
|
|
475
|
+
}
|
|
476
|
+
function ensureLoop() {
|
|
477
|
+
if (raf === 0) {
|
|
478
|
+
last = win.performance.now();
|
|
479
|
+
raf = win.requestAnimationFrame(tick);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
function finishPuck() {
|
|
483
|
+
placePuck(main.cur.x, main.cur.y);
|
|
484
|
+
ui.puck.classList.remove("pb-ghost");
|
|
485
|
+
win.clearTimeout(fadeTimer);
|
|
486
|
+
fadeTimer = win.setTimeout(hideMorph, SWAP_FADE);
|
|
487
|
+
mode = "puck";
|
|
488
|
+
persist();
|
|
489
|
+
host.onSettled(true, keyboardToggle);
|
|
490
|
+
}
|
|
491
|
+
function finishBar() {
|
|
492
|
+
bar.classList.remove("pb-ghost");
|
|
493
|
+
win.clearTimeout(fadeTimer);
|
|
494
|
+
fadeTimer = win.setTimeout(hideMorph, SWAP_FADE);
|
|
495
|
+
mode = "bar";
|
|
496
|
+
persist();
|
|
497
|
+
host.onSettled(false, keyboardToggle);
|
|
498
|
+
}
|
|
499
|
+
function minimize(keyboard = false) {
|
|
500
|
+
if (mode !== "bar") return;
|
|
501
|
+
pdown = null;
|
|
502
|
+
keyboardToggle = keyboard;
|
|
503
|
+
const r = bar.getBoundingClientRect();
|
|
504
|
+
const d = clampPos(dock ?? defaultDock());
|
|
505
|
+
bar.classList.add("pb-ghost");
|
|
506
|
+
if (host.reduced) {
|
|
507
|
+
placePuck(d.x, d.y);
|
|
508
|
+
ui.puck.classList.remove("pb-ghost");
|
|
509
|
+
mode = "puck";
|
|
510
|
+
persist();
|
|
511
|
+
host.onSettled(true, keyboard);
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
main.snap({
|
|
515
|
+
x: r.left,
|
|
516
|
+
y: r.top,
|
|
517
|
+
w: r.width,
|
|
518
|
+
h: r.height,
|
|
519
|
+
r: BAR_RADIUS
|
|
520
|
+
});
|
|
521
|
+
mode = "toPuck";
|
|
522
|
+
render();
|
|
523
|
+
showMorph();
|
|
524
|
+
win.clearTimeout(holdTimer);
|
|
525
|
+
holdTimer = win.setTimeout(() => {
|
|
526
|
+
main.to({
|
|
527
|
+
x: d.x,
|
|
528
|
+
y: d.y,
|
|
529
|
+
w: PUCK,
|
|
530
|
+
h: PUCK,
|
|
531
|
+
r: PUCK / 2
|
|
532
|
+
}, MORPH_SPRING);
|
|
533
|
+
ensureLoop();
|
|
534
|
+
}, HOLD_MINIMIZE);
|
|
535
|
+
}
|
|
536
|
+
function restore(keyboard = false) {
|
|
537
|
+
if (mode !== "puck" || puckPos === null) return;
|
|
538
|
+
pdown = null;
|
|
539
|
+
keyboardToggle = keyboard;
|
|
540
|
+
dock = { ...puckPos };
|
|
541
|
+
ui.puck.classList.add("pb-ghost");
|
|
542
|
+
if (host.reduced) {
|
|
543
|
+
bar.classList.remove("pb-ghost");
|
|
544
|
+
mode = "bar";
|
|
545
|
+
persist();
|
|
546
|
+
host.onSettled(false, keyboard);
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
const r = bar.getBoundingClientRect();
|
|
550
|
+
main.snap({
|
|
551
|
+
x: puckPos.x,
|
|
552
|
+
y: puckPos.y,
|
|
553
|
+
w: PUCK,
|
|
554
|
+
h: PUCK,
|
|
555
|
+
r: PUCK / 2
|
|
556
|
+
});
|
|
557
|
+
mode = "toBar";
|
|
558
|
+
render();
|
|
559
|
+
showMorph();
|
|
560
|
+
win.clearTimeout(holdTimer);
|
|
561
|
+
holdTimer = win.setTimeout(() => {
|
|
562
|
+
main.to({
|
|
563
|
+
x: r.left,
|
|
564
|
+
y: r.top,
|
|
565
|
+
w: r.width,
|
|
566
|
+
h: r.height,
|
|
567
|
+
r: BAR_RADIUS
|
|
568
|
+
}, MORPH_SPRING);
|
|
569
|
+
ensureLoop();
|
|
570
|
+
}, HOLD_RESTORE);
|
|
571
|
+
}
|
|
572
|
+
function onPointerDown(e) {
|
|
573
|
+
if (mode !== "puck" || e.button !== 0) return;
|
|
574
|
+
try {
|
|
575
|
+
ui.puck.setPointerCapture(e.pointerId);
|
|
576
|
+
} catch {}
|
|
577
|
+
if (puckPos === null) return;
|
|
578
|
+
pdown = {
|
|
579
|
+
px: e.clientX,
|
|
580
|
+
py: e.clientY,
|
|
581
|
+
ox: puckPos.x,
|
|
582
|
+
oy: puckPos.y,
|
|
583
|
+
lx: e.clientX,
|
|
584
|
+
ly: e.clientY,
|
|
585
|
+
moved: false
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
function onPointerMove(e) {
|
|
589
|
+
if (pdown === null) return;
|
|
590
|
+
pdown.lx = e.clientX;
|
|
591
|
+
pdown.ly = e.clientY;
|
|
592
|
+
const dx = e.clientX - pdown.px;
|
|
593
|
+
const dy = e.clientY - pdown.py;
|
|
594
|
+
if (!pdown.moved) {
|
|
595
|
+
if (mode !== "puck") {
|
|
596
|
+
pdown = null;
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
if (Math.hypot(dx, dy) < DRAG_START) return;
|
|
600
|
+
pdown.moved = true;
|
|
601
|
+
mode = "drag";
|
|
602
|
+
if (!host.reduced) {
|
|
603
|
+
ui.puck.classList.add("pb-ghost");
|
|
604
|
+
main.snap({
|
|
605
|
+
x: pdown.ox,
|
|
606
|
+
y: pdown.oy,
|
|
607
|
+
w: PUCK,
|
|
608
|
+
h: PUCK,
|
|
609
|
+
r: PUCK / 2
|
|
610
|
+
});
|
|
611
|
+
render();
|
|
612
|
+
showMorph();
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
const next = {
|
|
616
|
+
x: pdown.ox + dx,
|
|
617
|
+
y: pdown.oy + dy
|
|
618
|
+
};
|
|
619
|
+
if (host.reduced) {
|
|
620
|
+
const p = clampPos(next);
|
|
621
|
+
placePuck(p.x, p.y);
|
|
622
|
+
} else {
|
|
623
|
+
main.to({
|
|
624
|
+
...next,
|
|
625
|
+
w: PUCK,
|
|
626
|
+
h: PUCK,
|
|
627
|
+
r: PUCK / 2
|
|
628
|
+
}, FOLLOW_SPRING);
|
|
629
|
+
ensureLoop();
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
function onPointerUp() {
|
|
633
|
+
if (pdown === null) return;
|
|
634
|
+
const total = Math.hypot(pdown.lx - pdown.px, pdown.ly - pdown.py);
|
|
635
|
+
const wasDrag = pdown.moved && total >= TAP_MAX;
|
|
636
|
+
const origin = {
|
|
637
|
+
x: pdown.ox,
|
|
638
|
+
y: pdown.oy
|
|
639
|
+
};
|
|
640
|
+
const startedDrag = pdown.moved;
|
|
641
|
+
pdown = null;
|
|
642
|
+
if (!wasDrag) {
|
|
643
|
+
if (startedDrag && mode === "drag") {
|
|
644
|
+
main.snap({
|
|
645
|
+
x: origin.x,
|
|
646
|
+
y: origin.y,
|
|
647
|
+
w: PUCK,
|
|
648
|
+
h: PUCK,
|
|
649
|
+
r: PUCK / 2
|
|
650
|
+
});
|
|
651
|
+
placePuck(origin.x, origin.y);
|
|
652
|
+
ui.puck.classList.remove("pb-ghost");
|
|
653
|
+
hideMorph();
|
|
654
|
+
mode = "puck";
|
|
655
|
+
}
|
|
656
|
+
restore(false);
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
if (host.reduced) {
|
|
660
|
+
if (puckPos) {
|
|
661
|
+
const p = clampPos(puckPos);
|
|
662
|
+
placePuck(p.x, p.y);
|
|
663
|
+
dock = { ...p };
|
|
664
|
+
}
|
|
665
|
+
mode = "puck";
|
|
666
|
+
persist();
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
669
|
+
const p = clampPos({
|
|
670
|
+
x: main.tgt.x,
|
|
671
|
+
y: main.tgt.y
|
|
672
|
+
});
|
|
673
|
+
main.to({
|
|
674
|
+
...p,
|
|
675
|
+
w: PUCK,
|
|
676
|
+
h: PUCK,
|
|
677
|
+
r: PUCK / 2
|
|
678
|
+
}, MORPH_SPRING);
|
|
679
|
+
mode = "settle";
|
|
680
|
+
ensureLoop();
|
|
681
|
+
}
|
|
682
|
+
/** Keyboard/AT activation is a synthesized click (detail 0) with no pointer events. */
|
|
683
|
+
function onClick(e) {
|
|
684
|
+
if (e.detail === 0) restore(true);
|
|
685
|
+
}
|
|
686
|
+
function onResize() {
|
|
687
|
+
if (mode === "puck" && puckPos !== null) {
|
|
688
|
+
const p = clampPos(puckPos);
|
|
689
|
+
placePuck(p.x, p.y);
|
|
690
|
+
}
|
|
691
|
+
if (dock !== null) dock = clampPos(dock);
|
|
692
|
+
}
|
|
693
|
+
ui.puck.addEventListener("pointerdown", onPointerDown);
|
|
694
|
+
ui.puck.addEventListener("pointermove", onPointerMove);
|
|
695
|
+
ui.puck.addEventListener("pointerup", onPointerUp);
|
|
696
|
+
ui.puck.addEventListener("pointercancel", onPointerUp);
|
|
697
|
+
ui.puck.addEventListener("click", onClick);
|
|
698
|
+
win.addEventListener("resize", onResize);
|
|
699
|
+
return {
|
|
700
|
+
minimized: () => mode !== "bar",
|
|
701
|
+
mode: () => mode,
|
|
702
|
+
minimize,
|
|
703
|
+
restore,
|
|
704
|
+
applyInitial() {
|
|
705
|
+
if (!loadMinimized()) return;
|
|
706
|
+
const apply = () => {
|
|
707
|
+
if (mode !== "bar") return;
|
|
708
|
+
const d = clampPos(dock ?? defaultDock());
|
|
709
|
+
bar.classList.add("pb-ghost");
|
|
710
|
+
placePuck(d.x, d.y);
|
|
711
|
+
ui.puck.classList.remove("pb-ghost");
|
|
712
|
+
mode = "puck";
|
|
713
|
+
host.onSettled(true, false);
|
|
714
|
+
};
|
|
715
|
+
if (host.reduced) apply();
|
|
716
|
+
else win.requestAnimationFrame(apply);
|
|
717
|
+
},
|
|
718
|
+
destroy() {
|
|
719
|
+
ui.puck.removeEventListener("pointerdown", onPointerDown);
|
|
720
|
+
ui.puck.removeEventListener("pointermove", onPointerMove);
|
|
721
|
+
ui.puck.removeEventListener("pointerup", onPointerUp);
|
|
722
|
+
ui.puck.removeEventListener("pointercancel", onPointerUp);
|
|
723
|
+
ui.puck.removeEventListener("click", onClick);
|
|
724
|
+
win.removeEventListener("resize", onResize);
|
|
725
|
+
if (raf !== 0) win.cancelAnimationFrame(raf);
|
|
726
|
+
raf = 0;
|
|
727
|
+
win.clearTimeout(holdTimer);
|
|
728
|
+
win.clearTimeout(fadeTimer);
|
|
729
|
+
win.clearTimeout(hideTimer);
|
|
730
|
+
}
|
|
731
|
+
};
|
|
732
|
+
}
|
|
733
|
+
//#endregion
|
|
292
734
|
//#region src/screenshot.ts
|
|
293
735
|
const WEBP_QUALITY = .7;
|
|
294
736
|
const PLACEHOLDER_MAX = 32;
|
|
@@ -420,7 +862,8 @@ var Pinbox = (function(exports) {
|
|
|
420
862
|
activePinId: null,
|
|
421
863
|
inboxOpen: false,
|
|
422
864
|
connection: "connecting",
|
|
423
|
-
queuedIds: /* @__PURE__ */ new Set()
|
|
865
|
+
queuedIds: /* @__PURE__ */ new Set(),
|
|
866
|
+
minimized: false
|
|
424
867
|
};
|
|
425
868
|
}
|
|
426
869
|
function createStore() {
|
|
@@ -1115,6 +1558,7 @@ var Pinbox = (function(exports) {
|
|
|
1115
1558
|
const THEME_ICON = "<svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"M8 1.6a6.4 6.4 0 100 12.8A5 5 0 018 1.6z\"/></svg>";
|
|
1116
1559
|
const COPY_ICON = "<svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"5.5\" y=\"5.5\" width=\"8\" height=\"8\" rx=\"1\"/><path d=\"M10.5 3.5v-1a1 1 0 00-1-1h-6a1 1 0 00-1 1v6a1 1 0 001 1h1\"/></svg>";
|
|
1117
1560
|
const IDENT_ICON = "<svg width=\"15\" height=\"15\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"var(--pb-amber)\" stroke-width=\"1.4\"><rect x=\"2.5\" y=\"1.5\" width=\"11\" height=\"7\" rx=\"1\"/><path d=\"M8 8.5v6\"/><circle cx=\"8\" cy=\"14.6\" r=\".9\" fill=\"var(--pb-amber)\" stroke=\"none\"/></svg>";
|
|
1561
|
+
const MIN_ICON = "<svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"M6.5 2.5v4h-4\"/><path d=\"M9.5 13.5v-4h4\"/></svg>";
|
|
1118
1562
|
const CONNECTION_LABEL = {
|
|
1119
1563
|
connecting: "PINBOX",
|
|
1120
1564
|
live: "PINBOX",
|
|
@@ -1124,7 +1568,7 @@ var Pinbox = (function(exports) {
|
|
|
1124
1568
|
function createBar(doc, on) {
|
|
1125
1569
|
const root = doc.createElement("div");
|
|
1126
1570
|
root.className = "pb-bar";
|
|
1127
|
-
root.innerHTML = `<div class="armed-ring"></div><div class="ident">${IDENT_ICON}<span class="bl" data-ref="label">PINBOX</span></div><div class="div"></div><button type="button" class="pb-tb" data-ref="pin" title="Pin (P)">${PIN_ICON}PIN</button><button type="button" class="pb-tb" data-ref="inbox" title="Inbox (I)">${INBOX_ICON}<span data-ref="count">0</span></button><div class="div" style="margin:0 3px"></div><button type="button" class="pb-tb sq" data-ref="copy" title="Copy open pins (C)">${COPY_ICON}</button><button type="button" class="pb-tb sq" data-ref="theme" title="Theme (D)">${THEME_ICON}</button><button type="button" class="pb-tb sq" data-ref="help" title="Shortcuts (?)">?</button>`;
|
|
1571
|
+
root.innerHTML = `<div class="armed-ring"></div><div class="ident">${IDENT_ICON}<span class="bl" data-ref="label">PINBOX</span></div><div class="div"></div><button type="button" class="pb-tb" data-ref="pin" title="Pin (P)">${PIN_ICON}PIN</button><button type="button" class="pb-tb" data-ref="inbox" title="Inbox (I)">${INBOX_ICON}<span data-ref="count">0</span></button><div class="div" style="margin:0 3px"></div><button type="button" class="pb-tb sq" data-ref="copy" title="Copy open pins (C)">${COPY_ICON}</button><button type="button" class="pb-tb sq" data-ref="theme" title="Theme (D)">${THEME_ICON}</button><button type="button" class="pb-tb sq" data-ref="help" title="Shortcuts (?)">?</button><button type="button" class="pb-tb sq" data-ref="min" title="Minimize (M)" aria-label="Minimize toolbar">${MIN_ICON}</button>`;
|
|
1128
1572
|
const ref = (name) => root.querySelector(`[data-ref="${name}"]`);
|
|
1129
1573
|
const label = ref("label");
|
|
1130
1574
|
const pinBtn = ref("pin");
|
|
@@ -1135,6 +1579,7 @@ var Pinbox = (function(exports) {
|
|
|
1135
1579
|
ref("copy").addEventListener("click", on.onCopy);
|
|
1136
1580
|
ref("theme").addEventListener("click", on.onTheme);
|
|
1137
1581
|
ref("help").addEventListener("click", on.onHelp);
|
|
1582
|
+
ref("min").addEventListener("click", (e) => on.onMinimize(e.detail === 0));
|
|
1138
1583
|
return {
|
|
1139
1584
|
root,
|
|
1140
1585
|
update(state) {
|
|
@@ -1631,6 +2076,43 @@ var Pinbox = (function(exports) {
|
|
|
1631
2076
|
if (state.draft) patchNode(ensureNode(layer, "draft", true), state.draft.placedAt, true, chipInner(visible.length + 1, null));
|
|
1632
2077
|
}
|
|
1633
2078
|
//#endregion
|
|
2079
|
+
//#region src/ui/puck.ts
|
|
2080
|
+
/** The bar's ident mark, sized up for the 48px puck face. */
|
|
2081
|
+
const PUCK_ICON = "<svg width=\"17\" height=\"17\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"2.5\" y=\"1.5\" width=\"11\" height=\"7\" rx=\"1\"/><path d=\"M8 8.5v6\"/><circle cx=\"8\" cy=\"14.6\" r=\".9\" fill=\"currentColor\" stroke=\"none\"/></svg>";
|
|
2082
|
+
function createMinimizeUi(doc) {
|
|
2083
|
+
const puck = doc.createElement("button");
|
|
2084
|
+
puck.type = "button";
|
|
2085
|
+
puck.className = "pb-puck pb-ghost";
|
|
2086
|
+
puck.setAttribute("aria-label", "Restore Pinbox toolbar");
|
|
2087
|
+
puck.innerHTML = `<span class="in">${PUCK_ICON}</span><span class="badge" data-ref="count" hidden>0</span><span class="cdot"></span>`;
|
|
2088
|
+
const morphWrap = doc.createElement("div");
|
|
2089
|
+
morphWrap.className = "pb-morph-wrap";
|
|
2090
|
+
morphWrap.hidden = true;
|
|
2091
|
+
const surface = doc.createElement("div");
|
|
2092
|
+
surface.className = "pb-morph";
|
|
2093
|
+
const carrier = doc.createElement("div");
|
|
2094
|
+
carrier.className = "pb-carrier";
|
|
2095
|
+
carrier.innerHTML = `${PUCK_ICON}<span class="badge" data-ref="count" hidden>0</span>`;
|
|
2096
|
+
morphWrap.appendChild(surface);
|
|
2097
|
+
morphWrap.appendChild(carrier);
|
|
2098
|
+
const badges = [puck.querySelector("[data-ref=\"count\"]"), carrier.querySelector("[data-ref=\"count\"]")];
|
|
2099
|
+
return {
|
|
2100
|
+
puck,
|
|
2101
|
+
morphWrap,
|
|
2102
|
+
surface,
|
|
2103
|
+
carrier,
|
|
2104
|
+
update(state) {
|
|
2105
|
+
const open = String(state.pins.filter((p) => p.status !== "resolved").length);
|
|
2106
|
+
for (const badge of badges) {
|
|
2107
|
+
if (badge.textContent !== open) badge.textContent = open;
|
|
2108
|
+
badge.hidden = open === "0";
|
|
2109
|
+
}
|
|
2110
|
+
const degraded = state.connection === "offline" || state.connection === "incompatible";
|
|
2111
|
+
puck.classList.toggle("degraded", degraded);
|
|
2112
|
+
}
|
|
2113
|
+
};
|
|
2114
|
+
}
|
|
2115
|
+
//#endregion
|
|
1634
2116
|
//#region src/ui/reticle.ts
|
|
1635
2117
|
function createReticle(doc) {
|
|
1636
2118
|
const crosshair = doc.createElement("div");
|
|
@@ -1686,6 +2168,7 @@ var Pinbox = (function(exports) {
|
|
|
1686
2168
|
["Send comment", "⌘ ↵"],
|
|
1687
2169
|
["Mark pin resolved", "R"],
|
|
1688
2170
|
["Copy open pins", "C"],
|
|
2171
|
+
["Minimize toolbar", "M"],
|
|
1689
2172
|
["Cancel", "ESC"]
|
|
1690
2173
|
];
|
|
1691
2174
|
function createShortcutsModal(doc, onClose) {
|
|
@@ -1896,6 +2379,27 @@ button { font: inherit; color: inherit; background: none; border: 0; cursor: poi
|
|
|
1896
2379
|
.pb-item .mm .sdot { width: 5px; height: 5px; border-radius: 999px; }
|
|
1897
2380
|
.pb-empty { padding: 26px 16px; font-size: 12.5px; color: var(--pb-fg3); }
|
|
1898
2381
|
|
|
2382
|
+
/* minimize: floating puck + morph layer (ui/puck.ts, minimize.ts) — v3 design.
|
|
2383
|
+
The morph surface is styled identically to the bar so endpoint handoffs are
|
|
2384
|
+
pixel-invisible. Ghosting keeps layout (getBoundingClientRect still measures
|
|
2385
|
+
morph targets) while dropping the element from paint and the tab order. */
|
|
2386
|
+
.pb-ghost { opacity: 0 !important; pointer-events: none !important; visibility: hidden; transition: opacity 90ms linear, visibility 0s 90ms; }
|
|
2387
|
+
.pb-bar { transition: opacity 90ms linear; }
|
|
2388
|
+
.pb-morph-wrap { position: fixed; inset: 0; z-index: 89; pointer-events: none; opacity: 0; transition: opacity 90ms linear; }
|
|
2389
|
+
.pb-morph-wrap.on { opacity: 1; }
|
|
2390
|
+
.pb-morph { position: absolute; left: 0; top: 0; background: var(--pb-bar); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); border: 1px solid var(--pb-line-2); box-shadow: var(--pb-shadow); will-change: transform, width, height; }
|
|
2391
|
+
.pb-carrier { position: absolute; left: 0; top: 0; width: 48px; height: 48px; display: flex; align-items: center; justify-content: center; color: var(--pb-amber); opacity: 0; transition: opacity 140ms linear; will-change: transform; }
|
|
2392
|
+
.pb-carrier.show { opacity: 1; }
|
|
2393
|
+
/* Above the bar (90) and drawer (85), below the aim layer (100) and modal (120). */
|
|
2394
|
+
.pb-puck { position: fixed; left: 0; top: 0; width: 48px; height: 48px; z-index: 95; border-radius: 999px; background: var(--pb-bar); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); border: 1px solid var(--pb-line-2); box-shadow: var(--pb-shadow); display: flex; align-items: center; justify-content: center; color: var(--pb-amber); cursor: grab; touch-action: none; transition: opacity 90ms linear; }
|
|
2395
|
+
.pb-puck:active { cursor: grabbing; }
|
|
2396
|
+
.pb-puck .in { display: flex; transition: transform 160ms var(--pb-ease); }
|
|
2397
|
+
.pb-puck:hover .in { transform: scale(1.12); }
|
|
2398
|
+
.pb-puck .badge, .pb-carrier .badge { position: absolute; top: -5px; right: -5px; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 999px; background: var(--pb-amber); color: var(--pb-amber-ink); font-family: var(--pb-font-mono); font-size: 9px; font-weight: 500; display: flex; align-items: center; justify-content: center; }
|
|
2399
|
+
/* The bar says "· OFFLINE" in words; the puck's amber dot is the same signal. */
|
|
2400
|
+
.pb-puck .cdot { position: absolute; bottom: -1px; right: -1px; width: 9px; height: 9px; border-radius: 999px; background: var(--pb-amber); border: 2px solid var(--pb-canvas); display: none; }
|
|
2401
|
+
.pb-puck.degraded .cdot { display: block; }
|
|
2402
|
+
|
|
1899
2403
|
/* shortcuts modal (ui/shortcuts.ts) — prototype lines 226–232 */
|
|
1900
2404
|
.pb-modal { position: fixed; inset: 0; z-index: 120; display: flex; align-items: center; justify-content: center; background: var(--pb-scrim); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); animation: pb-fade 200ms ease-out both; }
|
|
1901
2405
|
.pb-modal .mx { width: 430px; background: var(--pb-elev); border: 1px solid var(--pb-line-2); border-radius: 4px; box-shadow: var(--pb-shadow); animation: pb-in 280ms var(--pb-ease) both; }
|
|
@@ -1951,6 +2455,8 @@ button { font: inherit; color: inherit; background: none; border: 0; cursor: poi
|
|
|
1951
2455
|
/** Pending viewport-refresh frame, 0 when none is queued. */
|
|
1952
2456
|
#viewportFrame = 0;
|
|
1953
2457
|
#modal = null;
|
|
2458
|
+
#minUi = null;
|
|
2459
|
+
#min = null;
|
|
1954
2460
|
#helpOpen = false;
|
|
1955
2461
|
#pageStyle = null;
|
|
1956
2462
|
#unsubscribe = null;
|
|
@@ -1991,6 +2497,7 @@ button { font: inherit; color: inherit; background: none; border: 0; cursor: poi
|
|
|
1991
2497
|
document.head.appendChild(style);
|
|
1992
2498
|
this.#pageStyle = style;
|
|
1993
2499
|
if (this.#aim === null) this.#mountAim();
|
|
2500
|
+
if (this.#min === null) this.#mountMinimize();
|
|
1994
2501
|
document.addEventListener("mousemove", this.#onMouseMove);
|
|
1995
2502
|
window.addEventListener("scroll", this.#onViewportChange, { passive: true });
|
|
1996
2503
|
window.addEventListener("resize", this.#onViewportChange);
|
|
@@ -2036,6 +2543,8 @@ button { font: inherit; color: inherit; background: none; border: 0; cursor: poi
|
|
|
2036
2543
|
this.#viewportFrame = 0;
|
|
2037
2544
|
this.#aim?.destroy();
|
|
2038
2545
|
this.#aim = null;
|
|
2546
|
+
this.#min?.destroy();
|
|
2547
|
+
this.#min = null;
|
|
2039
2548
|
this.#unsubscribe?.();
|
|
2040
2549
|
this.#unsubscribe = null;
|
|
2041
2550
|
this.#pageStyle?.remove();
|
|
@@ -2089,9 +2598,13 @@ button { font: inherit; color: inherit; background: none; border: 0; cursor: poi
|
|
|
2089
2598
|
onInbox: () => this.store.update({ inboxOpen: !this.store.get().inboxOpen }),
|
|
2090
2599
|
onTheme: () => this.#toggleTheme(),
|
|
2091
2600
|
onHelp: () => this.#toggleHelp(),
|
|
2092
|
-
onCopy: () => this.#copyOpenPins()
|
|
2601
|
+
onCopy: () => this.#copyOpenPins(),
|
|
2602
|
+
onMinimize: (keyboard) => this.minimize(keyboard)
|
|
2093
2603
|
});
|
|
2094
2604
|
shadow.appendChild(this.#bar.root);
|
|
2605
|
+
this.#minUi = createMinimizeUi(document);
|
|
2606
|
+
shadow.appendChild(this.#minUi.morphWrap);
|
|
2607
|
+
shadow.appendChild(this.#minUi.puck);
|
|
2095
2608
|
this.#drawer = createDrawer(document, {
|
|
2096
2609
|
onActivate: (pinId) => this.#activateFromInbox(pinId),
|
|
2097
2610
|
onClose: () => this.store.update({ inboxOpen: false })
|
|
@@ -2102,6 +2615,52 @@ button { font: inherit; color: inherit; background: none; border: 0; cursor: poi
|
|
|
2102
2615
|
shadow.appendChild(this.#modal.root);
|
|
2103
2616
|
this.#pinsLayer.addEventListener("click", (e) => this.#onChipClick(e));
|
|
2104
2617
|
}
|
|
2618
|
+
/** Same lifetime split as #mountAim: the controller's window listeners and timers die on
|
|
2619
|
+
* disconnect, so it is (re)built on connect and re-applies the persisted resting state. */
|
|
2620
|
+
#mountMinimize() {
|
|
2621
|
+
const ui = this.#minUi;
|
|
2622
|
+
const bar = this.#bar;
|
|
2623
|
+
if (ui === null || bar === null) return;
|
|
2624
|
+
this.#min = createMinimize({
|
|
2625
|
+
win: window,
|
|
2626
|
+
bar: bar.root,
|
|
2627
|
+
ui,
|
|
2628
|
+
storage: globalThis.localStorage ?? null,
|
|
2629
|
+
storagePrefix: `pinbox:${this.config?.endpoint ?? ""}`,
|
|
2630
|
+
reduced: window.matchMedia("(prefers-reduced-motion: reduce)").matches,
|
|
2631
|
+
initialMinimized: this.config?.minimized === true,
|
|
2632
|
+
onSettled: (minimized, keyboard) => this.#onMinimizeSettled(minimized, keyboard)
|
|
2633
|
+
});
|
|
2634
|
+
this.#min.applyInitial();
|
|
2635
|
+
}
|
|
2636
|
+
#onMinimizeSettled(minimized, keyboard) {
|
|
2637
|
+
if (this.store.get().minimized !== minimized) this.store.update({ minimized });
|
|
2638
|
+
this.dispatchEvent(new CustomEvent(minimized ? "pinbox:minimize" : "pinbox:restore", {
|
|
2639
|
+
bubbles: true,
|
|
2640
|
+
composed: true
|
|
2641
|
+
}));
|
|
2642
|
+
if (!keyboard) return;
|
|
2643
|
+
if (minimized) this.#minUi?.puck.focus();
|
|
2644
|
+
else this.#bar?.root.querySelector("[data-ref=\"min\"]")?.focus();
|
|
2645
|
+
}
|
|
2646
|
+
/** Public: collapse the bar to the floating puck. Bar surfaces close first —
|
|
2647
|
+
* the morph must never sweep over an open card, drawer, or armed reticle. */
|
|
2648
|
+
minimize(keyboard = false) {
|
|
2649
|
+
const state = this.store.get();
|
|
2650
|
+
if (state.mode === "placing" || state.activePinId !== null || state.draft !== null) this.#dismiss();
|
|
2651
|
+
if (state.inboxOpen) this.store.update({ inboxOpen: false });
|
|
2652
|
+
this.#setHelp(false);
|
|
2653
|
+
this.#min?.minimize(keyboard);
|
|
2654
|
+
}
|
|
2655
|
+
/** Public: bring the bar back from the puck. */
|
|
2656
|
+
restore(keyboard = false) {
|
|
2657
|
+
this.#min?.restore(keyboard);
|
|
2658
|
+
}
|
|
2659
|
+
/** Bar-surface shortcuts pressed while minimized restore the bar, then run. */
|
|
2660
|
+
#surfaced(run) {
|
|
2661
|
+
if (this.#min?.minimized() === true) this.restore(false);
|
|
2662
|
+
run();
|
|
2663
|
+
}
|
|
2105
2664
|
/**
|
|
2106
2665
|
* Task 8 wiring: WS events mutate the store, connection state renders in the
|
|
2107
2666
|
* bar, card actions hit the hub. The mirror seeds pins so an offline reload
|
|
@@ -2325,14 +2884,15 @@ button { font: inherit; color: inherit; background: none; border: 0; cursor: poi
|
|
|
2325
2884
|
if (state.inboxOpen) this.store.update({ inboxOpen: false });
|
|
2326
2885
|
if (state.activePinId || state.draft) this.#dismiss();
|
|
2327
2886
|
};
|
|
2328
|
-
/** Prototype keyboard map (v2-command-bar.html lines 701–712). */
|
|
2887
|
+
/** Prototype keyboard map (v2-command-bar.html lines 701–712) + M (v3 minimize). */
|
|
2329
2888
|
#shortcuts = {
|
|
2330
2889
|
escape: () => this.#dismiss(),
|
|
2331
|
-
p: () => this.#togglePlacing(),
|
|
2332
|
-
i: () => this.#toggleInbox(),
|
|
2890
|
+
p: () => this.#surfaced(() => this.#togglePlacing()),
|
|
2891
|
+
i: () => this.#surfaced(() => this.#toggleInbox()),
|
|
2333
2892
|
d: () => this.#toggleTheme(),
|
|
2334
2893
|
r: () => this.#resolveActive(),
|
|
2335
2894
|
c: () => this.#copyOpenPins(),
|
|
2895
|
+
m: () => this.#min?.minimized() === true ? this.restore(true) : this.minimize(true),
|
|
2336
2896
|
"?": () => this.#toggleHelp()
|
|
2337
2897
|
};
|
|
2338
2898
|
#onKeyDown = (e) => {
|
|
@@ -2370,6 +2930,7 @@ button { font: inherit; color: inherit; background: none; border: 0; cursor: poi
|
|
|
2370
2930
|
if (this.shadowRoot) renderCard(this.shadowRoot, state, this.#cardActions);
|
|
2371
2931
|
this.#drawer?.update(state);
|
|
2372
2932
|
this.#bar?.update(state);
|
|
2933
|
+
this.#minUi?.update(state);
|
|
2373
2934
|
}
|
|
2374
2935
|
};
|
|
2375
2936
|
//#endregion
|
package/dist/vue.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { d as PinboxToolbarElement, n as PinboxConfig } from "./index-
|
|
1
|
+
import { d as PinboxToolbarElement, n as PinboxConfig } from "./index-DK_kVd2Z.js";
|
|
2
2
|
import { VNode } from "vue";
|
|
3
3
|
//#region src/vue.d.ts
|
|
4
4
|
/** The slice of the Vue component instance this wrapper touches. */
|
package/dist/vue.js
CHANGED