@autono/pinbox-toolbar 0.10.0 → 0.12.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.js +1 -1
- package/dist/react.js +1 -1
- package/dist/{src-ChTPrRo5.js → src-C-gslo8y.js} +120 -14
- package/dist/svelte.js +1 -1
- package/dist/toolbar.iife.js +120 -14
- package/dist/vue.js +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as HubError, c as createStore, i as HubTransport, l as deriveUiStatus, n as defineToolbarElement, o as appendThreadMessage, r as PinboxToolbarElement, s as applyHubEvent, t as Pinbox, u as upsertPin } from "./src-
|
|
1
|
+
import { a as HubError, c as createStore, i as HubTransport, l as deriveUiStatus, n as defineToolbarElement, o as appendThreadMessage, r as PinboxToolbarElement, s as applyHubEvent, t as Pinbox, u as upsertPin } from "./src-C-gslo8y.js";
|
|
2
2
|
export { HubError, HubTransport, Pinbox, PinboxToolbarElement, appendThreadMessage, applyHubEvent, createStore, defineToolbarElement, deriveUiStatus, upsertPin };
|
package/dist/react.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as defineToolbarElement, r as PinboxToolbarElement } from "./src-
|
|
1
|
+
import { n as defineToolbarElement, r as PinboxToolbarElement } from "./src-C-gslo8y.js";
|
|
2
2
|
import { createElement, useEffect, useRef } from "react";
|
|
3
3
|
//#region src/react.ts
|
|
4
4
|
/**
|
|
@@ -367,6 +367,8 @@ const LAYER_HIDE = 140;
|
|
|
367
367
|
const BAR_RADIUS = 4;
|
|
368
368
|
/** The carrier icon rides the surface only while it is puck-like (< this width). */
|
|
369
369
|
const CARRIER_MAX_W = 260;
|
|
370
|
+
/** Fan close transition length before display:none. */
|
|
371
|
+
const FAN_HIDE = 300;
|
|
370
372
|
function createMinimize(host) {
|
|
371
373
|
const { win, bar, ui } = host;
|
|
372
374
|
const main = mkSpring({
|
|
@@ -386,6 +388,8 @@ function createMinimize(host) {
|
|
|
386
388
|
let holdTimer = 0;
|
|
387
389
|
let fadeTimer = 0;
|
|
388
390
|
let hideTimer = 0;
|
|
391
|
+
let fanOpen = false;
|
|
392
|
+
let fanTimer = 0;
|
|
389
393
|
function loadDock() {
|
|
390
394
|
try {
|
|
391
395
|
const raw = host.storage?.getItem(`${host.storagePrefix}:dock`);
|
|
@@ -533,6 +537,7 @@ function createMinimize(host) {
|
|
|
533
537
|
}
|
|
534
538
|
function restore(keyboard = false) {
|
|
535
539
|
if (mode !== "puck" || puckPos === null) return;
|
|
540
|
+
closeFan();
|
|
536
541
|
pdown = null;
|
|
537
542
|
keyboardToggle = keyboard;
|
|
538
543
|
dock = { ...puckPos };
|
|
@@ -567,6 +572,54 @@ function createMinimize(host) {
|
|
|
567
572
|
ensureLoop();
|
|
568
573
|
}, HOLD_RESTORE);
|
|
569
574
|
}
|
|
575
|
+
/** Fan out of the puck: direction away from the nearer vertical edge,
|
|
576
|
+
* labels sliding toward screen center. */
|
|
577
|
+
function openFan() {
|
|
578
|
+
if (mode !== "puck" || puckPos === null) return;
|
|
579
|
+
win.clearTimeout(fanTimer);
|
|
580
|
+
ui.fan.hidden = false;
|
|
581
|
+
const upward = puckPos.y + PUCK / 2 > win.innerHeight / 2;
|
|
582
|
+
ui.fan.classList.toggle("up", upward);
|
|
583
|
+
ui.fan.classList.toggle("down", !upward);
|
|
584
|
+
ui.fan.classList.toggle("labels-right", puckPos.x + PUCK / 2 < win.innerWidth / 2);
|
|
585
|
+
ui.fan.classList.toggle("labels-left", puckPos.x + PUCK / 2 >= win.innerWidth / 2);
|
|
586
|
+
ui.fan.style.left = `${puckPos.x + PUCK / 2 - 20}px`;
|
|
587
|
+
ui.fan.offsetHeight;
|
|
588
|
+
const h = ui.fan.offsetHeight;
|
|
589
|
+
ui.fan.style.top = upward ? `${puckPos.y - h - 10}px` : `${puckPos.y + PUCK + 10}px`;
|
|
590
|
+
ui.fan.classList.add("on");
|
|
591
|
+
ui.puck.setAttribute("aria-expanded", "true");
|
|
592
|
+
fanOpen = true;
|
|
593
|
+
}
|
|
594
|
+
function closeFan() {
|
|
595
|
+
if (!fanOpen) return false;
|
|
596
|
+
ui.fan.classList.remove("on");
|
|
597
|
+
ui.puck.setAttribute("aria-expanded", "false");
|
|
598
|
+
fanOpen = false;
|
|
599
|
+
win.clearTimeout(fanTimer);
|
|
600
|
+
fanTimer = win.setTimeout(() => {
|
|
601
|
+
ui.fan.hidden = true;
|
|
602
|
+
}, FAN_HIDE);
|
|
603
|
+
return true;
|
|
604
|
+
}
|
|
605
|
+
function onFanClick(e) {
|
|
606
|
+
const act = (e.target.closest?.("[data-act]"))?.getAttribute("data-act");
|
|
607
|
+
if (act == null) return;
|
|
608
|
+
if (act === "expand") {
|
|
609
|
+
closeFan();
|
|
610
|
+
restore(e.detail === 0);
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
host.onFanAction(act);
|
|
614
|
+
}
|
|
615
|
+
/** Click-away, at the document level: shadow events retarget, so membership
|
|
616
|
+
* is checked via composedPath, not target. */
|
|
617
|
+
function onDocPointerDown(e) {
|
|
618
|
+
if (!fanOpen) return;
|
|
619
|
+
const path = e.composedPath();
|
|
620
|
+
if (path.includes(ui.fan) || path.includes(ui.puck)) return;
|
|
621
|
+
closeFan();
|
|
622
|
+
}
|
|
570
623
|
function onPointerDown(e) {
|
|
571
624
|
if (mode !== "puck" || e.button !== 0) return;
|
|
572
625
|
try {
|
|
@@ -596,6 +649,7 @@ function createMinimize(host) {
|
|
|
596
649
|
}
|
|
597
650
|
if (Math.hypot(dx, dy) < DRAG_START) return;
|
|
598
651
|
pdown.moved = true;
|
|
652
|
+
closeFan();
|
|
599
653
|
mode = "drag";
|
|
600
654
|
if (!host.reduced) {
|
|
601
655
|
ui.puck.classList.add("pb-ghost");
|
|
@@ -651,7 +705,7 @@ function createMinimize(host) {
|
|
|
651
705
|
hideMorph();
|
|
652
706
|
mode = "puck";
|
|
653
707
|
}
|
|
654
|
-
|
|
708
|
+
if (!closeFan()) openFan();
|
|
655
709
|
return;
|
|
656
710
|
}
|
|
657
711
|
if (host.reduced) {
|
|
@@ -679,9 +733,11 @@ function createMinimize(host) {
|
|
|
679
733
|
}
|
|
680
734
|
/** Keyboard/AT activation is a synthesized click (detail 0) with no pointer events. */
|
|
681
735
|
function onClick(e) {
|
|
682
|
-
if (e.detail
|
|
736
|
+
if (e.detail !== 0) return;
|
|
737
|
+
if (!closeFan()) openFan();
|
|
683
738
|
}
|
|
684
739
|
function onResize() {
|
|
740
|
+
closeFan();
|
|
685
741
|
if (mode === "puck" && puckPos !== null) {
|
|
686
742
|
const p = clampPos(puckPos);
|
|
687
743
|
placePuck(p.x, p.y);
|
|
@@ -693,12 +749,15 @@ function createMinimize(host) {
|
|
|
693
749
|
ui.puck.addEventListener("pointerup", onPointerUp);
|
|
694
750
|
ui.puck.addEventListener("pointercancel", onPointerUp);
|
|
695
751
|
ui.puck.addEventListener("click", onClick);
|
|
752
|
+
ui.fan.addEventListener("click", onFanClick);
|
|
753
|
+
win.document.addEventListener("pointerdown", onDocPointerDown);
|
|
696
754
|
win.addEventListener("resize", onResize);
|
|
697
755
|
return {
|
|
698
756
|
minimized: () => mode !== "bar",
|
|
699
757
|
mode: () => mode,
|
|
700
758
|
minimize,
|
|
701
759
|
restore,
|
|
760
|
+
closeFan,
|
|
702
761
|
applyInitial() {
|
|
703
762
|
if (!loadMinimized()) return;
|
|
704
763
|
const apply = () => {
|
|
@@ -719,12 +778,18 @@ function createMinimize(host) {
|
|
|
719
778
|
ui.puck.removeEventListener("pointerup", onPointerUp);
|
|
720
779
|
ui.puck.removeEventListener("pointercancel", onPointerUp);
|
|
721
780
|
ui.puck.removeEventListener("click", onClick);
|
|
781
|
+
ui.fan.removeEventListener("click", onFanClick);
|
|
782
|
+
win.document.removeEventListener("pointerdown", onDocPointerDown);
|
|
722
783
|
win.removeEventListener("resize", onResize);
|
|
723
784
|
if (raf !== 0) win.cancelAnimationFrame(raf);
|
|
724
785
|
raf = 0;
|
|
725
786
|
win.clearTimeout(holdTimer);
|
|
726
787
|
win.clearTimeout(fadeTimer);
|
|
727
788
|
win.clearTimeout(hideTimer);
|
|
789
|
+
win.clearTimeout(fanTimer);
|
|
790
|
+
ui.fan.hidden = true;
|
|
791
|
+
ui.fan.classList.remove("on");
|
|
792
|
+
fanOpen = false;
|
|
728
793
|
}
|
|
729
794
|
};
|
|
730
795
|
}
|
|
@@ -2077,12 +2142,25 @@ function renderPins(layer, state) {
|
|
|
2077
2142
|
//#region src/ui/puck.ts
|
|
2078
2143
|
/** The bar's ident mark, sized up for the 48px puck face. */
|
|
2079
2144
|
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>";
|
|
2145
|
+
const FAN_PIN = "<svg width=\"15\" height=\"15\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"3\" y=\"1.5\" width=\"10\" height=\"6.5\" rx=\"1\"/><path d=\"M8 8v6.5\"/></svg>";
|
|
2146
|
+
const FAN_INBOX = "<svg width=\"15\" height=\"15\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"M1.8 8.5h3.4l1 2h3.6l1-2h3.4\"/><path d=\"M2.6 3.2h10.8l1.2 5.3v4a1 1 0 01-1 1H2.4a1 1 0 01-1-1v-4z\"/></svg>";
|
|
2147
|
+
const FAN_THEME = "<svg width=\"15\" height=\"15\" 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>";
|
|
2148
|
+
const FAN_EXPAND = "<svg width=\"15\" height=\"15\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"M9.5 6.5v-4h4\"/><path d=\"M6.5 9.5v4h-4\"/></svg>";
|
|
2149
|
+
function fanItem(act, index, icon, label, key) {
|
|
2150
|
+
return `<button type="button" class="pb-fan-item" data-act="${act}" style="--i:${index}" aria-label="${label}">${icon}${act === "inbox" ? "<span class=\"badge\" data-ref=\"count\" hidden>0</span>" : ""}<span class="fl">${label.toUpperCase()}<i>${key}</i></span></button>`;
|
|
2151
|
+
}
|
|
2080
2152
|
function createMinimizeUi(doc) {
|
|
2081
2153
|
const puck = doc.createElement("button");
|
|
2082
2154
|
puck.type = "button";
|
|
2083
2155
|
puck.className = "pb-puck pb-ghost";
|
|
2084
|
-
puck.setAttribute("aria-label", "
|
|
2156
|
+
puck.setAttribute("aria-label", "Pinbox menu");
|
|
2157
|
+
puck.setAttribute("aria-haspopup", "menu");
|
|
2085
2158
|
puck.innerHTML = `<span class="in">${PUCK_ICON}</span><span class="badge" data-ref="count" hidden>0</span><span class="cdot"></span>`;
|
|
2159
|
+
const fan = doc.createElement("div");
|
|
2160
|
+
fan.className = "pb-fan";
|
|
2161
|
+
fan.hidden = true;
|
|
2162
|
+
fan.setAttribute("role", "menu");
|
|
2163
|
+
fan.innerHTML = fanItem("pin", 0, FAN_PIN, "Drop a pin", "P") + fanItem("inbox", 1, FAN_INBOX, "Inbox", "I") + fanItem("theme", 2, FAN_THEME, "Theme", "D") + fanItem("expand", 3, FAN_EXPAND, "Expand", "M");
|
|
2086
2164
|
const morphWrap = doc.createElement("div");
|
|
2087
2165
|
morphWrap.className = "pb-morph-wrap";
|
|
2088
2166
|
morphWrap.hidden = true;
|
|
@@ -2093,9 +2171,14 @@ function createMinimizeUi(doc) {
|
|
|
2093
2171
|
carrier.innerHTML = `${PUCK_ICON}<span class="badge" data-ref="count" hidden>0</span>`;
|
|
2094
2172
|
morphWrap.appendChild(surface);
|
|
2095
2173
|
morphWrap.appendChild(carrier);
|
|
2096
|
-
const badges = [
|
|
2174
|
+
const badges = [
|
|
2175
|
+
puck.querySelector("[data-ref=\"count\"]"),
|
|
2176
|
+
carrier.querySelector("[data-ref=\"count\"]"),
|
|
2177
|
+
fan.querySelector("[data-ref=\"count\"]")
|
|
2178
|
+
];
|
|
2097
2179
|
return {
|
|
2098
2180
|
puck,
|
|
2181
|
+
fan,
|
|
2099
2182
|
morphWrap,
|
|
2100
2183
|
surface,
|
|
2101
2184
|
carrier,
|
|
@@ -2107,6 +2190,7 @@ function createMinimizeUi(doc) {
|
|
|
2107
2190
|
}
|
|
2108
2191
|
const degraded = state.connection === "offline" || state.connection === "incompatible";
|
|
2109
2192
|
puck.classList.toggle("degraded", degraded);
|
|
2193
|
+
puck.classList.toggle("armed", state.mode === "placing");
|
|
2110
2194
|
}
|
|
2111
2195
|
};
|
|
2112
2196
|
}
|
|
@@ -2393,10 +2477,28 @@ button { font: inherit; color: inherit; background: none; border: 0; cursor: poi
|
|
|
2393
2477
|
.pb-puck:active { cursor: grabbing; }
|
|
2394
2478
|
.pb-puck .in { display: flex; transition: transform 160ms var(--pb-ease); }
|
|
2395
2479
|
.pb-puck:hover .in { transform: scale(1.12); }
|
|
2396
|
-
.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; }
|
|
2480
|
+
.pb-puck .badge, .pb-carrier .badge, .pb-fan-item .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; }
|
|
2397
2481
|
/* The bar says "· OFFLINE" in words; the puck's amber dot is the same signal. */
|
|
2398
2482
|
.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; }
|
|
2399
2483
|
.pb-puck.degraded .cdot { display: block; }
|
|
2484
|
+
/* Placing armed from the fan: the bar's armed-ring is hidden with the bar. */
|
|
2485
|
+
.pb-puck.armed { border-color: var(--pb-amber); box-shadow: 0 0 0 4px var(--pb-amber-soft), var(--pb-shadow); }
|
|
2486
|
+
|
|
2487
|
+
/* puck fan menu (ui/puck.ts, minimize.ts) — tap the puck and a vertical
|
|
2488
|
+
quick-menu fans out of it; EXPAND is how the bar comes back. Items stagger
|
|
2489
|
+
from the puck; hovering slides a label + key chip toward screen center. */
|
|
2490
|
+
.pb-fan { position: fixed; z-index: 96; display: flex; flex-direction: column; gap: 6px; align-items: center; }
|
|
2491
|
+
.pb-fan-item { position: relative; width: 40px; height: 40px; 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); color: var(--pb-fg2); display: flex; align-items: center; justify-content: center; opacity: 0; transform: var(--fan-from) scale(0.5); transition: transform 300ms var(--pb-ease), opacity 180ms linear, color 140ms linear, border-color 140ms linear; transition-delay: calc(var(--i) * 35ms); }
|
|
2492
|
+
.pb-fan.up { --fan-from: translateY(16px); }
|
|
2493
|
+
.pb-fan.down { --fan-from: translateY(-16px); }
|
|
2494
|
+
.pb-fan.on .pb-fan-item { opacity: 1; transform: none; }
|
|
2495
|
+
.pb-fan-item:hover { color: var(--pb-amber); border-color: var(--pb-amber); }
|
|
2496
|
+
.pb-fan-item .badge { pointer-events: none; }
|
|
2497
|
+
.pb-fan-item .fl { position: absolute; top: 50%; display: flex; align-items: center; gap: 6px; padding: 4px 8px; background: var(--pb-elev); border: 1px solid var(--pb-line-2); border-radius: 2px; box-shadow: var(--pb-shadow); font-family: var(--pb-font-mono); font-size: 9px; letter-spacing: .14em; color: var(--pb-fg1); white-space: nowrap; opacity: 0; pointer-events: none; transition: opacity 140ms linear, transform 200ms var(--pb-ease); }
|
|
2498
|
+
.pb-fan.labels-right .fl { left: calc(100% + 10px); transform: translateY(-50%) translateX(-6px); }
|
|
2499
|
+
.pb-fan.labels-left .fl { right: calc(100% + 10px); transform: translateY(-50%) translateX(6px); }
|
|
2500
|
+
.pb-fan-item:hover .fl { opacity: 1; transform: translateY(-50%) translateX(0); }
|
|
2501
|
+
.pb-fan-item .fl i { font-style: normal; padding: 1px 5px; border: 1px solid var(--pb-line-2); border-radius: 2px; background: var(--pb-sunken); color: var(--pb-fg3); }
|
|
2400
2502
|
|
|
2401
2503
|
/* shortcuts modal (ui/shortcuts.ts) — prototype lines 226–232 */
|
|
2402
2504
|
.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; }
|
|
@@ -2603,6 +2705,7 @@ var PinboxToolbarElement = class extends BaseElement {
|
|
|
2603
2705
|
this.#minUi = createMinimizeUi(document);
|
|
2604
2706
|
shadow.appendChild(this.#minUi.morphWrap);
|
|
2605
2707
|
shadow.appendChild(this.#minUi.puck);
|
|
2708
|
+
shadow.appendChild(this.#minUi.fan);
|
|
2606
2709
|
this.#drawer = createDrawer(document, {
|
|
2607
2710
|
onActivate: (pinId) => this.#activateFromInbox(pinId),
|
|
2608
2711
|
onClose: () => this.store.update({ inboxOpen: false })
|
|
@@ -2627,7 +2730,12 @@ var PinboxToolbarElement = class extends BaseElement {
|
|
|
2627
2730
|
storagePrefix: `pinbox:${this.config?.endpoint ?? ""}`,
|
|
2628
2731
|
reduced: window.matchMedia("(prefers-reduced-motion: reduce)").matches,
|
|
2629
2732
|
initialMinimized: this.config?.minimized === true,
|
|
2630
|
-
onSettled: (minimized, keyboard) => this.#onMinimizeSettled(minimized, keyboard)
|
|
2733
|
+
onSettled: (minimized, keyboard) => this.#onMinimizeSettled(minimized, keyboard),
|
|
2734
|
+
onFanAction: (action) => {
|
|
2735
|
+
if (action === "pin") this.#togglePlacing();
|
|
2736
|
+
else if (action === "inbox") this.#toggleInbox();
|
|
2737
|
+
else this.#toggleTheme();
|
|
2738
|
+
}
|
|
2631
2739
|
});
|
|
2632
2740
|
this.#min.applyInitial();
|
|
2633
2741
|
}
|
|
@@ -2654,11 +2762,6 @@ var PinboxToolbarElement = class extends BaseElement {
|
|
|
2654
2762
|
restore(keyboard = false) {
|
|
2655
2763
|
this.#min?.restore(keyboard);
|
|
2656
2764
|
}
|
|
2657
|
-
/** Bar-surface shortcuts pressed while minimized restore the bar, then run. */
|
|
2658
|
-
#surfaced(run) {
|
|
2659
|
-
if (this.#min?.minimized() === true) this.restore(false);
|
|
2660
|
-
run();
|
|
2661
|
-
}
|
|
2662
2765
|
/**
|
|
2663
2766
|
* Task 8 wiring: WS events mutate the store, connection state renders in the
|
|
2664
2767
|
* bar, card actions hit the hub. The mirror seeds pins so an offline reload
|
|
@@ -2884,9 +2987,12 @@ var PinboxToolbarElement = class extends BaseElement {
|
|
|
2884
2987
|
};
|
|
2885
2988
|
/** Prototype keyboard map (v2-command-bar.html lines 701–712) + M (v3 minimize). */
|
|
2886
2989
|
#shortcuts = {
|
|
2887
|
-
escape: () =>
|
|
2888
|
-
|
|
2889
|
-
|
|
2990
|
+
escape: () => {
|
|
2991
|
+
if (this.#min?.closeFan() === true) return;
|
|
2992
|
+
this.#dismiss();
|
|
2993
|
+
},
|
|
2994
|
+
p: () => this.#togglePlacing(),
|
|
2995
|
+
i: () => this.#toggleInbox(),
|
|
2890
2996
|
d: () => this.#toggleTheme(),
|
|
2891
2997
|
r: () => this.#resolveActive(),
|
|
2892
2998
|
c: () => this.#copyOpenPins(),
|
package/dist/svelte.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as HubError, c as createStore, i as HubTransport, l as deriveUiStatus, n as defineToolbarElement, o as appendThreadMessage, r as PinboxToolbarElement, s as applyHubEvent, t as Pinbox, u as upsertPin } from "./src-
|
|
1
|
+
import { a as HubError, c as createStore, i as HubTransport, l as deriveUiStatus, n as defineToolbarElement, o as appendThreadMessage, r as PinboxToolbarElement, s as applyHubEvent, t as Pinbox, u as upsertPin } from "./src-C-gslo8y.js";
|
|
2
2
|
//#region src/svelte.ts
|
|
3
3
|
/**
|
|
4
4
|
* `<div use:pinbox={{ endpoint }} />` — creates + configures the element BEFORE insertion
|
package/dist/toolbar.iife.js
CHANGED
|
@@ -369,6 +369,8 @@ var Pinbox = (function(exports) {
|
|
|
369
369
|
const BAR_RADIUS = 4;
|
|
370
370
|
/** The carrier icon rides the surface only while it is puck-like (< this width). */
|
|
371
371
|
const CARRIER_MAX_W = 260;
|
|
372
|
+
/** Fan close transition length before display:none. */
|
|
373
|
+
const FAN_HIDE = 300;
|
|
372
374
|
function createMinimize(host) {
|
|
373
375
|
const { win, bar, ui } = host;
|
|
374
376
|
const main = mkSpring({
|
|
@@ -388,6 +390,8 @@ var Pinbox = (function(exports) {
|
|
|
388
390
|
let holdTimer = 0;
|
|
389
391
|
let fadeTimer = 0;
|
|
390
392
|
let hideTimer = 0;
|
|
393
|
+
let fanOpen = false;
|
|
394
|
+
let fanTimer = 0;
|
|
391
395
|
function loadDock() {
|
|
392
396
|
try {
|
|
393
397
|
const raw = host.storage?.getItem(`${host.storagePrefix}:dock`);
|
|
@@ -535,6 +539,7 @@ var Pinbox = (function(exports) {
|
|
|
535
539
|
}
|
|
536
540
|
function restore(keyboard = false) {
|
|
537
541
|
if (mode !== "puck" || puckPos === null) return;
|
|
542
|
+
closeFan();
|
|
538
543
|
pdown = null;
|
|
539
544
|
keyboardToggle = keyboard;
|
|
540
545
|
dock = { ...puckPos };
|
|
@@ -569,6 +574,54 @@ var Pinbox = (function(exports) {
|
|
|
569
574
|
ensureLoop();
|
|
570
575
|
}, HOLD_RESTORE);
|
|
571
576
|
}
|
|
577
|
+
/** Fan out of the puck: direction away from the nearer vertical edge,
|
|
578
|
+
* labels sliding toward screen center. */
|
|
579
|
+
function openFan() {
|
|
580
|
+
if (mode !== "puck" || puckPos === null) return;
|
|
581
|
+
win.clearTimeout(fanTimer);
|
|
582
|
+
ui.fan.hidden = false;
|
|
583
|
+
const upward = puckPos.y + PUCK / 2 > win.innerHeight / 2;
|
|
584
|
+
ui.fan.classList.toggle("up", upward);
|
|
585
|
+
ui.fan.classList.toggle("down", !upward);
|
|
586
|
+
ui.fan.classList.toggle("labels-right", puckPos.x + PUCK / 2 < win.innerWidth / 2);
|
|
587
|
+
ui.fan.classList.toggle("labels-left", puckPos.x + PUCK / 2 >= win.innerWidth / 2);
|
|
588
|
+
ui.fan.style.left = `${puckPos.x + PUCK / 2 - 20}px`;
|
|
589
|
+
ui.fan.offsetHeight;
|
|
590
|
+
const h = ui.fan.offsetHeight;
|
|
591
|
+
ui.fan.style.top = upward ? `${puckPos.y - h - 10}px` : `${puckPos.y + PUCK + 10}px`;
|
|
592
|
+
ui.fan.classList.add("on");
|
|
593
|
+
ui.puck.setAttribute("aria-expanded", "true");
|
|
594
|
+
fanOpen = true;
|
|
595
|
+
}
|
|
596
|
+
function closeFan() {
|
|
597
|
+
if (!fanOpen) return false;
|
|
598
|
+
ui.fan.classList.remove("on");
|
|
599
|
+
ui.puck.setAttribute("aria-expanded", "false");
|
|
600
|
+
fanOpen = false;
|
|
601
|
+
win.clearTimeout(fanTimer);
|
|
602
|
+
fanTimer = win.setTimeout(() => {
|
|
603
|
+
ui.fan.hidden = true;
|
|
604
|
+
}, FAN_HIDE);
|
|
605
|
+
return true;
|
|
606
|
+
}
|
|
607
|
+
function onFanClick(e) {
|
|
608
|
+
const act = (e.target.closest?.("[data-act]"))?.getAttribute("data-act");
|
|
609
|
+
if (act == null) return;
|
|
610
|
+
if (act === "expand") {
|
|
611
|
+
closeFan();
|
|
612
|
+
restore(e.detail === 0);
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
host.onFanAction(act);
|
|
616
|
+
}
|
|
617
|
+
/** Click-away, at the document level: shadow events retarget, so membership
|
|
618
|
+
* is checked via composedPath, not target. */
|
|
619
|
+
function onDocPointerDown(e) {
|
|
620
|
+
if (!fanOpen) return;
|
|
621
|
+
const path = e.composedPath();
|
|
622
|
+
if (path.includes(ui.fan) || path.includes(ui.puck)) return;
|
|
623
|
+
closeFan();
|
|
624
|
+
}
|
|
572
625
|
function onPointerDown(e) {
|
|
573
626
|
if (mode !== "puck" || e.button !== 0) return;
|
|
574
627
|
try {
|
|
@@ -598,6 +651,7 @@ var Pinbox = (function(exports) {
|
|
|
598
651
|
}
|
|
599
652
|
if (Math.hypot(dx, dy) < DRAG_START) return;
|
|
600
653
|
pdown.moved = true;
|
|
654
|
+
closeFan();
|
|
601
655
|
mode = "drag";
|
|
602
656
|
if (!host.reduced) {
|
|
603
657
|
ui.puck.classList.add("pb-ghost");
|
|
@@ -653,7 +707,7 @@ var Pinbox = (function(exports) {
|
|
|
653
707
|
hideMorph();
|
|
654
708
|
mode = "puck";
|
|
655
709
|
}
|
|
656
|
-
|
|
710
|
+
if (!closeFan()) openFan();
|
|
657
711
|
return;
|
|
658
712
|
}
|
|
659
713
|
if (host.reduced) {
|
|
@@ -681,9 +735,11 @@ var Pinbox = (function(exports) {
|
|
|
681
735
|
}
|
|
682
736
|
/** Keyboard/AT activation is a synthesized click (detail 0) with no pointer events. */
|
|
683
737
|
function onClick(e) {
|
|
684
|
-
if (e.detail
|
|
738
|
+
if (e.detail !== 0) return;
|
|
739
|
+
if (!closeFan()) openFan();
|
|
685
740
|
}
|
|
686
741
|
function onResize() {
|
|
742
|
+
closeFan();
|
|
687
743
|
if (mode === "puck" && puckPos !== null) {
|
|
688
744
|
const p = clampPos(puckPos);
|
|
689
745
|
placePuck(p.x, p.y);
|
|
@@ -695,12 +751,15 @@ var Pinbox = (function(exports) {
|
|
|
695
751
|
ui.puck.addEventListener("pointerup", onPointerUp);
|
|
696
752
|
ui.puck.addEventListener("pointercancel", onPointerUp);
|
|
697
753
|
ui.puck.addEventListener("click", onClick);
|
|
754
|
+
ui.fan.addEventListener("click", onFanClick);
|
|
755
|
+
win.document.addEventListener("pointerdown", onDocPointerDown);
|
|
698
756
|
win.addEventListener("resize", onResize);
|
|
699
757
|
return {
|
|
700
758
|
minimized: () => mode !== "bar",
|
|
701
759
|
mode: () => mode,
|
|
702
760
|
minimize,
|
|
703
761
|
restore,
|
|
762
|
+
closeFan,
|
|
704
763
|
applyInitial() {
|
|
705
764
|
if (!loadMinimized()) return;
|
|
706
765
|
const apply = () => {
|
|
@@ -721,12 +780,18 @@ var Pinbox = (function(exports) {
|
|
|
721
780
|
ui.puck.removeEventListener("pointerup", onPointerUp);
|
|
722
781
|
ui.puck.removeEventListener("pointercancel", onPointerUp);
|
|
723
782
|
ui.puck.removeEventListener("click", onClick);
|
|
783
|
+
ui.fan.removeEventListener("click", onFanClick);
|
|
784
|
+
win.document.removeEventListener("pointerdown", onDocPointerDown);
|
|
724
785
|
win.removeEventListener("resize", onResize);
|
|
725
786
|
if (raf !== 0) win.cancelAnimationFrame(raf);
|
|
726
787
|
raf = 0;
|
|
727
788
|
win.clearTimeout(holdTimer);
|
|
728
789
|
win.clearTimeout(fadeTimer);
|
|
729
790
|
win.clearTimeout(hideTimer);
|
|
791
|
+
win.clearTimeout(fanTimer);
|
|
792
|
+
ui.fan.hidden = true;
|
|
793
|
+
ui.fan.classList.remove("on");
|
|
794
|
+
fanOpen = false;
|
|
730
795
|
}
|
|
731
796
|
};
|
|
732
797
|
}
|
|
@@ -2079,12 +2144,25 @@ var Pinbox = (function(exports) {
|
|
|
2079
2144
|
//#region src/ui/puck.ts
|
|
2080
2145
|
/** The bar's ident mark, sized up for the 48px puck face. */
|
|
2081
2146
|
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>";
|
|
2147
|
+
const FAN_PIN = "<svg width=\"15\" height=\"15\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><rect x=\"3\" y=\"1.5\" width=\"10\" height=\"6.5\" rx=\"1\"/><path d=\"M8 8v6.5\"/></svg>";
|
|
2148
|
+
const FAN_INBOX = "<svg width=\"15\" height=\"15\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"M1.8 8.5h3.4l1 2h3.6l1-2h3.4\"/><path d=\"M2.6 3.2h10.8l1.2 5.3v4a1 1 0 01-1 1H2.4a1 1 0 01-1-1v-4z\"/></svg>";
|
|
2149
|
+
const FAN_THEME = "<svg width=\"15\" height=\"15\" 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>";
|
|
2150
|
+
const FAN_EXPAND = "<svg width=\"15\" height=\"15\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"M9.5 6.5v-4h4\"/><path d=\"M6.5 9.5v4h-4\"/></svg>";
|
|
2151
|
+
function fanItem(act, index, icon, label, key) {
|
|
2152
|
+
return `<button type="button" class="pb-fan-item" data-act="${act}" style="--i:${index}" aria-label="${label}">${icon}${act === "inbox" ? "<span class=\"badge\" data-ref=\"count\" hidden>0</span>" : ""}<span class="fl">${label.toUpperCase()}<i>${key}</i></span></button>`;
|
|
2153
|
+
}
|
|
2082
2154
|
function createMinimizeUi(doc) {
|
|
2083
2155
|
const puck = doc.createElement("button");
|
|
2084
2156
|
puck.type = "button";
|
|
2085
2157
|
puck.className = "pb-puck pb-ghost";
|
|
2086
|
-
puck.setAttribute("aria-label", "
|
|
2158
|
+
puck.setAttribute("aria-label", "Pinbox menu");
|
|
2159
|
+
puck.setAttribute("aria-haspopup", "menu");
|
|
2087
2160
|
puck.innerHTML = `<span class="in">${PUCK_ICON}</span><span class="badge" data-ref="count" hidden>0</span><span class="cdot"></span>`;
|
|
2161
|
+
const fan = doc.createElement("div");
|
|
2162
|
+
fan.className = "pb-fan";
|
|
2163
|
+
fan.hidden = true;
|
|
2164
|
+
fan.setAttribute("role", "menu");
|
|
2165
|
+
fan.innerHTML = fanItem("pin", 0, FAN_PIN, "Drop a pin", "P") + fanItem("inbox", 1, FAN_INBOX, "Inbox", "I") + fanItem("theme", 2, FAN_THEME, "Theme", "D") + fanItem("expand", 3, FAN_EXPAND, "Expand", "M");
|
|
2088
2166
|
const morphWrap = doc.createElement("div");
|
|
2089
2167
|
morphWrap.className = "pb-morph-wrap";
|
|
2090
2168
|
morphWrap.hidden = true;
|
|
@@ -2095,9 +2173,14 @@ var Pinbox = (function(exports) {
|
|
|
2095
2173
|
carrier.innerHTML = `${PUCK_ICON}<span class="badge" data-ref="count" hidden>0</span>`;
|
|
2096
2174
|
morphWrap.appendChild(surface);
|
|
2097
2175
|
morphWrap.appendChild(carrier);
|
|
2098
|
-
const badges = [
|
|
2176
|
+
const badges = [
|
|
2177
|
+
puck.querySelector("[data-ref=\"count\"]"),
|
|
2178
|
+
carrier.querySelector("[data-ref=\"count\"]"),
|
|
2179
|
+
fan.querySelector("[data-ref=\"count\"]")
|
|
2180
|
+
];
|
|
2099
2181
|
return {
|
|
2100
2182
|
puck,
|
|
2183
|
+
fan,
|
|
2101
2184
|
morphWrap,
|
|
2102
2185
|
surface,
|
|
2103
2186
|
carrier,
|
|
@@ -2109,6 +2192,7 @@ var Pinbox = (function(exports) {
|
|
|
2109
2192
|
}
|
|
2110
2193
|
const degraded = state.connection === "offline" || state.connection === "incompatible";
|
|
2111
2194
|
puck.classList.toggle("degraded", degraded);
|
|
2195
|
+
puck.classList.toggle("armed", state.mode === "placing");
|
|
2112
2196
|
}
|
|
2113
2197
|
};
|
|
2114
2198
|
}
|
|
@@ -2395,10 +2479,28 @@ button { font: inherit; color: inherit; background: none; border: 0; cursor: poi
|
|
|
2395
2479
|
.pb-puck:active { cursor: grabbing; }
|
|
2396
2480
|
.pb-puck .in { display: flex; transition: transform 160ms var(--pb-ease); }
|
|
2397
2481
|
.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; }
|
|
2482
|
+
.pb-puck .badge, .pb-carrier .badge, .pb-fan-item .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
2483
|
/* The bar says "· OFFLINE" in words; the puck's amber dot is the same signal. */
|
|
2400
2484
|
.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
2485
|
.pb-puck.degraded .cdot { display: block; }
|
|
2486
|
+
/* Placing armed from the fan: the bar's armed-ring is hidden with the bar. */
|
|
2487
|
+
.pb-puck.armed { border-color: var(--pb-amber); box-shadow: 0 0 0 4px var(--pb-amber-soft), var(--pb-shadow); }
|
|
2488
|
+
|
|
2489
|
+
/* puck fan menu (ui/puck.ts, minimize.ts) — tap the puck and a vertical
|
|
2490
|
+
quick-menu fans out of it; EXPAND is how the bar comes back. Items stagger
|
|
2491
|
+
from the puck; hovering slides a label + key chip toward screen center. */
|
|
2492
|
+
.pb-fan { position: fixed; z-index: 96; display: flex; flex-direction: column; gap: 6px; align-items: center; }
|
|
2493
|
+
.pb-fan-item { position: relative; width: 40px; height: 40px; 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); color: var(--pb-fg2); display: flex; align-items: center; justify-content: center; opacity: 0; transform: var(--fan-from) scale(0.5); transition: transform 300ms var(--pb-ease), opacity 180ms linear, color 140ms linear, border-color 140ms linear; transition-delay: calc(var(--i) * 35ms); }
|
|
2494
|
+
.pb-fan.up { --fan-from: translateY(16px); }
|
|
2495
|
+
.pb-fan.down { --fan-from: translateY(-16px); }
|
|
2496
|
+
.pb-fan.on .pb-fan-item { opacity: 1; transform: none; }
|
|
2497
|
+
.pb-fan-item:hover { color: var(--pb-amber); border-color: var(--pb-amber); }
|
|
2498
|
+
.pb-fan-item .badge { pointer-events: none; }
|
|
2499
|
+
.pb-fan-item .fl { position: absolute; top: 50%; display: flex; align-items: center; gap: 6px; padding: 4px 8px; background: var(--pb-elev); border: 1px solid var(--pb-line-2); border-radius: 2px; box-shadow: var(--pb-shadow); font-family: var(--pb-font-mono); font-size: 9px; letter-spacing: .14em; color: var(--pb-fg1); white-space: nowrap; opacity: 0; pointer-events: none; transition: opacity 140ms linear, transform 200ms var(--pb-ease); }
|
|
2500
|
+
.pb-fan.labels-right .fl { left: calc(100% + 10px); transform: translateY(-50%) translateX(-6px); }
|
|
2501
|
+
.pb-fan.labels-left .fl { right: calc(100% + 10px); transform: translateY(-50%) translateX(6px); }
|
|
2502
|
+
.pb-fan-item:hover .fl { opacity: 1; transform: translateY(-50%) translateX(0); }
|
|
2503
|
+
.pb-fan-item .fl i { font-style: normal; padding: 1px 5px; border: 1px solid var(--pb-line-2); border-radius: 2px; background: var(--pb-sunken); color: var(--pb-fg3); }
|
|
2402
2504
|
|
|
2403
2505
|
/* shortcuts modal (ui/shortcuts.ts) — prototype lines 226–232 */
|
|
2404
2506
|
.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; }
|
|
@@ -2605,6 +2707,7 @@ button { font: inherit; color: inherit; background: none; border: 0; cursor: poi
|
|
|
2605
2707
|
this.#minUi = createMinimizeUi(document);
|
|
2606
2708
|
shadow.appendChild(this.#minUi.morphWrap);
|
|
2607
2709
|
shadow.appendChild(this.#minUi.puck);
|
|
2710
|
+
shadow.appendChild(this.#minUi.fan);
|
|
2608
2711
|
this.#drawer = createDrawer(document, {
|
|
2609
2712
|
onActivate: (pinId) => this.#activateFromInbox(pinId),
|
|
2610
2713
|
onClose: () => this.store.update({ inboxOpen: false })
|
|
@@ -2629,7 +2732,12 @@ button { font: inherit; color: inherit; background: none; border: 0; cursor: poi
|
|
|
2629
2732
|
storagePrefix: `pinbox:${this.config?.endpoint ?? ""}`,
|
|
2630
2733
|
reduced: window.matchMedia("(prefers-reduced-motion: reduce)").matches,
|
|
2631
2734
|
initialMinimized: this.config?.minimized === true,
|
|
2632
|
-
onSettled: (minimized, keyboard) => this.#onMinimizeSettled(minimized, keyboard)
|
|
2735
|
+
onSettled: (minimized, keyboard) => this.#onMinimizeSettled(minimized, keyboard),
|
|
2736
|
+
onFanAction: (action) => {
|
|
2737
|
+
if (action === "pin") this.#togglePlacing();
|
|
2738
|
+
else if (action === "inbox") this.#toggleInbox();
|
|
2739
|
+
else this.#toggleTheme();
|
|
2740
|
+
}
|
|
2633
2741
|
});
|
|
2634
2742
|
this.#min.applyInitial();
|
|
2635
2743
|
}
|
|
@@ -2656,11 +2764,6 @@ button { font: inherit; color: inherit; background: none; border: 0; cursor: poi
|
|
|
2656
2764
|
restore(keyboard = false) {
|
|
2657
2765
|
this.#min?.restore(keyboard);
|
|
2658
2766
|
}
|
|
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
|
-
}
|
|
2664
2767
|
/**
|
|
2665
2768
|
* Task 8 wiring: WS events mutate the store, connection state renders in the
|
|
2666
2769
|
* bar, card actions hit the hub. The mirror seeds pins so an offline reload
|
|
@@ -2886,9 +2989,12 @@ button { font: inherit; color: inherit; background: none; border: 0; cursor: poi
|
|
|
2886
2989
|
};
|
|
2887
2990
|
/** Prototype keyboard map (v2-command-bar.html lines 701–712) + M (v3 minimize). */
|
|
2888
2991
|
#shortcuts = {
|
|
2889
|
-
escape: () =>
|
|
2890
|
-
|
|
2891
|
-
|
|
2992
|
+
escape: () => {
|
|
2993
|
+
if (this.#min?.closeFan() === true) return;
|
|
2994
|
+
this.#dismiss();
|
|
2995
|
+
},
|
|
2996
|
+
p: () => this.#togglePlacing(),
|
|
2997
|
+
i: () => this.#toggleInbox(),
|
|
2892
2998
|
d: () => this.#toggleTheme(),
|
|
2893
2999
|
r: () => this.#resolveActive(),
|
|
2894
3000
|
c: () => this.#copyOpenPins(),
|
package/dist/vue.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autono/pinbox-toolbar",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
}
|
|
72
72
|
},
|
|
73
73
|
"devDependencies": {
|
|
74
|
-
"@autono/pinbox-core": "0.
|
|
74
|
+
"@autono/pinbox-core": "0.12.0",
|
|
75
75
|
"@types/react": "^19.2.0",
|
|
76
76
|
"typescript": "^7.0.0",
|
|
77
77
|
"tsdown": "^0.22.0",
|