@tsingroc/tsingroc-components 2.5.1 → 3.0.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.
@@ -2,10 +2,6 @@ import { type ReactNode } from "react";
2
2
  import { type JwtPayload } from "jwt-decode";
3
3
  import Sdk from "casdoor-js-sdk";
4
4
  import type { SdkConfig } from "casdoor-js-sdk/lib/esm/sdk";
5
- /** 获取全局的 Casdoor SDK,如果还没有初始化,就用 `config` 新建一个。*/
6
- export declare function getCasdoorSdk(config: SdkConfig): Sdk;
7
- /** 获取全局的 access token。未登录时返回 `null`。*/
8
- export declare function getAccessToken(): string | null;
9
5
  export interface AccessTokenPayload extends JwtPayload {
10
6
  /**
11
7
  * Token 的发布者。见 [JWT 标准][1]。
@@ -59,9 +55,6 @@ export interface AccessTokenPayload extends JwtPayload {
59
55
  tokenType: "access-token";
60
56
  scope: "profile";
61
57
  }
62
- /** 获取全局的 access token 并解码。解码得到的 payload 中也有一些用户信息,
63
- * 可以在一定程度上代替通过 API 获取用户信息。未登录时返回 `null`。*/
64
- export declare function getDecodedAccessToken(): AccessTokenPayload | undefined;
65
58
  export interface UserInfo {
66
59
  /**
67
60
  * Token 的发布者。见 [JWT 标准][1]。
@@ -100,53 +93,101 @@ export interface UserInfo {
100
93
  /** 用户的角色。*/
101
94
  roles: string[];
102
95
  }
96
+ interface User {
97
+ /** 用户的个人信息,未经过 {@linkcode AuthCheck} 验证时为空。*/
98
+ userInfo?: UserInfo;
99
+ /** Access Token,未登录时为空。*/
100
+ accessToken?: string;
101
+ /** 解码后的 Access Token,未登录时为空。这里也会有一些用户的个人信息。*/
102
+ decodedAccessToken?: AccessTokenPayload;
103
+ }
104
+ export interface Auth extends User {
105
+ /** 全局的 Casdoor SDK 对象。*/
106
+ sdk: Sdk;
107
+ /** 跳转到登录。*/
108
+ login(): void;
109
+ /** 从登录页面返回时应该调用的回调。当登录状态无效时会**抛出异常**。*/
110
+ callback(): Promise<void>;
111
+ /** 在线检查用户是否登录。用户未登录时会**抛出异常**。*/
112
+ validate(): Promise<void>;
113
+ /**
114
+ * 登出。
115
+ *
116
+ * 该函数只会清除全局的登录状态,不会自动做任何跳转。
117
+ * 因此,在调用 {@linkcode logout} 之后,请立刻紧跟一个跳转到合适页面(通常是主页)的操作!
118
+ */
119
+ logout(): void;
120
+ }
103
121
  /**
104
- * 获取用户信息。必须在开启了 {@linkcode AuthProviderProps.onlineCheck | onlineCheck}
105
- * 的 {@linkcode AuthProvider} 内部使用,否则返回 `undefined`。
122
+ * 获取登录鉴权相关的工具函数和全局状态。必须在 {@linkcode AuthProvider} 内部才能使用。
123
+ *
124
+ * 参数 `user` 仅供组件库内部使用,编写项目代码时可以忽略。
106
125
  */
107
- export declare function useUserInfo(): UserInfo | undefined;
126
+ export declare function useAuth(user?: string): Auth;
108
127
  export interface AuthProviderProps {
109
128
  /**
110
- * Casdoor SDK 的配置。
111
- *
112
- * **注意**:初始化的 SDK 将保存为全局变量,因此一个项目内不可有多个不同的 SDK 配置。
113
- * 通过 {@linkcode getCasdoorSdk} 可以获取到全局的 SDK。
129
+ * 用于初始化 Casdoor SDK 的配置对象。
130
+ * {@linkcode SdkConfig.redirectPath | sdkConfig.redirectPath} 应该指向一个包含
131
+ * {@linkcode AuthCallback} 组件的路径。
114
132
  */
115
133
  sdkConfig: SdkConfig;
134
+ /** 登录 API 的源点,末尾不带 `/`。*/
135
+ signinOrigin: string;
136
+ /**
137
+ * 登陆 API 的路径。
138
+ * @default "/api/signin"
139
+ */
140
+ signinPath?: string;
141
+ /** 需要管理登录状态的内容。*/
142
+ children: ReactNode;
143
+ }
144
+ /**
145
+ * 为包裹的内容提供登陆状态管理服务,通常应该包裹在整个 App 组件外部。
146
+ *
147
+ * 使用时至少需要提供 {@linkcode AuthProviderProps.sdkConfig | sdkConfig} 和
148
+ * {@linkcode AuthProviderProps.signinOrigin | signinOrigin} 两个属性。
149
+ * 其中,{@linkcode SdkConfig.redirectPath | sdkConfig.redirectPath} 应该指向一个包含
150
+ * {@linkcode AuthCallback} 组件的路径。
151
+ *
152
+ * 在 {@linkcode AuthProvider} 的内部,
153
+ * 可以使用 {@linkcode useAuth} 来获取登录鉴权相关的工具函数和全局状态,
154
+ * 也可以使用 {@linkcode AuthCheck} 来确保某个页面或内容只有已登录用户可以访问。
155
+ */
156
+ export declare function AuthProvider(props: AuthProviderProps): ReactNode;
157
+ export interface AuthCheckProps {
116
158
  /**
117
- * 是否联网检查用户登录状态有效性。如果检查,那么在内部还可以使用 {@linkcode useUserInfo} 访问到用户信息。
118
- * @default false
159
+ * 用户必须拥有的角色。用户必须拥有这里列出的所有角色才能访问被保护的内容。
160
+ * 如果省略,则只需要登录即可访问。
119
161
  */
120
- onlineCheck?: boolean;
162
+ roles?: string[];
121
163
  /**
122
- * 如果开启了 {@linkcode AuthProviderProps.onlineCheck | onlineCheck},在检查过程中时向用户显示的加载界面。
164
+ * 在检查过程中时向用户显示的加载界面。
123
165
  * @default "正在登录……"
124
166
  */
125
167
  loading?: ReactNode;
168
+ /**
169
+ * 当用户未登录或登录状态验证失败时的回调。默认会跳转到登录。
170
+ * @default () => auth.login() // auth = useAuth()
171
+ */
172
+ onFail?: (err: unknown) => void;
173
+ /**
174
+ * 用户已登录,但不满足权限要求时显示的内容。
175
+ * @default "您无权访问此页面!"
176
+ */
177
+ forbidden?: ReactNode;
126
178
  /** 用户登录后显示的内容。*/
127
179
  children: ReactNode;
128
180
  }
129
181
  /**
130
- * 确保只有已登录的用户可以访问到内部的内容,未登录的用户将被重定向到登录界面。
182
+ * 在线检查用户是否登录、是否满足权限要求。
183
+ * 未登录的用户会被跳转到登录,不满足权限要求的用户会见到警告信息,只有检验通过的用户才能访问内部的内容。
184
+ *
185
+ * 该组件必须在 {@linkcode AuthProvider} 内部才能使用。
131
186
  */
132
- export declare function AuthProvider(props: AuthProviderProps): ReactNode;
187
+ export declare function AuthCheck(props: AuthCheckProps): ReactNode;
133
188
  export interface AuthCallbackProps {
134
189
  /**
135
- * Casdoor SDK 的配置。
136
- *
137
- * **注意**:初始化的 SDK 将保存为全局变量,因此一个项目内不可有多个不同的 SDK 配置。
138
- * 通过 {@linkcode getCasdoorSdk} 可以获取到全局的 SDK。
139
- */
140
- sdkConfig: SdkConfig;
141
- /** 登录的 API 源点,末尾不带 `/`。*/
142
- signinOrigin: string;
143
- /**
144
- * 登陆的 API 路径。
145
- * @default "/api/signin"
146
- */
147
- signinPath?: string;
148
- /**
149
- * 跳转时的回调。可以使用 React Router 的跳转函数。
190
+ * 跳转时的回调。默认会跳转回主页。
150
191
  * @default () => { location.href = "/"; }
151
192
  */
152
193
  onRedirect?: () => void;
@@ -161,11 +202,10 @@ export interface AuthCallbackProps {
161
202
  */
162
203
  children?: ReactNode;
163
204
  }
164
- /** 登录的回调页面。*/
165
- export declare function AuthCallback(props: AuthCallbackProps): ReactNode;
166
205
  /**
167
- * 获得一个用于登出账号的函数。必须在 {@linkcode AuthProvider} 内部使用,否则在登出后将不会自动跳转。
206
+ * 从登录页面返回到的回调页面。
168
207
  *
169
- * **注意**:登出后默认会自动跳转到登录页面!为了更好的用户体验,最好在调用登出之后立即跳转到网站主页或者其它合适的页面。
208
+ * 该组件必须在 {@linkcode AuthProvider} 内部才能使用。
170
209
  */
171
- export declare function useLogout(): () => void;
210
+ export declare function AuthCallback(props: AuthCallbackProps): ReactNode;
211
+ export {};
@@ -1,102 +1,139 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { createContext, useContext, useEffect, useState, } from "react";
2
+ import { createContext, useContext, useEffect, useMemo, useState, } from "react";
3
3
  import { jwtDecode } from "jwt-decode";
4
4
  import Sdk from "casdoor-js-sdk";
5
- let casdoorSdk;
6
- /** 获取全局的 Casdoor SDK,如果还没有初始化,就用 `config` 新建一个。*/
7
- export function getCasdoorSdk(config) {
8
- return (casdoorSdk ?? (casdoorSdk = new Sdk(config)));
9
- }
10
- /** 获取全局的 access token。未登录时返回 `null`。*/
11
- export function getAccessToken() {
12
- return localStorage.getItem("access_token");
13
- }
14
- /** 获取全局的 access token 并解码。解码得到的 payload 中也有一些用户信息,
15
- * 可以在一定程度上代替通过 API 获取用户信息。未登录时返回 `null`。*/
16
- export function getDecodedAccessToken() {
17
- const token = getAccessToken();
18
- if (token === null)
19
- return;
20
- return jwtDecode(token);
21
- }
22
- const AuthContext = createContext({
23
- recheckToken: () => { },
24
- });
5
+ const AuthContext = createContext(undefined);
25
6
  /**
26
- * 获取用户信息。必须在开启了 {@linkcode AuthProviderProps.onlineCheck | onlineCheck}
27
- * 的 {@linkcode AuthProvider} 内部使用,否则返回 `undefined`。
7
+ * 获取登录鉴权相关的工具函数和全局状态。必须在 {@linkcode AuthProvider} 内部才能使用。
8
+ *
9
+ * 参数 `user` 仅供组件库内部使用,编写项目代码时可以忽略。
28
10
  */
29
- export function useUserInfo() {
30
- const { userInfo } = useContext(AuthContext);
31
- return userInfo;
11
+ export function useAuth(user = "useAuth") {
12
+ const auth = useContext(AuthContext);
13
+ if (auth === undefined) {
14
+ throw new Error(user + " 必须在 AuthProvider 内部使用!");
15
+ }
16
+ return auth;
32
17
  }
33
18
  /**
34
- * 确保只有已登录的用户可以访问到内部的内容,未登录的用户将被重定向到登录界面。
19
+ * 为包裹的内容提供登陆状态管理服务,通常应该包裹在整个 App 组件外部。
20
+ *
21
+ * 使用时至少需要提供 {@linkcode AuthProviderProps.sdkConfig | sdkConfig} 和
22
+ * {@linkcode AuthProviderProps.signinOrigin | signinOrigin} 两个属性。
23
+ * 其中,{@linkcode SdkConfig.redirectPath | sdkConfig.redirectPath} 应该指向一个包含
24
+ * {@linkcode AuthCallback} 组件的路径。
25
+ *
26
+ * 在 {@linkcode AuthProvider} 的内部,
27
+ * 可以使用 {@linkcode useAuth} 来获取登录鉴权相关的工具函数和全局状态,
28
+ * 也可以使用 {@linkcode AuthCheck} 来确保某个页面或内容只有已登录用户可以访问。
35
29
  */
36
30
  export function AuthProvider(props) {
37
- const sdk = getCasdoorSdk(props.sdkConfig);
38
- const [, recheckToken] = useState(0);
39
- const token = getAccessToken();
40
- const [userInfo, setUserInfo] = useState();
41
- useEffect(() => {
42
- if (token === null) {
43
- location.href = sdk.getSigninUrl();
31
+ const [user, setUser] = useState(() => {
32
+ const token = localStorage.getItem("access_token");
33
+ if (!token) {
34
+ return {};
44
35
  }
45
36
  else {
46
- if (props.onlineCheck) {
47
- sdk.getUserInfo(token).then((_resp) => {
48
- // sdk 的类型声明有误
49
- const resp = _resp;
50
- if ("status" in resp) {
51
- location.href = sdk.getSigninUrl();
52
- }
53
- else {
54
- setUserInfo(resp);
55
- }
56
- });
57
- }
37
+ return {
38
+ accessToken: token,
39
+ get decodedAccessToken() {
40
+ return jwtDecode(token);
41
+ },
42
+ };
58
43
  }
59
- }, [token, props.onlineCheck]);
60
- return token === null ? ("正在跳转到登录页……") : props.onlineCheck && userInfo === undefined ? ((props.loading ?? "正在登录……")) : (_jsx(AuthContext.Provider, { value: { userInfo, recheckToken: () => recheckToken((i) => i + 1) }, children: props.children }));
61
- }
62
- /** 登录的回调页面。*/
63
- export function AuthCallback(props) {
64
- const [error, setError] = useState();
65
- useEffect(() => {
66
- getCasdoorSdk(props.sdkConfig)
67
- .signin(props.signinOrigin, props.signinPath)
68
- .then((_resp) => {
44
+ });
45
+ const auth = useMemo(() => ({
46
+ sdk: new Sdk(props.sdkConfig),
47
+ login() {
48
+ location.href = this.sdk.getSigninUrl();
49
+ throw "unreachable";
50
+ },
51
+ async callback() {
69
52
  // sdk 的类型声明有误
70
- const resp = _resp;
71
- if (!resp.token) {
53
+ const resp = (await this.sdk.signin(props.signinOrigin, props.signinPath));
54
+ const token = resp.token;
55
+ if (!token) {
72
56
  throw new Error("登录 API 返回了异常的结果:" + JSON.stringify(resp));
73
57
  }
74
- localStorage.setItem("access_token", resp.token);
75
- if (props.onRedirect) {
76
- props.onRedirect();
58
+ localStorage.setItem("access_token", token);
59
+ setUser({
60
+ accessToken: token,
61
+ get decodedAccessToken() {
62
+ return jwtDecode(token);
63
+ },
64
+ });
65
+ },
66
+ async validate() {
67
+ const token = user.accessToken;
68
+ if (!token) {
69
+ throw new Error("未登录!");
70
+ }
71
+ // sdk 的类型声明有误
72
+ const resp = (await this.sdk.getUserInfo(token));
73
+ if ("status" in resp) {
74
+ localStorage.removeItem("access_token");
75
+ setUser({});
76
+ throw new Error("登陆状态无效!");
77
77
  }
78
78
  else {
79
- location.href = "/";
79
+ setUser({ ...user, userInfo: resp });
80
80
  }
81
- })
82
- .catch((err) => setError(err));
81
+ },
82
+ logout() {
83
+ localStorage.removeItem("access_token");
84
+ setTimeout(() => setUser({}), 0);
85
+ },
86
+ ...user,
87
+ }), [props.sdkConfig, props.signinOrigin, props.signinPath, user]);
88
+ return (_jsx(AuthContext.Provider, { value: auth, children: props.children }));
89
+ }
90
+ /**
91
+ * 在线检查用户是否登录、是否满足权限要求。
92
+ * 未登录的用户会被跳转到登录,不满足权限要求的用户会见到警告信息,只有检验通过的用户才能访问内部的内容。
93
+ *
94
+ * 该组件必须在 {@linkcode AuthProvider} 内部才能使用。
95
+ */
96
+ export function AuthCheck(props) {
97
+ const auth = useAuth("AuthCheck");
98
+ const userInfo = auth.userInfo;
99
+ useEffect(() => {
100
+ if (!auth.userInfo) {
101
+ auth.validate().catch(props.onFail ?? (() => auth.login()));
102
+ }
103
+ // 这个副作用只在首次渲染时执行
104
+ // eslint-disable-next-line react-hooks/exhaustive-deps
83
105
  }, []);
84
- return error
85
- ? props.error
86
- ? props.error(error)
87
- : error.toString()
88
- : (props.children ?? "正在跳转……");
106
+ if (userInfo) {
107
+ if ((props.roles ?? []).every((role) => userInfo.roles.includes(role))) {
108
+ return props.children;
109
+ }
110
+ else {
111
+ return props.forbidden ?? "您无权访问此页面!";
112
+ }
113
+ }
114
+ else {
115
+ return props.loading ?? "正在登录……";
116
+ }
89
117
  }
90
118
  /**
91
- * 获得一个用于登出账号的函数。必须在 {@linkcode AuthProvider} 内部使用,否则在登出后将不会自动跳转。
119
+ * 从登录页面返回到的回调页面。
92
120
  *
93
- * **注意**:登出后默认会自动跳转到登录页面!为了更好的用户体验,最好在调用登出之后立即跳转到网站主页或者其它合适的页面。
121
+ * 该组件必须在 {@linkcode AuthProvider} 内部才能使用。
94
122
  */
95
- export function useLogout() {
96
- const { recheckToken } = useContext(AuthContext);
97
- return () => {
98
- localStorage.removeItem("access_token");
99
- recheckToken();
100
- };
123
+ export function AuthCallback(props) {
124
+ const auth = useAuth("AuthCallback");
125
+ const [error, setError] = useState();
126
+ useEffect(() => {
127
+ auth.callback().then(props.onRedirect ??
128
+ (() => {
129
+ location.href = "/";
130
+ }), setError);
131
+ }, [auth, props.onRedirect]);
132
+ if (error) {
133
+ return props.error ? props.error(error) : error.toString();
134
+ }
135
+ else {
136
+ return props.children ?? "正在跳转……";
137
+ }
101
138
  }
102
139
  //# sourceMappingURL=Auth.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Auth.js","sourceRoot":"","sources":["../../src/components/Auth.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Auth.js","sourceRoot":"","sources":["../../src/components/Auth.tsx"],"names":[],"mappings":"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"}
@@ -58,8 +58,9 @@ export interface SidebarProps extends MenuProps {
58
58
  }
59
59
  /**
60
60
  * 出自 TMS 系统的侧边栏组件。该组件需要放置在 [Ant Design 的 `Layout` 组件][1]内部才能正常工作。
61
- * 如果没有提供 {@linkcode SidebarProps.footer | footer} 属性,
62
- * 那么还需要包裹在 {@linkcode AuthProvider} 内才能正常显示边栏底部的用户信息按钮。
61
+ * 如果没有指定 {@linkcode SidebarProps.footer | footer} 属性,
62
+ * 那么还需要包裹在 {@linkcode AuthProvider} 内,并且经过 {@linkcode AuthCheck} 验证后
63
+ * 才能正常显示边栏底部的用户信息按钮。
63
64
  *
64
65
  * 一般来说,使用该组件时至少需要提供 `logo`、`items` 和 `onSelect` 三个属性,具体用法请参照范例。
65
66
  *
@@ -4,7 +4,7 @@ import { Button, Flex, Layout, Menu } from "antd";
4
4
  import { useState } from "react";
5
5
  import { createStyles } from "antd-style";
6
6
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
7
- import { AuthProvider } from "./Auth";
7
+ import { AuthCheck, AuthProvider } from "./Auth";
8
8
  import UserButton from "./UserButton";
9
9
  const { Sider } = Layout;
10
10
  const menuItem = (label, key, icon, children) => ({ key, icon, children, label });
@@ -90,8 +90,9 @@ const useStyles = createStyles(({ token, css, cx, prefixCls }, collapsed) => {
90
90
  });
91
91
  /**
92
92
  * 出自 TMS 系统的侧边栏组件。该组件需要放置在 [Ant Design 的 `Layout` 组件][1]内部才能正常工作。
93
- * 如果没有提供 {@linkcode SidebarProps.footer | footer} 属性,
94
- * 那么还需要包裹在 {@linkcode AuthProvider} 内才能正常显示边栏底部的用户信息按钮。
93
+ * 如果没有指定 {@linkcode SidebarProps.footer | footer} 属性,
94
+ * 那么还需要包裹在 {@linkcode AuthProvider} 内,并且经过 {@linkcode AuthCheck} 验证后
95
+ * 才能正常显示边栏底部的用户信息按钮。
95
96
  *
96
97
  * 一般来说,使用该组件时至少需要提供 `logo`、`items` 和 `onSelect` 三个属性,具体用法请参照范例。
97
98
  *
@@ -1 +1 @@
1
- {"version":3,"file":"Sidebar.js","sourceRoot":"","sources":["../../src/components/Sidebar.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,YAAY,GACb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAkB,MAAM,MAAM,CAAC;AAClE,OAAO,EAA4B,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,6DAA6D;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,UAAU,MAAM,cAAc,CAAC;AAEtC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;AAIzB,MAAM,QAAQ,GAAG,CACf,KAAgB,EAChB,GAAQ,EACR,IAAgB,EAChB,QAAqB,EACX,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;AAEhD,yBAAyB;AACzB,MAAM,kBAAkB,GAAe;IACrC,QAAQ,CAAC,MAAM,EAAE,YAAY,EAAE,KAAC,gBAAgB,KAAG,EAAE;QACnD,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;QAC9B,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;QACrC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;KAChC,CAAC;IACF,QAAQ,CAAC,MAAM,EAAE,kBAAkB,EAAE,KAAC,YAAY,KAAG,EAAE;QACrD,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;QACnC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;QAC9B,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;KACrC,CAAC;IACF,QAAQ,CAAC,MAAM,EAAE,qBAAqB,EAAE,KAAC,YAAY,KAAG,EAAE;QACxD,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;QACrC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;QACpC,QAAQ,CAAC,OAAO,EAAE,qBAAqB,CAAC;QACxC,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;KACxC,CAAC;CACH,CAAC;AA0DF,MAAM,SAAS,GAAG,YAAY,CAC5B,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,SAAkB,EAAE,EAAE;IACpD,MAAM,aAAa,GAAG,GAAG,CAAA;oBACT,KAAK,CAAC,SAAS;;;;;;;kBAOjB,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS;qBAC5B,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ;;;;uBAI5B,KAAK,CAAC,iBAAiB;sBACxB,KAAK,CAAC,iBAAiB;;KAExC,CAAC;IACF,MAAM,WAAW,GAAG,GAAG,CAAA;;;KAGtB,CAAC;IACF,MAAM,UAAU,GAAG,GAAG,CAAA;;;;;;mBAMP,KAAK,CAAC,MAAM;;4BAEH,KAAK,CAAC,iBAAiB;;KAE9C,CAAC;IACF,MAAM,OAAO,GAAG,GAAG,CAAA;;;;WAIZ,SAAS;;;;;;WAMT,EAAE,CAAC,UAAU,CAAC;iBACR,KAAK,CAAC,eAAe;;WAE3B,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,WAAW,CAAC;;;;iBAI5B,EAAE,CAAC,UAAU,CAAC;;;KAG1B,CAAC;IACF,OAAO;QACL,OAAO;QACP,aAAa;QACb,WAAW;QACX,UAAU;KACX,CAAC;AACJ,CAAC,CACF,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,SAAS,OAAO,CAAC,KAAmB;IAClC,MAAM,EACJ,KAAK,GAAG,GAAG,EACX,WAAW,GAAG,KAAK,EACnB,IAAI,EACJ,KAAK,EACL,YAAY,GAAG,GAAG,EAClB,MAAM,EACN,KAAK,GAAG,kBAAkB,EAC1B,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,MAAM,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,KAAC,UAAU,IAAC,OAAO,EAAE,SAAS,GAAI,EAC1D,GAAG,IAAI,EACR,GAAG,KAAK,CAAC;IAEV,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;IAE5C,OAAO,CACL,MAAC,KAAK,IACJ,KAAK,EAAC,OAAO,EACb,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,EAC1C,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,IAAI,EACb,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,aAE5B,MAAM,CAAC,CAAC,CAAC,CACR,MAAM,CAAC,SAAS,CAAC,CAClB,CAAC,CAAC,CAAC,CACF,MAAC,IAAI,IACH,QAAQ,QACR,KAAK,EAAC,QAAQ,EACd,OAAO,EAAC,QAAQ,EAChB,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,EACnC,KAAK,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,aAE/B,cAAK,GAAG,EAAC,MAAM,EAAC,GAAG,EAAE,IAAI,GAAI,EAC7B,uBAAK,KAAK,GAAM,IACX,CACR,EACD,KAAC,IAAI,IACH,IAAI,EAAC,QAAQ,EACb,YAAY,EAAE,YAAY,EAC1B,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,QAAQ,EAClB,YAAY,EAAE,YAAY,EAC1B,KAAK,EAAE,KAAK,EACZ,eAAe,EAAE,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,EAChD,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,KAC7C,IAAI,GACR,EACD,MAAM,EAAE,CAAC,SAAS,CAAC,EACnB,WAAW,IAAI,CACd,KAAC,MAAM,IACL,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,EAChC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,KAAC,aAAa,KAAG,CAAC,CAAC,CAAC,KAAC,YAAY,KAAG,EACtD,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,GACvC,CACH,IACK,CACT,CAAC;AACJ,CAAC;AAED,eAAe,OAAO,CAAC"}
1
+ {"version":3,"file":"Sidebar.js","sourceRoot":"","sources":["../../src/components/Sidebar.tsx"],"names":[],"mappings":"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"}
@@ -1,33 +1,24 @@
1
1
  import { type ButtonProps, type DropdownProps } from "antd";
2
- import { type UserInfo } from "./Auth";
3
2
  export interface UserButtonProps extends ButtonProps {
4
3
  /**
5
4
  * 是否显示为缩小形态(只显示头像)。
6
5
  * @default false
7
6
  */
8
7
  compact?: boolean;
9
- /**
10
- * 用户的信息。
11
- *
12
- * 若省略,则将通过 {@linkcode useUserInfo} 获取,
13
- * 这意味着该组件必须放置在启用了 {@linkcode AuthProviderProps.onlineCheck | onlineCheck}
14
- * 的 {@linkcode AuthProvider} 内部。
15
- *
16
- * @default useUserInfo()
17
- */
18
- userInfo?: Partial<UserInfo>;
19
- /** 打开账户页面的回调。若省略,将不显示弹出菜单中的“账户”选项。*/
8
+ /** 点击“账户”时的操作。若省略,将不显示弹出菜单中的“账户”选项。*/
20
9
  onOpenProfile?: () => void;
21
10
  /**
22
- * 登出操作的回调。
23
- *
24
- * 若省略,则将使用 {@linkcode useLogout},这意味着该组件必须放置在 {@linkcode AuthProvider} 内部。
11
+ * 点击“登出”时的操作。默认先登出,然后跳转到主页。
25
12
  *
26
- * @default useLogout()
13
+ * @default
14
+ * () => {
15
+ * auth.logout(); // auth = useAuth()
16
+ * location.href = "/";
17
+ * }
27
18
  */
28
19
  onLogout?: () => void;
29
20
  /**
30
- * 下拉菜单的属性,见 [Ant Design 文档][1]
21
+ * 下拉菜单的属性,见 [Ant Design 文档][1]。你可以在这里覆盖弹出菜单的内容和样式。
31
22
  *
32
23
  * [1]: https://ant-design.antgroup.com/components/dropdown-cn
33
24
  */
@@ -35,7 +26,8 @@ export interface UserButtonProps extends ButtonProps {
35
26
  }
36
27
  /**
37
28
  * 显示用户信息的按钮,点击弹出登出或跳转到账户页的菜单。
38
- * 默认设置下,该组件必须包裹在 {@linkcode AuthProvider} 内才能正常工作。
29
+ * 该组件必须包裹在 {@linkcode AuthProvider} 内,并且经过 {@linkcode AuthCheck} 验证后,
30
+ * 才能正常显示用户信息,否则只会显示占位数据。
39
31
  *
40
32
  * 除了文档中列出的属性以外,该组件会把额外的属性传递给内部的 [`Button`][1] 组件。
41
33
  *
@@ -1,12 +1,12 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Avatar, Button, Dropdown, theme, } from "antd";
3
3
  import { LogoutOutlined, UpOutlined, UserOutlined } from "@ant-design/icons";
4
- import {
5
4
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
6
- AuthProvider, useLogout, useUserInfo, } from "./Auth";
5
+ import { AuthCheck, AuthProvider, useAuth } from "./Auth";
7
6
  /**
8
7
  * 显示用户信息的按钮,点击弹出登出或跳转到账户页的菜单。
9
- * 默认设置下,该组件必须包裹在 {@linkcode AuthProvider} 内才能正常工作。
8
+ * 该组件必须包裹在 {@linkcode AuthProvider} 内,并且经过 {@linkcode AuthCheck} 验证后,
9
+ * 才能正常显示用户信息,否则只会显示占位数据。
10
10
  *
11
11
  * 除了文档中列出的属性以外,该组件会把额外的属性传递给内部的 [`Button`][1] 组件。
12
12
  *
@@ -14,11 +14,12 @@ AuthProvider, useLogout, useUserInfo, } from "./Auth";
14
14
  */
15
15
  function UserButton(props) {
16
16
  const { token } = theme.useToken();
17
- const { compact,
18
- // eslint-disable-next-line react-hooks/rules-of-hooks
19
- userInfo = useUserInfo(), onOpenProfile,
20
- // eslint-disable-next-line react-hooks/rules-of-hooks
21
- onLogout = useLogout(), dropdownProps, ...rest } = props;
17
+ const auth = useAuth("UserButton");
18
+ const userInfo = auth.userInfo;
19
+ const { compact, onOpenProfile, onLogout = () => {
20
+ auth.logout();
21
+ location.href = "/";
22
+ }, dropdownProps, ...rest } = props;
22
23
  return (_jsx(Dropdown, { trigger: ["click"], placement: "topLeft", ...dropdownProps, menu: {
23
24
  items: [
24
25
  onOpenProfile
@@ -1 +1 @@
1
- {"version":3,"file":"UserButton.js","sourceRoot":"","sources":["../../src/components/UserButton.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,MAAM,EACN,MAAM,EAEN,QAAQ,EAER,KAAK,GACN,MAAM,MAAM,CAAC;AACd,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE7E,OAAO;AACL,6DAA6D;AAC7D,YAAY,EAGZ,SAAS,EAET,WAAW,GACZ,MAAM,QAAQ,CAAC;AAoChB;;;;;;;GAOG;AACH,SAAS,UAAU,CAAC,KAAsB;IACxC,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;IACnC,MAAM,EACJ,OAAO;IACP,sDAAsD;IACtD,QAAQ,GAAG,WAAW,EAAE,EACxB,aAAa;IACb,sDAAsD;IACtD,QAAQ,GAAG,SAAS,EAAE,EACtB,aAAa,EACb,GAAG,IAAI,EACR,GAAG,KAAK,CAAC;IACV,OAAO,CACL,KAAC,QAAQ,IACP,OAAO,EAAE,CAAC,OAAO,CAAC,EAClB,SAAS,EAAC,SAAS,KACf,aAAa,EACjB,IAAI,EAAE;YACJ,KAAK,EAAE;gBACL,aAAa;oBACX,CAAC,CAAC;wBACE,GAAG,EAAE,SAAS;wBACd,KAAK,EAAE,6CAAO,EAAE,0BAA0B;wBAC1C,IAAI,EAAE,KAAC,YAAY,KAAG;wBACtB,KAAK,EAAE,EAAE,EAAE,4BAA4B;wBACvC,OAAO,EAAE,aAAa;qBACvB;oBACH,CAAC,CAAC,IAAI;gBACR;oBACE,GAAG,EAAE,QAAQ;oBACb,IAAI,EAAE,KAAC,cAAc,KAAG;oBACxB,KAAK,EAAE,6CAAO;oBACd,KAAK,EAAE,EAAE;oBACT,OAAO,EAAE,QAAQ;iBAClB;aACF;YACD,GAAG,aAAa,EAAE,IAAI;YACtB,KAAK,EAAE;gBACL,QAAQ,EAAE,MAAM;gBAChB,GAAG,aAAa,EAAE,IAAI,EAAE,KAAK;aAC9B;SACF,YAED,KAAC,MAAM,IACL,IAAI,EAAC,MAAM,EACX,IAAI,EAAE,KAAC,MAAM,IAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAC,YAAY,KAAG,GAAI,KAC5D,IAAI,EACR,KAAK,EAAE;gBACL,KAAK,EAAE,MAAM;gBACb,MAAM,EAAE,KAAK,CAAC,SAAS;gBACvB,OAAO,EAAE,KAAK,CAAC,UAAU;gBACzB,GAAG,IAAI,CAAC,MAAM;aACf,YAEA,CAAC,OAAO,IAAI,CACX,8BACG,QAAQ,EAAE,IAAI,IAAI,QAAQ,EAAE,iBAAiB,IAAI,MAAM,EACxD,KAAC,UAAU,IAAC,KAAK,EAAE,EAAE,UAAU,EAAE,KAAK,CAAC,SAAS,EAAE,GAAI,IACrD,CACJ,GACM,GACA,CACZ,CAAC;AACJ,CAAC;AAED,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"UserButton.js","sourceRoot":"","sources":["../../src/components/UserButton.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,MAAM,EACN,MAAM,EAEN,QAAQ,EAER,KAAK,GACN,MAAM,MAAM,CAAC;AACd,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE7E,6DAA6D;AAC7D,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AA4B1D;;;;;;;;GAQG;AACH,SAAS,UAAU,CAAC,KAAsB;IACxC,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;IACnC,MAAM,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;IAC/B,MAAM,EACJ,OAAO,EACP,aAAa,EACb,QAAQ,GAAG,GAAG,EAAE;QACd,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,QAAQ,CAAC,IAAI,GAAG,GAAG,CAAC;IACtB,CAAC,EACD,aAAa,EACb,GAAG,IAAI,EACR,GAAG,KAAK,CAAC;IACV,OAAO,CACL,KAAC,QAAQ,IACP,OAAO,EAAE,CAAC,OAAO,CAAC,EAClB,SAAS,EAAC,SAAS,KACf,aAAa,EACjB,IAAI,EAAE;YACJ,KAAK,EAAE;gBACL,aAAa;oBACX,CAAC,CAAC;wBACE,GAAG,EAAE,SAAS;wBACd,KAAK,EAAE,6CAAO,EAAE,0BAA0B;wBAC1C,IAAI,EAAE,KAAC,YAAY,KAAG;wBACtB,KAAK,EAAE,EAAE,EAAE,4BAA4B;wBACvC,OAAO,EAAE,aAAa;qBACvB;oBACH,CAAC,CAAC,IAAI;gBACR;oBACE,GAAG,EAAE,QAAQ;oBACb,IAAI,EAAE,KAAC,cAAc,KAAG;oBACxB,KAAK,EAAE,6CAAO;oBACd,KAAK,EAAE,EAAE;oBACT,OAAO,EAAE,QAAQ;iBAClB;aACF;YACD,GAAG,aAAa,EAAE,IAAI;YACtB,KAAK,EAAE;gBACL,QAAQ,EAAE,MAAM;gBAChB,GAAG,aAAa,EAAE,IAAI,EAAE,KAAK;aAC9B;SACF,YAED,KAAC,MAAM,IACL,IAAI,EAAC,MAAM,EACX,IAAI,EAAE,KAAC,MAAM,IAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAC,YAAY,KAAG,GAAI,KAC5D,IAAI,EACR,KAAK,EAAE;gBACL,KAAK,EAAE,MAAM;gBACb,MAAM,EAAE,KAAK,CAAC,SAAS;gBACvB,OAAO,EAAE,KAAK,CAAC,UAAU;gBACzB,GAAG,IAAI,CAAC,MAAM;aACf,YAEA,CAAC,OAAO,IAAI,CACX,8BACG,QAAQ,EAAE,IAAI,IAAI,QAAQ,EAAE,iBAAiB,IAAI,MAAM,EACxD,KAAC,UAAU,IAAC,KAAK,EAAE,EAAE,UAAU,EAAE,KAAK,CAAC,SAAS,EAAE,GAAI,IACrD,CACJ,GACM,GACA,CACZ,CAAC;AACJ,CAAC;AAED,eAAe,UAAU,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,14 +1,10 @@
1
- export { getCasdoorSdk, getAccessToken, getDecodedAccessToken, useUserInfo, AuthProvider, type AuthProviderProps, AuthCallback, type AuthCallbackProps, useLogout, } from "./components/Auth";
1
+ export { AuthProvider, type AuthProviderProps, AuthCheck, type AuthCheckProps, AuthCallback, type AuthCallbackProps, useAuth, } from "./components/Auth";
2
2
  export { default as Calendar, type CalendarProps } from "./components/Calendar";
3
3
  export { default as CircularProgress, type CircularProgressProps, } from "./components/CircularProgress";
4
4
  export { default as ImageBackground, type ImageBackgroundProps, } from "./components/ImageBackground";
5
5
  export { default as QuickDateRangePicker, type QuickDateRangePickerProps, } from "./components/QuickDateRangePicker";
6
6
  export { default as SegmentedButtons, TimeUnitSwitcher, type TimeUnitSwitcherProps, } from "./components/SegmentedButtons";
7
- export { default as Sidebar,
8
- /** @deprecated 该名称已弃用,请改为导入 `Sidebar`。*/
9
- default as TmsSidebar, type SidebarProps,
10
- /** @deprecated 该名称已弃用,请改为导入 `SidebarProps`。*/
11
- type SidebarProps as TmsSidebarProps, } from "./components/Sidebar";
7
+ export { default as Sidebar, type SidebarProps } from "./components/Sidebar";
12
8
  export { default as TsingrocDatePicker, type DatePickerProps, } from "./components/TsingrocDatePicker";
13
9
  export { default as TsingrocTheme, type TsingrocThemeProps, } from "./components/TsingrocTheme";
14
10
  export { default as UserButton, type UserButtonProps, } from "./components/UserButton";
package/dist/index.js CHANGED
@@ -1,12 +1,10 @@
1
- export { getCasdoorSdk, getAccessToken, getDecodedAccessToken, useUserInfo, AuthProvider, AuthCallback, useLogout, } from "./components/Auth";
1
+ export { AuthProvider, AuthCheck, AuthCallback, useAuth, } from "./components/Auth";
2
2
  export { default as Calendar } from "./components/Calendar";
3
3
  export { default as CircularProgress, } from "./components/CircularProgress";
4
4
  export { default as ImageBackground, } from "./components/ImageBackground";
5
5
  export { default as QuickDateRangePicker, } from "./components/QuickDateRangePicker";
6
6
  export { default as SegmentedButtons, TimeUnitSwitcher, } from "./components/SegmentedButtons";
7
- export { default as Sidebar,
8
- /** @deprecated 该名称已弃用,请改为导入 `Sidebar`。*/
9
- default as TmsSidebar, } from "./components/Sidebar";
7
+ export { default as Sidebar } from "./components/Sidebar";
10
8
  export { default as TsingrocDatePicker, } from "./components/TsingrocDatePicker";
11
9
  export { default as TsingrocTheme, } from "./components/TsingrocTheme";
12
10
  export { default as UserButton, } from "./components/UserButton";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,cAAc,EACd,qBAAqB,EACrB,WAAW,EACX,YAAY,EAEZ,YAAY,EAEZ,SAAS,GACV,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAsB,MAAM,uBAAuB,CAAC;AAEhF,OAAO,EACL,OAAO,IAAI,gBAAgB,GAE5B,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EACL,OAAO,IAAI,eAAe,GAE3B,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,OAAO,IAAI,oBAAoB,GAEhC,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EACL,OAAO,IAAI,gBAAgB,EAC3B,gBAAgB,GAEjB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EACL,OAAO,IAAI,OAAO;AAClB,yCAAyC;AACzC,OAAO,IAAI,UAAU,GAItB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,OAAO,IAAI,kBAAkB,GAE9B,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EACL,OAAO,IAAI,aAAa,GAEzB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,OAAO,IAAI,UAAU,GAEtB,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EAEZ,SAAS,EAET,YAAY,EAEZ,OAAO,GACR,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAsB,MAAM,uBAAuB,CAAC;AAEhF,OAAO,EACL,OAAO,IAAI,gBAAgB,GAE5B,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EACL,OAAO,IAAI,eAAe,GAE3B,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,OAAO,IAAI,oBAAoB,GAEhC,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EACL,OAAO,IAAI,gBAAgB,EAC3B,gBAAgB,GAEjB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EAAE,OAAO,IAAI,OAAO,EAAqB,MAAM,sBAAsB,CAAC;AAE7E,OAAO,EACL,OAAO,IAAI,kBAAkB,GAE9B,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EACL,OAAO,IAAI,aAAa,GAEzB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,OAAO,IAAI,UAAU,GAEtB,MAAM,yBAAyB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsingroc/tsingroc-components",
3
- "version": "2.5.1",
3
+ "version": "3.0.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -26,7 +26,7 @@
26
26
  "license": "ISC",
27
27
  "dependencies": {
28
28
  "@ant-design/icons": "^5.6.1",
29
- "antd": "^5.24.7",
29
+ "antd": "^5.24.8",
30
30
  "antd-style": "^3.7.1",
31
31
  "casdoor-js-sdk": "^0.16.0",
32
32
  "dayjs": "^1.11.13",
@@ -38,14 +38,14 @@
38
38
  },
39
39
  "devDependencies": {
40
40
  "@eslint/js": "^9.21.0",
41
- "@rsbuild/core": "^1.3.9",
41
+ "@rsbuild/core": "^1.3.10",
42
42
  "@rsbuild/plugin-react": "^1.2.0",
43
43
  "@rspress/plugin-preview": "^2.0.0-alpha.0",
44
44
  "@types/node": "^22.14.1",
45
45
  "@types/react": "^18.3.20",
46
46
  "@types/react-dom": "^18.3.6",
47
47
  "echarts-for-react": "^3.0.2",
48
- "eslint": "^9.25.0",
48
+ "eslint": "^9.25.1",
49
49
  "eslint-plugin-react-hooks": "^5.2.0",
50
50
  "globals": "^16.0.0",
51
51
  "prettier": "^3.5.3",
@@ -54,7 +54,7 @@
54
54
  "rspress": "^2.0.0-alpha.8",
55
55
  "typedoc": "^0.28.3",
56
56
  "typescript": "^5.8.3",
57
- "typescript-eslint": "^8.30.1"
57
+ "typescript-eslint": "^8.31.0"
58
58
  },
59
59
  "directories": {
60
60
  "example": "example",