@cowwo/dsh-lookout 0.1.1 → 0.1.2
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/client/client.js +53 -8
- package/package.json +1 -1
package/client/client.js
CHANGED
|
@@ -7339,6 +7339,15 @@ window.__ModuleLoader__.load({
|
|
|
7339
7339
|
const ROW_MENU_QUIET_MS = 250;
|
|
7340
7340
|
const ROW_MENU_FEEDBACK_MS = 1500;
|
|
7341
7341
|
const ROW_MENU_TOAST_MS = 3000;
|
|
7342
|
+
/**
|
|
7343
|
+
* How long after opening the menu a scroll/resize counts as part of the tap.
|
|
7344
|
+
*
|
|
7345
|
+
* Phones fire scroll and resize while the tap is still settling (visual viewport
|
|
7346
|
+
* shifts, focus-driven scrolling, the browser chrome collapsing). Closing on those
|
|
7347
|
+
* made the menu flash and vanish on mobile, so inside this window the menu only
|
|
7348
|
+
* repositions; a later, real scroll closes it as usual.
|
|
7349
|
+
*/
|
|
7350
|
+
const ROW_MENU_SCROLL_GRACE_MS = 700;
|
|
7342
7351
|
const ROW_MENU_BUTTON_PADDING = "32px";
|
|
7343
7352
|
const ROW_MENU_ENABLED_KEY = "dsh-lookout:file-row-menu:enabled";
|
|
7344
7353
|
const ROW_MENU_DISMISSED_KEY = "dsh-lookout:file-row-menu:gave-up-dismissed";
|
|
@@ -7386,12 +7395,12 @@ window.__ModuleLoader__.load({
|
|
|
7386
7395
|
* No literal colour is written here, so light/dark follows the host.
|
|
7387
7396
|
*/
|
|
7388
7397
|
const ROW_MENU_CSS = [
|
|
7389
|
-
".dsh-lookout-rowmenu{position:absolute;top:4px;right:4px;z-index:2;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:0;border-radius:6px;background:transparent;color:var(--dsw-alias-label-tertiary);cursor:pointer;line-height:1;}",
|
|
7398
|
+
".dsh-lookout-rowmenu{position:absolute;top:4px;right:4px;z-index:2;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:0;border-radius:6px;background:transparent;color:var(--dsw-alias-label-tertiary);cursor:pointer;line-height:1;touch-action:manipulation;-webkit-tap-highlight-color:transparent;}",
|
|
7390
7399
|
".dsh-lookout-rowmenu:hover,.dsh-lookout-rowmenu:focus-visible{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover);outline:none;}",
|
|
7391
7400
|
".dsh-lookout-rowmenu svg{display:block;width:16px;height:16px;pointer-events:none;}",
|
|
7392
7401
|
".dsh-lookout-rowmenu[data-lookout-copied]{color:var(--dsw-alias-state-success-primary);}",
|
|
7393
|
-
".dsh-lookout-rowmenu-pop{position:fixed;z-index:
|
|
7394
|
-
".dsh-lookout-rowmenu-item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;padding:7px 10px;border:0;border-radius:6px;background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer;}",
|
|
7402
|
+
".dsh-lookout-rowmenu-pop{position:fixed;z-index:2147482000;min-width:176px;padding:4px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-overlay);color:var(--dsw-alias-label-primary);font-size:13px;line-height:1.4;box-shadow:0 8px 24px var(--dsw-alias-bg-mask-drop);}",
|
|
7403
|
+
".dsh-lookout-rowmenu-item{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;padding:7px 10px;border:0;border-radius:6px;background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent;}",
|
|
7395
7404
|
".dsh-lookout-rowmenu-item:hover,.dsh-lookout-rowmenu-item:focus-visible{background:var(--dsw-alias-interactive-bg-hover);outline:none;}",
|
|
7396
7405
|
".dsh-lookout-rowmenu-item[aria-disabled=\"true\"]{color:var(--dsw-alias-label-dimmed);cursor:not-allowed;}",
|
|
7397
7406
|
".dsh-lookout-rowmenu-item[aria-disabled=\"true\"]:hover{background:transparent;}",
|
|
@@ -7483,6 +7492,7 @@ window.__ModuleLoader__.load({
|
|
|
7483
7492
|
let menuAnchor = null;
|
|
7484
7493
|
let menuRow = null;
|
|
7485
7494
|
let menuPath = "";
|
|
7495
|
+
let menuOpenedAt = 0;
|
|
7486
7496
|
let toast = null;
|
|
7487
7497
|
let toastTimer = 0;
|
|
7488
7498
|
const feedbackTimers = new Map();
|
|
@@ -7899,16 +7909,19 @@ window.__ModuleLoader__.load({
|
|
|
7899
7909
|
menuAnchor = anchor;
|
|
7900
7910
|
menuRow = anchor.closest("li");
|
|
7901
7911
|
menuPath = path;
|
|
7912
|
+
menuOpenedAt = Date.now();
|
|
7902
7913
|
anchor.setAttribute("aria-expanded", "true");
|
|
7903
7914
|
paintedAt = Date.now();
|
|
7904
7915
|
document.addEventListener("pointerdown", onDocumentPointerDown, true);
|
|
7905
7916
|
document.addEventListener("keydown", onDocumentKeyDown, true);
|
|
7906
|
-
window.addEventListener("scroll",
|
|
7907
|
-
window.addEventListener("resize",
|
|
7917
|
+
window.addEventListener("scroll", onDocumentScroll, true);
|
|
7918
|
+
window.addEventListener("resize", repositionMenu, true);
|
|
7919
|
+
watchVisualViewport(true);
|
|
7908
7920
|
window.setTimeout(() => {
|
|
7909
7921
|
if (menu !== popup) return;
|
|
7910
7922
|
const first = popup.querySelector('[role="menuitem"]:not([disabled])');
|
|
7911
|
-
if (first
|
|
7923
|
+
if (first === null) return;
|
|
7924
|
+
try { first.focus({ preventScroll: true }); } catch { try { first.focus(); } catch { /* best effort */ } }
|
|
7912
7925
|
}, 0);
|
|
7913
7926
|
}
|
|
7914
7927
|
|
|
@@ -7942,8 +7955,40 @@ window.__ModuleLoader__.load({
|
|
|
7942
7955
|
if (anchor !== null) { try { anchor.setAttribute("aria-expanded", "false"); } catch { /* gone */ } }
|
|
7943
7956
|
document.removeEventListener("pointerdown", onDocumentPointerDown, true);
|
|
7944
7957
|
document.removeEventListener("keydown", onDocumentKeyDown, true);
|
|
7945
|
-
window.removeEventListener("scroll",
|
|
7946
|
-
window.removeEventListener("resize",
|
|
7958
|
+
window.removeEventListener("scroll", onDocumentScroll, true);
|
|
7959
|
+
window.removeEventListener("resize", repositionMenu, true);
|
|
7960
|
+
watchVisualViewport(false);
|
|
7961
|
+
}
|
|
7962
|
+
|
|
7963
|
+
/** Move the open menu back inside the viewport without closing it. */
|
|
7964
|
+
function repositionMenu() {
|
|
7965
|
+
if (menu === null || menuAnchor === null) return;
|
|
7966
|
+
positionMenu(menu, menuAnchor);
|
|
7967
|
+
}
|
|
7968
|
+
|
|
7969
|
+
/**
|
|
7970
|
+
* A scroll normally means the anchor moved, but a phone fires one while the tap
|
|
7971
|
+
* settles; that churn must not close the menu the tap just opened.
|
|
7972
|
+
*/
|
|
7973
|
+
function onDocumentScroll() {
|
|
7974
|
+
if (menu === null) return;
|
|
7975
|
+
if (Date.now() - menuOpenedAt < ROW_MENU_SCROLL_GRACE_MS) { repositionMenu(); return; }
|
|
7976
|
+
closeMenu();
|
|
7977
|
+
}
|
|
7978
|
+
|
|
7979
|
+
/** Follow the visual viewport (URL bar, on-screen keyboard) instead of dying with it. */
|
|
7980
|
+
function watchVisualViewport(on) {
|
|
7981
|
+
try {
|
|
7982
|
+
const viewport = window.visualViewport;
|
|
7983
|
+
if (viewport === null || viewport === undefined || typeof viewport.addEventListener !== "function") return;
|
|
7984
|
+
if (on) {
|
|
7985
|
+
viewport.addEventListener("resize", repositionMenu);
|
|
7986
|
+
viewport.addEventListener("scroll", repositionMenu);
|
|
7987
|
+
} else {
|
|
7988
|
+
viewport.removeEventListener("resize", repositionMenu);
|
|
7989
|
+
viewport.removeEventListener("scroll", repositionMenu);
|
|
7990
|
+
}
|
|
7991
|
+
} catch { /* older browsers simply skip the follow-up */ }
|
|
7947
7992
|
}
|
|
7948
7993
|
|
|
7949
7994
|
function onDocumentPointerDown(event) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cowwo/dsh-lookout",
|
|
3
3
|
"description": "瞭望哨:盯着你的每个会话——谁跑完了、谁出错了、谁卡住了、谁在等你审批,用浏览器图标角标、红点/黄点和邮件通知你;顺带显示当前会话 ID。· Lookout: watches every session — who finished, who errored, who is stuck, and who is waiting for your approval — and notifies you through the browser favicon badge, red/yellow dots, and email, while also showing the current session ID.",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.2",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "lib/index.js",
|