46 lines
1.8 KiB
JavaScript
46 lines
1.8 KiB
JavaScript
// Generated, do not edit. sha256:6afcbeb7660ad5dcdb3d575aeb4495b0e547e5f54ce5b5f18abe560cc6fb7b7e
|
|||
|
|
const FOCUS_ANCHORS = ['data-field', 'data-convert', 'data-save', 'data-cancel'];
|
||
|
|
const SELECTION_TYPES = new Set(['text', 'search', 'url', 'tel', 'password']);
|
||
|
|
|
||
|
|
function hasSelection(node) {
|
||
|
|
if (!node) return false;
|
||
|
|
if (node.tagName === 'TEXTAREA') return true;
|
||
|
|
return node.tagName === 'INPUT' && SELECTION_TYPES.has(node.type);
|
||
|
|
}
|
||
|
|
|
||
|
|
function focusAnchor(node) {
|
||
|
|
for (const attr of FOCUS_ANCHORS) {
|
||
|
|
const host = node.closest(`[${attr}]`);
|
||
|
|
if (!host) continue;
|
||
|
|
const value = host.getAttribute(attr);
|
||
|
|
return { sel: value ? `[${attr}="${value}"]` : `[${attr}]`, node: host };
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
export function captureFocus(el, editing) {
|
||
|
|
if (!editing) return null;
|
||
|
|
const active = document.activeElement;
|
||
|
|
if (!active || !el.contains(active)) return null;
|
||
|
|
const anchor = focusAnchor(active);
|
||
|
|
if (!anchor) return null;
|
||
|
|
if (!hasSelection(anchor.node)) return { sel: anchor.sel, start: null, end: null };
|
||
|
|
return { sel: anchor.sel, start: anchor.node.selectionStart, end: anchor.node.selectionEnd };
|
||
|
|
}
|
||
|
|
|
||
|
|
export function restoreFocus(el, snap) {
|
||
|
|
if (!snap) return;
|
||
|
|
const field = el.querySelector(snap.sel);
|
||
|
|
if (!field || typeof field.focus !== 'function') return;
|
||
|
|
field.focus({ preventScroll: true });
|
||
|
|
if (snap.start == null || !hasSelection(field)) return;
|
||
|
|
try { field.setSelectionRange(snap.start, snap.end); } catch { }
|
||
|
|
}
|
||
|
|
|
||
|
|
const FOCUSABLE = 'input:not([disabled]):not([type="hidden"]), select:not([disabled]), textarea:not([disabled])';
|
||
|
|
export function focusFirstField(el) {
|
||
|
|
const row = el.querySelector('[data-edit-row]');
|
||
|
|
if (!row) return;
|
||
|
|
const field = row.querySelector(FOCUSABLE) || el.querySelector(`.edit-expand-row ${FOCUSABLE}`);
|
||
|
|
if (field) field.focus();
|
||
|
|
}
|