@ryuu-64/dsh-find-all 0.1.8 → 0.1.10
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 +16 -0
- package/lib/client.js +225 -34
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.10
|
|
4
|
+
|
|
5
|
+
- Keep the find bar below the conversation header and allow moving it within the conversation body with a drag handle or directional buttons.
|
|
6
|
+
- Preserve its manual position while the same conversation stays open, with a control to restore the default position; reset it when the bar reopens or the conversation changes.
|
|
7
|
+
- Constrain the bar to the available conversation area as the window, sidebar or input area changes, and reduce unused space in its default layout.
|
|
8
|
+
- Keep the current search match clear of the find bar, including matches in nested scrolling areas and when navigation feedback expands the bar.
|
|
9
|
+
|
|
10
|
+
The supported host-version list and return-to-reading-position behavior are unchanged.
|
|
11
|
+
|
|
12
|
+
## 0.1.9
|
|
13
|
+
|
|
14
|
+
- Reveal host-owned `hidden="until-found"` content before scrolling to a search match, instead of treating its layout geometry as proof that the match is visible.
|
|
15
|
+
- Wait for concealed matches to become visible before marking navigation as successful.
|
|
16
|
+
|
|
17
|
+
The supported host-version list is unchanged.
|
|
18
|
+
|
|
3
19
|
## 0.1.8
|
|
4
20
|
|
|
5
21
|
- Keep Ctrl+F and the header search button bound to the current main conversation across sidebar focus changes and main-view navigation.
|
package/lib/client.js
CHANGED
|
@@ -76,6 +76,7 @@ window.__ModuleLoader__.load({
|
|
|
76
76
|
prev: "上一个匹配",
|
|
77
77
|
next: "下一个匹配",
|
|
78
78
|
close: "关闭查找",
|
|
79
|
+
move: "拖动查找栏;点击展开移动按钮", moveLeft: "向左移动", moveRight: "向右移动", moveUp: "向上移动", moveDown: "向下移动", resetPosition: "恢复默认位置",
|
|
79
80
|
cap: "仅显示前 {n} 处匹配",
|
|
80
81
|
resultCount: "{n} 个结果",
|
|
81
82
|
scopeWhole: "包含更早内容",
|
|
@@ -106,6 +107,7 @@ window.__ModuleLoader__.load({
|
|
|
106
107
|
prev: "Previous match",
|
|
107
108
|
next: "Next match",
|
|
108
109
|
close: "Close find",
|
|
110
|
+
move: "Drag find bar; click for move controls", moveLeft: "Move left", moveRight: "Move right", moveUp: "Move up", moveDown: "Move down", resetPosition: "Reset position",
|
|
109
111
|
cap: "Showing only the first {n} matches",
|
|
110
112
|
resultCount: "{n} results",
|
|
111
113
|
scopeWhole: "Include earlier content",
|
|
@@ -234,14 +236,19 @@ window.__ModuleLoader__.load({
|
|
|
234
236
|
|
|
235
237
|
function cssText() {
|
|
236
238
|
return "" +
|
|
237
|
-
"#" + BAR_ID + "{--dsh-find-all-
|
|
239
|
+
"#" + BAR_ID + "{--dsh-find-all-max-width:600px;position:fixed;top:var(--dsh-find-all-bar-top);right:var(--dsh-find-all-bar-right);z-index:2147483000;visibility:hidden;isolation:isolate;box-sizing:border-box;align-items:stretch;gap:4px;padding:6px 8px;display:flex;flex-direction:column;width:min(var(--dsh-find-all-max-width),var(--dsh-find-all-panel-width));max-width:calc(100vw - 16px);max-height:var(--dsh-find-all-max-height);overflow:auto;background:transparent;--dsw-elevation-stroke-color:var(--dsw-alias-border-l1);border:0;border-radius:var(--dsw-radius-md,8px);box-shadow:var(--dsw-elevation-panel,var(--dsw-shadow-lv2))}" +
|
|
238
240
|
"#" + BAR_ID + "[data-positioned]{visibility:visible}" +
|
|
239
241
|
"#" + BAR_ID + ":before{content:\"\";position:absolute;inset:0;z-index:-1;pointer-events:none;border-radius:inherit;background:var(--dsw-specific-menu,var(--dsw-alias-bg-layer-2));-webkit-backdrop-filter:var(--dsw-menu-backdrop-filter,blur(40px) saturate(150%));backdrop-filter:var(--dsw-menu-backdrop-filter,blur(40px) saturate(150%))}" +
|
|
240
242
|
"#" + BAR_ID + " .controls{display:flex;flex-wrap:wrap;align-items:center;gap:6px;min-width:0}" +
|
|
241
|
-
"#" + BAR_ID + " input{flex:1 1
|
|
243
|
+
"#" + BAR_ID + " input{box-sizing:border-box;flex:1 1 160px;min-width:0;max-width:100%;width:auto;height:28px;color:var(--dsw-alias-label-primary);font:13px/1 var(--dsw-font-family);background:var(--dsw-alias-bg-base);border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-sm,6px);outline:none;padding:0 8px}" +
|
|
242
244
|
"#" + BAR_ID + " input:focus-visible{border-color:var(--dsw-alias-state-business-primary)}" +
|
|
243
245
|
"#" + BAR_ID + " .count{min-width:52px;color:var(--dsw-alias-label-tertiary);font:12px/1 var(--dsw-font-family);font-variant-numeric:tabular-nums;text-align:center}" +
|
|
244
|
-
"#" + BAR_ID + " .status{width:100%;
|
|
246
|
+
"#" + BAR_ID + " .status{width:100%;color:var(--dsw-alias-label-tertiary);font:12px/1.25 var(--dsw-font-family);text-align:left;white-space:normal;overflow-wrap:anywhere}" +
|
|
247
|
+
"#" + BAR_ID + " .status:empty{display:none}" +
|
|
248
|
+
"#" + BAR_ID + " .position-controls{display:flex;flex-wrap:wrap;align-items:center;gap:4px}" +
|
|
249
|
+
"#" + BAR_ID + " .position-controls[hidden]{display:none}" +
|
|
250
|
+
"#" + BAR_ID + " button.drag-handle{touch-action:none;user-select:none;cursor:grab;flex:none}" +
|
|
251
|
+
"#" + BAR_ID + "[data-dragging] button.drag-handle{cursor:grabbing}" +
|
|
245
252
|
"#" + BAR_ID + " .status[data-busy]{cursor:pointer;color:var(--dsw-alias-state-business-primary)}" +
|
|
246
253
|
"#" + BAR_ID + " .scope{width:auto;padding:0 9px;color:var(--dsw-alias-label-secondary);font:12px/1 var(--dsw-font-family);background:0 0;border:1px solid var(--dsw-alias-border-l2);border-radius:999px}" +
|
|
247
254
|
"#" + BAR_ID + " .scope[data-whole]{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-state-business-primary)}" +
|
|
@@ -423,13 +430,78 @@ window.__ModuleLoader__.load({
|
|
|
423
430
|
return highlight;
|
|
424
431
|
}
|
|
425
432
|
|
|
433
|
+
function matchBarRect() {
|
|
434
|
+
return isOpen() && state.bar.hasAttribute("data-positioned") ? state.bar.getBoundingClientRect() : null;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// Match visibility is deliberately independent of reading-origin capture
|
|
438
|
+
// and return. Range geometry alone does not account for floating UI.
|
|
439
|
+
function visibleMatchRect(range, viewport) {
|
|
440
|
+
if (!viewport || !rangeRect(range, viewport)) return null;
|
|
441
|
+
var clip = clippedViewport(range.startContainer.parentElement, viewport), bar = matchBarRect();
|
|
442
|
+
var rects = range.getClientRects();
|
|
443
|
+
for (var i = 0; i < rects.length; i++) {
|
|
444
|
+
var rect = rects[i], left = Math.max(rect.left, clip.left), right = Math.min(rect.right, clip.right);
|
|
445
|
+
var top = Math.max(rect.top, clip.top), bottom = Math.min(rect.bottom, clip.bottom);
|
|
446
|
+
if (right <= left || bottom <= top) continue;
|
|
447
|
+
if (!bar || right <= bar.left || left >= bar.right || bottom <= bar.top || top >= bar.bottom) return rect;
|
|
448
|
+
}
|
|
449
|
+
return null;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
function scrollRangeWithin(range, scroll, viewport, bar) {
|
|
453
|
+
var rect = rangeRect(range);
|
|
454
|
+
if (!rect) return;
|
|
455
|
+
var current = scroll.scrollTop, maximum = Math.max(0, scroll.scrollHeight - scroll.clientHeight);
|
|
456
|
+
var bands = [[viewport.top, viewport.bottom]];
|
|
457
|
+
if (bar && rect.right > bar.left && rect.left < bar.right && bar.bottom > viewport.top && bar.top < viewport.bottom) {
|
|
458
|
+
bands = [[viewport.top, Math.min(viewport.bottom, bar.top - 8)],
|
|
459
|
+
[Math.max(viewport.top, bar.bottom + 8), viewport.bottom]];
|
|
460
|
+
}
|
|
461
|
+
var best = null;
|
|
462
|
+
bands.forEach(function (band) {
|
|
463
|
+
if (band[1] <= band[0]) return;
|
|
464
|
+
var delta = rect.top < band[0] ? rect.top - band[0] :
|
|
465
|
+
rect.bottom > band[1] ? Math.min(rect.top - band[0], rect.bottom - band[1]) : 0;
|
|
466
|
+
delta = Math.max(0, Math.min(maximum, current + delta)) - current;
|
|
467
|
+
var shown = Math.max(0, Math.min(rect.bottom - delta, band[1]) - Math.max(rect.top - delta, band[0]));
|
|
468
|
+
// At either history boundary, prefer the region actually reachable
|
|
469
|
+
// after clamping rather than assuming the larger region is reachable.
|
|
470
|
+
if (!best || shown > best.shown || (shown === best.shown && Math.abs(delta) < Math.abs(best.delta))) best = { delta: delta, shown: shown };
|
|
471
|
+
});
|
|
472
|
+
var x = rect.left < viewport.left ? rect.left - viewport.left :
|
|
473
|
+
rect.right > viewport.right ? Math.min(rect.left - viewport.left, rect.right - viewport.right) : 0;
|
|
474
|
+
if ((best && best.delta) || x) {
|
|
475
|
+
try { scroll.scrollBy({ top: best ? best.delta : 0, left: x, behavior: "instant" }); } catch (error) {}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
426
479
|
function scrollToRange(range) {
|
|
427
480
|
var viewport = readingViewport(state.target);
|
|
428
|
-
if (viewport
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
481
|
+
if (!viewport || visibleMatchRect(range, viewport)) return;
|
|
482
|
+
// Reveal the exact Range, not its potentially very tall <pre>/<p>.
|
|
483
|
+
// Work from inner scroll clips outwards, without scrolling the window
|
|
484
|
+
// or unrelated panels. Re-read geometry after every scroll.
|
|
485
|
+
for (var node = range.startContainer.parentElement; node && node !== viewport.scroll; node = node.parentElement) {
|
|
486
|
+
var style = window.getComputedStyle(node);
|
|
487
|
+
var clipsY = /^(auto|scroll|hidden)$/.test(style.overflowY) && node.scrollHeight > node.clientHeight;
|
|
488
|
+
var clipsX = /^(auto|scroll|hidden)$/.test(style.overflowX) && node.scrollWidth > node.clientWidth;
|
|
489
|
+
if (!clipsX && !clipsY) continue;
|
|
490
|
+
var box = node.getBoundingClientRect(), top = box.top + node.clientTop, left = box.left + node.clientLeft;
|
|
491
|
+
var rect = rangeRect(range);
|
|
492
|
+
if (!rect) return;
|
|
493
|
+
var clip = clippedViewport(node, viewport);
|
|
494
|
+
var safeTop = Math.max(top, clip.top), safeBottom = Math.min(top + node.clientHeight, clip.bottom);
|
|
495
|
+
var shown = safeBottom > safeTop;
|
|
496
|
+
// A code scroller may still have room when the conversation is at
|
|
497
|
+
// its boundary. Let it avoid the overlay within its visible clip.
|
|
498
|
+
scrollRangeWithin(range, node, { top: clipsY ? (shown ? safeTop : top) : rect.top,
|
|
499
|
+
bottom: clipsY ? (shown ? safeBottom : top + node.clientHeight) : rect.bottom,
|
|
500
|
+
left: clipsX ? left : rect.left, right: clipsX ? left + node.clientWidth : rect.right },
|
|
501
|
+
clipsY && shown ? matchBarRect() : null);
|
|
432
502
|
}
|
|
503
|
+
viewport = readingViewport(state.target);
|
|
504
|
+
if (viewport && !visibleMatchRect(range, viewport)) scrollRangeWithin(range, viewport.scroll, viewport, matchBarRect());
|
|
433
505
|
}
|
|
434
506
|
|
|
435
507
|
//#region host adapter
|
|
@@ -727,6 +799,16 @@ window.__ModuleLoader__.load({
|
|
|
727
799
|
return null;
|
|
728
800
|
}
|
|
729
801
|
|
|
802
|
+
function hiddenUntilFoundAncestor(node, root) {
|
|
803
|
+
var element = node && (node.nodeType === 1 ? node : node.parentElement);
|
|
804
|
+
for (; element && root && root.contains(element); element = element.parentElement) {
|
|
805
|
+
var hidden = element.getAttribute && element.getAttribute('hidden');
|
|
806
|
+
if (typeof hidden === 'string' && hidden.toLowerCase() === 'until-found') return element;
|
|
807
|
+
if (element === root) break;
|
|
808
|
+
}
|
|
809
|
+
return null;
|
|
810
|
+
}
|
|
811
|
+
|
|
730
812
|
function captureReadingOrigin() {
|
|
731
813
|
var target = state.target, viewport = readingViewport(target);
|
|
732
814
|
var store = state.adapter && state.adapter.nodes(target);
|
|
@@ -844,19 +926,22 @@ window.__ModuleLoader__.load({
|
|
|
844
926
|
if (state.target !== target || !state.adapter.valid(target) || state.adapter.face(target) !== face) return;
|
|
845
927
|
}
|
|
846
928
|
var origin = state.origin, token = state.navigationToken, started = Date.now();
|
|
847
|
-
var activated = new Set(),
|
|
929
|
+
var activated = new Set(), announceReturn = false;
|
|
848
930
|
function check() {
|
|
849
931
|
state.navigationTimer = 0;
|
|
850
932
|
if (token !== state.navigationToken || !originValid(origin)) return;
|
|
933
|
+
positionBar();
|
|
851
934
|
var viewport = readingViewport(origin.target);
|
|
852
935
|
var current = state.ranges[state.index];
|
|
853
|
-
var
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
if (
|
|
936
|
+
var attached = current && origin.target.root.contains(current.startContainer);
|
|
937
|
+
// hidden=until-found uses content-visibility:hidden, so Chromium may
|
|
938
|
+
// report layout geometry for descendants that are not painted. Reveal
|
|
939
|
+
// the host-owned disclosure before trusting Range geometry.
|
|
940
|
+
var concealed = attached && hiddenUntilFoundAncestor(current.startContainer, origin.target.root);
|
|
941
|
+
var geometry = attached && !concealed && rangeRect(current);
|
|
942
|
+
if (current && (!geometry || concealed)) revealMatchRange(origin.target, current, activated);
|
|
943
|
+
if (geometry && !visibleMatchRect(current, viewport)) scrollToRange(current);
|
|
944
|
+
if (viewport && attached && !concealed && visibleMatchRect(current, viewport)) {
|
|
860
945
|
var firstNavigation = !origin.navigated;
|
|
861
946
|
origin.navigated = true;
|
|
862
947
|
updateReturnButton();
|
|
@@ -866,8 +951,13 @@ window.__ModuleLoader__.load({
|
|
|
866
951
|
var priorStatus = state.jumpStatus;
|
|
867
952
|
setStatus(priorStatus, false);
|
|
868
953
|
} else setStatus(L.returnAvailable, false);
|
|
869
|
-
|
|
954
|
+
announceReturn = true;
|
|
955
|
+
// Return/status controls can wrap and grow the overlay. Verify
|
|
956
|
+
// the resulting layout before declaring the match visible.
|
|
957
|
+
state.navigationTimer = setTimeout(check, 0);
|
|
958
|
+
return;
|
|
870
959
|
}
|
|
960
|
+
if (announceReturn && state.announcement) state.announcement.textContent = L.returnAvailable;
|
|
871
961
|
return;
|
|
872
962
|
}
|
|
873
963
|
if (Date.now() - started < 1500) {
|
|
@@ -1098,7 +1188,8 @@ window.__ModuleLoader__.load({
|
|
|
1098
1188
|
origin: null, restoring: null, returnBtn: null, announcement: null, navigationTimer: 0, navigationToken: 0,
|
|
1099
1189
|
jumpStatus: null,
|
|
1100
1190
|
positionObserver: null,
|
|
1101
|
-
positionFrame:
|
|
1191
|
+
positionFrame: null,
|
|
1192
|
+
positionOwner: null, manualPosition: null, drag: null, dragHandle: null, positionControls: null, suppressMoveClick: false
|
|
1102
1193
|
};
|
|
1103
1194
|
|
|
1104
1195
|
function barAnchor(target) {
|
|
@@ -1114,39 +1205,115 @@ window.__ModuleLoader__.load({
|
|
|
1114
1205
|
|
|
1115
1206
|
function positionBar() {
|
|
1116
1207
|
if (!isOpen() || !state.bar) return false;
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1208
|
+
var target = state.target, header = barAnchor(target), viewport = readingViewport(target);
|
|
1209
|
+
if (!target || !header || !header.isConnected || !target.panel.isConnected || !viewport) {
|
|
1210
|
+
state.bar.removeAttribute("data-positioned");
|
|
1211
|
+
return false;
|
|
1212
|
+
}
|
|
1213
|
+
var panel = target.panel.getBoundingClientRect(), headerRect = header.getBoundingClientRect();
|
|
1214
|
+
var leftEdge = Math.max(panel.left, viewport.left) + 8;
|
|
1215
|
+
var rightEdge = Math.min(panel.right, viewport.right) - 8;
|
|
1216
|
+
var topEdge = Math.max(panel.top, viewport.top, headerRect.bottom) + 8;
|
|
1217
|
+
var bottomEdge = Math.min(panel.bottom, viewport.bottom) - 8;
|
|
1218
|
+
if (rightEdge <= leftEdge || bottomEdge <= topEdge) {
|
|
1120
1219
|
state.bar.removeAttribute("data-positioned");
|
|
1121
1220
|
return false;
|
|
1122
1221
|
}
|
|
1123
|
-
var headerRect = header.getBoundingClientRect();
|
|
1124
|
-
var panelRect = state.target.panel.getBoundingClientRect();
|
|
1125
|
-
var viewportWidth = document.documentElement.clientWidth || window.innerWidth;
|
|
1126
|
-
var panelLeft = Math.max(0, panelRect.left);
|
|
1127
|
-
var panelRight = Math.min(viewportWidth, panelRect.right);
|
|
1128
1222
|
var dpr = window.devicePixelRatio || 1;
|
|
1129
1223
|
function cssPixel(value) { return Math.round(value * dpr) / dpr + "px"; }
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
state.bar.style.setProperty("--dsh-find-all-panel-width", cssPixel(
|
|
1224
|
+
// This is the only position writer, including pointer, resize, scroll
|
|
1225
|
+
// and polling updates. Manual placement never falls back to the anchor.
|
|
1226
|
+
state.bar.style.setProperty("--dsh-find-all-panel-width", cssPixel(rightEdge - leftEdge));
|
|
1227
|
+
state.bar.style.setProperty("--dsh-find-all-max-height", cssPixel(bottomEdge - topEdge));
|
|
1228
|
+
var box = state.bar.getBoundingClientRect(), manual = state.manualPosition;
|
|
1229
|
+
var left = manual ? manual.left : rightEdge - box.width;
|
|
1230
|
+
var top = manual ? manual.top : topEdge;
|
|
1231
|
+
left = Math.max(leftEdge, Math.min(left, rightEdge - box.width));
|
|
1232
|
+
top = Math.max(topEdge, Math.min(top, bottomEdge - box.height));
|
|
1233
|
+
if (manual) { manual.left = left; manual.top = top; }
|
|
1234
|
+
state.bar.style.setProperty("--dsh-find-all-bar-top", cssPixel(top));
|
|
1235
|
+
state.bar.style.setProperty("--dsh-find-all-bar-right", cssPixel(window.innerWidth - left - box.width));
|
|
1133
1236
|
state.bar.setAttribute("data-positioned", "");
|
|
1134
1237
|
return true;
|
|
1135
1238
|
}
|
|
1136
1239
|
|
|
1240
|
+
function finishBarDrag(event) {
|
|
1241
|
+
var drag = state.drag;
|
|
1242
|
+
if (!drag || (event && event.pointerId !== drag.id)) return;
|
|
1243
|
+
state.drag = null;
|
|
1244
|
+
state.bar.removeAttribute("data-dragging");
|
|
1245
|
+
try { if (drag.handle.hasPointerCapture(drag.id)) drag.handle.releasePointerCapture(drag.id); } catch (error) {}
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
function resetBarPosition() {
|
|
1249
|
+
finishBarDrag();
|
|
1250
|
+
state.manualPosition = null;
|
|
1251
|
+
scheduleBarPosition();
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
function moveBarBy(x, y) {
|
|
1255
|
+
if (!positionBar()) return;
|
|
1256
|
+
var box = state.bar.getBoundingClientRect();
|
|
1257
|
+
state.manualPosition = { left: box.left + x, top: box.top + y };
|
|
1258
|
+
scheduleBarPosition();
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
function buildPositionControls(controls, bar) {
|
|
1262
|
+
var moves = document.createElement("div");
|
|
1263
|
+
moves.className = "position-controls"; moves.id = BAR_ID + "-position"; moves.hidden = true;
|
|
1264
|
+
var handle = button(L.move, "M9 5h.01M15 5h.01M9 12h.01M15 12h.01M9 19h.01M15 19h.01", function (event) {
|
|
1265
|
+
if (event.detail && state.suppressMoveClick) { state.suppressMoveClick = false; return; }
|
|
1266
|
+
moves.hidden = !moves.hidden;
|
|
1267
|
+
handle.setAttribute("aria-expanded", String(!moves.hidden));
|
|
1268
|
+
scheduleBarPosition();
|
|
1269
|
+
});
|
|
1270
|
+
handle.className = "drag-handle";
|
|
1271
|
+
handle.setAttribute("aria-expanded", "false"); handle.setAttribute("aria-controls", moves.id);
|
|
1272
|
+
handle.addEventListener("pointerdown", function (event) {
|
|
1273
|
+
if (!event.isPrimary || event.button !== 0 || state.drag || !positionBar()) return;
|
|
1274
|
+
state.suppressMoveClick = false;
|
|
1275
|
+
try { handle.setPointerCapture(event.pointerId); } catch (error) { return; }
|
|
1276
|
+
var box = state.bar.getBoundingClientRect();
|
|
1277
|
+
state.drag = { id: event.pointerId, handle: handle, x: event.clientX, y: event.clientY, left: box.left, top: box.top };
|
|
1278
|
+
// Dragging the handle must not steal focus/selection from the query.
|
|
1279
|
+
event.preventDefault();
|
|
1280
|
+
});
|
|
1281
|
+
handle.addEventListener("pointermove", function (event) {
|
|
1282
|
+
var drag = state.drag;
|
|
1283
|
+
if (!drag || event.pointerId !== drag.id) return;
|
|
1284
|
+
var x = event.clientX - drag.x, y = event.clientY - drag.y;
|
|
1285
|
+
if (!state.suppressMoveClick && Math.abs(x) + Math.abs(y) < 4) return;
|
|
1286
|
+
state.suppressMoveClick = true;
|
|
1287
|
+
state.bar.setAttribute("data-dragging", "");
|
|
1288
|
+
state.manualPosition = { left: drag.left + x, top: drag.top + y };
|
|
1289
|
+
scheduleBarPosition();
|
|
1290
|
+
});
|
|
1291
|
+
["pointerup", "pointercancel", "lostpointercapture"].forEach(function (type) { handle.addEventListener(type, finishBarDrag); });
|
|
1292
|
+
moves.appendChild(button(L.moveLeft, "m14 6-6 6 6 6", function () { moveBarBy(-32, 0); }));
|
|
1293
|
+
moves.appendChild(button(L.moveRight, "m10 6 6 6-6 6", function () { moveBarBy(32, 0); }));
|
|
1294
|
+
moves.appendChild(button(L.moveUp, "m6 14 6-6 6 6", function () { moveBarBy(0, -32); }));
|
|
1295
|
+
moves.appendChild(button(L.moveDown, "m6 10 6 6 6-6", function () { moveBarBy(0, 32); }));
|
|
1296
|
+
var reset = button(L.resetPosition, "M3 10a9 9 0 1 1 2 8M3 4v6h6", resetBarPosition);
|
|
1297
|
+
moves.appendChild(reset);
|
|
1298
|
+
state.dragHandle = handle; state.positionControls = moves;
|
|
1299
|
+
controls.appendChild(handle);
|
|
1300
|
+
bar.appendChild(moves);
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1137
1303
|
function scheduleBarPosition() {
|
|
1138
|
-
if (!isOpen() || state.positionFrame) return;
|
|
1304
|
+
if (!isOpen() || state.positionFrame !== null) return;
|
|
1139
1305
|
if (typeof requestAnimationFrame !== "function") { positionBar(); return; }
|
|
1140
1306
|
state.positionFrame = requestAnimationFrame(function () {
|
|
1141
|
-
state.positionFrame =
|
|
1307
|
+
state.positionFrame = null;
|
|
1142
1308
|
positionBar();
|
|
1143
1309
|
});
|
|
1144
1310
|
}
|
|
1145
1311
|
|
|
1146
1312
|
function stopBarPositioning() {
|
|
1313
|
+
finishBarDrag();
|
|
1147
1314
|
if (state.positionObserver) { state.positionObserver.disconnect(); state.positionObserver = null; }
|
|
1148
|
-
if (state.positionFrame && typeof cancelAnimationFrame === "function") cancelAnimationFrame(state.positionFrame);
|
|
1149
|
-
state.positionFrame =
|
|
1315
|
+
if (state.positionFrame !== null && typeof cancelAnimationFrame === "function") cancelAnimationFrame(state.positionFrame);
|
|
1316
|
+
state.positionFrame = null;
|
|
1150
1317
|
}
|
|
1151
1318
|
|
|
1152
1319
|
function startBarPositioning() {
|
|
@@ -1156,6 +1323,13 @@ window.__ModuleLoader__.load({
|
|
|
1156
1323
|
if (!header || typeof ResizeObserver === "undefined") return;
|
|
1157
1324
|
state.positionObserver = new ResizeObserver(scheduleBarPosition);
|
|
1158
1325
|
state.positionObserver.observe(header);
|
|
1326
|
+
var viewport = readingViewport(state.target);
|
|
1327
|
+
if (viewport) {
|
|
1328
|
+
state.positionObserver.observe(viewport.scroll);
|
|
1329
|
+
var composer = viewport.scroll.querySelector("[data-composer-seat]");
|
|
1330
|
+
if (composer) state.positionObserver.observe(composer);
|
|
1331
|
+
}
|
|
1332
|
+
state.positionObserver.observe(state.bar);
|
|
1159
1333
|
if (state.target.panel !== header) state.positionObserver.observe(state.target.panel);
|
|
1160
1334
|
}
|
|
1161
1335
|
|
|
@@ -1438,6 +1612,15 @@ window.__ModuleLoader__.load({
|
|
|
1438
1612
|
function syncTarget(target, passive) {
|
|
1439
1613
|
if (!state.adapter) return;
|
|
1440
1614
|
var selected = passive ? state.adapter.refresh(state.target) : state.adapter.select(target || document.activeElement, state.target);
|
|
1615
|
+
if (selected) {
|
|
1616
|
+
var owner = state.positionOwner;
|
|
1617
|
+
if (owner && (owner.id !== selected.id || owner.panel !== selected.panel)) {
|
|
1618
|
+
resetBarPosition();
|
|
1619
|
+
if (state.positionControls) state.positionControls.hidden = true;
|
|
1620
|
+
if (state.dragHandle) state.dragHandle.setAttribute("aria-expanded", "false");
|
|
1621
|
+
}
|
|
1622
|
+
state.positionOwner = { id: selected.id, panel: selected.panel };
|
|
1623
|
+
}
|
|
1441
1624
|
if (selected && state.target && selected.id === state.target.id && selected.anchor === state.target.anchor && selected.root === state.target.root && selected.panel === state.target.panel && selected.registration === state.target.registration) {
|
|
1442
1625
|
if (state.origin && !originValid(state.origin)) { discardOrigin(); setStatus(returnFailure('unavailable'), false); }
|
|
1443
1626
|
scheduleBarPosition();
|
|
@@ -1554,6 +1737,7 @@ window.__ModuleLoader__.load({
|
|
|
1554
1737
|
setStatus(L.incomplete, false);
|
|
1555
1738
|
});
|
|
1556
1739
|
|
|
1740
|
+
buildPositionControls(controls, bar);
|
|
1557
1741
|
controls.appendChild(input);
|
|
1558
1742
|
controls.appendChild(scopeBtn);
|
|
1559
1743
|
controls.appendChild(count);
|
|
@@ -1566,7 +1750,7 @@ window.__ModuleLoader__.load({
|
|
|
1566
1750
|
state.returnBtn = returnBtn;
|
|
1567
1751
|
controls.appendChild(returnBtn);
|
|
1568
1752
|
controls.appendChild(button(L.close, "M18 6 6 18M6 6l12 12", close));
|
|
1569
|
-
bar.
|
|
1753
|
+
bar.insertBefore(controls, bar.firstChild);
|
|
1570
1754
|
bar.appendChild(status);
|
|
1571
1755
|
|
|
1572
1756
|
state.bar = bar;
|
|
@@ -1616,6 +1800,10 @@ window.__ModuleLoader__.load({
|
|
|
1616
1800
|
cancelPageIn();
|
|
1617
1801
|
stopWatchingSession();
|
|
1618
1802
|
stopBarPositioning();
|
|
1803
|
+
state.manualPosition = state.positionOwner = null;
|
|
1804
|
+
state.suppressMoveClick = false;
|
|
1805
|
+
if (state.positionControls) state.positionControls.hidden = true;
|
|
1806
|
+
if (state.dragHandle) state.dragHandle.setAttribute("aria-expanded", "false");
|
|
1619
1807
|
if (state.bar) { state.bar.style.display = "none"; state.bar.removeAttribute("data-positioned"); }
|
|
1620
1808
|
state.ranges = [];
|
|
1621
1809
|
state.index = -1;
|
|
@@ -1692,6 +1880,8 @@ window.__ModuleLoader__.load({
|
|
|
1692
1880
|
window.addEventListener("focusin", focus, true);
|
|
1693
1881
|
window.addEventListener("pointerdown", focus, true);
|
|
1694
1882
|
window.addEventListener("wheel", readingFocus, true);
|
|
1883
|
+
function blur() { finishBarDrag(); }
|
|
1884
|
+
window.addEventListener("blur", blur);
|
|
1695
1885
|
window.addEventListener("resize", scheduleBarPosition);
|
|
1696
1886
|
window.addEventListener("scroll", scheduleBarPosition, true);
|
|
1697
1887
|
return function () {
|
|
@@ -1700,13 +1890,14 @@ window.__ModuleLoader__.load({
|
|
|
1700
1890
|
window.removeEventListener("focusin", focus, true);
|
|
1701
1891
|
window.removeEventListener("pointerdown", focus, true);
|
|
1702
1892
|
window.removeEventListener("wheel", readingFocus, true);
|
|
1893
|
+
window.removeEventListener("blur", blur);
|
|
1703
1894
|
window.removeEventListener("resize", scheduleBarPosition);
|
|
1704
1895
|
window.removeEventListener("scroll", scheduleBarPosition, true);
|
|
1705
1896
|
close();
|
|
1706
1897
|
state.query = "";
|
|
1707
1898
|
if (state.bar) state.bar.remove();
|
|
1708
1899
|
if (state.announcement) state.announcement.remove();
|
|
1709
|
-
state.announcement = state.returnBtn = null;
|
|
1900
|
+
state.announcement = state.returnBtn = state.dragHandle = state.positionControls = null;
|
|
1710
1901
|
var style = document.querySelector('style[data-plugin-css="dsh-find-all/bar.css"]');
|
|
1711
1902
|
if (style) style.remove();
|
|
1712
1903
|
state.bar = state.input = state.count = state.status = state.scopeBtn = null;
|
package/package.json
CHANGED