@zag-js/tabbable
Advanced tools
Comparing version 0.0.0-dev-20230601120732 to 0.0.0-dev-20230605130234
@@ -1,13 +0,10 @@ | ||
import { IncludeContainerType } from './shared.js'; | ||
import { IncludeContainerType } from "./shared"; | ||
/** | ||
* Returns the focusable elements within the element | ||
*/ | ||
declare const getFocusables: (container: Pick<HTMLElement, "querySelectorAll"> | null, includeContainer?: IncludeContainerType) => HTMLElement[]; | ||
export declare const getFocusables: (container: Pick<HTMLElement, "querySelectorAll"> | null, includeContainer?: IncludeContainerType) => HTMLElement[]; | ||
/** | ||
* Whether this element is focusable | ||
*/ | ||
declare function isFocusable(element: HTMLElement | null): element is HTMLElement; | ||
declare function getFirstFocusable(container: HTMLElement, includeContainer?: IncludeContainerType): HTMLElement; | ||
export { getFirstFocusable, getFocusables, isFocusable }; | ||
export declare function isFocusable(element: HTMLElement | null): element is HTMLElement; | ||
export declare function getFirstFocusable(container: HTMLElement, includeContainer?: IncludeContainerType): HTMLElement; |
@@ -1,46 +0,13 @@ | ||
"use strict"; | ||
var __defProp = Object.defineProperty; | ||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
var __getOwnPropNames = Object.getOwnPropertyNames; | ||
var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
var __export = (target, all) => { | ||
for (var name in all) | ||
__defProp(target, name, { get: all[name], enumerable: true }); | ||
}; | ||
var __copyProps = (to, from, except, desc) => { | ||
if (from && typeof from === "object" || typeof from === "function") { | ||
for (let key of __getOwnPropNames(from)) | ||
if (!__hasOwnProp.call(to, key) && key !== except) | ||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
} | ||
return to; | ||
}; | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
'use strict'; | ||
// src/focusable.ts | ||
var focusable_exports = {}; | ||
__export(focusable_exports, { | ||
getFirstFocusable: () => getFirstFocusable, | ||
getFocusables: () => getFocusables, | ||
isFocusable: () => isFocusable | ||
}); | ||
module.exports = __toCommonJS(focusable_exports); | ||
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
// src/shared.ts | ||
var isHTMLElement = (element) => typeof element === "object" && element !== null && element.nodeType === 1; | ||
var isFrame = (element) => isHTMLElement(element) && element.tagName === "IFRAME"; | ||
function isVisible(el) { | ||
if (!isHTMLElement(el)) | ||
return false; | ||
return el.offsetWidth > 0 || el.offsetHeight > 0 || el.getClientRects().length > 0; | ||
} | ||
var focusableSelector = "input:not([type='hidden']):not([disabled]), select:not([disabled]), textarea:not([disabled]), a[href], button:not([disabled]), [tabindex], iframe, object, embed, area[href], audio[controls], video[controls], [contenteditable]:not([contenteditable='false']), details > summary:first-of-type"; | ||
const shared = require('./shared.js'); | ||
// src/focusable.ts | ||
var getFocusables = (container, includeContainer = false) => { | ||
const getFocusables = (container, includeContainer = false) => { | ||
if (!container) | ||
return []; | ||
const elements = Array.from(container.querySelectorAll(focusableSelector)); | ||
const elements = Array.from(container.querySelectorAll(shared.focusableSelector)); | ||
const include = includeContainer == true || includeContainer == "if-empty" && elements.length === 0; | ||
if (include && isHTMLElement(container) && isFocusable(container)) { | ||
if (include && shared.isHTMLElement(container) && isFocusable(container)) { | ||
elements.unshift(container); | ||
@@ -50,3 +17,3 @@ } | ||
focusableElements.forEach((element, i) => { | ||
if (isFrame(element) && element.contentDocument) { | ||
if (shared.isFrame(element) && element.contentDocument) { | ||
const frameBody = element.contentDocument.body; | ||
@@ -61,3 +28,3 @@ focusableElements.splice(i, 1, ...getFocusables(frameBody)); | ||
return false; | ||
return element.matches(focusableSelector) && isVisible(element); | ||
return element.matches(shared.focusableSelector) && shared.isVisible(element); | ||
} | ||
@@ -68,7 +35,5 @@ function getFirstFocusable(container, includeContainer) { | ||
} | ||
// Annotate the CommonJS export names for ESM import in node: | ||
0 && (module.exports = { | ||
getFirstFocusable, | ||
getFocusables, | ||
isFocusable | ||
}); | ||
exports.getFirstFocusable = getFirstFocusable; | ||
exports.getFocusables = getFocusables; | ||
exports.isFocusable = isFocusable; |
@@ -1,4 +0,3 @@ | ||
export { proxyTabFocus } from './proxy-tab-focus.js'; | ||
export { getFirstFocusable, getFocusables, isFocusable } from './focusable.js'; | ||
export { getFirstTabbable, getLastTabbable, getNextTabbable, getTabbableEdges, getTabbables, isTabbable } from './tabbable.js'; | ||
import './shared.js'; | ||
export { proxyTabFocus } from "./proxy-tab-focus"; | ||
export { getFirstFocusable, getFocusables, isFocusable } from "./focusable"; | ||
export { isTabbable, getFirstTabbable, getLastTabbable, getNextTabbable, getTabbableEdges, getTabbables, } from "./tabbable"; |
@@ -1,186 +0,20 @@ | ||
"use strict"; | ||
var __defProp = Object.defineProperty; | ||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
var __getOwnPropNames = Object.getOwnPropertyNames; | ||
var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
var __export = (target, all) => { | ||
for (var name in all) | ||
__defProp(target, name, { get: all[name], enumerable: true }); | ||
}; | ||
var __copyProps = (to, from, except, desc) => { | ||
if (from && typeof from === "object" || typeof from === "function") { | ||
for (let key of __getOwnPropNames(from)) | ||
if (!__hasOwnProp.call(to, key) && key !== except) | ||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
} | ||
return to; | ||
}; | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
'use strict'; | ||
// src/index.ts | ||
var src_exports = {}; | ||
__export(src_exports, { | ||
getFirstFocusable: () => getFirstFocusable, | ||
getFirstTabbable: () => getFirstTabbable, | ||
getFocusables: () => getFocusables, | ||
getLastTabbable: () => getLastTabbable, | ||
getNextTabbable: () => getNextTabbable, | ||
getTabbableEdges: () => getTabbableEdges, | ||
getTabbables: () => getTabbables, | ||
isFocusable: () => isFocusable, | ||
isTabbable: () => isTabbable, | ||
proxyTabFocus: () => proxyTabFocus | ||
}); | ||
module.exports = __toCommonJS(src_exports); | ||
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
// src/proxy-tab-focus.ts | ||
var import_dom_query = require("@zag-js/dom-query"); | ||
const proxyTabFocus = require('./proxy-tab-focus.js'); | ||
const focusable = require('./focusable.js'); | ||
const tabbable = require('./tabbable.js'); | ||
// src/shared.ts | ||
var isHTMLElement = (element) => typeof element === "object" && element !== null && element.nodeType === 1; | ||
var isFrame = (element) => isHTMLElement(element) && element.tagName === "IFRAME"; | ||
function isVisible(el) { | ||
if (!isHTMLElement(el)) | ||
return false; | ||
return el.offsetWidth > 0 || el.offsetHeight > 0 || el.getClientRects().length > 0; | ||
} | ||
function hasNegativeTabIndex(element) { | ||
const tabIndex = parseInt(element.getAttribute("tabindex") || "0", 10); | ||
return tabIndex < 0; | ||
} | ||
var focusableSelector = "input:not([type='hidden']):not([disabled]), select:not([disabled]), textarea:not([disabled]), a[href], button:not([disabled]), [tabindex], iframe, object, embed, area[href], audio[controls], video[controls], [contenteditable]:not([contenteditable='false']), details > summary:first-of-type"; | ||
// src/focusable.ts | ||
var getFocusables = (container, includeContainer = false) => { | ||
if (!container) | ||
return []; | ||
const elements = Array.from(container.querySelectorAll(focusableSelector)); | ||
const include = includeContainer == true || includeContainer == "if-empty" && elements.length === 0; | ||
if (include && isHTMLElement(container) && isFocusable(container)) { | ||
elements.unshift(container); | ||
} | ||
const focusableElements = elements.filter(isFocusable); | ||
focusableElements.forEach((element, i) => { | ||
if (isFrame(element) && element.contentDocument) { | ||
const frameBody = element.contentDocument.body; | ||
focusableElements.splice(i, 1, ...getFocusables(frameBody)); | ||
} | ||
}); | ||
return focusableElements; | ||
}; | ||
function isFocusable(element) { | ||
if (!element || element.closest("[inert]")) | ||
return false; | ||
return element.matches(focusableSelector) && isVisible(element); | ||
} | ||
function getFirstFocusable(container, includeContainer) { | ||
const [first] = getFocusables(container, includeContainer); | ||
return first || null; | ||
} | ||
// src/tabbable.ts | ||
function getTabbables(container, includeContainer) { | ||
if (!container) | ||
return []; | ||
const elements = Array.from(container.querySelectorAll(focusableSelector)); | ||
const tabbableElements = elements.filter(isTabbable); | ||
if (includeContainer && isTabbable(container)) { | ||
tabbableElements.unshift(container); | ||
} | ||
tabbableElements.forEach((element, i) => { | ||
if (isFrame(element) && element.contentDocument) { | ||
const frameBody = element.contentDocument.body; | ||
const allFrameTabbable = getTabbables(frameBody); | ||
tabbableElements.splice(i, 1, ...allFrameTabbable); | ||
} | ||
}); | ||
if (!tabbableElements.length && includeContainer) { | ||
return elements; | ||
} | ||
return tabbableElements; | ||
} | ||
function isTabbable(el) { | ||
if (el != null && el.tabIndex > 0) | ||
return true; | ||
return isFocusable(el) && !hasNegativeTabIndex(el); | ||
} | ||
function getFirstTabbable(container, includeContainer) { | ||
const [first] = getTabbables(container, includeContainer); | ||
return first || null; | ||
} | ||
function getLastTabbable(container, includeContainer) { | ||
const elements = getTabbables(container, includeContainer); | ||
return elements[elements.length - 1] || null; | ||
} | ||
function getTabbableEdges(container, includeContainer) { | ||
const elements = getTabbables(container, includeContainer); | ||
const first = elements[0] || null; | ||
const last = elements[elements.length - 1] || null; | ||
return [first, last]; | ||
} | ||
function getNextTabbable(container, current) { | ||
const tabbables = getTabbables(container); | ||
const doc = container?.ownerDocument || document; | ||
const currentElement = current ?? doc.activeElement; | ||
if (!currentElement) | ||
return null; | ||
const index = tabbables.indexOf(currentElement); | ||
return tabbables[index + 1] || null; | ||
} | ||
// src/proxy-tab-focus.ts | ||
function proxyTabFocusImpl(container, options = {}) { | ||
const { triggerElement, onFocus } = options; | ||
const doc = container?.ownerDocument || document; | ||
const body = doc.body; | ||
function onKeyDown(event) { | ||
if (event.key !== "Tab") | ||
return; | ||
let elementToFocus = null; | ||
const [firstTabbable, lastTabbable] = getTabbableEdges(container, true); | ||
const noTabbableElements = !firstTabbable && !lastTabbable; | ||
if (event.shiftKey && (doc.activeElement === firstTabbable || noTabbableElements)) { | ||
elementToFocus = triggerElement; | ||
} else if (!event.shiftKey && doc.activeElement === triggerElement) { | ||
elementToFocus = firstTabbable; | ||
} else if (!event.shiftKey && (doc.activeElement === lastTabbable || noTabbableElements)) { | ||
elementToFocus = getNextTabbable(body, triggerElement); | ||
} | ||
if (!elementToFocus) | ||
return; | ||
event.preventDefault(); | ||
onFocus?.(elementToFocus) ?? elementToFocus.focus(); | ||
} | ||
doc?.addEventListener("keydown", onKeyDown, true); | ||
return () => { | ||
doc?.removeEventListener("keydown", onKeyDown, true); | ||
}; | ||
} | ||
function proxyTabFocus(container, options) { | ||
const { defer, triggerElement, ...restOptions } = options; | ||
const func = defer ? import_dom_query.raf : (v) => v(); | ||
const cleanups = []; | ||
cleanups.push( | ||
func(() => { | ||
const node = typeof container === "function" ? container() : container; | ||
const trigger = typeof triggerElement === "function" ? triggerElement() : triggerElement; | ||
cleanups.push(proxyTabFocusImpl(node, { triggerElement: trigger, ...restOptions })); | ||
}) | ||
); | ||
return () => { | ||
cleanups.forEach((fn) => fn?.()); | ||
}; | ||
} | ||
// Annotate the CommonJS export names for ESM import in node: | ||
0 && (module.exports = { | ||
getFirstFocusable, | ||
getFirstTabbable, | ||
getFocusables, | ||
getLastTabbable, | ||
getNextTabbable, | ||
getTabbableEdges, | ||
getTabbables, | ||
isFocusable, | ||
isTabbable, | ||
proxyTabFocus | ||
}); | ||
exports.proxyTabFocus = proxyTabFocus.proxyTabFocus; | ||
exports.getFirstFocusable = focusable.getFirstFocusable; | ||
exports.getFocusables = focusable.getFocusables; | ||
exports.isFocusable = focusable.isFocusable; | ||
exports.getFirstTabbable = tabbable.getFirstTabbable; | ||
exports.getLastTabbable = tabbable.getLastTabbable; | ||
exports.getNextTabbable = tabbable.getNextTabbable; | ||
exports.getTabbableEdges = tabbable.getTabbableEdges; | ||
exports.getTabbables = tabbable.getTabbables; | ||
exports.isTabbable = tabbable.isTabbable; |
@@ -8,4 +8,3 @@ type MaybeElement = HTMLElement | null; | ||
}; | ||
declare function proxyTabFocus(container: NodeOrFn, options: ProxyTabFocusOptions<NodeOrFn>): () => void; | ||
export { proxyTabFocus }; | ||
export declare function proxyTabFocus(container: NodeOrFn, options: ProxyTabFocusOptions<NodeOrFn>): () => void; | ||
export {}; |
@@ -1,92 +0,8 @@ | ||
"use strict"; | ||
var __defProp = Object.defineProperty; | ||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
var __getOwnPropNames = Object.getOwnPropertyNames; | ||
var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
var __export = (target, all) => { | ||
for (var name in all) | ||
__defProp(target, name, { get: all[name], enumerable: true }); | ||
}; | ||
var __copyProps = (to, from, except, desc) => { | ||
if (from && typeof from === "object" || typeof from === "function") { | ||
for (let key of __getOwnPropNames(from)) | ||
if (!__hasOwnProp.call(to, key) && key !== except) | ||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
} | ||
return to; | ||
}; | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
'use strict'; | ||
// src/proxy-tab-focus.ts | ||
var proxy_tab_focus_exports = {}; | ||
__export(proxy_tab_focus_exports, { | ||
proxyTabFocus: () => proxyTabFocus | ||
}); | ||
module.exports = __toCommonJS(proxy_tab_focus_exports); | ||
var import_dom_query = require("@zag-js/dom-query"); | ||
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
// src/shared.ts | ||
var isHTMLElement = (element) => typeof element === "object" && element !== null && element.nodeType === 1; | ||
var isFrame = (element) => isHTMLElement(element) && element.tagName === "IFRAME"; | ||
function isVisible(el) { | ||
if (!isHTMLElement(el)) | ||
return false; | ||
return el.offsetWidth > 0 || el.offsetHeight > 0 || el.getClientRects().length > 0; | ||
} | ||
function hasNegativeTabIndex(element) { | ||
const tabIndex = parseInt(element.getAttribute("tabindex") || "0", 10); | ||
return tabIndex < 0; | ||
} | ||
var focusableSelector = "input:not([type='hidden']):not([disabled]), select:not([disabled]), textarea:not([disabled]), a[href], button:not([disabled]), [tabindex], iframe, object, embed, area[href], audio[controls], video[controls], [contenteditable]:not([contenteditable='false']), details > summary:first-of-type"; | ||
const domQuery = require('@zag-js/dom-query'); | ||
const tabbable = require('./tabbable.js'); | ||
// src/focusable.ts | ||
function isFocusable(element) { | ||
if (!element || element.closest("[inert]")) | ||
return false; | ||
return element.matches(focusableSelector) && isVisible(element); | ||
} | ||
// src/tabbable.ts | ||
function getTabbables(container, includeContainer) { | ||
if (!container) | ||
return []; | ||
const elements = Array.from(container.querySelectorAll(focusableSelector)); | ||
const tabbableElements = elements.filter(isTabbable); | ||
if (includeContainer && isTabbable(container)) { | ||
tabbableElements.unshift(container); | ||
} | ||
tabbableElements.forEach((element, i) => { | ||
if (isFrame(element) && element.contentDocument) { | ||
const frameBody = element.contentDocument.body; | ||
const allFrameTabbable = getTabbables(frameBody); | ||
tabbableElements.splice(i, 1, ...allFrameTabbable); | ||
} | ||
}); | ||
if (!tabbableElements.length && includeContainer) { | ||
return elements; | ||
} | ||
return tabbableElements; | ||
} | ||
function isTabbable(el) { | ||
if (el != null && el.tabIndex > 0) | ||
return true; | ||
return isFocusable(el) && !hasNegativeTabIndex(el); | ||
} | ||
function getTabbableEdges(container, includeContainer) { | ||
const elements = getTabbables(container, includeContainer); | ||
const first = elements[0] || null; | ||
const last = elements[elements.length - 1] || null; | ||
return [first, last]; | ||
} | ||
function getNextTabbable(container, current) { | ||
const tabbables = getTabbables(container); | ||
const doc = container?.ownerDocument || document; | ||
const currentElement = current ?? doc.activeElement; | ||
if (!currentElement) | ||
return null; | ||
const index = tabbables.indexOf(currentElement); | ||
return tabbables[index + 1] || null; | ||
} | ||
// src/proxy-tab-focus.ts | ||
function proxyTabFocusImpl(container, options = {}) { | ||
@@ -100,3 +16,3 @@ const { triggerElement, onFocus } = options; | ||
let elementToFocus = null; | ||
const [firstTabbable, lastTabbable] = getTabbableEdges(container, true); | ||
const [firstTabbable, lastTabbable] = tabbable.getTabbableEdges(container, true); | ||
const noTabbableElements = !firstTabbable && !lastTabbable; | ||
@@ -108,3 +24,3 @@ if (event.shiftKey && (doc.activeElement === firstTabbable || noTabbableElements)) { | ||
} else if (!event.shiftKey && (doc.activeElement === lastTabbable || noTabbableElements)) { | ||
elementToFocus = getNextTabbable(body, triggerElement); | ||
elementToFocus = tabbable.getNextTabbable(body, triggerElement); | ||
} | ||
@@ -123,3 +39,3 @@ if (!elementToFocus) | ||
const { defer, triggerElement, ...restOptions } = options; | ||
const func = defer ? import_dom_query.raf : (v) => v(); | ||
const func = defer ? domQuery.raf : (v) => v(); | ||
const cleanups = []; | ||
@@ -137,5 +53,3 @@ cleanups.push( | ||
} | ||
// Annotate the CommonJS export names for ESM import in node: | ||
0 && (module.exports = { | ||
proxyTabFocus | ||
}); | ||
exports.proxyTabFocus = proxyTabFocus; |
@@ -1,8 +0,6 @@ | ||
declare const isHTMLElement: (element: any) => element is HTMLElement; | ||
declare const isFrame: (element: any) => element is HTMLIFrameElement; | ||
declare function isVisible(el: any): boolean; | ||
type IncludeContainerType = boolean | "if-empty"; | ||
declare function hasNegativeTabIndex(element: Element): boolean; | ||
declare const focusableSelector: string; | ||
export { IncludeContainerType, focusableSelector, hasNegativeTabIndex, isFrame, isHTMLElement, isVisible }; | ||
export declare const isHTMLElement: (element: any) => element is HTMLElement; | ||
export declare const isFrame: (element: any) => element is HTMLIFrameElement; | ||
export declare function isVisible(el: any): boolean; | ||
export type IncludeContainerType = boolean | "if-empty"; | ||
export declare function hasNegativeTabIndex(element: Element): boolean; | ||
export declare const focusableSelector: string; |
@@ -1,32 +0,7 @@ | ||
"use strict"; | ||
var __defProp = Object.defineProperty; | ||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
var __getOwnPropNames = Object.getOwnPropertyNames; | ||
var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
var __export = (target, all) => { | ||
for (var name in all) | ||
__defProp(target, name, { get: all[name], enumerable: true }); | ||
}; | ||
var __copyProps = (to, from, except, desc) => { | ||
if (from && typeof from === "object" || typeof from === "function") { | ||
for (let key of __getOwnPropNames(from)) | ||
if (!__hasOwnProp.call(to, key) && key !== except) | ||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
} | ||
return to; | ||
}; | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
'use strict'; | ||
// src/shared.ts | ||
var shared_exports = {}; | ||
__export(shared_exports, { | ||
focusableSelector: () => focusableSelector, | ||
hasNegativeTabIndex: () => hasNegativeTabIndex, | ||
isFrame: () => isFrame, | ||
isHTMLElement: () => isHTMLElement, | ||
isVisible: () => isVisible | ||
}); | ||
module.exports = __toCommonJS(shared_exports); | ||
var isHTMLElement = (element) => typeof element === "object" && element !== null && element.nodeType === 1; | ||
var isFrame = (element) => isHTMLElement(element) && element.tagName === "IFRAME"; | ||
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
const isHTMLElement = (element) => typeof element === "object" && element !== null && element.nodeType === 1; | ||
const isFrame = (element) => isHTMLElement(element) && element.tagName === "IFRAME"; | ||
function isVisible(el) { | ||
@@ -41,10 +16,8 @@ if (!isHTMLElement(el)) | ||
} | ||
var focusableSelector = "input:not([type='hidden']):not([disabled]), select:not([disabled]), textarea:not([disabled]), a[href], button:not([disabled]), [tabindex], iframe, object, embed, area[href], audio[controls], video[controls], [contenteditable]:not([contenteditable='false']), details > summary:first-of-type"; | ||
// Annotate the CommonJS export names for ESM import in node: | ||
0 && (module.exports = { | ||
focusableSelector, | ||
hasNegativeTabIndex, | ||
isFrame, | ||
isHTMLElement, | ||
isVisible | ||
}); | ||
const focusableSelector = "input:not([type='hidden']):not([disabled]), select:not([disabled]), textarea:not([disabled]), a[href], button:not([disabled]), [tabindex], iframe, object, embed, area[href], audio[controls], video[controls], [contenteditable]:not([contenteditable='false']), details > summary:first-of-type"; | ||
exports.focusableSelector = focusableSelector; | ||
exports.hasNegativeTabIndex = hasNegativeTabIndex; | ||
exports.isFrame = isFrame; | ||
exports.isHTMLElement = isHTMLElement; | ||
exports.isVisible = isVisible; |
@@ -1,28 +0,25 @@ | ||
import { IncludeContainerType } from './shared.js'; | ||
import { IncludeContainerType } from "./shared"; | ||
/** | ||
* Returns the tabbable elements within the element | ||
*/ | ||
declare function getTabbables(container: HTMLElement | null, includeContainer?: IncludeContainerType): HTMLElement[]; | ||
export declare function getTabbables(container: HTMLElement | null, includeContainer?: IncludeContainerType): HTMLElement[]; | ||
/** | ||
* Whether this element is tabbable | ||
*/ | ||
declare function isTabbable(el: HTMLElement | null): el is HTMLElement; | ||
export declare function isTabbable(el: HTMLElement | null): el is HTMLElement; | ||
/** | ||
* Returns the first focusable element within the element | ||
*/ | ||
declare function getFirstTabbable(container: HTMLElement | null, includeContainer?: IncludeContainerType): HTMLElement; | ||
export declare function getFirstTabbable(container: HTMLElement | null, includeContainer?: IncludeContainerType): HTMLElement; | ||
/** | ||
* Returns the last focusable element within the element | ||
*/ | ||
declare function getLastTabbable(container: HTMLElement | null, includeContainer?: IncludeContainerType): HTMLElement; | ||
export declare function getLastTabbable(container: HTMLElement | null, includeContainer?: IncludeContainerType): HTMLElement; | ||
/** | ||
* Returns the first and last focusable elements within the element | ||
*/ | ||
declare function getTabbableEdges(container: HTMLElement | null, includeContainer?: IncludeContainerType): HTMLElement[]; | ||
export declare function getTabbableEdges(container: HTMLElement | null, includeContainer?: IncludeContainerType): HTMLElement[]; | ||
/** | ||
* Returns the next tabbable element after the current element | ||
*/ | ||
declare function getNextTabbable(container: HTMLElement | null, current?: HTMLElement | null): HTMLElement | null; | ||
export { getFirstTabbable, getLastTabbable, getNextTabbable, getTabbableEdges, getTabbables, isTabbable }; | ||
export declare function getNextTabbable(container: HTMLElement | null, current?: HTMLElement | null): HTMLElement | null; |
@@ -1,58 +0,12 @@ | ||
"use strict"; | ||
var __defProp = Object.defineProperty; | ||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
var __getOwnPropNames = Object.getOwnPropertyNames; | ||
var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
var __export = (target, all) => { | ||
for (var name in all) | ||
__defProp(target, name, { get: all[name], enumerable: true }); | ||
}; | ||
var __copyProps = (to, from, except, desc) => { | ||
if (from && typeof from === "object" || typeof from === "function") { | ||
for (let key of __getOwnPropNames(from)) | ||
if (!__hasOwnProp.call(to, key) && key !== except) | ||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
} | ||
return to; | ||
}; | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
'use strict'; | ||
// src/tabbable.ts | ||
var tabbable_exports = {}; | ||
__export(tabbable_exports, { | ||
getFirstTabbable: () => getFirstTabbable, | ||
getLastTabbable: () => getLastTabbable, | ||
getNextTabbable: () => getNextTabbable, | ||
getTabbableEdges: () => getTabbableEdges, | ||
getTabbables: () => getTabbables, | ||
isTabbable: () => isTabbable | ||
}); | ||
module.exports = __toCommonJS(tabbable_exports); | ||
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
// src/shared.ts | ||
var isHTMLElement = (element) => typeof element === "object" && element !== null && element.nodeType === 1; | ||
var isFrame = (element) => isHTMLElement(element) && element.tagName === "IFRAME"; | ||
function isVisible(el) { | ||
if (!isHTMLElement(el)) | ||
return false; | ||
return el.offsetWidth > 0 || el.offsetHeight > 0 || el.getClientRects().length > 0; | ||
} | ||
function hasNegativeTabIndex(element) { | ||
const tabIndex = parseInt(element.getAttribute("tabindex") || "0", 10); | ||
return tabIndex < 0; | ||
} | ||
var focusableSelector = "input:not([type='hidden']):not([disabled]), select:not([disabled]), textarea:not([disabled]), a[href], button:not([disabled]), [tabindex], iframe, object, embed, area[href], audio[controls], video[controls], [contenteditable]:not([contenteditable='false']), details > summary:first-of-type"; | ||
const focusable = require('./focusable.js'); | ||
const shared = require('./shared.js'); | ||
// src/focusable.ts | ||
function isFocusable(element) { | ||
if (!element || element.closest("[inert]")) | ||
return false; | ||
return element.matches(focusableSelector) && isVisible(element); | ||
} | ||
// src/tabbable.ts | ||
function getTabbables(container, includeContainer) { | ||
if (!container) | ||
return []; | ||
const elements = Array.from(container.querySelectorAll(focusableSelector)); | ||
const elements = Array.from(container.querySelectorAll(shared.focusableSelector)); | ||
const tabbableElements = elements.filter(isTabbable); | ||
@@ -63,3 +17,3 @@ if (includeContainer && isTabbable(container)) { | ||
tabbableElements.forEach((element, i) => { | ||
if (isFrame(element) && element.contentDocument) { | ||
if (shared.isFrame(element) && element.contentDocument) { | ||
const frameBody = element.contentDocument.body; | ||
@@ -78,3 +32,3 @@ const allFrameTabbable = getTabbables(frameBody); | ||
return true; | ||
return isFocusable(el) && !hasNegativeTabIndex(el); | ||
return focusable.isFocusable(el) && !shared.hasNegativeTabIndex(el); | ||
} | ||
@@ -104,10 +58,8 @@ function getFirstTabbable(container, includeContainer) { | ||
} | ||
// Annotate the CommonJS export names for ESM import in node: | ||
0 && (module.exports = { | ||
getFirstTabbable, | ||
getLastTabbable, | ||
getNextTabbable, | ||
getTabbableEdges, | ||
getTabbables, | ||
isTabbable | ||
}); | ||
exports.getFirstTabbable = getFirstTabbable; | ||
exports.getLastTabbable = getLastTabbable; | ||
exports.getNextTabbable = getNextTabbable; | ||
exports.getTabbableEdges = getTabbableEdges; | ||
exports.getTabbables = getTabbables; | ||
exports.isTabbable = isTabbable; |
{ | ||
"name": "@zag-js/tabbable", | ||
"version": "0.0.0-dev-20230601120732", | ||
"version": "0.0.0-dev-20230605130234", | ||
"description": "Small utility that returns an array of all* tabbable DOM nodes within a containing node.", | ||
@@ -31,3 +31,3 @@ "keywords": [ | ||
"dependencies": { | ||
"@zag-js/dom-query": "0.0.0-dev-20230601120732" | ||
"@zag-js/dom-query": "0.0.0-dev-20230605130234" | ||
}, | ||
@@ -45,11 +45,6 @@ "module": "dist/index.mjs", | ||
"scripts": { | ||
"build-fast": "tsup src", | ||
"start": "pnpm build --watch", | ||
"build": "tsup src --dts", | ||
"test": "jest --config ../../../jest.config.js --rootDir . --passWithNoTests", | ||
"build": "vite build -c ../../../vite.config.ts", | ||
"lint": "eslint src --ext .ts,.tsx", | ||
"test-ci": "pnpm test --ci --runInBand", | ||
"test-watch": "pnpm test --watch -u", | ||
"typecheck": "tsc --noEmit" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
26661
23
554
1
+ Added@zag-js/dom-query@0.0.0-dev-20230605130234(transitive)
- Removed@zag-js/dom-query@0.0.0-dev-20230601120732(transitive)