芝麻web文件管理V1.00
编辑当前文件:/home/digitalh/public_html/node_modules/@alpinejs/focus/src/index.js
import { createFocusTrap } from 'focus-trap' import { focusable, isFocusable } from 'tabbable' export default function (Alpine) { let lastFocused let currentFocused window.addEventListener('focusin', () => { lastFocused = currentFocused currentFocused = document.activeElement }) Alpine.magic('focus', el => { let within = el return { __noscroll: false, __wrapAround: false, within(el) { within = el; return this }, withoutScrolling() { this.__noscroll = true; return this }, noscroll() { this.__noscroll = true; return this }, withWrapAround() { this.__wrapAround = true; return this }, wrap() { return this.withWrapAround() }, focusable(el) { return isFocusable(el) }, previouslyFocused() { return lastFocused }, lastFocused() { return lastFocused }, focused() { return currentFocused }, focusables() { if (Array.isArray(within)) return within return focusable(within, { displayCheck: 'none' }) }, all() { return this.focusables() }, isFirst(el) { let els = this.all() return els[0] && els[0].isSameNode(el) }, isLast(el) { let els = this.all() return els.length && els.slice(-1)[0].isSameNode(el) }, getFirst() { return this.all()[0] }, getLast() { return this.all().slice(-1)[0] }, getNext() { let list = this.all() let current = document.activeElement // Can't find currently focusable element in list. if (list.indexOf(current) === -1) return // This is the last element in the list and we want to wrap around. if (this.__wrapAround && list.indexOf(current) === list.length - 1) { return list[0] } return list[list.indexOf(current) + 1] }, getPrevious() { let list = this.all() let current = document.activeElement // Can't find currently focusable element in list. if (list.indexOf(current) === -1) return // This is the first element in the list and we want to wrap around. if (this.__wrapAround && list.indexOf(current) === 0) { return list.slice(-1)[0] } return list[list.indexOf(current) - 1] }, first() { this.focus(this.getFirst()) }, last() { this.focus(this.getLast()) }, next() { this.focus(this.getNext()) }, previous() { this.focus(this.getPrevious()) }, prev() { return this.previous() }, focus(el) { if (! el) return setTimeout(() => { if (! el.hasAttribute('tabindex')) el.setAttribute('tabindex', '0') el.focus({ preventScroll: this._noscroll }) }) } } }) Alpine.directive('trap', Alpine.skipDuringClone( (el, { expression, modifiers }, { effect, evaluateLater, cleanup }) => { let evaluator = evaluateLater(expression) let oldValue = false let trap = createFocusTrap(el, { escapeDeactivates: false, allowOutsideClick: true, fallbackFocus: () => el, initialFocus: el.querySelector('[autofocus]') }) let undoInert = () => {} let undoDisableScrolling = () => {} const releaseFocus = () => { undoInert() undoInert = () => {} undoDisableScrolling() undoDisableScrolling = () => {} trap.deactivate({ returnFocus: !modifiers.includes('noreturn') }) } effect(() => evaluator(value => { if (oldValue === value) return // Start trapping. if (value && ! oldValue) { setTimeout(() => { if (modifiers.includes('inert')) undoInert = setInert(el) if (modifiers.includes('noscroll')) undoDisableScrolling = disableScrolling() trap.activate() }); } // Stop trapping. if (! value && oldValue) { releaseFocus() } oldValue = !! value })) cleanup(releaseFocus) }, // When cloning, we only want to add aria-hidden attributes to the // DOM and not try to actually trap, as trapping can mess with the // live DOM and isn't just isolated to the cloned DOM. (el, { expression, modifiers }, { evaluate }) => { if (modifiers.includes('inert') && evaluate(expression)) setInert(el) }, )) } function setInert(el) { let undos = [] crawlSiblingsUp(el, (sibling) => { let cache = sibling.hasAttribute('aria-hidden') sibling.setAttribute('aria-hidden', 'true') undos.push(() => cache || sibling.removeAttribute('aria-hidden')) }) return () => { while(undos.length) undos.pop()() } } function crawlSiblingsUp(el, callback) { if (el.isSameNode(document.body) || ! el.parentNode) return Array.from(el.parentNode.children).forEach(sibling => { if (sibling.isSameNode(el)) { crawlSiblingsUp(el.parentNode, callback) } else { callback(sibling) } }) } function disableScrolling() { let overflow = document.documentElement.style.overflow let paddingRight = document.documentElement.style.paddingRight let scrollbarWidth = window.innerWidth - document.documentElement.clientWidth document.documentElement.style.overflow = 'hidden' document.documentElement.style.paddingRight = `${scrollbarWidth}px` return () => { document.documentElement.style.overflow = overflow document.documentElement.style.paddingRight = paddingRight } }