@flux-ui/internals 3.0.0-next.56 → 3.0.0-next.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -8,13 +8,13 @@ Built with [`tsdown`](https://github.com/rolldown/tsdown).
|
|
|
8
8
|
|
|
9
9
|
The package exposes four sub-entry points alongside the root export:
|
|
10
10
|
|
|
11
|
-
| Entry
|
|
12
|
-
|
|
13
|
-
| `@flux-ui/internals`
|
|
14
|
-
| `@flux-ui/internals/composable` | `useCalendar`, `useEventListener`, `useFocusTrap`, `useFocusZone`, `useInView`, `useRemembered`, `useScrollEdges`, `useScrollPosition`, …
|
|
15
|
-
| `@flux-ui/internals/data`
|
|
16
|
-
| `@flux-ui/internals/directive`
|
|
17
|
-
| `@flux-ui/internals/util`
|
|
11
|
+
| Entry | Contents |
|
|
12
|
+
|---------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
13
|
+
| `@flux-ui/internals` | Re-exports of every entry below. |
|
|
14
|
+
| `@flux-ui/internals/composable` | `useCalendar`, `useEventListener`, `useFocusTrap`, `useFocusZone`, `useInView`, `useRemembered`, `useScrollEdges`, `useScrollPosition`, … |
|
|
15
|
+
| `@flux-ui/internals/data` | Data helpers — e.g. color utilities. |
|
|
16
|
+
| `@flux-ui/internals/directive` | Vue directives — `focusTrap`, `heightTransition`. |
|
|
17
|
+
| `@flux-ui/internals/util` | Focus helpers (`wrapFocus`, `getFocusableElement(s)`, `getKeyboardFocusableElements`, `getBidirectionalFocusElement`), `flattenVNodeTree`, `animationFrameDebounce`, `warn`, … |
|
|
18
18
|
|
|
19
19
|
## ⭐️ Prerequisites
|
|
20
20
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util-CwaOsSvo.js","names":["getFocusableElements","getFocusableElements","#traps","#listeners"],"sources":["../src/util/animationFrameDebounce.ts","../src/util/flattenVNodeTree.ts","../src/util/getFocusableElements.ts","../src/util/getBidirectionalFocusElement.ts","../src/util/getComponentName.ts","../src/util/getComponentProps.ts","../src/util/getExposedRef.ts","../src/util/getFocusableElement.ts","../src/util/getKeyboardFocusableElements.ts","../src/util/unrefTemplateElement.ts","../src/util/warn.ts","../src/util/wrapFocus.ts","../src/util/focusTrap.ts","../src/util/index.ts"],"sourcesContent":["import type { FluxMaybePromise } from '@flux-ui/types';\n\nexport default function <T extends () => FluxMaybePromise<void>>(fn: T): T {\n if (typeof requestAnimationFrame === 'undefined') {\n return (() => {}) as T;\n }\n\n let animationFrame = 0;\n\n return (() => {\n cancelAnimationFrame(animationFrame);\n animationFrame = requestAnimationFrame(fn);\n }) as T;\n}\n","import type { VNode } from 'vue';\nimport { Fragment } from 'vue';\n\nexport default function (vnodes: VNode[]): VNode[] {\n const flattened: VNode[] = [];\n\n for (const vnode of vnodes) {\n if (vnode.type === Fragment && Array.isArray(vnode.children)) {\n flattened.push(...(vnode.children as VNode[]));\n continue;\n }\n\n flattened.push(vnode);\n }\n\n return flattened;\n}\n","import { isHtmlElement } from '@basmilius/utils';\n\nconst FOCUSABLE_ELEMENTS = [\n 'a:not([disabled])',\n 'button:not([disabled])',\n 'input[type=checkbox]:not([disabled])',\n 'input[type=radio]:not([disabled])',\n 'input[type=text]:not([disabled])',\n '[tabindex]:not([disabled]):not([tabindex=\"-1\"])'\n].join(',');\n\nexport default function (container: HTMLElement): HTMLElement[] {\n return Array.from(container.querySelectorAll(FOCUSABLE_ELEMENTS))\n .filter(isHtmlElement)\n .filter(elm => elm.offsetWidth > 0 || elm.offsetHeight > 0 || elm === document.activeElement);\n}\n","import getFocusableElements from './getFocusableElements';\n\nexport default function (container: HTMLElement, currentElement: HTMLElement, direction: 'up' | 'down' | 'left' | 'right'): HTMLElement | null {\n const elements = getFocusableElements(container);\n const currentIndex = elements.indexOf(currentElement);\n\n if (currentIndex === -1) {\n return null;\n }\n\n const elementInfos = getBidirectionalInfoForElements(elements);\n\n calculateBidirectionalDistances(elementInfos, currentIndex, direction);\n\n let candidate = determineBidirectionalCandidate(currentIndex, direction, elementInfos, elements);\n\n if (!candidate) {\n if (direction === 'up' || direction === 'left') {\n candidate = elements[currentIndex - 1];\n }\n\n if (direction === 'down' || direction === 'right') {\n candidate = elements[currentIndex + 1];\n }\n }\n\n return candidate;\n}\n\nfunction calculateBidirectionalDistances(elementInfos: BidirectionalInfo[], currentIndex: number, direction: 'up' | 'down' | 'left' | 'right'): void {\n const current = elementInfos[currentIndex];\n\n elementInfos.forEach(r => {\n let point = r.center;\n\n switch (direction) {\n case 'up':\n point = {x: point.x, y: r.top + r.height};\n break;\n\n case 'down':\n point = {x: point.x, y: r.top};\n break;\n\n case 'left':\n point = {x: r.left + r.width, y: point.y};\n break;\n\n case 'right':\n point = {x: r.left, y: point.y};\n break;\n }\n\n r.distance = Math.sqrt(Math.pow(current.center.x - point.x, 2) + Math.pow(current.center.y - point.y, 2));\n });\n}\n\nfunction determineBidirectionalCandidate(currentIndex: number, direction: 'up' | 'down' | 'left' | 'right', elementInfos: BidirectionalInfo[], elements: HTMLElement[]): HTMLElement | null {\n const current = elementInfos[currentIndex];\n let distances: number[] = [];\n\n switch (direction) {\n case 'up':\n distances = elementInfos.map((r, index) => index === currentIndex || r.top + r.height > current.top ? Number.MAX_SAFE_INTEGER : r.distance);\n break;\n\n case 'down':\n distances = elementInfos.map((r, index) => index === currentIndex || r.top < current.top + current.height ? Number.MAX_SAFE_INTEGER : r.distance);\n break;\n\n case 'left':\n distances = elementInfos.map((r, index) => index === currentIndex || r.left + r.width > current.left ? Number.MAX_SAFE_INTEGER : r.distance);\n break;\n\n case 'right':\n distances = elementInfos.map((r, index) => index === currentIndex || r.left < current.left + current.width ? Number.MAX_SAFE_INTEGER : r.distance);\n break;\n }\n\n const candidateIndex = distances.indexOf(Math.min(...distances));\n\n if (distances[candidateIndex] !== Number.MAX_SAFE_INTEGER) {\n return elements[candidateIndex];\n }\n\n return null;\n}\n\nfunction getBidirectionalInfoForElements(elements: HTMLElement[]): BidirectionalInfo[] {\n return elements\n .map(elm => elm.getBoundingClientRect())\n .map(rect => ({\n height: rect.height,\n width: rect.width,\n top: rect.top,\n left: rect.left,\n right: rect.right,\n bottom: rect.bottom,\n center: {\n x: rect.left + rect.width / 2,\n y: rect.top + rect.height / 2\n },\n distance: 0\n }));\n}\n\ntype BidirectionalInfo = Omit<DOMRect, 'x' | 'y' | 'toJSON'> & {\n center: { x: number; y: number; };\n distance: number;\n}\n","import type { VNode } from 'vue';\n\nexport default function (component: ExtendedVNode): string {\n let name = 'UnknownComponent';\n\n if (component.type && component.type.__name) {\n name = component.type.__name;\n }\n\n return name;\n}\n\ntype ExtendedVNode = {\n readonly type: VNode['type'] & {\n readonly __name?: string;\n };\n}\n","import { camelCase } from 'lodash-es';\n\nexport default function <T extends object>(component: any): T {\n return Object.fromEntries(\n Object.entries(component.props ?? {})\n .map(([key, value]) => [camelCase(key), value])\n ) as T;\n}\n","import type { ComponentInternalInstance, Ref } from 'vue';\n\nexport default function <T>(instance: ComponentInternalInstance, key: string): Ref<T> {\n if (!instance.exposed || !(key in instance.exposed)) {\n throw new Error(`'${key}' was not exposed by the component.`);\n }\n\n return instance.exposed[key];\n}\n","import { isHtmlElement } from '@basmilius/utils';\nimport getFocusableElements from './getFocusableElements';\n\nexport default function (container: HTMLElement, direction: number, activeElement: HTMLElement | undefined = undefined): HTMLElement | undefined {\n const elements = getFocusableElements(container);\n const focusedElement = activeElement || document.activeElement;\n\n if (!focusedElement || !isHtmlElement(focusedElement))\n return elements[0] || undefined;\n\n const currentIndex = elements.indexOf(focusedElement);\n\n return elements[currentIndex + direction] || undefined;\n}\n","export default function (root: HTMLElement): HTMLElement[] {\n return Array.from<HTMLElement>(root.querySelectorAll('a[href], button, input, textarea, select, details, [tabindex]:not([tabindex=\"-1\"])'))\n .filter(elm => !elm.hasAttribute('disabled') || elm.getAttribute('disabled') !== 'true')\n .filter(elm => !elm.hasAttribute('aria-disabled') || elm.getAttribute('aria-disabled') !== 'true');\n}\n","import { isHtmlElement } from '@basmilius/utils';\nimport { ComponentPublicInstance, ShallowRef, unref } from 'vue';\n\nexport type TemplateElement<TElement extends HTMLElement> = ComponentPublicInstance<any, any, any, any, any, any, any, any, any, any, any, any, any, any, TElement> | TElement | null;\nexport type TemplateRef<TElement extends HTMLElement> = Readonly<ShallowRef<TemplateElement<TElement>>>;\n\nexport default function <T extends HTMLElement>(ref: TemplateRef<T>): T | null {\n const value = unref(ref);\n\n if (isHtmlElement(value)) {\n return value as T;\n }\n\n return value?.$el;\n}\n","export default function (...data: any): void {\n console.warn('[Flux]', ...data);\n}\n","export default function (elm: HTMLElement, targetElm: Element, forceFirst: boolean = false): void {\n const walker = createFocusWalker(elm);\n const position = targetElm.compareDocumentPosition(elm);\n let wrappedTarget: HTMLElement | null;\n\n if (position && Node.DOCUMENT_POSITION_PRECEDING || forceFirst) {\n wrappedTarget = walker.firstChild() as HTMLElement | null;\n } else {\n wrappedTarget = walker.lastChild() as HTMLElement | null;\n }\n\n const newFocus = wrappedTarget !== null ? wrappedTarget : elm;\n newFocus.focus();\n}\n\nfunction createFocusWalker(elm: HTMLElement): TreeWalker {\n return document.createTreeWalker(elm, NodeFilter.SHOW_ELEMENT, {\n acceptNode: (node: HTMLButtonElement) => node.tabIndex >= 0 && !node.disabled ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP\n });\n}\n","class FocusTrapLockStack {\n get active(): boolean {\n return this.current?.isEnabled ?? false;\n }\n\n get current(): FocusTrap | null {\n return this.#traps[this.#traps.length - 1] ?? null;\n }\n\n #listeners: FocusTrapListener[] = [];\n #traps: FocusTrap[] = [];\n\n add(id: FocusTrap['id'], setEnabled: FocusTrap['setEnabled'], autoFocus: boolean = true): void {\n const trap: FocusTrap = {id, setEnabled, isEnabled: true};\n this.current && this.toggle(this.current, false);\n this.#traps.push(trap);\n\n if (autoFocus) {\n this.toggle(trap, true);\n this.emit();\n }\n }\n\n remove(id: FocusTrap['id']): void {\n const trap = this.#traps.find(t => t.id === id);\n trap && this.toggle(trap, false);\n\n const current = this.current;\n const wasCurrent = current?.id === id;\n this.#traps = this.#traps.filter(t => t.id !== id);\n\n wasCurrent && this.current && this.toggle(this.current, true);\n this.emit();\n }\n\n emit(): void {\n this.#listeners.forEach(listener => listener(this.active, this.#traps));\n }\n\n subscribe(listener: FocusTrapListener): () => void {\n this.#listeners.push(listener);\n listener(this.active, this.#traps);\n\n return () => this.#listeners = this.#listeners.filter(l => l !== listener);\n }\n\n toggle(trap: FocusTrap, isEnabled: boolean): void {\n trap.setEnabled(isEnabled);\n trap.isEnabled = isEnabled;\n }\n}\n\ninterface FocusTrap {\n id: string;\n isEnabled: boolean;\n\n setEnabled(isEnabled: boolean): void;\n}\n\nexport type FocusTrapListener = (isEnabled: boolean, focusTraps: FocusTrap[]) => void;\n\nconst _default: FocusTrapLockStack = new FocusTrapLockStack();\nexport default _default;\n","export { default as animationFrameDebounce } from './animationFrameDebounce';\nexport { default as flattenVNodeTree } from './flattenVNodeTree';\nexport { default as getBidirectionalFocusElement } from './getBidirectionalFocusElement';\nexport { default as getComponentName } from './getComponentName';\nexport { default as getComponentProps } from './getComponentProps';\nexport { default as getExposedRef } from './getExposedRef';\nexport { default as getFocusableElement } from './getFocusableElement';\nexport { default as getFocusableElements } from './getFocusableElements';\nexport { default as getKeyboardFocusableElements } from './getKeyboardFocusableElements';\nexport { default as unrefTemplateElement, type TemplateElement, type TemplateRef } from './unrefTemplateElement';\nexport { default as warn } from './warn';\nexport { default as wrapFocus } from './wrapFocus';\n\nexport { default as FOCUS_TRAP_LOCKS, type FocusTrapListener } from './focusTrap';\n\nexport const isSSR: boolean = !globalThis.document;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"util-CwaOsSvo.js","names":["getFocusableElements","getFocusableElements","#traps","#listeners"],"sources":["../src/util/animationFrameDebounce.ts","../src/util/flattenVNodeTree.ts","../src/util/getFocusableElements.ts","../src/util/getBidirectionalFocusElement.ts","../src/util/getComponentName.ts","../src/util/getComponentProps.ts","../src/util/getExposedRef.ts","../src/util/getFocusableElement.ts","../src/util/getKeyboardFocusableElements.ts","../src/util/unrefTemplateElement.ts","../src/util/warn.ts","../src/util/wrapFocus.ts","../src/util/focusTrap.ts","../src/util/index.ts"],"sourcesContent":["import type { FluxMaybePromise } from '@flux-ui/types';\n\nexport default function <T extends () => FluxMaybePromise<void>>(fn: T): T {\n if (typeof requestAnimationFrame === 'undefined') {\n return (() => {\n }) as T;\n }\n\n let animationFrame = 0;\n\n return (() => {\n cancelAnimationFrame(animationFrame);\n animationFrame = requestAnimationFrame(fn);\n }) as T;\n}\n","import type { VNode } from 'vue';\nimport { Fragment } from 'vue';\n\nexport default function (vnodes: VNode[]): VNode[] {\n const flattened: VNode[] = [];\n\n for (const vnode of vnodes) {\n if (vnode.type === Fragment && Array.isArray(vnode.children)) {\n flattened.push(...(vnode.children as VNode[]));\n continue;\n }\n\n flattened.push(vnode);\n }\n\n return flattened;\n}\n","import { isHtmlElement } from '@basmilius/utils';\n\nconst FOCUSABLE_ELEMENTS = [\n 'a:not([disabled])',\n 'button:not([disabled])',\n 'input[type=checkbox]:not([disabled])',\n 'input[type=radio]:not([disabled])',\n 'input[type=text]:not([disabled])',\n '[tabindex]:not([disabled]):not([tabindex=\"-1\"])'\n].join(',');\n\nexport default function (container: HTMLElement): HTMLElement[] {\n return Array.from(container.querySelectorAll(FOCUSABLE_ELEMENTS))\n .filter(isHtmlElement)\n .filter(elm => elm.offsetWidth > 0 || elm.offsetHeight > 0 || elm === document.activeElement);\n}\n","import getFocusableElements from './getFocusableElements';\n\nexport default function (container: HTMLElement, currentElement: HTMLElement, direction: 'up' | 'down' | 'left' | 'right'): HTMLElement | null {\n const elements = getFocusableElements(container);\n const currentIndex = elements.indexOf(currentElement);\n\n if (currentIndex === -1) {\n return null;\n }\n\n const elementInfos = getBidirectionalInfoForElements(elements);\n\n calculateBidirectionalDistances(elementInfos, currentIndex, direction);\n\n let candidate = determineBidirectionalCandidate(currentIndex, direction, elementInfos, elements);\n\n if (!candidate) {\n if (direction === 'up' || direction === 'left') {\n candidate = elements[currentIndex - 1];\n }\n\n if (direction === 'down' || direction === 'right') {\n candidate = elements[currentIndex + 1];\n }\n }\n\n return candidate;\n}\n\nfunction calculateBidirectionalDistances(elementInfos: BidirectionalInfo[], currentIndex: number, direction: 'up' | 'down' | 'left' | 'right'): void {\n const current = elementInfos[currentIndex];\n\n elementInfos.forEach(r => {\n let point = r.center;\n\n switch (direction) {\n case 'up':\n point = {x: point.x, y: r.top + r.height};\n break;\n\n case 'down':\n point = {x: point.x, y: r.top};\n break;\n\n case 'left':\n point = {x: r.left + r.width, y: point.y};\n break;\n\n case 'right':\n point = {x: r.left, y: point.y};\n break;\n }\n\n r.distance = Math.sqrt(Math.pow(current.center.x - point.x, 2) + Math.pow(current.center.y - point.y, 2));\n });\n}\n\nfunction determineBidirectionalCandidate(currentIndex: number, direction: 'up' | 'down' | 'left' | 'right', elementInfos: BidirectionalInfo[], elements: HTMLElement[]): HTMLElement | null {\n const current = elementInfos[currentIndex];\n let distances: number[] = [];\n\n switch (direction) {\n case 'up':\n distances = elementInfos.map((r, index) => index === currentIndex || r.top + r.height > current.top ? Number.MAX_SAFE_INTEGER : r.distance);\n break;\n\n case 'down':\n distances = elementInfos.map((r, index) => index === currentIndex || r.top < current.top + current.height ? Number.MAX_SAFE_INTEGER : r.distance);\n break;\n\n case 'left':\n distances = elementInfos.map((r, index) => index === currentIndex || r.left + r.width > current.left ? Number.MAX_SAFE_INTEGER : r.distance);\n break;\n\n case 'right':\n distances = elementInfos.map((r, index) => index === currentIndex || r.left < current.left + current.width ? Number.MAX_SAFE_INTEGER : r.distance);\n break;\n }\n\n const candidateIndex = distances.indexOf(Math.min(...distances));\n\n if (distances[candidateIndex] !== Number.MAX_SAFE_INTEGER) {\n return elements[candidateIndex];\n }\n\n return null;\n}\n\nfunction getBidirectionalInfoForElements(elements: HTMLElement[]): BidirectionalInfo[] {\n return elements\n .map(elm => elm.getBoundingClientRect())\n .map(rect => ({\n height: rect.height,\n width: rect.width,\n top: rect.top,\n left: rect.left,\n right: rect.right,\n bottom: rect.bottom,\n center: {\n x: rect.left + rect.width / 2,\n y: rect.top + rect.height / 2\n },\n distance: 0\n }));\n}\n\ntype BidirectionalInfo = Omit<DOMRect, 'x' | 'y' | 'toJSON'> & {\n center: { x: number; y: number; };\n distance: number;\n}\n","import type { VNode } from 'vue';\n\nexport default function (component: ExtendedVNode): string {\n let name = 'UnknownComponent';\n\n if (component.type && component.type.__name) {\n name = component.type.__name;\n }\n\n return name;\n}\n\ntype ExtendedVNode = {\n readonly type: VNode['type'] & {\n readonly __name?: string;\n };\n}\n","import { camelCase } from 'lodash-es';\n\nexport default function <T extends object>(component: any): T {\n return Object.fromEntries(\n Object.entries(component.props ?? {})\n .map(([key, value]) => [camelCase(key), value])\n ) as T;\n}\n","import type { ComponentInternalInstance, Ref } from 'vue';\n\nexport default function <T>(instance: ComponentInternalInstance, key: string): Ref<T> {\n if (!instance.exposed || !(key in instance.exposed)) {\n throw new Error(`'${key}' was not exposed by the component.`);\n }\n\n return instance.exposed[key];\n}\n","import { isHtmlElement } from '@basmilius/utils';\nimport getFocusableElements from './getFocusableElements';\n\nexport default function (container: HTMLElement, direction: number, activeElement: HTMLElement | undefined = undefined): HTMLElement | undefined {\n const elements = getFocusableElements(container);\n const focusedElement = activeElement || document.activeElement;\n\n if (!focusedElement || !isHtmlElement(focusedElement))\n return elements[0] || undefined;\n\n const currentIndex = elements.indexOf(focusedElement);\n\n return elements[currentIndex + direction] || undefined;\n}\n","export default function (root: HTMLElement): HTMLElement[] {\n return Array.from<HTMLElement>(root.querySelectorAll('a[href], button, input, textarea, select, details, [tabindex]:not([tabindex=\"-1\"])'))\n .filter(elm => !elm.hasAttribute('disabled') || elm.getAttribute('disabled') !== 'true')\n .filter(elm => !elm.hasAttribute('aria-disabled') || elm.getAttribute('aria-disabled') !== 'true');\n}\n","import { isHtmlElement } from '@basmilius/utils';\nimport { ComponentPublicInstance, ShallowRef, unref } from 'vue';\n\nexport type TemplateElement<TElement extends HTMLElement> = ComponentPublicInstance<any, any, any, any, any, any, any, any, any, any, any, any, any, any, TElement> | TElement | null;\nexport type TemplateRef<TElement extends HTMLElement> = Readonly<ShallowRef<TemplateElement<TElement>>>;\n\nexport default function <T extends HTMLElement>(ref: TemplateRef<T>): T | null {\n const value = unref(ref);\n\n if (isHtmlElement(value)) {\n return value as T;\n }\n\n return value?.$el;\n}\n","export default function (...data: any): void {\n console.warn('[Flux]', ...data);\n}\n","export default function (elm: HTMLElement, targetElm: Element, forceFirst: boolean = false): void {\n const walker = createFocusWalker(elm);\n const position = targetElm.compareDocumentPosition(elm);\n let wrappedTarget: HTMLElement | null;\n\n if (position && Node.DOCUMENT_POSITION_PRECEDING || forceFirst) {\n wrappedTarget = walker.firstChild() as HTMLElement | null;\n } else {\n wrappedTarget = walker.lastChild() as HTMLElement | null;\n }\n\n const newFocus = wrappedTarget !== null ? wrappedTarget : elm;\n newFocus.focus();\n}\n\nfunction createFocusWalker(elm: HTMLElement): TreeWalker {\n return document.createTreeWalker(elm, NodeFilter.SHOW_ELEMENT, {\n acceptNode: (node: HTMLButtonElement) => node.tabIndex >= 0 && !node.disabled ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP\n });\n}\n","class FocusTrapLockStack {\n get active(): boolean {\n return this.current?.isEnabled ?? false;\n }\n\n get current(): FocusTrap | null {\n return this.#traps[this.#traps.length - 1] ?? null;\n }\n\n #listeners: FocusTrapListener[] = [];\n #traps: FocusTrap[] = [];\n\n add(id: FocusTrap['id'], setEnabled: FocusTrap['setEnabled'], autoFocus: boolean = true): void {\n const trap: FocusTrap = {id, setEnabled, isEnabled: true};\n this.current && this.toggle(this.current, false);\n this.#traps.push(trap);\n\n if (autoFocus) {\n this.toggle(trap, true);\n this.emit();\n }\n }\n\n remove(id: FocusTrap['id']): void {\n const trap = this.#traps.find(t => t.id === id);\n trap && this.toggle(trap, false);\n\n const current = this.current;\n const wasCurrent = current?.id === id;\n this.#traps = this.#traps.filter(t => t.id !== id);\n\n wasCurrent && this.current && this.toggle(this.current, true);\n this.emit();\n }\n\n emit(): void {\n this.#listeners.forEach(listener => listener(this.active, this.#traps));\n }\n\n subscribe(listener: FocusTrapListener): () => void {\n this.#listeners.push(listener);\n listener(this.active, this.#traps);\n\n return () => this.#listeners = this.#listeners.filter(l => l !== listener);\n }\n\n toggle(trap: FocusTrap, isEnabled: boolean): void {\n trap.setEnabled(isEnabled);\n trap.isEnabled = isEnabled;\n }\n}\n\ninterface FocusTrap {\n id: string;\n isEnabled: boolean;\n\n setEnabled(isEnabled: boolean): void;\n}\n\nexport type FocusTrapListener = (isEnabled: boolean, focusTraps: FocusTrap[]) => void;\n\nconst _default: FocusTrapLockStack = new FocusTrapLockStack();\nexport default _default;\n","export { default as animationFrameDebounce } from './animationFrameDebounce';\nexport { default as flattenVNodeTree } from './flattenVNodeTree';\nexport { default as getBidirectionalFocusElement } from './getBidirectionalFocusElement';\nexport { default as getComponentName } from './getComponentName';\nexport { default as getComponentProps } from './getComponentProps';\nexport { default as getExposedRef } from './getExposedRef';\nexport { default as getFocusableElement } from './getFocusableElement';\nexport { default as getFocusableElements } from './getFocusableElements';\nexport { default as getKeyboardFocusableElements } from './getKeyboardFocusableElements';\nexport { default as unrefTemplateElement, type TemplateElement, type TemplateRef } from './unrefTemplateElement';\nexport { default as warn } from './warn';\nexport { default as wrapFocus } from './wrapFocus';\n\nexport { default as FOCUS_TRAP_LOCKS, type FocusTrapListener } from './focusTrap';\n\nexport const isSSR: boolean = !globalThis.document;\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flux-ui/internals",
|
|
3
3
|
"description": "Contains internal workings of Flux UI packages.",
|
|
4
|
-
"version": "3.0.0-next.
|
|
4
|
+
"version": "3.0.0-next.58",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"funding": "https://github.com/sponsors/basmilius",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"dependencies": {
|
|
62
62
|
"@basmilius/common": "^3.21.0",
|
|
63
63
|
"@basmilius/utils": "^3.21.0",
|
|
64
|
-
"@flux-ui/types": "3.0.0-next.
|
|
64
|
+
"@flux-ui/types": "3.0.0-next.58",
|
|
65
65
|
"lodash-es": "^4.18.1"
|
|
66
66
|
},
|
|
67
67
|
"peerDependencies": {
|
package/src/directive/index.ts
CHANGED
|
@@ -2,7 +2,8 @@ import type { FluxMaybePromise } from '@flux-ui/types';
|
|
|
2
2
|
|
|
3
3
|
export default function <T extends () => FluxMaybePromise<void>>(fn: T): T {
|
|
4
4
|
if (typeof requestAnimationFrame === 'undefined') {
|
|
5
|
-
return (() => {
|
|
5
|
+
return (() => {
|
|
6
|
+
}) as T;
|
|
6
7
|
}
|
|
7
8
|
|
|
8
9
|
let animationFrame = 0;
|