@pawover/kit 0.5.1 → 0.7.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/README.en.md +123 -0
- package/README.md +123 -1
- package/entry/eslint-rules.cjs +1 -0
- package/entry/eslint-rules.d.cts +1 -0
- package/entry/eslint-rules.d.ts +2 -0
- package/entry/eslint-rules.js +2 -0
- package/entry/hooks-alova.cjs +1 -0
- package/entry/hooks-alova.d.cts +1 -0
- package/entry/hooks-alova.d.ts +1 -0
- package/entry/hooks-alova.js +1 -0
- package/entry/hooks-react.cjs +1 -0
- package/entry/hooks-react.d.cts +1 -0
- package/entry/hooks-react.d.ts +1 -0
- package/entry/hooks-react.js +1 -0
- package/entry/index.cjs +1 -0
- package/entry/index.d.cts +1 -0
- package/entry/index.d.ts +1 -0
- package/entry/index.js +1 -0
- package/entry/math.cjs +1 -0
- package/entry/math.d.cts +1 -0
- package/entry/math.d.ts +1 -0
- package/entry/math.js +1 -0
- package/entry/types-react.cjs +1 -0
- package/entry/types-react.d.cts +1 -0
- package/entry/types-react.d.ts +1 -0
- package/entry/types-react.js +1 -0
- package/entry/types.cjs +1 -0
- package/entry/types.d.cts +1 -0
- package/entry/types.d.ts +1 -0
- package/entry/types.js +1 -0
- package/entry/vite.cjs +1 -0
- package/entry/vite.d.cts +1 -0
- package/entry/vite.d.ts +1 -0
- package/entry/vite.js +1 -0
- package/entry/zod.cjs +1 -0
- package/entry/zod.d.cts +1 -0
- package/entry/zod.d.ts +1 -0
- package/entry/zod.js +1 -0
- package/package.json +78 -63
- package/packages/hooks/dist/alova.cjs +0 -53
- package/packages/hooks/dist/alova.d.cts +0 -1
- package/packages/hooks/dist/alova.d.ts +0 -33
- package/packages/hooks/dist/alova.js +0 -50
- package/packages/hooks/dist/index.cjs +0 -0
- package/packages/hooks/dist/index.d.cts +0 -1
- package/packages/hooks/dist/index.d.ts +0 -1
- package/packages/hooks/dist/index.js +0 -0
- package/packages/hooks/dist/react.cjs +0 -169
- package/packages/hooks/dist/react.d.cts +0 -1
- package/packages/hooks/dist/react.d.ts +0 -95
- package/packages/hooks/dist/react.js +0 -163
- package/packages/utils/dist/index.cjs +0 -2300
- package/packages/utils/dist/index.d.cts +0 -1
- package/packages/utils/dist/index.d.ts +0 -2739
- package/packages/utils/dist/index.js +0 -2287
- package/packages/utils/dist/math-BznvO4qI.cjs +0 -1029
- package/packages/utils/dist/math-DRbCtLQH.js +0 -1012
- package/packages/utils/dist/math.cjs +0 -3
- package/packages/utils/dist/math.d.cts +0 -1
- package/packages/utils/dist/math.d.ts +0 -60
- package/packages/utils/dist/math.js +0 -2
- package/packages/utils/dist/vite.cjs +0 -44
- package/packages/utils/dist/vite.d.cts +0 -1
- package/packages/utils/dist/vite.d.ts +0 -28
- package/packages/utils/dist/vite.js +0 -43
- package/packages/zod/dist/index.cjs +0 -91
- package/packages/zod/dist/index.d.cts +0 -1
- package/packages/zod/dist/index.d.ts +0 -57
- package/packages/zod/dist/index.js +0 -61
- /package/{packages/hooks/dist/metadata.json → entry/hooks-metadata.json} +0 -0
- /package/{packages/utils/dist → entry}/metadata.json +0 -0
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
let alova_client = require("alova/client");
|
|
3
|
-
//#region src/alova/createBeforeRequestMiddleware.ts
|
|
4
|
-
function createBeforeRequestMiddleware(middleware, onBeforeRequest) {
|
|
5
|
-
return async (context, next) => {
|
|
6
|
-
onBeforeRequest?.(context);
|
|
7
|
-
if (middleware) return middleware(context, next);
|
|
8
|
-
return next();
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
//#endregion
|
|
12
|
-
//#region src/alova/useAlovaPagination.ts
|
|
13
|
-
function useAlovaPagination(methodHandler, hookOptions) {
|
|
14
|
-
const options = {
|
|
15
|
-
...hookOptions,
|
|
16
|
-
immediate: hookOptions?.immediate ?? true
|
|
17
|
-
};
|
|
18
|
-
if (options.onBeforeRequest) options.middleware = createBeforeRequestMiddleware(options.middleware, options.onBeforeRequest);
|
|
19
|
-
const exposure = (0, alova_client.usePagination)(methodHandler, options);
|
|
20
|
-
if (options.onSuccess) exposure.onSuccess(options.onSuccess);
|
|
21
|
-
if (options.onError) exposure.onError(options.onError);
|
|
22
|
-
if (options.onComplete) exposure.onComplete(options.onComplete);
|
|
23
|
-
return exposure;
|
|
24
|
-
}
|
|
25
|
-
//#endregion
|
|
26
|
-
//#region src/alova/useAlovaRequest.ts
|
|
27
|
-
function useAlovaRequest(methodHandler, hookOptions) {
|
|
28
|
-
const options = {
|
|
29
|
-
...hookOptions,
|
|
30
|
-
immediate: hookOptions?.immediate ?? true
|
|
31
|
-
};
|
|
32
|
-
if (options.onBeforeRequest) options.middleware = createBeforeRequestMiddleware(options.middleware, options.onBeforeRequest);
|
|
33
|
-
const exposure = (0, alova_client.useRequest)(methodHandler, options);
|
|
34
|
-
if (options.onSuccess) exposure.onSuccess(options.onSuccess);
|
|
35
|
-
if (options.onError) exposure.onError(options.onError);
|
|
36
|
-
if (options.onComplete) exposure.onComplete(options.onComplete);
|
|
37
|
-
return exposure;
|
|
38
|
-
}
|
|
39
|
-
//#endregion
|
|
40
|
-
//#region src/alova/useAlovaWatcher.ts
|
|
41
|
-
function useAlovaWatcher(methodHandler, watchingStates, hookOptions = {}) {
|
|
42
|
-
const options = { ...hookOptions };
|
|
43
|
-
if (options.onBeforeRequest) options.middleware = createBeforeRequestMiddleware(options.middleware, options.onBeforeRequest);
|
|
44
|
-
const exposure = (0, alova_client.useWatcher)(methodHandler, watchingStates, options);
|
|
45
|
-
if (options.onSuccess) exposure.onSuccess(options.onSuccess);
|
|
46
|
-
if (options.onError) exposure.onError(options.onError);
|
|
47
|
-
if (options.onComplete) exposure.onComplete(options.onComplete);
|
|
48
|
-
return exposure;
|
|
49
|
-
}
|
|
50
|
-
//#endregion
|
|
51
|
-
exports.useAlovaPagination = useAlovaPagination;
|
|
52
|
-
exports.useAlovaRequest = useAlovaRequest;
|
|
53
|
-
exports.useAlovaWatcher = useAlovaWatcher;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export type * from './alova.d.ts'
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { AlovaFrontMiddlewareContext, AlovaMethodHandler, CompleteHandler, ErrorHandler, PaginationHookConfig, RequestHookConfig, SuccessHandler, WatcherHookConfig } from "alova/client";
|
|
2
|
-
import { AlovaGenerics, Method } from "alova";
|
|
3
|
-
//#region src/alova/useAlovaPagination.d.ts
|
|
4
|
-
interface HookOptions$2<AG extends AlovaGenerics, L extends any[], Args extends any[]> extends PaginationHookConfig<AG, L> {
|
|
5
|
-
onBeforeRequest?: BeforeRequestHandler<AG, any[]> | undefined;
|
|
6
|
-
onSuccess?: SuccessHandler<AG, Args> | undefined;
|
|
7
|
-
onError?: ErrorHandler<AG, Args> | undefined;
|
|
8
|
-
onComplete?: CompleteHandler<AG, Args> | undefined;
|
|
9
|
-
}
|
|
10
|
-
declare function useAlovaPagination<AG extends AlovaGenerics, L extends any[], Args extends any[]>(methodHandler: (page: number, pageSize: number, ...args: Args) => Method<AG>, hookOptions?: HookOptions$2<AG, L, Args> | undefined): import("alova/client").UsePaginationExposure<AG, L, Args>;
|
|
11
|
-
//#endregion
|
|
12
|
-
//#region src/alova/useAlovaRequest.d.ts
|
|
13
|
-
interface HookOptions$1<AG extends AlovaGenerics, Args extends any[]> extends RequestHookConfig<AG, Args> {
|
|
14
|
-
onBeforeRequest?: BeforeRequestHandler<AG, Args> | undefined;
|
|
15
|
-
onSuccess?: SuccessHandler<AG, Args> | undefined;
|
|
16
|
-
onError?: ErrorHandler<AG, Args> | undefined;
|
|
17
|
-
onComplete?: CompleteHandler<AG, Args> | undefined;
|
|
18
|
-
}
|
|
19
|
-
declare function useAlovaRequest<AG extends AlovaGenerics, Args extends any[] = any[]>(methodHandler: Method<AG> | AlovaMethodHandler<AG, Args>, hookOptions?: HookOptions$1<AG, Args> | undefined): import("alova/client").UseHookExposure<AG, Args, unknown>;
|
|
20
|
-
//#endregion
|
|
21
|
-
//#region src/alova/useAlovaWatcher.d.ts
|
|
22
|
-
interface HookOptions<AG extends AlovaGenerics, Args extends any[]> extends WatcherHookConfig<AG, Args> {
|
|
23
|
-
onBeforeRequest?: BeforeRequestHandler<AG, Args> | undefined;
|
|
24
|
-
onSuccess?: SuccessHandler<AG, Args> | undefined;
|
|
25
|
-
onError?: ErrorHandler<AG, Args> | undefined;
|
|
26
|
-
onComplete?: CompleteHandler<AG, Args> | undefined;
|
|
27
|
-
}
|
|
28
|
-
declare function useAlovaWatcher<AG extends AlovaGenerics, Args extends any[] = any[]>(methodHandler: Method<AG> | AlovaMethodHandler<AG, Args>, watchingStates: AG["StatesExport"]["Watched"][], hookOptions?: HookOptions<AG, Args>): import("alova/client").UseHookExposure<AG, Args, unknown>;
|
|
29
|
-
//#endregion
|
|
30
|
-
//#region src/alova/index.d.ts
|
|
31
|
-
type BeforeRequestHandler<AG extends AlovaGenerics, Args extends any[] = any[]> = (context: AlovaFrontMiddlewareContext<AG, Args>) => void;
|
|
32
|
-
//#endregion
|
|
33
|
-
export { BeforeRequestHandler, useAlovaPagination, useAlovaRequest, useAlovaWatcher };
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { usePagination, useRequest, useWatcher } from "alova/client";
|
|
2
|
-
//#region src/alova/createBeforeRequestMiddleware.ts
|
|
3
|
-
function createBeforeRequestMiddleware(middleware, onBeforeRequest) {
|
|
4
|
-
return async (context, next) => {
|
|
5
|
-
onBeforeRequest?.(context);
|
|
6
|
-
if (middleware) return middleware(context, next);
|
|
7
|
-
return next();
|
|
8
|
-
};
|
|
9
|
-
}
|
|
10
|
-
//#endregion
|
|
11
|
-
//#region src/alova/useAlovaPagination.ts
|
|
12
|
-
function useAlovaPagination(methodHandler, hookOptions) {
|
|
13
|
-
const options = {
|
|
14
|
-
...hookOptions,
|
|
15
|
-
immediate: hookOptions?.immediate ?? true
|
|
16
|
-
};
|
|
17
|
-
if (options.onBeforeRequest) options.middleware = createBeforeRequestMiddleware(options.middleware, options.onBeforeRequest);
|
|
18
|
-
const exposure = usePagination(methodHandler, options);
|
|
19
|
-
if (options.onSuccess) exposure.onSuccess(options.onSuccess);
|
|
20
|
-
if (options.onError) exposure.onError(options.onError);
|
|
21
|
-
if (options.onComplete) exposure.onComplete(options.onComplete);
|
|
22
|
-
return exposure;
|
|
23
|
-
}
|
|
24
|
-
//#endregion
|
|
25
|
-
//#region src/alova/useAlovaRequest.ts
|
|
26
|
-
function useAlovaRequest(methodHandler, hookOptions) {
|
|
27
|
-
const options = {
|
|
28
|
-
...hookOptions,
|
|
29
|
-
immediate: hookOptions?.immediate ?? true
|
|
30
|
-
};
|
|
31
|
-
if (options.onBeforeRequest) options.middleware = createBeforeRequestMiddleware(options.middleware, options.onBeforeRequest);
|
|
32
|
-
const exposure = useRequest(methodHandler, options);
|
|
33
|
-
if (options.onSuccess) exposure.onSuccess(options.onSuccess);
|
|
34
|
-
if (options.onError) exposure.onError(options.onError);
|
|
35
|
-
if (options.onComplete) exposure.onComplete(options.onComplete);
|
|
36
|
-
return exposure;
|
|
37
|
-
}
|
|
38
|
-
//#endregion
|
|
39
|
-
//#region src/alova/useAlovaWatcher.ts
|
|
40
|
-
function useAlovaWatcher(methodHandler, watchingStates, hookOptions = {}) {
|
|
41
|
-
const options = { ...hookOptions };
|
|
42
|
-
if (options.onBeforeRequest) options.middleware = createBeforeRequestMiddleware(options.middleware, options.onBeforeRequest);
|
|
43
|
-
const exposure = useWatcher(methodHandler, watchingStates, options);
|
|
44
|
-
if (options.onSuccess) exposure.onSuccess(options.onSuccess);
|
|
45
|
-
if (options.onError) exposure.onError(options.onError);
|
|
46
|
-
if (options.onComplete) exposure.onComplete(options.onComplete);
|
|
47
|
-
return exposure;
|
|
48
|
-
}
|
|
49
|
-
//#endregion
|
|
50
|
-
export { useAlovaPagination, useAlovaRequest, useAlovaWatcher };
|
|
File without changes
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export type * from './index.d.ts'
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {}
|
|
File without changes
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
let react = require("react");
|
|
3
|
-
let _pawover_kit_utils = require("@pawover/kit-utils");
|
|
4
|
-
let es_toolkit = require("es-toolkit");
|
|
5
|
-
//#region src/react/useLatest.ts
|
|
6
|
-
/**
|
|
7
|
-
* 返回当前最新值的 Hook
|
|
8
|
-
*
|
|
9
|
-
* @param value
|
|
10
|
-
*/
|
|
11
|
-
function useLatest(value) {
|
|
12
|
-
const ref = (0, react.useRef)(value);
|
|
13
|
-
ref.current = value;
|
|
14
|
-
return ref;
|
|
15
|
-
}
|
|
16
|
-
//#endregion
|
|
17
|
-
//#region src/react/useMount.ts
|
|
18
|
-
/**
|
|
19
|
-
* 在组件初始化时执行的 Hook
|
|
20
|
-
* - 即使在严格模式(React StrictMode)也只执行一次
|
|
21
|
-
* - 自动使用最新版 effect 函数
|
|
22
|
-
*
|
|
23
|
-
* @param effect 副作用函数(必须为同步函数;若为异步函数,清理逻辑需自行处理)
|
|
24
|
-
* @example
|
|
25
|
-
* useMount(() => {
|
|
26
|
-
* console.log('组件挂载');
|
|
27
|
-
* return () => console.log('组件卸载');
|
|
28
|
-
* });
|
|
29
|
-
*
|
|
30
|
-
* useMount(async () => {
|
|
31
|
-
* const data = await fetchData();
|
|
32
|
-
* // 清理逻辑需通过 ref/AbortController 自行管理
|
|
33
|
-
* // ❌ 不要 return cleanupFn(async 函数返回 Promise,无法作为清理函数)
|
|
34
|
-
* });
|
|
35
|
-
*/
|
|
36
|
-
function useMount(effect) {
|
|
37
|
-
const isMountedRef = (0, react.useRef)(false);
|
|
38
|
-
const effectRef = useLatest(effect);
|
|
39
|
-
(0, react.useEffect)(() => {
|
|
40
|
-
if (!_pawover_kit_utils.TypeUtil.isFunction(effectRef.current)) {
|
|
41
|
-
console.error(`hook [useMount] Expected parameter to be a function, but got ${typeof effectRef.current}. This effect will not execute.`);
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
if (isMountedRef.current) return;
|
|
45
|
-
isMountedRef.current = true;
|
|
46
|
-
const cleanup = effectRef.current?.();
|
|
47
|
-
return _pawover_kit_utils.TypeUtil.isFunction(cleanup) && !_pawover_kit_utils.TypeUtil.isPromise(cleanup) ? cleanup : void 0;
|
|
48
|
-
}, [effectRef]);
|
|
49
|
-
}
|
|
50
|
-
//#endregion
|
|
51
|
-
//#region src/react/useResponsive.ts
|
|
52
|
-
/** 屏幕响应断点 token 配置 */
|
|
53
|
-
const BREAK_POINT_TOKEN = {
|
|
54
|
-
XS: 480,
|
|
55
|
-
XSMax: 575,
|
|
56
|
-
XSMin: 480,
|
|
57
|
-
SM: 576,
|
|
58
|
-
SMMax: 767,
|
|
59
|
-
SMMin: 576,
|
|
60
|
-
MD: 768,
|
|
61
|
-
MDMax: 991,
|
|
62
|
-
MDMin: 768,
|
|
63
|
-
LG: 992,
|
|
64
|
-
LGMax: 1199,
|
|
65
|
-
LGMin: 992,
|
|
66
|
-
XL: 1200,
|
|
67
|
-
XLMax: 1599,
|
|
68
|
-
XLMin: 1200,
|
|
69
|
-
XXL: 1600,
|
|
70
|
-
XXLMax: 1919,
|
|
71
|
-
XXLMin: 1600,
|
|
72
|
-
XXXL: 1920,
|
|
73
|
-
XXXLMin: 1920
|
|
74
|
-
};
|
|
75
|
-
const SUBSCRIBER_SET = /* @__PURE__ */ new Set();
|
|
76
|
-
const BREAK_POINTS = [
|
|
77
|
-
"xxxl",
|
|
78
|
-
"xxl",
|
|
79
|
-
"xl",
|
|
80
|
-
"lg",
|
|
81
|
-
"md",
|
|
82
|
-
"sm",
|
|
83
|
-
"xs"
|
|
84
|
-
];
|
|
85
|
-
const DEFAULT_VALUES = Object.freeze(_pawover_kit_utils.ArrayUtil.zipToObject(BREAK_POINTS, false));
|
|
86
|
-
let responsiveValues = { ...DEFAULT_VALUES };
|
|
87
|
-
let responsiveTokens = (0, es_toolkit.clone)(BREAK_POINT_TOKEN);
|
|
88
|
-
function useResponsive(options) {
|
|
89
|
-
const { breakPointTokens = {} } = options || {};
|
|
90
|
-
const tokens = (0, react.useMemo)(() => Object.assign(BREAK_POINT_TOKEN, breakPointTokens), [breakPointTokens]);
|
|
91
|
-
const [responsive, setResponsive] = (0, react.useState)(() => calculateResponsive(tokens));
|
|
92
|
-
const current = _pawover_kit_utils.ObjectUtil.keys(DEFAULT_VALUES).find((key) => responsive[key] === true) || "xs";
|
|
93
|
-
(0, react.useLayoutEffect)(() => {
|
|
94
|
-
responsiveTokens = tokens;
|
|
95
|
-
window.addEventListener("resize", resizeListener);
|
|
96
|
-
const subscriber = () => {
|
|
97
|
-
setResponsive(responsiveValues);
|
|
98
|
-
};
|
|
99
|
-
SUBSCRIBER_SET.add(subscriber);
|
|
100
|
-
return () => {
|
|
101
|
-
SUBSCRIBER_SET.delete(subscriber);
|
|
102
|
-
if (!SUBSCRIBER_SET.size) window.removeEventListener("resize", resizeListener);
|
|
103
|
-
};
|
|
104
|
-
}, [tokens]);
|
|
105
|
-
return {
|
|
106
|
-
responsive,
|
|
107
|
-
current,
|
|
108
|
-
breakPointTokens: tokens
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
function resizeListener() {
|
|
112
|
-
const newValues = calculateResponsive(responsiveTokens);
|
|
113
|
-
if (!(0, es_toolkit.isEqual)(responsiveValues, newValues)) {
|
|
114
|
-
responsiveValues = newValues;
|
|
115
|
-
for (const subscriber of SUBSCRIBER_SET) subscriber();
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
function calculateResponsive(tokens) {
|
|
119
|
-
const config = _pawover_kit_utils.ArrayUtil.zipToObject(BREAK_POINTS, BREAK_POINTS.map((t) => tokens[_pawover_kit_utils.StringUtil.toUpperCase(t)]));
|
|
120
|
-
return _pawover_kit_utils.ObjectUtil.entriesMap(DEFAULT_VALUES, (key) => [key, window.innerWidth >= config[key]]);
|
|
121
|
-
}
|
|
122
|
-
//#endregion
|
|
123
|
-
//#region src/react/useUnmount.ts
|
|
124
|
-
/**
|
|
125
|
-
* 在组件卸载时执行的 Hook
|
|
126
|
-
*
|
|
127
|
-
* @param effect 副作用函数
|
|
128
|
-
*/
|
|
129
|
-
function useUnmount(effect) {
|
|
130
|
-
const effectRef = useLatest(effect);
|
|
131
|
-
(0, react.useEffect)(() => () => {
|
|
132
|
-
if (!_pawover_kit_utils.TypeUtil.isFunction(effectRef.current)) {
|
|
133
|
-
console.error(`hook [useUnmount] Expected parameter to be a function, but got ${typeof effectRef.current}. This effect will not execute.`);
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
effectRef.current?.();
|
|
137
|
-
}, [effectRef]);
|
|
138
|
-
}
|
|
139
|
-
//#endregion
|
|
140
|
-
//#region src/react/useTitle.ts
|
|
141
|
-
/**
|
|
142
|
-
* 设置页面标题
|
|
143
|
-
* - 轻量级,适用于无路由库时设置页面标题
|
|
144
|
-
* - 多个 `useTitle` 实例会互相干扰,需在顶层组件使用
|
|
145
|
-
* - 无法处理 `document.title` 固有的竞态问题
|
|
146
|
-
*
|
|
147
|
-
* @param title 页面标题
|
|
148
|
-
* @param options 配置选项
|
|
149
|
-
*/
|
|
150
|
-
function useTitle(title, options) {
|
|
151
|
-
const titleRef = (0, react.useRef)(_pawover_kit_utils.EnvUtil.isBrowser() ? document.title : "");
|
|
152
|
-
(0, react.useEffect)(() => {
|
|
153
|
-
if (!_pawover_kit_utils.TypeUtil.isString(title)) {
|
|
154
|
-
console.error(`hook [useTitle] Expected parameter to be a string, but got ${typeof title}. This effect will not execute.`);
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
if (_pawover_kit_utils.EnvUtil.isBrowser()) document.title = title;
|
|
158
|
-
}, [title]);
|
|
159
|
-
useUnmount(() => {
|
|
160
|
-
if (_pawover_kit_utils.EnvUtil.isBrowser() && options?.isRestoreOnUnmount) document.title = titleRef.current;
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
//#endregion
|
|
164
|
-
exports.BREAK_POINT_TOKEN = BREAK_POINT_TOKEN;
|
|
165
|
-
exports.useLatest = useLatest;
|
|
166
|
-
exports.useMount = useMount;
|
|
167
|
-
exports.useResponsive = useResponsive;
|
|
168
|
-
exports.useTitle = useTitle;
|
|
169
|
-
exports.useUnmount = useUnmount;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export type * from './react.d.ts'
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { EffectCallback, RefObject } from "react";
|
|
2
|
-
import { AnyAsyncFunction, AnyFunction } from "@pawover/types";
|
|
3
|
-
import { TupleToUnion } from "type-fest";
|
|
4
|
-
//#region src/react/useLatest.d.ts
|
|
5
|
-
/**
|
|
6
|
-
* 返回当前最新值的 Hook
|
|
7
|
-
*
|
|
8
|
-
* @param value
|
|
9
|
-
*/
|
|
10
|
-
declare function useLatest<T>(value: T): RefObject<T>;
|
|
11
|
-
//#endregion
|
|
12
|
-
//#region src/react/useMount.d.ts
|
|
13
|
-
/**
|
|
14
|
-
* 在组件初始化时执行的 Hook
|
|
15
|
-
* - 即使在严格模式(React StrictMode)也只执行一次
|
|
16
|
-
* - 自动使用最新版 effect 函数
|
|
17
|
-
*
|
|
18
|
-
* @param effect 副作用函数(必须为同步函数;若为异步函数,清理逻辑需自行处理)
|
|
19
|
-
* @example
|
|
20
|
-
* useMount(() => {
|
|
21
|
-
* console.log('组件挂载');
|
|
22
|
-
* return () => console.log('组件卸载');
|
|
23
|
-
* });
|
|
24
|
-
*
|
|
25
|
-
* useMount(async () => {
|
|
26
|
-
* const data = await fetchData();
|
|
27
|
-
* // 清理逻辑需通过 ref/AbortController 自行管理
|
|
28
|
-
* // ❌ 不要 return cleanupFn(async 函数返回 Promise,无法作为清理函数)
|
|
29
|
-
* });
|
|
30
|
-
*/
|
|
31
|
-
declare function useMount(effect: EffectCallback | AnyAsyncFunction): void;
|
|
32
|
-
//#endregion
|
|
33
|
-
//#region src/react/useResponsive.d.ts
|
|
34
|
-
type Breakpoint = TupleToUnion<typeof BREAK_POINTS>;
|
|
35
|
-
type ResponsiveValues = Record<Breakpoint, boolean>;
|
|
36
|
-
type BreakPointTokens = Record<keyof typeof BREAK_POINT_TOKEN, number>;
|
|
37
|
-
/** 屏幕响应断点 token 配置 */
|
|
38
|
-
declare const BREAK_POINT_TOKEN: {
|
|
39
|
-
readonly XS: 480;
|
|
40
|
-
readonly XSMax: 575;
|
|
41
|
-
readonly XSMin: 480;
|
|
42
|
-
readonly SM: 576;
|
|
43
|
-
readonly SMMax: 767;
|
|
44
|
-
readonly SMMin: 576;
|
|
45
|
-
readonly MD: 768;
|
|
46
|
-
readonly MDMax: 991;
|
|
47
|
-
readonly MDMin: 768;
|
|
48
|
-
readonly LG: 992;
|
|
49
|
-
readonly LGMax: 1199;
|
|
50
|
-
readonly LGMin: 992;
|
|
51
|
-
readonly XL: 1200;
|
|
52
|
-
readonly XLMax: 1599;
|
|
53
|
-
readonly XLMin: 1200;
|
|
54
|
-
readonly XXL: 1600;
|
|
55
|
-
readonly XXLMax: 1919;
|
|
56
|
-
readonly XXLMin: 1600;
|
|
57
|
-
readonly XXXL: 1920;
|
|
58
|
-
readonly XXXLMin: 1920;
|
|
59
|
-
};
|
|
60
|
-
declare const BREAK_POINTS: readonly ["xxxl", "xxl", "xl", "lg", "md", "sm", "xs"];
|
|
61
|
-
interface ResponsiveHookOptions {
|
|
62
|
-
/** 屏幕响应断点 token 配置 */
|
|
63
|
-
breakPointTokens?: BreakPointTokens;
|
|
64
|
-
}
|
|
65
|
-
declare function useResponsive(options?: ResponsiveHookOptions | undefined): {
|
|
66
|
-
responsive: ResponsiveValues;
|
|
67
|
-
current: "xxxl" | "xxl" | "xl" | "lg" | "md" | "sm" | "xs";
|
|
68
|
-
breakPointTokens: BreakPointTokens;
|
|
69
|
-
};
|
|
70
|
-
//#endregion
|
|
71
|
-
//#region src/react/useTitle.d.ts
|
|
72
|
-
interface TitleHookOptions {
|
|
73
|
-
/** 件卸载时是否恢复原始标题 */
|
|
74
|
-
isRestoreOnUnmount?: boolean;
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* 设置页面标题
|
|
78
|
-
* - 轻量级,适用于无路由库时设置页面标题
|
|
79
|
-
* - 多个 `useTitle` 实例会互相干扰,需在顶层组件使用
|
|
80
|
-
* - 无法处理 `document.title` 固有的竞态问题
|
|
81
|
-
*
|
|
82
|
-
* @param title 页面标题
|
|
83
|
-
* @param options 配置选项
|
|
84
|
-
*/
|
|
85
|
-
declare function useTitle(title: string, options?: TitleHookOptions | undefined): void;
|
|
86
|
-
//#endregion
|
|
87
|
-
//#region src/react/useUnmount.d.ts
|
|
88
|
-
/**
|
|
89
|
-
* 在组件卸载时执行的 Hook
|
|
90
|
-
*
|
|
91
|
-
* @param effect 副作用函数
|
|
92
|
-
*/
|
|
93
|
-
declare function useUnmount(effect: AnyFunction): void;
|
|
94
|
-
//#endregion
|
|
95
|
-
export { BREAK_POINT_TOKEN, BreakPointTokens, ResponsiveHookOptions, useLatest, useMount, useResponsive, useTitle, useUnmount };
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import { useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
2
|
-
import { ArrayUtil, EnvUtil, ObjectUtil, StringUtil, TypeUtil } from "@pawover/kit-utils";
|
|
3
|
-
import { clone, isEqual } from "es-toolkit";
|
|
4
|
-
//#region src/react/useLatest.ts
|
|
5
|
-
/**
|
|
6
|
-
* 返回当前最新值的 Hook
|
|
7
|
-
*
|
|
8
|
-
* @param value
|
|
9
|
-
*/
|
|
10
|
-
function useLatest(value) {
|
|
11
|
-
const ref = useRef(value);
|
|
12
|
-
ref.current = value;
|
|
13
|
-
return ref;
|
|
14
|
-
}
|
|
15
|
-
//#endregion
|
|
16
|
-
//#region src/react/useMount.ts
|
|
17
|
-
/**
|
|
18
|
-
* 在组件初始化时执行的 Hook
|
|
19
|
-
* - 即使在严格模式(React StrictMode)也只执行一次
|
|
20
|
-
* - 自动使用最新版 effect 函数
|
|
21
|
-
*
|
|
22
|
-
* @param effect 副作用函数(必须为同步函数;若为异步函数,清理逻辑需自行处理)
|
|
23
|
-
* @example
|
|
24
|
-
* useMount(() => {
|
|
25
|
-
* console.log('组件挂载');
|
|
26
|
-
* return () => console.log('组件卸载');
|
|
27
|
-
* });
|
|
28
|
-
*
|
|
29
|
-
* useMount(async () => {
|
|
30
|
-
* const data = await fetchData();
|
|
31
|
-
* // 清理逻辑需通过 ref/AbortController 自行管理
|
|
32
|
-
* // ❌ 不要 return cleanupFn(async 函数返回 Promise,无法作为清理函数)
|
|
33
|
-
* });
|
|
34
|
-
*/
|
|
35
|
-
function useMount(effect) {
|
|
36
|
-
const isMountedRef = useRef(false);
|
|
37
|
-
const effectRef = useLatest(effect);
|
|
38
|
-
useEffect(() => {
|
|
39
|
-
if (!TypeUtil.isFunction(effectRef.current)) {
|
|
40
|
-
console.error(`hook [useMount] Expected parameter to be a function, but got ${typeof effectRef.current}. This effect will not execute.`);
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
if (isMountedRef.current) return;
|
|
44
|
-
isMountedRef.current = true;
|
|
45
|
-
const cleanup = effectRef.current?.();
|
|
46
|
-
return TypeUtil.isFunction(cleanup) && !TypeUtil.isPromise(cleanup) ? cleanup : void 0;
|
|
47
|
-
}, [effectRef]);
|
|
48
|
-
}
|
|
49
|
-
//#endregion
|
|
50
|
-
//#region src/react/useResponsive.ts
|
|
51
|
-
/** 屏幕响应断点 token 配置 */
|
|
52
|
-
const BREAK_POINT_TOKEN = {
|
|
53
|
-
XS: 480,
|
|
54
|
-
XSMax: 575,
|
|
55
|
-
XSMin: 480,
|
|
56
|
-
SM: 576,
|
|
57
|
-
SMMax: 767,
|
|
58
|
-
SMMin: 576,
|
|
59
|
-
MD: 768,
|
|
60
|
-
MDMax: 991,
|
|
61
|
-
MDMin: 768,
|
|
62
|
-
LG: 992,
|
|
63
|
-
LGMax: 1199,
|
|
64
|
-
LGMin: 992,
|
|
65
|
-
XL: 1200,
|
|
66
|
-
XLMax: 1599,
|
|
67
|
-
XLMin: 1200,
|
|
68
|
-
XXL: 1600,
|
|
69
|
-
XXLMax: 1919,
|
|
70
|
-
XXLMin: 1600,
|
|
71
|
-
XXXL: 1920,
|
|
72
|
-
XXXLMin: 1920
|
|
73
|
-
};
|
|
74
|
-
const SUBSCRIBER_SET = /* @__PURE__ */ new Set();
|
|
75
|
-
const BREAK_POINTS = [
|
|
76
|
-
"xxxl",
|
|
77
|
-
"xxl",
|
|
78
|
-
"xl",
|
|
79
|
-
"lg",
|
|
80
|
-
"md",
|
|
81
|
-
"sm",
|
|
82
|
-
"xs"
|
|
83
|
-
];
|
|
84
|
-
const DEFAULT_VALUES = Object.freeze(ArrayUtil.zipToObject(BREAK_POINTS, false));
|
|
85
|
-
let responsiveValues = { ...DEFAULT_VALUES };
|
|
86
|
-
let responsiveTokens = clone(BREAK_POINT_TOKEN);
|
|
87
|
-
function useResponsive(options) {
|
|
88
|
-
const { breakPointTokens = {} } = options || {};
|
|
89
|
-
const tokens = useMemo(() => Object.assign(BREAK_POINT_TOKEN, breakPointTokens), [breakPointTokens]);
|
|
90
|
-
const [responsive, setResponsive] = useState(() => calculateResponsive(tokens));
|
|
91
|
-
const current = ObjectUtil.keys(DEFAULT_VALUES).find((key) => responsive[key] === true) || "xs";
|
|
92
|
-
useLayoutEffect(() => {
|
|
93
|
-
responsiveTokens = tokens;
|
|
94
|
-
window.addEventListener("resize", resizeListener);
|
|
95
|
-
const subscriber = () => {
|
|
96
|
-
setResponsive(responsiveValues);
|
|
97
|
-
};
|
|
98
|
-
SUBSCRIBER_SET.add(subscriber);
|
|
99
|
-
return () => {
|
|
100
|
-
SUBSCRIBER_SET.delete(subscriber);
|
|
101
|
-
if (!SUBSCRIBER_SET.size) window.removeEventListener("resize", resizeListener);
|
|
102
|
-
};
|
|
103
|
-
}, [tokens]);
|
|
104
|
-
return {
|
|
105
|
-
responsive,
|
|
106
|
-
current,
|
|
107
|
-
breakPointTokens: tokens
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
function resizeListener() {
|
|
111
|
-
const newValues = calculateResponsive(responsiveTokens);
|
|
112
|
-
if (!isEqual(responsiveValues, newValues)) {
|
|
113
|
-
responsiveValues = newValues;
|
|
114
|
-
for (const subscriber of SUBSCRIBER_SET) subscriber();
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
function calculateResponsive(tokens) {
|
|
118
|
-
const config = ArrayUtil.zipToObject(BREAK_POINTS, BREAK_POINTS.map((t) => tokens[StringUtil.toUpperCase(t)]));
|
|
119
|
-
return ObjectUtil.entriesMap(DEFAULT_VALUES, (key) => [key, window.innerWidth >= config[key]]);
|
|
120
|
-
}
|
|
121
|
-
//#endregion
|
|
122
|
-
//#region src/react/useUnmount.ts
|
|
123
|
-
/**
|
|
124
|
-
* 在组件卸载时执行的 Hook
|
|
125
|
-
*
|
|
126
|
-
* @param effect 副作用函数
|
|
127
|
-
*/
|
|
128
|
-
function useUnmount(effect) {
|
|
129
|
-
const effectRef = useLatest(effect);
|
|
130
|
-
useEffect(() => () => {
|
|
131
|
-
if (!TypeUtil.isFunction(effectRef.current)) {
|
|
132
|
-
console.error(`hook [useUnmount] Expected parameter to be a function, but got ${typeof effectRef.current}. This effect will not execute.`);
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
effectRef.current?.();
|
|
136
|
-
}, [effectRef]);
|
|
137
|
-
}
|
|
138
|
-
//#endregion
|
|
139
|
-
//#region src/react/useTitle.ts
|
|
140
|
-
/**
|
|
141
|
-
* 设置页面标题
|
|
142
|
-
* - 轻量级,适用于无路由库时设置页面标题
|
|
143
|
-
* - 多个 `useTitle` 实例会互相干扰,需在顶层组件使用
|
|
144
|
-
* - 无法处理 `document.title` 固有的竞态问题
|
|
145
|
-
*
|
|
146
|
-
* @param title 页面标题
|
|
147
|
-
* @param options 配置选项
|
|
148
|
-
*/
|
|
149
|
-
function useTitle(title, options) {
|
|
150
|
-
const titleRef = useRef(EnvUtil.isBrowser() ? document.title : "");
|
|
151
|
-
useEffect(() => {
|
|
152
|
-
if (!TypeUtil.isString(title)) {
|
|
153
|
-
console.error(`hook [useTitle] Expected parameter to be a string, but got ${typeof title}. This effect will not execute.`);
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
if (EnvUtil.isBrowser()) document.title = title;
|
|
157
|
-
}, [title]);
|
|
158
|
-
useUnmount(() => {
|
|
159
|
-
if (EnvUtil.isBrowser() && options?.isRestoreOnUnmount) document.title = titleRef.current;
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
//#endregion
|
|
163
|
-
export { BREAK_POINT_TOKEN, useLatest, useMount, useResponsive, useTitle, useUnmount };
|