diff --git a/base.js b/base.js
index 5244fc6..8ecb0ec 100644
--- a/base.js
+++ b/base.js
@@ -232,9 +232,14 @@
_unlockScroll();
// Remove trap handler
if (el._ltTrapHandler) { el.removeEventListener('keydown', el._ltTrapHandler); delete el._ltTrapHandler; }
- // Return focus to trigger
+ // Return focus to trigger (only if no other modal remains open)
const trigger = _modalTriggers.get(el);
- if (trigger) { trigger.focus(); _modalTriggers.delete(el); }
+ if (trigger) {
+ _modalTriggers.delete(el);
+ if (!document.querySelector('.lt-modal-overlay.is-open') && document.contains(trigger)) {
+ trigger.focus();
+ }
+ }
}
function closeAllModals() {
@@ -1672,9 +1677,10 @@
lt.contextMenu.register(selector, items)
items = [{ label, icon, kbd, danger, divider, action }]
================================================================ */
- let _ctxMenu = null;
+ let _ctxMenu = null, _ctxTrigger = null;
const _ctxItems = {};
- function _ctxShow(x, y, items) {
+ function _ctxShow(x, y, items, trigger) {
+ _ctxTrigger = trigger || (document.activeElement !== document.body ? document.activeElement : null);
if (!_ctxMenu) {
_ctxMenu = document.createElement('div');
_ctxMenu.className = 'lt-context-menu';
@@ -1706,6 +1712,8 @@
}
function _ctxHide() {
if (_ctxMenu) _ctxMenu.classList.remove('is-open');
+ if (_ctxTrigger && document.contains(_ctxTrigger)) { _ctxTrigger.focus(); }
+ _ctxTrigger = null;
}
document.addEventListener('click', () => _ctxHide());
document.addEventListener('contextmenu', e => {
@@ -1714,7 +1722,7 @@
e.preventDefault();
const menuId = target.dataset.contextMenu;
const items = _ctxItems[menuId];
- if (items) _ctxShow(e.clientX, e.clientY, items);
+ if (items) _ctxShow(e.clientX, e.clientY, items, target);
});
document.addEventListener('keydown', e => { if (e.key === 'Escape') _ctxHide(); });
const contextMenu = {
@@ -2724,12 +2732,12 @@
// Links — block javascript: and data: URIs
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_, text, url) => {
const safeUrl = /^(https?:\/\/|\/|#|\.\.?\/)/i.test(url) ? url : '#';
- return `
${text}`;
+ return `
${escHtml(text)}`;
})
// Images — block javascript: and data: URIs
.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, (_, alt, src) => {
const safeSrc = /^(https?:\/\/|\/|\.\.?\/)/i.test(src) ? src : '';
- return `

`;
+ return `

`;
})
// Blockquote
.replace(/^>\s(.+)$/gm, '
$1
')
@@ -2775,7 +2783,7 @@
const pages = _pages();
let html = '';
// Prev
- html += `
`;
+ html += `
`;
// Page buttons with ellipsis
const half = Math.floor((maxBtns - 2) / 2);
let start = Math.max(2, page - half);
@@ -2784,15 +2792,17 @@
if (start === 2) end = Math.min(pages - 1, start + maxBtns - 3);
else start = Math.max(2, end - maxBtns + 3);
}
- html += `
`;
- if (start > 2) html += `
`;
+ html += `
`;
+ if (start > 2) html += `
`;
for (let i = start; i <= end; i++) {
- html += `
`;
+ html += `
`;
}
- if (end < pages - 1) html += `
`;
- if (pages > 1) html += `
`;
+ if (end < pages - 1) html += `
`;
+ if (pages > 1) html += `
`;
// Next
- html += `
`;
+ html += `
`;
+ if (!nav.getAttribute('role')) nav.setAttribute('role', 'navigation');
+ if (!nav.getAttribute('aria-label')) nav.setAttribute('aria-label', 'Pagination');
nav.innerHTML = html;
}