@zhencai/vue-focus-scope 1.0.1 → 1.0.3
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/index.js +66 -100
- package/package.json +3 -16
- package/index.d.ts +0 -30
- package/vue-focus-scope.css +0 -5
package/index.js
CHANGED
|
@@ -1,107 +1,73 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createCommentVNode as e, createElementBlock as t, createElementVNode as n, defineComponent as r, openBlock as i, renderSlot as a, useTemplateRef as o } from "vue";
|
|
2
2
|
//#region src/components/FocusScope.vue?vue&type=script&setup=true&lang.ts
|
|
3
|
-
var
|
|
4
|
-
|
|
3
|
+
var s = {
|
|
4
|
+
key: 0,
|
|
5
|
+
tabindex: "0"
|
|
6
|
+
}, c = /* @__PURE__ */ r({
|
|
5
7
|
__name: "FocusScope",
|
|
6
|
-
props: {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
let active = false;
|
|
17
|
-
let previous = null;
|
|
18
|
-
const getFocusable = () => {
|
|
19
|
-
if (!scopeRef.value) return [];
|
|
20
|
-
return [...scopeRef.value.querySelectorAll(selector)];
|
|
21
|
-
};
|
|
22
|
-
const focusFirst = () => {
|
|
23
|
-
getFocusable()[0]?.focus();
|
|
24
|
-
};
|
|
25
|
-
const focusLast = () => {
|
|
26
|
-
const list = getFocusable();
|
|
27
|
-
list[list.length - 1]?.focus();
|
|
28
|
-
};
|
|
29
|
-
const handleMouseDown = () => {
|
|
30
|
-
scopeRef.value?.focus();
|
|
31
|
-
};
|
|
32
|
-
const handleKeydown = (e) => {
|
|
33
|
-
if (!active) return;
|
|
34
|
-
if (e.key !== "Tab") return;
|
|
35
|
-
if (!scopeRef.value) return;
|
|
36
|
-
const list = getFocusable();
|
|
37
|
-
if (!list.length) return;
|
|
38
|
-
const first = list[0];
|
|
39
|
-
const last = list[list.length - 1];
|
|
40
|
-
const current = document.activeElement;
|
|
41
|
-
if (e.shiftKey) {
|
|
42
|
-
if (current === first) {
|
|
43
|
-
e.preventDefault();
|
|
44
|
-
if (props.tabMode === "loop") last.focus();
|
|
45
|
-
else scopeRef.value.focus();
|
|
46
|
-
} else if (current === scopeRef.value) {
|
|
47
|
-
e.preventDefault();
|
|
48
|
-
last.focus();
|
|
8
|
+
props: { tabMode: { default: "loop" } },
|
|
9
|
+
setup(r) {
|
|
10
|
+
let c = o("wrapper");
|
|
11
|
+
function l(e) {
|
|
12
|
+
if (!e) return [];
|
|
13
|
+
let t = Array.from(e.querySelectorAll("a[href]:not([tabindex=\"-1\"]):not(.sentinel-start):not(.sentinel-end), button:not([tabindex=\"-1\"]):not([disabled]):not(.sentinel-start):not(.sentinel-end), input:not([tabindex=\"-1\"]):not([disabled]):not(.sentinel-start):not(.sentinel-end), select:not([tabindex=\"-1\"]):not([disabled]):not(.sentinel-start):not(.sentinel-end), textarea:not([tabindex=\"-1\"]):not([disabled]):not(.sentinel-start):not(.sentinel-end), [tabindex]:not([tabindex=\"-1\"]):not(.sentinel-start):not(.sentinel-end)")).filter((e) => {
|
|
14
|
+
let t = e.parentElement;
|
|
15
|
+
for (; t;) {
|
|
16
|
+
if (t.tagName === "FIELDSET" && t.disabled) return !1;
|
|
17
|
+
t = t.parentElement;
|
|
49
18
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
19
|
+
return !0;
|
|
20
|
+
});
|
|
21
|
+
return console.log("当前可聚焦元素:", t), t;
|
|
22
|
+
}
|
|
23
|
+
function u() {
|
|
24
|
+
try {
|
|
25
|
+
if (c.value) {
|
|
26
|
+
let e = l(c.value);
|
|
27
|
+
if (e.length === 0) return;
|
|
28
|
+
console.log("执行聚焦第一个:", e[0]), e[0].focus();
|
|
29
|
+
}
|
|
30
|
+
} catch (e) {
|
|
31
|
+
console.error("focusFirst error:", e);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function d() {
|
|
35
|
+
if (c.value) {
|
|
36
|
+
let e = l(c.value);
|
|
37
|
+
if (e.length === 0) return;
|
|
38
|
+
e[e.length - 1].focus();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function f(e) {
|
|
42
|
+
if (!c.value) return;
|
|
43
|
+
let t = e.relatedTarget;
|
|
44
|
+
if (!(t instanceof Node)) {
|
|
45
|
+
u();
|
|
46
|
+
return;
|
|
57
47
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
return openBlock(), createElementBlock("div", {
|
|
81
|
-
ref_key: "scopeRef",
|
|
82
|
-
ref: scopeRef,
|
|
83
|
-
tabindex: "-1",
|
|
84
|
-
onMousedown: handleMouseDown,
|
|
85
|
-
"data-focus-scope": ""
|
|
86
|
-
}, [renderSlot(_ctx.$slots, "default", {}, void 0, true)], 544);
|
|
87
|
-
};
|
|
48
|
+
c.value.contains(t) ? d() : u();
|
|
49
|
+
}
|
|
50
|
+
function p() {
|
|
51
|
+
u();
|
|
52
|
+
}
|
|
53
|
+
return (o, l) => (i(), t("div", {
|
|
54
|
+
ref_key: "wrapper",
|
|
55
|
+
ref: c
|
|
56
|
+
}, [
|
|
57
|
+
n("div", {
|
|
58
|
+
tabindex: "0",
|
|
59
|
+
class: "sentinel-start",
|
|
60
|
+
onFocus: f
|
|
61
|
+
}, null, 32),
|
|
62
|
+
a(o.$slots, "default"),
|
|
63
|
+
r.tabMode === "soft-loop" ? (i(), t("div", s)) : e("", !0),
|
|
64
|
+
n("div", {
|
|
65
|
+
tabindex: "0",
|
|
66
|
+
class: "sentinel-end",
|
|
67
|
+
onFocus: p
|
|
68
|
+
}, null, 32)
|
|
69
|
+
], 512));
|
|
88
70
|
}
|
|
89
71
|
});
|
|
90
72
|
//#endregion
|
|
91
|
-
|
|
92
|
-
var _plugin_vue_export_helper_default = (sfc, props) => {
|
|
93
|
-
const target = sfc.__vccOpts || sfc;
|
|
94
|
-
for (const [key, val] of props) target[key] = val;
|
|
95
|
-
return target;
|
|
96
|
-
};
|
|
97
|
-
//#endregion
|
|
98
|
-
//#region src/components/FocusScope.vue
|
|
99
|
-
var FocusScope_default = /* @__PURE__ */ _plugin_vue_export_helper_default(FocusScope_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-5ffda61b"]]);
|
|
100
|
-
//#endregion
|
|
101
|
-
//#region src/index.ts
|
|
102
|
-
var src_default = FocusScope_default;
|
|
103
|
-
|
|
104
|
-
//#endregion
|
|
105
|
-
export { FocusScope_default as FocusScope, src_default as default };
|
|
106
|
-
|
|
107
|
-
//# sourceMappingURL=index.js.map
|
|
73
|
+
export { c as FocusScope };
|
package/package.json
CHANGED
|
@@ -1,22 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhencai/vue-focus-scope",
|
|
3
|
-
"version": "1.0.1",
|
|
4
3
|
"main": "index.js",
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"index.js",
|
|
8
|
-
"index.d.ts",
|
|
9
|
-
"vue-focus-scope.css"
|
|
10
|
-
],
|
|
11
|
-
"keywords": [
|
|
12
|
-
"vue",
|
|
13
|
-
"focus",
|
|
14
|
-
"ui",
|
|
15
|
-
"component"
|
|
16
|
-
],
|
|
17
|
-
"author": "严硕",
|
|
18
|
-
"license": "MIT",
|
|
4
|
+
"version": "1.0.3",
|
|
5
|
+
"module": "index.js",
|
|
19
6
|
"peerDependencies": {
|
|
20
|
-
"vue": "^3.
|
|
7
|
+
"vue": "^3.0.0"
|
|
21
8
|
}
|
|
22
9
|
}
|
package/index.d.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
// index.d.ts
|
|
2
|
-
import { DefineComponent } from "vue";
|
|
3
|
-
|
|
4
|
-
type TabMode = "loop" | "loop-sentinel";
|
|
5
|
-
|
|
6
|
-
interface FocusScopeProps {
|
|
7
|
-
autoFocus?: "first" | "last" | false;
|
|
8
|
-
tabMode?: TabMode;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface FocusScopeExpose {
|
|
12
|
-
activate: () => void;
|
|
13
|
-
deactivate: () => void;
|
|
14
|
-
focusFirst: () => void;
|
|
15
|
-
focusLast: () => void;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
declare const FocusScope: DefineComponent<
|
|
19
|
-
FocusScopeProps,
|
|
20
|
-
{},
|
|
21
|
-
{},
|
|
22
|
-
{},
|
|
23
|
-
{},
|
|
24
|
-
{},
|
|
25
|
-
{},
|
|
26
|
-
{},
|
|
27
|
-
FocusScopeExpose
|
|
28
|
-
>;
|
|
29
|
-
|
|
30
|
-
export default FocusScope;
|