@v-c/util 1.0.18-beta.1 → 1.0.19

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.
@@ -16,4 +16,7 @@ export declare function lockFocus(element: HTMLElement, id: string): VoidFunctio
16
16
  * If multiple elements are locked, only the last locked element will be effective.
17
17
  * @returns A function to mark an element as ignored, which will temporarily allow focus on that element even if it's outside the locked area.
18
18
  */
19
- export declare function useLockFocus(lock: Ref<boolean>, getElement: () => HTMLElement | null): [ignoreElement: (ele: HTMLElement) => void];
19
+ export declare function useLockFocus(lock: Ref<boolean>, getElement: () => HTMLElement | null): [
20
+ ignoreElement: (ele: HTMLElement) => void,
21
+ registerAllowedElement: (ele: HTMLElement) => VoidFunction
22
+ ];
package/dist/Dom/focus.js CHANGED
@@ -49,21 +49,27 @@ var lastFocusElement = null;
49
49
  var focusElements = [];
50
50
  var idToElementMap = /* @__PURE__ */ new Map();
51
51
  var ignoredElementMap = /* @__PURE__ */ new Map();
52
+ var allowedElementMap = /* @__PURE__ */ new Map();
52
53
  function getLastElement() {
53
54
  return focusElements[focusElements.length - 1];
54
55
  }
55
- function isIgnoredElement(element) {
56
+ function getLastLockId() {
56
57
  const lastElement = getLastElement();
57
- if (element && lastElement) {
58
- let lockId;
59
- for (const [id, ele] of idToElementMap.entries()) if (ele === lastElement) {
60
- lockId = id;
61
- break;
62
- }
63
- if (!lockId) return false;
64
- const ignoredEle = ignoredElementMap.get(lockId);
65
- return !!ignoredEle && (ignoredEle === element || ignoredEle.contains(element));
66
- }
58
+ if (!lastElement) return void 0;
59
+ for (const [id, ele] of idToElementMap.entries()) if (ele === lastElement) return id;
60
+ }
61
+ function isIgnoredElement(element) {
62
+ const lockId = getLastLockId();
63
+ if (!lockId || !element) return false;
64
+ const ignoredEle = ignoredElementMap.get(lockId);
65
+ return !!ignoredEle && (ignoredEle === element || ignoredEle.contains(element));
66
+ }
67
+ function isAllowedElement(element) {
68
+ const lockId = getLastLockId();
69
+ if (!lockId || !element) return false;
70
+ const allowedElements = allowedElementMap.get(lockId);
71
+ if (!allowedElements?.size) return false;
72
+ for (const allowedElement of allowedElements) if (allowedElement === element || allowedElement.contains(element)) return true;
67
73
  return false;
68
74
  }
69
75
  function hasFocus(element) {
@@ -73,7 +79,7 @@ function hasFocus(element) {
73
79
  function syncFocus() {
74
80
  const lastElement = getLastElement();
75
81
  const { activeElement } = document;
76
- if (isIgnoredElement(activeElement)) return;
82
+ if (isIgnoredElement(activeElement) || isAllowedElement(activeElement)) return;
77
83
  if (lastElement && !hasFocus(lastElement)) {
78
84
  const focusableList = getFocusNodeList(lastElement);
79
85
  (focusableList.includes(lastFocusElement) ? lastFocusElement : focusableList[0])?.focus({ preventScroll: true });
@@ -102,6 +108,7 @@ function lockFocus(element, id) {
102
108
  focusElements = focusElements.filter((ele) => ele !== element);
103
109
  idToElementMap.delete(id);
104
110
  ignoredElementMap.delete(id);
111
+ allowedElementMap.delete(id);
105
112
  if (focusElements.length === 0) {
106
113
  window.removeEventListener("focusin", syncFocus);
107
114
  window.removeEventListener("keydown", onWindowKeyDown, true);
@@ -120,6 +127,20 @@ function useLockFocus(lock, getElement) {
120
127
  const ignoreElement = (ele) => {
121
128
  if (ele) ignoredElementMap.set(id, ele);
122
129
  };
123
- return [ignoreElement];
130
+ const registerAllowedElement = (ele) => {
131
+ if (!ele) return () => {};
132
+ let allowedElements = allowedElementMap.get(id);
133
+ if (!allowedElements) {
134
+ allowedElements = /* @__PURE__ */ new Set();
135
+ allowedElementMap.set(id, allowedElements);
136
+ }
137
+ allowedElements.add(ele);
138
+ return () => {
139
+ const nextAllowedElements = allowedElementMap.get(id);
140
+ nextAllowedElements?.delete(ele);
141
+ if (!nextAllowedElements?.size) allowedElementMap.delete(id);
142
+ };
143
+ };
144
+ return [ignoreElement, registerAllowedElement];
124
145
  }
125
146
  export { getFocusNodeList, lockFocus, triggerFocus, useLockFocus };
@@ -0,0 +1,5 @@
1
+ export interface FocusBoundaryContextProps {
2
+ registerAllowedElement: (element: HTMLElement) => VoidFunction;
3
+ }
4
+ export declare function useFocusBoundaryProvider(props: FocusBoundaryContextProps): void;
5
+ export declare function useFocusBoundary(): FocusBoundaryContextProps;
@@ -0,0 +1,9 @@
1
+ import { inject, provide } from "vue";
2
+ var FocusBoundaryContextKey = Symbol("FocusBoundaryContext");
3
+ function useFocusBoundaryProvider(props) {
4
+ provide(FocusBoundaryContextKey, props);
5
+ }
6
+ function useFocusBoundary() {
7
+ return inject(FocusBoundaryContextKey, null);
8
+ }
9
+ export { useFocusBoundary, useFocusBoundaryProvider };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@v-c/util",
3
3
  "type": "module",
4
- "version": "1.0.18-beta.1",
4
+ "version": "1.0.19",
5
5
  "description": "Vue3 components utils",
6
6
  "publishConfig": {
7
7
  "access": "public"