@yh-ui/hooks 0.1.0
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/LICENSE +21 -0
- package/dist/index.cjs +585 -0
- package/dist/index.d.cts +259 -0
- package/dist/index.d.mts +259 -0
- package/dist/index.d.ts +259 -0
- package/dist/index.mjs +542 -0
- package/dist/use-cache/index.cjs +21 -0
- package/dist/use-cache/index.d.ts +10 -0
- package/dist/use-cache/index.mjs +15 -0
- package/dist/use-click-outside/index.cjs +20 -0
- package/dist/use-click-outside/index.d.ts +2 -0
- package/dist/use-click-outside/index.mjs +14 -0
- package/dist/use-config/index.cjs +30 -0
- package/dist/use-config/index.d.ts +22 -0
- package/dist/use-config/index.mjs +25 -0
- package/dist/use-event-listener/index.cjs +40 -0
- package/dist/use-event-listener/index.d.ts +2 -0
- package/dist/use-event-listener/index.mjs +34 -0
- package/dist/use-form-item/index.cjs +27 -0
- package/dist/use-form-item/index.d.ts +43 -0
- package/dist/use-form-item/index.mjs +20 -0
- package/dist/use-id/index.cjs +29 -0
- package/dist/use-id/index.d.ts +21 -0
- package/dist/use-id/index.mjs +21 -0
- package/dist/use-locale/dayjs-locale.cjs +129 -0
- package/dist/use-locale/dayjs-locale.d.ts +37 -0
- package/dist/use-locale/dayjs-locale.mjs +131 -0
- package/dist/use-locale/index.cjs +88 -0
- package/dist/use-locale/index.d.ts +16 -0
- package/dist/use-locale/index.mjs +63 -0
- package/dist/use-namespace/index.cjs +76 -0
- package/dist/use-namespace/index.d.ts +34 -0
- package/dist/use-namespace/index.mjs +68 -0
- package/dist/use-scroll-lock/index.cjs +73 -0
- package/dist/use-scroll-lock/index.d.ts +8 -0
- package/dist/use-scroll-lock/index.mjs +60 -0
- package/dist/use-virtual-scroll/index.cjs +64 -0
- package/dist/use-virtual-scroll/index.d.ts +35 -0
- package/dist/use-virtual-scroll/index.mjs +53 -0
- package/dist/use-z-index/index.cjs +57 -0
- package/dist/use-z-index/index.d.ts +30 -0
- package/dist/use-z-index/index.mjs +45 -0
- package/package.json +56 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { computed, unref, watch } from "vue";
|
|
2
|
+
import { zhCn } from "@yh-ui/locale";
|
|
3
|
+
import { useConfig } from "../use-config/index.mjs";
|
|
4
|
+
import { setDayjsLocale } from "./dayjs-locale.mjs";
|
|
5
|
+
export {
|
|
6
|
+
setDayjsLocale,
|
|
7
|
+
getDayjsLocale,
|
|
8
|
+
setDayjsLocaleSync,
|
|
9
|
+
updateDayjsMonths
|
|
10
|
+
} from "./dayjs-locale.mjs";
|
|
11
|
+
export const useLocale = (localeOverrides) => {
|
|
12
|
+
const { globalLocale } = useConfig();
|
|
13
|
+
const locale = computed(() => {
|
|
14
|
+
return unref(localeOverrides) ?? unref(globalLocale) ?? zhCn;
|
|
15
|
+
});
|
|
16
|
+
const lang = computed(() => locale.value.name);
|
|
17
|
+
watch(
|
|
18
|
+
lang,
|
|
19
|
+
(newLang) => {
|
|
20
|
+
setDayjsLocale(newLang);
|
|
21
|
+
},
|
|
22
|
+
{ immediate: true }
|
|
23
|
+
);
|
|
24
|
+
const t = (path, options) => {
|
|
25
|
+
const keys = path.split(".");
|
|
26
|
+
let result = locale.value.yh;
|
|
27
|
+
for (const key of keys) {
|
|
28
|
+
if (result && typeof result === "object") {
|
|
29
|
+
result = result[key];
|
|
30
|
+
} else {
|
|
31
|
+
result = void 0;
|
|
32
|
+
}
|
|
33
|
+
if (result === void 0) return path;
|
|
34
|
+
}
|
|
35
|
+
if (typeof result !== "string") return path;
|
|
36
|
+
if (options) {
|
|
37
|
+
return result.replace(/\{(\w+)\}/g, (_match, key) => {
|
|
38
|
+
const val = options[key];
|
|
39
|
+
return val !== void 0 ? String(val) : `{${key}}`;
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
const tRaw = (path) => {
|
|
45
|
+
const keys = path.split(".");
|
|
46
|
+
let result = locale.value.yh;
|
|
47
|
+
for (const key of keys) {
|
|
48
|
+
if (result && typeof result === "object") {
|
|
49
|
+
result = result[key];
|
|
50
|
+
} else {
|
|
51
|
+
result = void 0;
|
|
52
|
+
}
|
|
53
|
+
if (result === void 0) return path;
|
|
54
|
+
}
|
|
55
|
+
return result;
|
|
56
|
+
};
|
|
57
|
+
return {
|
|
58
|
+
locale,
|
|
59
|
+
lang,
|
|
60
|
+
t,
|
|
61
|
+
tRaw
|
|
62
|
+
};
|
|
63
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.useNamespace = exports.useGlobalNamespace = exports.namespaceContextKey = exports.defaultNamespace = void 0;
|
|
7
|
+
var _vue = require("vue");
|
|
8
|
+
const defaultNamespace = exports.defaultNamespace = "yh";
|
|
9
|
+
const statePrefix = "is-";
|
|
10
|
+
const namespaceContextKey = exports.namespaceContextKey = Symbol("namespaceContextKey");
|
|
11
|
+
const useGlobalNamespace = () => {
|
|
12
|
+
return (0, _vue.inject)(namespaceContextKey, (0, _vue.ref)(defaultNamespace));
|
|
13
|
+
};
|
|
14
|
+
exports.useGlobalNamespace = useGlobalNamespace;
|
|
15
|
+
const useNamespace = block => {
|
|
16
|
+
const namespace = useGlobalNamespace();
|
|
17
|
+
const b = (blockSuffix = "") => {
|
|
18
|
+
const ns = (0, _vue.unref)(namespace);
|
|
19
|
+
return blockSuffix ? `${ns}-${block}-${blockSuffix}` : `${ns}-${block}`;
|
|
20
|
+
};
|
|
21
|
+
const e = element => {
|
|
22
|
+
return element ? `${b()}__${element}` : "";
|
|
23
|
+
};
|
|
24
|
+
const m = modifier => {
|
|
25
|
+
return modifier ? `${b()}--${modifier}` : "";
|
|
26
|
+
};
|
|
27
|
+
const bem = (blockSuffix, element, modifier) => {
|
|
28
|
+
let cls = b(blockSuffix);
|
|
29
|
+
if (element) cls += `__${element}`;
|
|
30
|
+
if (modifier) cls += `--${modifier}`;
|
|
31
|
+
return cls;
|
|
32
|
+
};
|
|
33
|
+
const em = (element, modifier) => {
|
|
34
|
+
return element && modifier ? `${b()}__${element}--${modifier}` : "";
|
|
35
|
+
};
|
|
36
|
+
function is(state, value) {
|
|
37
|
+
if (arguments.length === 1) {
|
|
38
|
+
return `${statePrefix}${state}`;
|
|
39
|
+
}
|
|
40
|
+
return value ? `${statePrefix}${state}` : "";
|
|
41
|
+
}
|
|
42
|
+
const cssVar = name => {
|
|
43
|
+
return `--${(0, _vue.unref)(namespace)}-${block}-${name}`;
|
|
44
|
+
};
|
|
45
|
+
const cssVarObj = vars => {
|
|
46
|
+
const obj = {};
|
|
47
|
+
Object.entries(vars).forEach(([key, value]) => {
|
|
48
|
+
obj[cssVar(key)] = value;
|
|
49
|
+
});
|
|
50
|
+
return obj;
|
|
51
|
+
};
|
|
52
|
+
const cssVarBlock = name => {
|
|
53
|
+
return `--${(0, _vue.unref)(namespace)}-${name}`;
|
|
54
|
+
};
|
|
55
|
+
const cssVarBlockObj = vars => {
|
|
56
|
+
const obj = {};
|
|
57
|
+
Object.entries(vars).forEach(([key, value]) => {
|
|
58
|
+
obj[cssVarBlock(key)] = value;
|
|
59
|
+
});
|
|
60
|
+
return obj;
|
|
61
|
+
};
|
|
62
|
+
return {
|
|
63
|
+
namespace,
|
|
64
|
+
b,
|
|
65
|
+
e,
|
|
66
|
+
m,
|
|
67
|
+
bem,
|
|
68
|
+
em,
|
|
69
|
+
is,
|
|
70
|
+
cssVar,
|
|
71
|
+
cssVarObj,
|
|
72
|
+
cssVarBlock,
|
|
73
|
+
cssVarBlockObj
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
exports.useNamespace = useNamespace;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { InjectionKey, Ref } from 'vue';
|
|
2
|
+
export declare const defaultNamespace = "yh";
|
|
3
|
+
export declare const namespaceContextKey: InjectionKey<Ref<string>>;
|
|
4
|
+
/**
|
|
5
|
+
* 获取全局命名空间
|
|
6
|
+
*/
|
|
7
|
+
export declare const useGlobalNamespace: () => Ref<string, string>;
|
|
8
|
+
/**
|
|
9
|
+
* useNamespace - 生成 BEM 类名
|
|
10
|
+
* @param block - 块名称
|
|
11
|
+
* @returns BEM 类名生成器
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const ns = useNamespace('button')
|
|
15
|
+
* ns.b() // 'yh-button'
|
|
16
|
+
* ns.e('icon') // 'yh-button__icon'
|
|
17
|
+
* ns.m('primary') // 'yh-button--primary'
|
|
18
|
+
* ns.is('disabled') // 'is-disabled'
|
|
19
|
+
* ns.bem('box', 'item', 'active') // 'yh-button-box__item--active'
|
|
20
|
+
*/
|
|
21
|
+
export declare const useNamespace: (block: string) => {
|
|
22
|
+
namespace: Ref<string, string>;
|
|
23
|
+
b: (blockSuffix?: string) => string;
|
|
24
|
+
e: (element?: string) => string;
|
|
25
|
+
m: (modifier?: string) => string;
|
|
26
|
+
bem: (blockSuffix?: string, element?: string, modifier?: string) => string;
|
|
27
|
+
em: (element?: string, modifier?: string) => string;
|
|
28
|
+
is: (state: string, value?: boolean) => string;
|
|
29
|
+
cssVar: (name: string) => string;
|
|
30
|
+
cssVarObj: (vars: Record<string, string>) => Record<string, string>;
|
|
31
|
+
cssVarBlock: (name: string) => string;
|
|
32
|
+
cssVarBlockObj: (vars: Record<string, string>) => Record<string, string>;
|
|
33
|
+
};
|
|
34
|
+
export type UseNamespaceReturn = ReturnType<typeof useNamespace>;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { inject, ref, unref } from "vue";
|
|
2
|
+
export const defaultNamespace = "yh";
|
|
3
|
+
const statePrefix = "is-";
|
|
4
|
+
export const namespaceContextKey = Symbol("namespaceContextKey");
|
|
5
|
+
export const useGlobalNamespace = () => {
|
|
6
|
+
return inject(namespaceContextKey, ref(defaultNamespace));
|
|
7
|
+
};
|
|
8
|
+
export const useNamespace = (block) => {
|
|
9
|
+
const namespace = useGlobalNamespace();
|
|
10
|
+
const b = (blockSuffix = "") => {
|
|
11
|
+
const ns = unref(namespace);
|
|
12
|
+
return blockSuffix ? `${ns}-${block}-${blockSuffix}` : `${ns}-${block}`;
|
|
13
|
+
};
|
|
14
|
+
const e = (element) => {
|
|
15
|
+
return element ? `${b()}__${element}` : "";
|
|
16
|
+
};
|
|
17
|
+
const m = (modifier) => {
|
|
18
|
+
return modifier ? `${b()}--${modifier}` : "";
|
|
19
|
+
};
|
|
20
|
+
const bem = (blockSuffix, element, modifier) => {
|
|
21
|
+
let cls = b(blockSuffix);
|
|
22
|
+
if (element) cls += `__${element}`;
|
|
23
|
+
if (modifier) cls += `--${modifier}`;
|
|
24
|
+
return cls;
|
|
25
|
+
};
|
|
26
|
+
const em = (element, modifier) => {
|
|
27
|
+
return element && modifier ? `${b()}__${element}--${modifier}` : "";
|
|
28
|
+
};
|
|
29
|
+
function is(state, value) {
|
|
30
|
+
if (arguments.length === 1) {
|
|
31
|
+
return `${statePrefix}${state}`;
|
|
32
|
+
}
|
|
33
|
+
return value ? `${statePrefix}${state}` : "";
|
|
34
|
+
}
|
|
35
|
+
const cssVar = (name) => {
|
|
36
|
+
return `--${unref(namespace)}-${block}-${name}`;
|
|
37
|
+
};
|
|
38
|
+
const cssVarObj = (vars) => {
|
|
39
|
+
const obj = {};
|
|
40
|
+
Object.entries(vars).forEach(([key, value]) => {
|
|
41
|
+
obj[cssVar(key)] = value;
|
|
42
|
+
});
|
|
43
|
+
return obj;
|
|
44
|
+
};
|
|
45
|
+
const cssVarBlock = (name) => {
|
|
46
|
+
return `--${unref(namespace)}-${name}`;
|
|
47
|
+
};
|
|
48
|
+
const cssVarBlockObj = (vars) => {
|
|
49
|
+
const obj = {};
|
|
50
|
+
Object.entries(vars).forEach(([key, value]) => {
|
|
51
|
+
obj[cssVarBlock(key)] = value;
|
|
52
|
+
});
|
|
53
|
+
return obj;
|
|
54
|
+
};
|
|
55
|
+
return {
|
|
56
|
+
namespace,
|
|
57
|
+
b,
|
|
58
|
+
e,
|
|
59
|
+
m,
|
|
60
|
+
bem,
|
|
61
|
+
em,
|
|
62
|
+
is,
|
|
63
|
+
cssVar,
|
|
64
|
+
cssVarObj,
|
|
65
|
+
cssVarBlock,
|
|
66
|
+
cssVarBlockObj
|
|
67
|
+
};
|
|
68
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.useScrollLock = void 0;
|
|
7
|
+
var _vue = require("vue");
|
|
8
|
+
const useScrollLock = trigger => {
|
|
9
|
+
const isLocked = (0, _vue.ref)(false);
|
|
10
|
+
let initialHtmlStyle = {
|
|
11
|
+
overflow: "",
|
|
12
|
+
paddingRight: ""
|
|
13
|
+
};
|
|
14
|
+
let initialBodyStyle = {
|
|
15
|
+
overflow: "",
|
|
16
|
+
paddingRight: ""
|
|
17
|
+
};
|
|
18
|
+
const getScrollbarWidth = () => {
|
|
19
|
+
return window.innerWidth - document.documentElement.clientWidth;
|
|
20
|
+
};
|
|
21
|
+
const lock = () => {
|
|
22
|
+
if (isLocked.value) return;
|
|
23
|
+
const width = getScrollbarWidth();
|
|
24
|
+
const html = document.documentElement;
|
|
25
|
+
const body = document.body;
|
|
26
|
+
initialHtmlStyle = {
|
|
27
|
+
overflow: html.style.overflow,
|
|
28
|
+
paddingRight: html.style.paddingRight
|
|
29
|
+
};
|
|
30
|
+
initialBodyStyle = {
|
|
31
|
+
overflow: body.style.overflow,
|
|
32
|
+
paddingRight: body.style.paddingRight
|
|
33
|
+
};
|
|
34
|
+
if (width > 0) {
|
|
35
|
+
const scrollbarWidth = `${width}px`;
|
|
36
|
+
html.style.setProperty("--yh-scrollbar-width", scrollbarWidth);
|
|
37
|
+
const computedBodyPadding = window.getComputedStyle(body).paddingRight;
|
|
38
|
+
body.style.paddingRight = `calc(${computedBodyPadding} + ${scrollbarWidth})`;
|
|
39
|
+
}
|
|
40
|
+
html.style.overflow = "hidden";
|
|
41
|
+
body.style.overflow = "hidden";
|
|
42
|
+
html.classList.add("yh-popup-parent--hidden");
|
|
43
|
+
isLocked.value = true;
|
|
44
|
+
};
|
|
45
|
+
const unlock = () => {
|
|
46
|
+
if (!isLocked.value) return;
|
|
47
|
+
const html = document.documentElement;
|
|
48
|
+
const body = document.body;
|
|
49
|
+
html.style.overflow = initialHtmlStyle.overflow;
|
|
50
|
+
html.style.paddingRight = initialHtmlStyle.paddingRight;
|
|
51
|
+
body.style.overflow = initialBodyStyle.overflow;
|
|
52
|
+
body.style.paddingRight = initialBodyStyle.paddingRight;
|
|
53
|
+
html.classList.remove("yh-popup-parent--hidden");
|
|
54
|
+
setTimeout(() => {
|
|
55
|
+
if (!html.classList.contains("yh-popup-parent--hidden")) {
|
|
56
|
+
html.style.removeProperty("--yh-scrollbar-width");
|
|
57
|
+
}
|
|
58
|
+
}, 400);
|
|
59
|
+
isLocked.value = false;
|
|
60
|
+
};
|
|
61
|
+
(0, _vue.watch)(trigger, val => {
|
|
62
|
+
if (val) {
|
|
63
|
+
lock();
|
|
64
|
+
} else {
|
|
65
|
+
unlock();
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
(0, _vue.onUnmounted)(unlock);
|
|
69
|
+
return {
|
|
70
|
+
isLocked
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
exports.useScrollLock = useScrollLock;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { ref, watch, onUnmounted } from "vue";
|
|
2
|
+
export const useScrollLock = (trigger) => {
|
|
3
|
+
const isLocked = ref(false);
|
|
4
|
+
let initialHtmlStyle = { overflow: "", paddingRight: "" };
|
|
5
|
+
let initialBodyStyle = { overflow: "", paddingRight: "" };
|
|
6
|
+
const getScrollbarWidth = () => {
|
|
7
|
+
return window.innerWidth - document.documentElement.clientWidth;
|
|
8
|
+
};
|
|
9
|
+
const lock = () => {
|
|
10
|
+
if (isLocked.value) return;
|
|
11
|
+
const width = getScrollbarWidth();
|
|
12
|
+
const html = document.documentElement;
|
|
13
|
+
const body = document.body;
|
|
14
|
+
initialHtmlStyle = {
|
|
15
|
+
overflow: html.style.overflow,
|
|
16
|
+
paddingRight: html.style.paddingRight
|
|
17
|
+
};
|
|
18
|
+
initialBodyStyle = {
|
|
19
|
+
overflow: body.style.overflow,
|
|
20
|
+
paddingRight: body.style.paddingRight
|
|
21
|
+
};
|
|
22
|
+
if (width > 0) {
|
|
23
|
+
const scrollbarWidth = `${width}px`;
|
|
24
|
+
html.style.setProperty("--yh-scrollbar-width", scrollbarWidth);
|
|
25
|
+
const computedBodyPadding = window.getComputedStyle(body).paddingRight;
|
|
26
|
+
body.style.paddingRight = `calc(${computedBodyPadding} + ${scrollbarWidth})`;
|
|
27
|
+
}
|
|
28
|
+
html.style.overflow = "hidden";
|
|
29
|
+
body.style.overflow = "hidden";
|
|
30
|
+
html.classList.add("yh-popup-parent--hidden");
|
|
31
|
+
isLocked.value = true;
|
|
32
|
+
};
|
|
33
|
+
const unlock = () => {
|
|
34
|
+
if (!isLocked.value) return;
|
|
35
|
+
const html = document.documentElement;
|
|
36
|
+
const body = document.body;
|
|
37
|
+
html.style.overflow = initialHtmlStyle.overflow;
|
|
38
|
+
html.style.paddingRight = initialHtmlStyle.paddingRight;
|
|
39
|
+
body.style.overflow = initialBodyStyle.overflow;
|
|
40
|
+
body.style.paddingRight = initialBodyStyle.paddingRight;
|
|
41
|
+
html.classList.remove("yh-popup-parent--hidden");
|
|
42
|
+
setTimeout(() => {
|
|
43
|
+
if (!html.classList.contains("yh-popup-parent--hidden")) {
|
|
44
|
+
html.style.removeProperty("--yh-scrollbar-width");
|
|
45
|
+
}
|
|
46
|
+
}, 400);
|
|
47
|
+
isLocked.value = false;
|
|
48
|
+
};
|
|
49
|
+
watch(trigger, (val) => {
|
|
50
|
+
if (val) {
|
|
51
|
+
lock();
|
|
52
|
+
} else {
|
|
53
|
+
unlock();
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
onUnmounted(unlock);
|
|
57
|
+
return {
|
|
58
|
+
isLocked
|
|
59
|
+
};
|
|
60
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
exports.useVirtualScroll = useVirtualScroll;
|
|
8
|
+
var _vue = require("vue");
|
|
9
|
+
function useVirtualScroll(options) {
|
|
10
|
+
const {
|
|
11
|
+
itemHeight,
|
|
12
|
+
containerHeight,
|
|
13
|
+
overscan = 3
|
|
14
|
+
} = options;
|
|
15
|
+
const containerRef = (0, _vue.ref)(null);
|
|
16
|
+
const scrollTop = (0, _vue.ref)(0);
|
|
17
|
+
const itemsRef = (0, _vue.computed)(() => {
|
|
18
|
+
const items = options.items;
|
|
19
|
+
return Array.isArray(items) ? items : items.value;
|
|
20
|
+
});
|
|
21
|
+
const totalHeight = (0, _vue.computed)(() => itemsRef.value.length * itemHeight);
|
|
22
|
+
const visibleCount = (0, _vue.computed)(() => Math.ceil(containerHeight / itemHeight));
|
|
23
|
+
const startIndex = (0, _vue.computed)(() => {
|
|
24
|
+
const items = itemsRef.value;
|
|
25
|
+
if (items.length === 0) return 0;
|
|
26
|
+
const start = Math.floor(scrollTop.value / itemHeight);
|
|
27
|
+
return Math.max(0, start - overscan);
|
|
28
|
+
});
|
|
29
|
+
const endIndex = (0, _vue.computed)(() => {
|
|
30
|
+
const items = itemsRef.value;
|
|
31
|
+
if (items.length === 0) return 0;
|
|
32
|
+
const start = Math.floor(scrollTop.value / itemHeight);
|
|
33
|
+
const end = start + visibleCount.value;
|
|
34
|
+
return Math.min(items.length, end + overscan);
|
|
35
|
+
});
|
|
36
|
+
const visibleItems = (0, _vue.computed)(() => {
|
|
37
|
+
const items = itemsRef.value;
|
|
38
|
+
if (items.length === 0) return [];
|
|
39
|
+
return items.slice(startIndex.value, endIndex.value);
|
|
40
|
+
});
|
|
41
|
+
const offsetY = (0, _vue.computed)(() => startIndex.value * itemHeight);
|
|
42
|
+
const onScroll = event => {
|
|
43
|
+
const target = event.target;
|
|
44
|
+
scrollTop.value = target.scrollTop;
|
|
45
|
+
};
|
|
46
|
+
const scrollToIndex = index => {
|
|
47
|
+
if (containerRef.value) {
|
|
48
|
+
const targetScrollTop = index * itemHeight;
|
|
49
|
+
containerRef.value.scrollTop = targetScrollTop;
|
|
50
|
+
scrollTop.value = targetScrollTop;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
return {
|
|
54
|
+
visibleItems,
|
|
55
|
+
totalHeight,
|
|
56
|
+
offsetY,
|
|
57
|
+
startIndex: (0, _vue.computed)(() => startIndex.value),
|
|
58
|
+
endIndex: (0, _vue.computed)(() => endIndex.value),
|
|
59
|
+
onScroll,
|
|
60
|
+
scrollToIndex,
|
|
61
|
+
containerRef
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
module.exports = useVirtualScroll;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useVirtualScroll - 虚拟滚动 Hook
|
|
3
|
+
* @description 用于大数据量列表的虚拟滚动渲染
|
|
4
|
+
*/
|
|
5
|
+
import { type Ref, type ComputedRef } from 'vue';
|
|
6
|
+
export interface VirtualScrollOptions<T = unknown> {
|
|
7
|
+
/** 每项高度 */
|
|
8
|
+
itemHeight: number;
|
|
9
|
+
/** 容器高度 */
|
|
10
|
+
containerHeight: number;
|
|
11
|
+
/** 数据列表 */
|
|
12
|
+
items: Ref<T[]> | T[];
|
|
13
|
+
/** 上下额外渲染数量 */
|
|
14
|
+
overscan?: number;
|
|
15
|
+
}
|
|
16
|
+
export interface VirtualScrollReturn<T = unknown> {
|
|
17
|
+
/** 可见项列表 */
|
|
18
|
+
visibleItems: ComputedRef<T[]>;
|
|
19
|
+
/** 总高度 */
|
|
20
|
+
totalHeight: ComputedRef<number>;
|
|
21
|
+
/** Y轴偏移量 */
|
|
22
|
+
offsetY: ComputedRef<number>;
|
|
23
|
+
/** 起始索引 */
|
|
24
|
+
startIndex: Ref<number>;
|
|
25
|
+
/** 结束索引 */
|
|
26
|
+
endIndex: Ref<number>;
|
|
27
|
+
/** 滚动事件处理 */
|
|
28
|
+
onScroll: (event: Event) => void;
|
|
29
|
+
/** 滚动到指定索引 */
|
|
30
|
+
scrollToIndex: (index: number) => void;
|
|
31
|
+
/** 容器引用 */
|
|
32
|
+
containerRef: Ref<HTMLElement | null>;
|
|
33
|
+
}
|
|
34
|
+
export declare function useVirtualScroll<T = unknown>(options: VirtualScrollOptions<T>): VirtualScrollReturn<T>;
|
|
35
|
+
export default useVirtualScroll;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { ref, computed } from "vue";
|
|
2
|
+
export function useVirtualScroll(options) {
|
|
3
|
+
const { itemHeight, containerHeight, overscan = 3 } = options;
|
|
4
|
+
const containerRef = ref(null);
|
|
5
|
+
const scrollTop = ref(0);
|
|
6
|
+
const itemsRef = computed(() => {
|
|
7
|
+
const items = options.items;
|
|
8
|
+
return Array.isArray(items) ? items : items.value;
|
|
9
|
+
});
|
|
10
|
+
const totalHeight = computed(() => itemsRef.value.length * itemHeight);
|
|
11
|
+
const visibleCount = computed(() => Math.ceil(containerHeight / itemHeight));
|
|
12
|
+
const startIndex = computed(() => {
|
|
13
|
+
const items = itemsRef.value;
|
|
14
|
+
if (items.length === 0) return 0;
|
|
15
|
+
const start = Math.floor(scrollTop.value / itemHeight);
|
|
16
|
+
return Math.max(0, start - overscan);
|
|
17
|
+
});
|
|
18
|
+
const endIndex = computed(() => {
|
|
19
|
+
const items = itemsRef.value;
|
|
20
|
+
if (items.length === 0) return 0;
|
|
21
|
+
const start = Math.floor(scrollTop.value / itemHeight);
|
|
22
|
+
const end = start + visibleCount.value;
|
|
23
|
+
return Math.min(items.length, end + overscan);
|
|
24
|
+
});
|
|
25
|
+
const visibleItems = computed(() => {
|
|
26
|
+
const items = itemsRef.value;
|
|
27
|
+
if (items.length === 0) return [];
|
|
28
|
+
return items.slice(startIndex.value, endIndex.value);
|
|
29
|
+
});
|
|
30
|
+
const offsetY = computed(() => startIndex.value * itemHeight);
|
|
31
|
+
const onScroll = (event) => {
|
|
32
|
+
const target = event.target;
|
|
33
|
+
scrollTop.value = target.scrollTop;
|
|
34
|
+
};
|
|
35
|
+
const scrollToIndex = (index) => {
|
|
36
|
+
if (containerRef.value) {
|
|
37
|
+
const targetScrollTop = index * itemHeight;
|
|
38
|
+
containerRef.value.scrollTop = targetScrollTop;
|
|
39
|
+
scrollTop.value = targetScrollTop;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
return {
|
|
43
|
+
visibleItems,
|
|
44
|
+
totalHeight,
|
|
45
|
+
offsetY,
|
|
46
|
+
startIndex: computed(() => startIndex.value),
|
|
47
|
+
endIndex: computed(() => endIndex.value),
|
|
48
|
+
onScroll,
|
|
49
|
+
scrollToIndex,
|
|
50
|
+
containerRef
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export default useVirtualScroll;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.zIndexCounterKey = exports.zIndexContextKey = exports.useZIndex = exports.resetZIndex = exports.getNextZIndex = exports.createZIndexCounter = void 0;
|
|
7
|
+
var _vue = require("vue");
|
|
8
|
+
const defaultInitialZIndex = 2e3;
|
|
9
|
+
const zIndexContextKey = exports.zIndexContextKey = Symbol("zIndexContextKey");
|
|
10
|
+
const zIndexCounterKey = exports.zIndexCounterKey = Symbol("zIndexCounterKey");
|
|
11
|
+
const getNextZIndex = () => {
|
|
12
|
+
if (typeof window !== "undefined") {
|
|
13
|
+
const windowContext = window;
|
|
14
|
+
if (windowContext.__YH_Z_INDEX__ === void 0) {
|
|
15
|
+
windowContext.__YH_Z_INDEX__ = defaultInitialZIndex;
|
|
16
|
+
}
|
|
17
|
+
return ++windowContext.__YH_Z_INDEX__;
|
|
18
|
+
}
|
|
19
|
+
return defaultInitialZIndex;
|
|
20
|
+
};
|
|
21
|
+
exports.getNextZIndex = getNextZIndex;
|
|
22
|
+
const resetZIndex = (value = defaultInitialZIndex) => {
|
|
23
|
+
if (typeof window !== "undefined") {
|
|
24
|
+
;
|
|
25
|
+
window.__YH_Z_INDEX__ = value;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
exports.resetZIndex = resetZIndex;
|
|
29
|
+
const createZIndexCounter = (initialValue = defaultInitialZIndex) => {
|
|
30
|
+
return {
|
|
31
|
+
current: initialValue
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
exports.createZIndexCounter = createZIndexCounter;
|
|
35
|
+
const useZIndex = zIndexOverrides => {
|
|
36
|
+
const injectedZIndex = (0, _vue.inject)(zIndexContextKey, void 0);
|
|
37
|
+
const appCounter = (0, _vue.inject)(zIndexCounterKey, null);
|
|
38
|
+
const initialZIndex = (0, _vue.computed)(() => {
|
|
39
|
+
const override = (0, _vue.unref)(zIndexOverrides);
|
|
40
|
+
return override ?? (0, _vue.unref)(injectedZIndex) ?? defaultInitialZIndex;
|
|
41
|
+
});
|
|
42
|
+
const currentZIndex = (0, _vue.computed)(() => initialZIndex.value);
|
|
43
|
+
const nextZIndex = () => {
|
|
44
|
+
const override = (0, _vue.unref)(zIndexOverrides);
|
|
45
|
+
if (override !== void 0) return override;
|
|
46
|
+
if (appCounter) {
|
|
47
|
+
return ++appCounter.current;
|
|
48
|
+
}
|
|
49
|
+
return getNextZIndex();
|
|
50
|
+
};
|
|
51
|
+
return {
|
|
52
|
+
initialZIndex,
|
|
53
|
+
currentZIndex,
|
|
54
|
+
nextZIndex
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
exports.useZIndex = useZIndex;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { InjectionKey, Ref } from 'vue';
|
|
2
|
+
export declare const zIndexContextKey: InjectionKey<Ref<number | undefined>>;
|
|
3
|
+
export declare const zIndexCounterKey: InjectionKey<{
|
|
4
|
+
current: number;
|
|
5
|
+
}>;
|
|
6
|
+
export declare const getNextZIndex: () => number;
|
|
7
|
+
/**
|
|
8
|
+
* 重置 z-index 计数器
|
|
9
|
+
*/
|
|
10
|
+
export declare const resetZIndex: (value?: number) => void;
|
|
11
|
+
/**
|
|
12
|
+
* 创建 z-index 计数器(用于 provide)
|
|
13
|
+
*/
|
|
14
|
+
export declare const createZIndexCounter: (initialValue?: number) => {
|
|
15
|
+
current: number;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* useZIndex - z-index 管理
|
|
19
|
+
* @param zIndexOverrides - 可选的自定义 z-index
|
|
20
|
+
* @returns z-index 相关方法
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* const { currentZIndex, nextZIndex } = useZIndex()
|
|
24
|
+
*/
|
|
25
|
+
export declare const useZIndex: (zIndexOverrides?: Ref<number>) => {
|
|
26
|
+
initialZIndex: import("vue").ComputedRef<number>;
|
|
27
|
+
currentZIndex: import("vue").ComputedRef<number>;
|
|
28
|
+
nextZIndex: () => number;
|
|
29
|
+
};
|
|
30
|
+
export type UseZIndexReturn = ReturnType<typeof useZIndex>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { computed, inject, unref } from "vue";
|
|
2
|
+
const defaultInitialZIndex = 2e3;
|
|
3
|
+
export const zIndexContextKey = Symbol("zIndexContextKey");
|
|
4
|
+
export const zIndexCounterKey = Symbol("zIndexCounterKey");
|
|
5
|
+
export const getNextZIndex = () => {
|
|
6
|
+
if (typeof window !== "undefined") {
|
|
7
|
+
const windowContext = window;
|
|
8
|
+
if (windowContext.__YH_Z_INDEX__ === void 0) {
|
|
9
|
+
windowContext.__YH_Z_INDEX__ = defaultInitialZIndex;
|
|
10
|
+
}
|
|
11
|
+
return ++windowContext.__YH_Z_INDEX__;
|
|
12
|
+
}
|
|
13
|
+
return defaultInitialZIndex;
|
|
14
|
+
};
|
|
15
|
+
export const resetZIndex = (value = defaultInitialZIndex) => {
|
|
16
|
+
if (typeof window !== "undefined") {
|
|
17
|
+
;
|
|
18
|
+
window.__YH_Z_INDEX__ = value;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
export const createZIndexCounter = (initialValue = defaultInitialZIndex) => {
|
|
22
|
+
return { current: initialValue };
|
|
23
|
+
};
|
|
24
|
+
export const useZIndex = (zIndexOverrides) => {
|
|
25
|
+
const injectedZIndex = inject(zIndexContextKey, void 0);
|
|
26
|
+
const appCounter = inject(zIndexCounterKey, null);
|
|
27
|
+
const initialZIndex = computed(() => {
|
|
28
|
+
const override = unref(zIndexOverrides);
|
|
29
|
+
return override ?? unref(injectedZIndex) ?? defaultInitialZIndex;
|
|
30
|
+
});
|
|
31
|
+
const currentZIndex = computed(() => initialZIndex.value);
|
|
32
|
+
const nextZIndex = () => {
|
|
33
|
+
const override = unref(zIndexOverrides);
|
|
34
|
+
if (override !== void 0) return override;
|
|
35
|
+
if (appCounter) {
|
|
36
|
+
return ++appCounter.current;
|
|
37
|
+
}
|
|
38
|
+
return getNextZIndex();
|
|
39
|
+
};
|
|
40
|
+
return {
|
|
41
|
+
initialZIndex,
|
|
42
|
+
currentZIndex,
|
|
43
|
+
nextZIndex
|
|
44
|
+
};
|
|
45
|
+
};
|