|
|
@@ -734,6 +734,7 @@
|
|
|
persistOwnerFilter();
|
|
|
updateOwnerFilterUi();
|
|
|
applyFilters();
|
|
|
+ setHidden(qs('[data-owner-filter-dropdown]'), true);
|
|
|
});
|
|
|
|
|
|
on(root, 'click', '[data-owner-filter-trigger]', function (ev) {
|
|
|
@@ -816,6 +817,7 @@
|
|
|
persistStatusFilter();
|
|
|
updateStatusFilterUi();
|
|
|
applyFilters();
|
|
|
+ setHidden(qs('[data-status-filter-dropdown]'), true);
|
|
|
});
|
|
|
|
|
|
on(root, 'click', '[data-status-filter-trigger]', function (ev) {
|
|
|
@@ -979,20 +981,35 @@
|
|
|
}
|
|
|
});
|
|
|
|
|
|
- // Close dropdowns when the cursor leaves the trigger+panel root. The
|
|
|
- // panel sits inside the root (`<div class="relative">`), so a single
|
|
|
- // mouseleave on the root fires only when the cursor exits both the
|
|
|
- // button and the dropdown.
|
|
|
+ // Close dropdowns when the cursor leaves both the trigger and the
|
|
|
+ // panel. The panel is absolutely positioned with a small mt-1 gap,
|
|
|
+ // so a naive mouseleave on the root fires while the cursor is in
|
|
|
+ // transit between button and panel — we use a 250 ms grace timer
|
|
|
+ // that is cancelled if the cursor enters the panel (or re-enters
|
|
|
+ // the root) within the window.
|
|
|
[
|
|
|
['[data-owner-filter-root]', '[data-owner-filter-dropdown]'],
|
|
|
['[data-status-filter-root]', '[data-status-filter-dropdown]'],
|
|
|
['[data-columns-root]', '[data-columns-dropdown]'],
|
|
|
].forEach(function (pair) {
|
|
|
- const r = qs(pair[0]);
|
|
|
- if (!r) { return; }
|
|
|
- r.addEventListener('mouseleave', function () {
|
|
|
- setHidden(qs(pair[1]), true);
|
|
|
- });
|
|
|
+ const r = qs(pair[0]);
|
|
|
+ const dd = qs(pair[1]);
|
|
|
+ if (!r || !dd) { return; }
|
|
|
+ let timer = null;
|
|
|
+ const cancel = function () {
|
|
|
+ if (timer) { clearTimeout(timer); timer = null; }
|
|
|
+ };
|
|
|
+ const schedule = function () {
|
|
|
+ cancel();
|
|
|
+ timer = setTimeout(function () {
|
|
|
+ setHidden(dd, true);
|
|
|
+ timer = null;
|
|
|
+ }, 250);
|
|
|
+ };
|
|
|
+ r.addEventListener('mouseenter', cancel);
|
|
|
+ r.addEventListener('mouseleave', schedule);
|
|
|
+ dd.addEventListener('mouseenter', cancel);
|
|
|
+ dd.addEventListener('mouseleave', schedule);
|
|
|
});
|
|
|
|
|
|
// --- Reset filters ---------------------------------------------------
|