@ryuu-64/dsh-find-all 0.1.9 → 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 +9 -0
- package/lib/client.js +208 -32
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
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
|
+
|
|
3
12
|
## 0.1.9
|
|
4
13
|
|
|
5
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.
|
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
|
|
@@ -854,10 +926,11 @@ window.__ModuleLoader__.load({
|
|
|
854
926
|
if (state.target !== target || !state.adapter.valid(target) || state.adapter.face(target) !== face) return;
|
|
855
927
|
}
|
|
856
928
|
var origin = state.origin, token = state.navigationToken, started = Date.now();
|
|
857
|
-
var activated = new Set(),
|
|
929
|
+
var activated = new Set(), announceReturn = false;
|
|
858
930
|
function check() {
|
|
859
931
|
state.navigationTimer = 0;
|
|
860
932
|
if (token !== state.navigationToken || !originValid(origin)) return;
|
|
933
|
+
positionBar();
|
|
861
934
|
var viewport = readingViewport(origin.target);
|
|
862
935
|
var current = state.ranges[state.index];
|
|
863
936
|
var attached = current && origin.target.root.contains(current.startContainer);
|
|
@@ -867,11 +940,8 @@ window.__ModuleLoader__.load({
|
|
|
867
940
|
var concealed = attached && hiddenUntilFoundAncestor(current.startContainer, origin.target.root);
|
|
868
941
|
var geometry = attached && !concealed && rangeRect(current);
|
|
869
942
|
if (current && (!geometry || concealed)) revealMatchRange(origin.target, current, activated);
|
|
870
|
-
if (geometry &&
|
|
871
|
-
|
|
872
|
-
scrolledRange = current;
|
|
873
|
-
}
|
|
874
|
-
if (viewport && attached && !concealed && rangeRect(current, viewport)) {
|
|
943
|
+
if (geometry && !visibleMatchRect(current, viewport)) scrollToRange(current);
|
|
944
|
+
if (viewport && attached && !concealed && visibleMatchRect(current, viewport)) {
|
|
875
945
|
var firstNavigation = !origin.navigated;
|
|
876
946
|
origin.navigated = true;
|
|
877
947
|
updateReturnButton();
|
|
@@ -881,8 +951,13 @@ window.__ModuleLoader__.load({
|
|
|
881
951
|
var priorStatus = state.jumpStatus;
|
|
882
952
|
setStatus(priorStatus, false);
|
|
883
953
|
} else setStatus(L.returnAvailable, false);
|
|
884
|
-
|
|
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;
|
|
885
959
|
}
|
|
960
|
+
if (announceReturn && state.announcement) state.announcement.textContent = L.returnAvailable;
|
|
886
961
|
return;
|
|
887
962
|
}
|
|
888
963
|
if (Date.now() - started < 1500) {
|
|
@@ -1113,7 +1188,8 @@ window.__ModuleLoader__.load({
|
|
|
1113
1188
|
origin: null, restoring: null, returnBtn: null, announcement: null, navigationTimer: 0, navigationToken: 0,
|
|
1114
1189
|
jumpStatus: null,
|
|
1115
1190
|
positionObserver: null,
|
|
1116
|
-
positionFrame:
|
|
1191
|
+
positionFrame: null,
|
|
1192
|
+
positionOwner: null, manualPosition: null, drag: null, dragHandle: null, positionControls: null, suppressMoveClick: false
|
|
1117
1193
|
};
|
|
1118
1194
|
|
|
1119
1195
|
function barAnchor(target) {
|
|
@@ -1129,39 +1205,115 @@ window.__ModuleLoader__.load({
|
|
|
1129
1205
|
|
|
1130
1206
|
function positionBar() {
|
|
1131
1207
|
if (!isOpen() || !state.bar) return false;
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
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) {
|
|
1135
1219
|
state.bar.removeAttribute("data-positioned");
|
|
1136
1220
|
return false;
|
|
1137
1221
|
}
|
|
1138
|
-
var headerRect = header.getBoundingClientRect();
|
|
1139
|
-
var panelRect = state.target.panel.getBoundingClientRect();
|
|
1140
|
-
var viewportWidth = document.documentElement.clientWidth || window.innerWidth;
|
|
1141
|
-
var panelLeft = Math.max(0, panelRect.left);
|
|
1142
|
-
var panelRight = Math.min(viewportWidth, panelRect.right);
|
|
1143
1222
|
var dpr = window.devicePixelRatio || 1;
|
|
1144
1223
|
function cssPixel(value) { return Math.round(value * dpr) / dpr + "px"; }
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
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));
|
|
1148
1236
|
state.bar.setAttribute("data-positioned", "");
|
|
1149
1237
|
return true;
|
|
1150
1238
|
}
|
|
1151
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
|
+
|
|
1152
1303
|
function scheduleBarPosition() {
|
|
1153
|
-
if (!isOpen() || state.positionFrame) return;
|
|
1304
|
+
if (!isOpen() || state.positionFrame !== null) return;
|
|
1154
1305
|
if (typeof requestAnimationFrame !== "function") { positionBar(); return; }
|
|
1155
1306
|
state.positionFrame = requestAnimationFrame(function () {
|
|
1156
|
-
state.positionFrame =
|
|
1307
|
+
state.positionFrame = null;
|
|
1157
1308
|
positionBar();
|
|
1158
1309
|
});
|
|
1159
1310
|
}
|
|
1160
1311
|
|
|
1161
1312
|
function stopBarPositioning() {
|
|
1313
|
+
finishBarDrag();
|
|
1162
1314
|
if (state.positionObserver) { state.positionObserver.disconnect(); state.positionObserver = null; }
|
|
1163
|
-
if (state.positionFrame && typeof cancelAnimationFrame === "function") cancelAnimationFrame(state.positionFrame);
|
|
1164
|
-
state.positionFrame =
|
|
1315
|
+
if (state.positionFrame !== null && typeof cancelAnimationFrame === "function") cancelAnimationFrame(state.positionFrame);
|
|
1316
|
+
state.positionFrame = null;
|
|
1165
1317
|
}
|
|
1166
1318
|
|
|
1167
1319
|
function startBarPositioning() {
|
|
@@ -1171,6 +1323,13 @@ window.__ModuleLoader__.load({
|
|
|
1171
1323
|
if (!header || typeof ResizeObserver === "undefined") return;
|
|
1172
1324
|
state.positionObserver = new ResizeObserver(scheduleBarPosition);
|
|
1173
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);
|
|
1174
1333
|
if (state.target.panel !== header) state.positionObserver.observe(state.target.panel);
|
|
1175
1334
|
}
|
|
1176
1335
|
|
|
@@ -1453,6 +1612,15 @@ window.__ModuleLoader__.load({
|
|
|
1453
1612
|
function syncTarget(target, passive) {
|
|
1454
1613
|
if (!state.adapter) return;
|
|
1455
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
|
+
}
|
|
1456
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) {
|
|
1457
1625
|
if (state.origin && !originValid(state.origin)) { discardOrigin(); setStatus(returnFailure('unavailable'), false); }
|
|
1458
1626
|
scheduleBarPosition();
|
|
@@ -1569,6 +1737,7 @@ window.__ModuleLoader__.load({
|
|
|
1569
1737
|
setStatus(L.incomplete, false);
|
|
1570
1738
|
});
|
|
1571
1739
|
|
|
1740
|
+
buildPositionControls(controls, bar);
|
|
1572
1741
|
controls.appendChild(input);
|
|
1573
1742
|
controls.appendChild(scopeBtn);
|
|
1574
1743
|
controls.appendChild(count);
|
|
@@ -1581,7 +1750,7 @@ window.__ModuleLoader__.load({
|
|
|
1581
1750
|
state.returnBtn = returnBtn;
|
|
1582
1751
|
controls.appendChild(returnBtn);
|
|
1583
1752
|
controls.appendChild(button(L.close, "M18 6 6 18M6 6l12 12", close));
|
|
1584
|
-
bar.
|
|
1753
|
+
bar.insertBefore(controls, bar.firstChild);
|
|
1585
1754
|
bar.appendChild(status);
|
|
1586
1755
|
|
|
1587
1756
|
state.bar = bar;
|
|
@@ -1631,6 +1800,10 @@ window.__ModuleLoader__.load({
|
|
|
1631
1800
|
cancelPageIn();
|
|
1632
1801
|
stopWatchingSession();
|
|
1633
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");
|
|
1634
1807
|
if (state.bar) { state.bar.style.display = "none"; state.bar.removeAttribute("data-positioned"); }
|
|
1635
1808
|
state.ranges = [];
|
|
1636
1809
|
state.index = -1;
|
|
@@ -1707,6 +1880,8 @@ window.__ModuleLoader__.load({
|
|
|
1707
1880
|
window.addEventListener("focusin", focus, true);
|
|
1708
1881
|
window.addEventListener("pointerdown", focus, true);
|
|
1709
1882
|
window.addEventListener("wheel", readingFocus, true);
|
|
1883
|
+
function blur() { finishBarDrag(); }
|
|
1884
|
+
window.addEventListener("blur", blur);
|
|
1710
1885
|
window.addEventListener("resize", scheduleBarPosition);
|
|
1711
1886
|
window.addEventListener("scroll", scheduleBarPosition, true);
|
|
1712
1887
|
return function () {
|
|
@@ -1715,13 +1890,14 @@ window.__ModuleLoader__.load({
|
|
|
1715
1890
|
window.removeEventListener("focusin", focus, true);
|
|
1716
1891
|
window.removeEventListener("pointerdown", focus, true);
|
|
1717
1892
|
window.removeEventListener("wheel", readingFocus, true);
|
|
1893
|
+
window.removeEventListener("blur", blur);
|
|
1718
1894
|
window.removeEventListener("resize", scheduleBarPosition);
|
|
1719
1895
|
window.removeEventListener("scroll", scheduleBarPosition, true);
|
|
1720
1896
|
close();
|
|
1721
1897
|
state.query = "";
|
|
1722
1898
|
if (state.bar) state.bar.remove();
|
|
1723
1899
|
if (state.announcement) state.announcement.remove();
|
|
1724
|
-
state.announcement = state.returnBtn = null;
|
|
1900
|
+
state.announcement = state.returnBtn = state.dragHandle = state.positionControls = null;
|
|
1725
1901
|
var style = document.querySelector('style[data-plugin-css="dsh-find-all/bar.css"]');
|
|
1726
1902
|
if (style) style.remove();
|
|
1727
1903
|
state.bar = state.input = state.count = state.status = state.scopeBtn = null;
|
package/package.json
CHANGED