@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 CHANGED
@@ -1,107 +1,73 @@
1
- import { createElementBlock, defineComponent, onMounted, onUnmounted, openBlock, ref, renderSlot } from "vue";
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 selector = "a[href],button:not([disabled]),textarea:not([disabled]),input:not([disabled]),select:not([disabled]),[tabindex]:not([tabindex='-1']),[contenteditable='true']";
4
- var FocusScope_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
3
+ var s = {
4
+ key: 0,
5
+ tabindex: "0"
6
+ }, c = /* @__PURE__ */ r({
5
7
  __name: "FocusScope",
6
- props: {
7
- autoFocus: {
8
- type: [String, Boolean],
9
- default: "first"
10
- },
11
- tabMode: { default: "loop" }
12
- },
13
- setup(__props) {
14
- const props = __props;
15
- const scopeRef = ref(null);
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
- } else if (current === last) {
51
- e.preventDefault();
52
- if (props.tabMode === "loop") first.focus();
53
- else scopeRef.value.focus();
54
- } else if (current === scopeRef.value) {
55
- e.preventDefault();
56
- first.focus();
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
- const activate = () => {
60
- if (!scopeRef.value) return;
61
- active = true;
62
- previous = document.activeElement;
63
- if (props.autoFocus === "first") focusFirst();
64
- if (props.autoFocus === "last") focusLast();
65
- };
66
- const deactivate = () => {
67
- active = false;
68
- if (previous && document.body.contains(previous)) previous.focus();
69
- previous = null;
70
- };
71
- onMounted(() => {
72
- document.addEventListener("keydown", handleKeydown);
73
- activate();
74
- });
75
- onUnmounted(() => {
76
- document.removeEventListener("keydown", handleKeydown);
77
- deactivate();
78
- });
79
- return (_ctx, _cache) => {
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
- //#region \0plugin-vue:export-helper
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
- "types": "index.d.ts",
6
- "files": [
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.2.0"
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;
@@ -1,5 +0,0 @@
1
-
2
- [data-focus-scope][data-v-5ffda61b]:focus {
3
- outline: none;
4
- }
5
- /*$vite$:1*/