@chaos_team/chaos-ui 1.0.5
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/CHANGELOG.md +286 -0
- package/LICENSE +21 -0
- package/README.md +295 -0
- package/THIRD_PARTY_NOTICES.md +22 -0
- package/dist/business.cjs +26 -0
- package/dist/business.d.cts +10311 -0
- package/dist/business.d.ts +10311 -0
- package/dist/business.js +26 -0
- package/dist/format-BUpOzeCo.d.cts +8 -0
- package/dist/format-BUpOzeCo.d.ts +8 -0
- package/dist/hooks.cjs +8 -0
- package/dist/hooks.d.cts +1148 -0
- package/dist/hooks.d.ts +1148 -0
- package/dist/hooks.js +8 -0
- package/dist/index.cjs +6 -0
- package/dist/index.d.cts +5616 -0
- package/dist/index.d.ts +5616 -0
- package/dist/index.js +6 -0
- package/dist/lib.cjs +42 -0
- package/dist/lib.d.cts +804 -0
- package/dist/lib.d.ts +804 -0
- package/dist/lib.js +42 -0
- package/dist/message-KJli9tvf.d.cts +71 -0
- package/dist/message-KJli9tvf.d.ts +71 -0
- package/dist/message-provider-BI-P3CNq.d.cts +11 -0
- package/dist/message-provider-BI-P3CNq.d.ts +11 -0
- package/dist/next.cjs +6 -0
- package/dist/next.d.cts +103 -0
- package/dist/next.d.ts +103 -0
- package/dist/next.js +6 -0
- package/dist/theme-toggle-JL_jZE-w.d.cts +81 -0
- package/dist/theme-toggle-JL_jZE-w.d.ts +81 -0
- package/dist/time-picker-H1AaecnE.d.cts +452 -0
- package/dist/time-picker-H1AaecnE.d.ts +452 -0
- package/dist/ui/icons.cjs +6 -0
- package/dist/ui/icons.d.cts +3 -0
- package/dist/ui/icons.d.ts +3 -0
- package/dist/ui/icons.js +6 -0
- package/dist/ui-icons.cjs +6 -0
- package/dist/ui-icons.d.cts +205 -0
- package/dist/ui-icons.d.ts +205 -0
- package/dist/ui-icons.js +6 -0
- package/dist/ui.cjs +6 -0
- package/dist/ui.d.cts +39 -0
- package/dist/ui.d.ts +39 -0
- package/dist/ui.js +6 -0
- package/package.json +265 -0
- package/styles.css +1300 -0
- package/styles.css.d.ts +11 -0
package/dist/hooks.d.ts
ADDED
|
@@ -0,0 +1,1148 @@
|
|
|
1
|
+
import { M as MessageOptions } from './message-KJli9tvf.js';
|
|
2
|
+
import * as React$1 from 'react';
|
|
3
|
+
import * as react_hook_form from 'react-hook-form';
|
|
4
|
+
import { FieldValues, UseFormProps, Resolver } from 'react-hook-form';
|
|
5
|
+
import { UseQueryOptions, UseQueryResult, UseMutationOptions, UseMutationResult } from '@tanstack/react-query';
|
|
6
|
+
export { UseMutationOptions, UseMutationResult, UseQueryOptions, UseQueryResult } from '@tanstack/react-query';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @hook useBreakpoint
|
|
10
|
+
* @category hooks/responsive
|
|
11
|
+
* @since 0.2.0
|
|
12
|
+
* @description 响应式断点检测 / Responsive breakpoint detection
|
|
13
|
+
* @returns Current breakpoint key ('xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl')
|
|
14
|
+
* @example
|
|
15
|
+
* const bp = useBreakpoint();
|
|
16
|
+
* if (bp === 'xs') { ... }
|
|
17
|
+
*/
|
|
18
|
+
declare const breakpoints: {
|
|
19
|
+
readonly xs: 0;
|
|
20
|
+
readonly sm: 640;
|
|
21
|
+
readonly md: 768;
|
|
22
|
+
readonly lg: 1024;
|
|
23
|
+
readonly xl: 1280;
|
|
24
|
+
readonly "2xl": 1536;
|
|
25
|
+
};
|
|
26
|
+
type Breakpoint = keyof typeof breakpoints;
|
|
27
|
+
declare function useBreakpoint(): Breakpoint | undefined;
|
|
28
|
+
declare function useIsBreakpoint(breakpoint: Breakpoint): boolean;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @hook useEventListener
|
|
32
|
+
* @category hooks/effect
|
|
33
|
+
* @since 0.2.0
|
|
34
|
+
* @description DOM 事件订阅 / DOM event listener hook
|
|
35
|
+
* @example
|
|
36
|
+
* useEventListener(window, 'resize', () => console.log('resized'));
|
|
37
|
+
* useEventListener(document, 'keydown', handler);
|
|
38
|
+
*/
|
|
39
|
+
declare function useEventListener<T extends HTMLElement | Window | Document | MediaQueryList, K extends keyof WindowEventMap>(target: T | null | undefined, eventName: K, handler: (event: WindowEventMap[K]) => void, options?: AddEventListenerOptions): void;
|
|
40
|
+
declare function useEventListener(target: HTMLElement | Window | Document | MediaQueryList | null | undefined, eventName: string, handler: (event: Event) => void, options?: AddEventListenerOptions): void;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @hook useKey
|
|
44
|
+
* @category hooks/effect
|
|
45
|
+
* @since 0.2.0
|
|
46
|
+
* @description 键盘事件 Hook / Keyboard event hook
|
|
47
|
+
* @example
|
|
48
|
+
* useKey('Escape', () => close());
|
|
49
|
+
* useKey(['Meta+k', 'Control+k'], () => openPalette());
|
|
50
|
+
*/
|
|
51
|
+
type KeyFilter = string | string[] | ((event: KeyboardEvent) => boolean);
|
|
52
|
+
type KeyHandler = (event: KeyboardEvent) => void;
|
|
53
|
+
interface UseKeyOptions {
|
|
54
|
+
/** Event type: 'keydown' | 'keyup' | 'keypress' / 事件类型 */
|
|
55
|
+
event?: "keydown" | "keyup" | "keypress";
|
|
56
|
+
/** Target element (default: window) / 目标元素 */
|
|
57
|
+
target?: HTMLElement | Window | Document | null;
|
|
58
|
+
/** Whether to prevent default / 是否阻止默认行为 */
|
|
59
|
+
preventDefault?: boolean;
|
|
60
|
+
/** Whether the hook is active / 是否激活 */
|
|
61
|
+
enabled?: boolean;
|
|
62
|
+
}
|
|
63
|
+
declare function useKey(keys: KeyFilter, handler: KeyHandler, options?: UseKeyOptions): void;
|
|
64
|
+
declare function useKeyCombo(combo: string, handler: KeyHandler, options?: UseKeyOptions): void;
|
|
65
|
+
|
|
66
|
+
interface MessageInstance {
|
|
67
|
+
success: (content: React.ReactNode, options?: MessageOptions) => string | number;
|
|
68
|
+
error: (content: React.ReactNode, options?: MessageOptions) => string | number;
|
|
69
|
+
warning: (content: React.ReactNode, options?: MessageOptions) => string | number;
|
|
70
|
+
info: (content: React.ReactNode, options?: MessageOptions) => string | number;
|
|
71
|
+
loading: (content: React.ReactNode, options?: MessageOptions) => string | number;
|
|
72
|
+
promise: <T>(promise: Promise<T>, options: {
|
|
73
|
+
loading?: React.ReactNode;
|
|
74
|
+
success?: React.ReactNode | ((data: T) => React.ReactNode);
|
|
75
|
+
error?: React.ReactNode | ((err: unknown) => React.ReactNode);
|
|
76
|
+
}) => Promise<T>;
|
|
77
|
+
destroy: (id?: string | number) => void;
|
|
78
|
+
}
|
|
79
|
+
declare function useMessage(): MessageInstance;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @hook useNotification
|
|
83
|
+
* @category hooks/feedback
|
|
84
|
+
* @since 0.2.0
|
|
85
|
+
* @description 命令式通知 API / Imperative notification API (antd App.useApp().notification equivalent)
|
|
86
|
+
* @example
|
|
87
|
+
* const notification = useNotification();
|
|
88
|
+
* notification.open({ title: 'New Order', description: 'Order #123 received' });
|
|
89
|
+
*/
|
|
90
|
+
interface NotificationOptions {
|
|
91
|
+
id?: string | number;
|
|
92
|
+
title: React$1.ReactNode;
|
|
93
|
+
description?: React$1.ReactNode;
|
|
94
|
+
type?: "success" | "error" | "warning" | "info";
|
|
95
|
+
duration?: number;
|
|
96
|
+
position?: "top-left" | "top-right" | "bottom-left" | "bottom-right" | "top-center" | "bottom-center";
|
|
97
|
+
action?: {
|
|
98
|
+
label: string;
|
|
99
|
+
onClick: () => void;
|
|
100
|
+
};
|
|
101
|
+
dismissible?: boolean;
|
|
102
|
+
}
|
|
103
|
+
interface NotificationInstance {
|
|
104
|
+
open: (options: NotificationOptions) => string | number;
|
|
105
|
+
success: (options: Omit<NotificationOptions, "type">) => string | number;
|
|
106
|
+
error: (options: Omit<NotificationOptions, "type">) => string | number;
|
|
107
|
+
warning: (options: Omit<NotificationOptions, "type">) => string | number;
|
|
108
|
+
info: (options: Omit<NotificationOptions, "type">) => string | number;
|
|
109
|
+
close: (id?: string | number) => void;
|
|
110
|
+
closeAll: () => void;
|
|
111
|
+
}
|
|
112
|
+
declare function useNotification(): NotificationInstance;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* @hook useModal
|
|
116
|
+
* @category hooks/feedback
|
|
117
|
+
* @since 0.2.0
|
|
118
|
+
* @description 命令式模态框 API / Imperative modal API (antd Modal.confirm equivalent)
|
|
119
|
+
* @example
|
|
120
|
+
* const modal = useModal();
|
|
121
|
+
* modal.confirm({ title: 'Delete?', content: 'Are you sure?', onOk: handleDelete });
|
|
122
|
+
*/
|
|
123
|
+
interface ModalOptions {
|
|
124
|
+
title?: React$1.ReactNode;
|
|
125
|
+
content?: React$1.ReactNode;
|
|
126
|
+
okText?: string;
|
|
127
|
+
cancelText?: string;
|
|
128
|
+
okVariant?: "default" | "destructive";
|
|
129
|
+
onOk?: () => void | Promise<void>;
|
|
130
|
+
onCancel?: () => void;
|
|
131
|
+
width?: string | number;
|
|
132
|
+
closable?: boolean;
|
|
133
|
+
maskClosable?: boolean;
|
|
134
|
+
}
|
|
135
|
+
interface ModalInstance {
|
|
136
|
+
confirm: (options: ModalOptions) => void;
|
|
137
|
+
info: (options: Omit<ModalOptions, "okVariant" | "cancelText">) => void;
|
|
138
|
+
warning: (options: Omit<ModalOptions, "okVariant">) => void;
|
|
139
|
+
success: (options: Omit<ModalOptions, "okVariant">) => void;
|
|
140
|
+
error: (options: Omit<ModalOptions, "okVariant">) => void;
|
|
141
|
+
}
|
|
142
|
+
declare function useModal(): ModalInstance;
|
|
143
|
+
/**
|
|
144
|
+
* Helper component to render the modal from useModal
|
|
145
|
+
* Usage:
|
|
146
|
+
* const modal = useModal();
|
|
147
|
+
* return (<>
|
|
148
|
+
* {modal.confirm.modal}
|
|
149
|
+
* <Button onClick={() => modal.confirm({ title: 'Hi' })}>Open</Button>
|
|
150
|
+
* </>)
|
|
151
|
+
*/
|
|
152
|
+
declare function ModalRenderer({ modal }: {
|
|
153
|
+
modal: ModalInstance;
|
|
154
|
+
}): React$1.JSX.Element;
|
|
155
|
+
|
|
156
|
+
type AsyncStatus = "idle" | "pending" | "success" | "error";
|
|
157
|
+
declare function useAsync<T, Args extends unknown[] = []>(fn: (...args: Args) => Promise<T>, immediate?: boolean): {
|
|
158
|
+
run: (...args: Args) => Promise<T | undefined>;
|
|
159
|
+
isLoading: boolean;
|
|
160
|
+
status: AsyncStatus;
|
|
161
|
+
data: T | undefined;
|
|
162
|
+
error: Error | undefined;
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
type Handler = (event: MouseEvent | TouchEvent) => void;
|
|
166
|
+
declare function useClickOutside<T extends HTMLElement = HTMLElement>(ref: React$1.RefObject<T | null>, handler: Handler, enabled?: boolean): void;
|
|
167
|
+
|
|
168
|
+
declare function useCopyToClipboard(): [
|
|
169
|
+
boolean,
|
|
170
|
+
(value: string) => Promise<boolean>,
|
|
171
|
+
() => void
|
|
172
|
+
];
|
|
173
|
+
|
|
174
|
+
declare function useCountdown(target: Date | number | string): {
|
|
175
|
+
days: number;
|
|
176
|
+
hours: number;
|
|
177
|
+
minutes: number;
|
|
178
|
+
seconds: number;
|
|
179
|
+
isFinished: boolean;
|
|
180
|
+
totalSeconds: number;
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
declare function useDebounce<T>(value: T, delay?: number): T;
|
|
184
|
+
|
|
185
|
+
type KeyCombo = string;
|
|
186
|
+
type HotkeyHandler = (event: KeyboardEvent) => void;
|
|
187
|
+
interface HotkeyOptions {
|
|
188
|
+
enabled?: boolean;
|
|
189
|
+
preventDefault?: boolean;
|
|
190
|
+
allowInInputs?: boolean;
|
|
191
|
+
}
|
|
192
|
+
declare function useHotkeys(keys: Record<KeyCombo, HotkeyHandler>, options?: HotkeyOptions): void;
|
|
193
|
+
|
|
194
|
+
interface UseInfiniteScrollOptions {
|
|
195
|
+
threshold?: number;
|
|
196
|
+
rootMargin?: string;
|
|
197
|
+
enabled?: boolean;
|
|
198
|
+
}
|
|
199
|
+
declare function useInfiniteScroll<T>(loadMore: () => Promise<{
|
|
200
|
+
items: T[];
|
|
201
|
+
hasMore: boolean;
|
|
202
|
+
}> | {
|
|
203
|
+
items: T[];
|
|
204
|
+
hasMore: boolean;
|
|
205
|
+
}, options?: UseInfiniteScrollOptions): {
|
|
206
|
+
items: T[];
|
|
207
|
+
hasMore: boolean;
|
|
208
|
+
loading: boolean;
|
|
209
|
+
error: Error | null;
|
|
210
|
+
sentinelRef: React$1.RefObject<HTMLDivElement | null>;
|
|
211
|
+
loadMore: () => Promise<void>;
|
|
212
|
+
reset: () => void;
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
interface Options {
|
|
216
|
+
root?: Element | null;
|
|
217
|
+
rootMargin?: string;
|
|
218
|
+
threshold?: number | number[];
|
|
219
|
+
triggerOnce?: boolean;
|
|
220
|
+
enabled?: boolean;
|
|
221
|
+
}
|
|
222
|
+
declare function useIntersectionObserver<T extends Element>(ref: React$1.RefObject<T | null>, options?: Options): IntersectionObserverEntry | null;
|
|
223
|
+
declare function useInView<T extends Element>(ref: React$1.RefObject<T | null>, options?: Omit<Options, "enabled">): boolean;
|
|
224
|
+
|
|
225
|
+
declare function useLocalStorage<T>(key: string, initialValue: T): [T, (value: T | ((prev: T) => T)) => void, () => void];
|
|
226
|
+
|
|
227
|
+
declare function useMediaQuery(query: string): boolean;
|
|
228
|
+
declare const useIsDesktop: (breakpoint?: number) => boolean;
|
|
229
|
+
declare const useIsTablet: (min?: number, max?: number) => boolean;
|
|
230
|
+
|
|
231
|
+
declare function useIsMobile(): boolean;
|
|
232
|
+
|
|
233
|
+
interface PaginationState {
|
|
234
|
+
page: number;
|
|
235
|
+
pageSize: number;
|
|
236
|
+
}
|
|
237
|
+
interface PaginationResult extends PaginationState {
|
|
238
|
+
total: number;
|
|
239
|
+
totalPages: number;
|
|
240
|
+
offset: number;
|
|
241
|
+
hasNext: boolean;
|
|
242
|
+
hasPrev: boolean;
|
|
243
|
+
setPage: (page: number) => void;
|
|
244
|
+
setPageSize: (size: number) => void;
|
|
245
|
+
next: () => void;
|
|
246
|
+
prev: () => void;
|
|
247
|
+
first: () => void;
|
|
248
|
+
last: () => void;
|
|
249
|
+
}
|
|
250
|
+
declare function usePagination(total: number, initial?: Partial<PaginationState>): PaginationResult;
|
|
251
|
+
|
|
252
|
+
declare function usePrevious<T>(value: T): T | undefined;
|
|
253
|
+
|
|
254
|
+
declare function useStep(max: number, initial?: number): {
|
|
255
|
+
step: number;
|
|
256
|
+
next: () => void;
|
|
257
|
+
prev: () => void;
|
|
258
|
+
goTo: (i: number) => void;
|
|
259
|
+
reset: () => void;
|
|
260
|
+
isFirst: boolean;
|
|
261
|
+
isLast: boolean;
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
declare function useThrottle<T>(value: T, interval?: number): T;
|
|
265
|
+
|
|
266
|
+
declare function useToggle(initial?: boolean): [boolean, () => void, (value: boolean) => void];
|
|
267
|
+
|
|
268
|
+
declare const supportedLocales: readonly ["zh-CN", "en-US"];
|
|
269
|
+
type SupportedLocale = (typeof supportedLocales)[number];
|
|
270
|
+
declare function getStoredLocale(): string;
|
|
271
|
+
interface LocaleContextValue {
|
|
272
|
+
locale: string;
|
|
273
|
+
setLocale: (locale: string) => void;
|
|
274
|
+
supportedLocales: readonly string[];
|
|
275
|
+
}
|
|
276
|
+
interface LocaleProviderProps {
|
|
277
|
+
initialLocale?: string;
|
|
278
|
+
children: React.ReactNode;
|
|
279
|
+
}
|
|
280
|
+
declare function LocaleProvider({ initialLocale, children, }: LocaleProviderProps): React$1.JSX.Element;
|
|
281
|
+
declare function useLocale(): LocaleContextValue;
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* @hook useCrud
|
|
285
|
+
* @category hooks/business
|
|
286
|
+
* @since 0.5.0
|
|
287
|
+
* @description Generic CRUD state manager. Uses separate type params for
|
|
288
|
+
* the data row (T) and the form (F), so interfaces with optional fields
|
|
289
|
+
* like `shortName?: string` work without type errors.
|
|
290
|
+
*
|
|
291
|
+
* Supports multi-field filtering (`filters`) and pre-submit validation
|
|
292
|
+
* (`onValidate`), replacing the per-page useAsync + usePagination + useEffect
|
|
293
|
+
* boilerplate duplicated across business list pages.
|
|
294
|
+
* / 通用 CRUD 状态管理 hook,分离行类型和表单类型,支持多字段筛选与提交前校验。
|
|
295
|
+
* @keywords crud, hook, pagination, form, modal, state, filter, validate
|
|
296
|
+
* @example
|
|
297
|
+
* const crud = useCrud<Company, Partial<Company>>({
|
|
298
|
+
* fetcher: (page, pageSize, filters) =>
|
|
299
|
+
* api.list({ page, pageSize, ...filters }),
|
|
300
|
+
* filterFields: [
|
|
301
|
+
* { name: "keyword", type: "search" },
|
|
302
|
+
* { name: "status", type: "select", options: [...] },
|
|
303
|
+
* ],
|
|
304
|
+
* onValidate: (form) => (form.code ? null : "请填写必填项"),
|
|
305
|
+
* emptyForm: { id: 0, name: "", shortName: "" },
|
|
306
|
+
* rowKey: "id",
|
|
307
|
+
* successMessage: { create: "公司创建成功", update: "更新成功", delete: "已删除" },
|
|
308
|
+
* });
|
|
309
|
+
* crud.setFilters({ keyword: "x", status: "OPEN" });
|
|
310
|
+
*/
|
|
311
|
+
/** Per-operation success messages / 按操作分别配置成功消息 */
|
|
312
|
+
interface SuccessMessageMap {
|
|
313
|
+
create?: string;
|
|
314
|
+
update?: string;
|
|
315
|
+
delete?: string;
|
|
316
|
+
}
|
|
317
|
+
type SuccessMessage = string | false | SuccessMessageMap;
|
|
318
|
+
/** Filter field descriptor (drives generated filter UI). / 筛选字段描述 */
|
|
319
|
+
interface FilterField {
|
|
320
|
+
name: string;
|
|
321
|
+
type: "search" | "select";
|
|
322
|
+
/** Options for `select` type / select 类型的选项 */
|
|
323
|
+
options?: {
|
|
324
|
+
label: string;
|
|
325
|
+
value: string | number;
|
|
326
|
+
}[];
|
|
327
|
+
/** Placeholder / 占位文案 */
|
|
328
|
+
placeholder?: string;
|
|
329
|
+
}
|
|
330
|
+
/** Aggregated filter values (string-keyed). / 筛选值聚合 */
|
|
331
|
+
type Filters = Record<string, unknown>;
|
|
332
|
+
interface UseCrudConfig<T, F = Partial<T>> {
|
|
333
|
+
/**
|
|
334
|
+
* Fetcher receives page, pageSize, and the current filters object.
|
|
335
|
+
* Replaces the old single-`keyword` signature so multi-filter pages
|
|
336
|
+
* (keyword + status + categoryId + ...) don't need hand-rolled wiring.
|
|
337
|
+
* / 获取数据,filters 替代旧的单 keyword 签名
|
|
338
|
+
*/
|
|
339
|
+
fetcher: (page: number, pageSize: number, filters: Filters) => Promise<{
|
|
340
|
+
list: T[];
|
|
341
|
+
total: number;
|
|
342
|
+
}>;
|
|
343
|
+
onCreate?: (form: F) => Promise<unknown>;
|
|
344
|
+
onUpdate?: (id: string | number, form: F) => Promise<unknown>;
|
|
345
|
+
onDelete?: (id: string | number) => Promise<unknown>;
|
|
346
|
+
rowKey?: keyof T & string;
|
|
347
|
+
/** Empty form template — type F, independent of T's required fields / 空表单模板 */
|
|
348
|
+
emptyForm: F;
|
|
349
|
+
defaultPageSize?: number;
|
|
350
|
+
/**
|
|
351
|
+
* Pre-submit validation. Return an error message string to block submit
|
|
352
|
+
* (shown via message.error), or `null` to proceed.
|
|
353
|
+
* / 提交前校验:返回错误文案拦截提交,null 放行
|
|
354
|
+
*/
|
|
355
|
+
onValidate?: (form: F) => string | null;
|
|
356
|
+
/** Filter field descriptors (for generated filter UI). / 筛选字段描述 */
|
|
357
|
+
filterFields?: FilterField[];
|
|
358
|
+
/** Initial filter values. / 初始筛选值 */
|
|
359
|
+
defaultFilters?: Filters;
|
|
360
|
+
/**
|
|
361
|
+
* Success message after create/update/delete.
|
|
362
|
+
* - `string` — used for all operations
|
|
363
|
+
* - `false` — disable success messages
|
|
364
|
+
* - `{ create?, update?, delete? }` — per-operation messages
|
|
365
|
+
* / 成功提示:字符串=全部, false=禁用, 对象=按操作分别配置
|
|
366
|
+
*/
|
|
367
|
+
successMessage?: SuccessMessage;
|
|
368
|
+
deleteConfirmTitle?: string;
|
|
369
|
+
}
|
|
370
|
+
interface UseCrudReturn<T, F = Partial<T>> {
|
|
371
|
+
data: T[];
|
|
372
|
+
total: number;
|
|
373
|
+
loading: boolean;
|
|
374
|
+
/** Current filter values / 当前筛选值 */
|
|
375
|
+
filters: Filters;
|
|
376
|
+
/**
|
|
377
|
+
* Merge a partial patch into filters (shallow merge) and reset to page 1.
|
|
378
|
+
* / 合并筛选值(浅合并)并重置到第 1 页
|
|
379
|
+
*/
|
|
380
|
+
setFilters: (patch: Filters) => void;
|
|
381
|
+
/** Replace filters entirely and reset to page 1. / 整体替换筛选值 */
|
|
382
|
+
resetFilters: (next: Filters) => void;
|
|
383
|
+
pagination: ReturnType<typeof usePagination>;
|
|
384
|
+
modalOpen: boolean;
|
|
385
|
+
setModalOpen: (v: boolean) => void;
|
|
386
|
+
editing: T | null;
|
|
387
|
+
form: F;
|
|
388
|
+
setForm: React$1.Dispatch<React$1.SetStateAction<F>>;
|
|
389
|
+
/** Update a single form field / 更新单个表单字段 */
|
|
390
|
+
updateFormField: <K extends keyof F>(key: K, value: F[K]) => void;
|
|
391
|
+
handleAdd: () => void;
|
|
392
|
+
handleEdit: (record: T) => void;
|
|
393
|
+
handleSubmit: () => Promise<void>;
|
|
394
|
+
handleDelete: (record: T) => Promise<void>;
|
|
395
|
+
refresh: () => void;
|
|
396
|
+
isEdit: boolean;
|
|
397
|
+
}
|
|
398
|
+
declare function useCrud<T extends Record<string, unknown>, F = Partial<T>>(config: UseCrudConfig<T, F>): UseCrudReturn<T, F>;
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* @hook usePageTitle
|
|
402
|
+
* @category hooks/browser
|
|
403
|
+
* @since 0.5.0
|
|
404
|
+
* @description Sets `document.title` with a template. Eliminates the manual
|
|
405
|
+
* `useEffect(() => { document.title = ... }, [pathname])` pattern.
|
|
406
|
+
* / 设置页面标题,自动拼接 title template,消除手动 useEffect 模式
|
|
407
|
+
* @keywords title, page, document, browser, hook
|
|
408
|
+
* @example
|
|
409
|
+
* usePageTitle("订单列表", { template: "{title} · 清香园营销管理系统" })
|
|
410
|
+
* // → "订单列表 · 清香园营销管理系统"
|
|
411
|
+
*/
|
|
412
|
+
interface UsePageTitleOptions {
|
|
413
|
+
/** Title template. `{title}` placeholder is replaced with the title arg.
|
|
414
|
+
* / 标题模板,{title} 占位符会被替换 */
|
|
415
|
+
template?: string;
|
|
416
|
+
/** Fallback title when no title is provided / 无标题时的回退值 */
|
|
417
|
+
defaultTitle?: string;
|
|
418
|
+
}
|
|
419
|
+
declare function usePageTitle(title?: string, { template, defaultTitle }?: UsePageTitleOptions): void;
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* @hook useConfirmAsync
|
|
423
|
+
* @category hooks/feedback
|
|
424
|
+
* @since 0.5.0
|
|
425
|
+
* @description Imperative confirm API. Two usage modes:
|
|
426
|
+
*
|
|
427
|
+
* 1. **Hook mode** — requires rendering `<ConfirmDialog />` in JSX:
|
|
428
|
+
* const [confirm, ConfirmDialog] = useConfirmAsync();
|
|
429
|
+
* const ok = await confirm({ title: "Delete?" });
|
|
430
|
+
* return <>{ConfirmDialog}</>
|
|
431
|
+
*
|
|
432
|
+
* 2. **Provider mode** — auto-mounts via `ConfirmProvider`, no JSX needed:
|
|
433
|
+
* // In app root:
|
|
434
|
+
* <ConfirmProvider>...</ConfirmProvider>
|
|
435
|
+
* // Anywhere:
|
|
436
|
+
* const confirmed = await confirmAsync({ title: "Delete?" });
|
|
437
|
+
*
|
|
438
|
+
* / 命令式确认 API,支持手动挂载和 Provider 自动挂载两种模式
|
|
439
|
+
* @keywords confirm, dialog, imperative, async, modal, provider
|
|
440
|
+
*/
|
|
441
|
+
interface ConfirmOptions {
|
|
442
|
+
title?: string;
|
|
443
|
+
content?: React$1.ReactNode;
|
|
444
|
+
okText?: string;
|
|
445
|
+
cancelText?: string;
|
|
446
|
+
okVariant?: "default" | "destructive";
|
|
447
|
+
icon?: React$1.ReactNode;
|
|
448
|
+
}
|
|
449
|
+
type ConfirmFn = (options: ConfirmOptions) => Promise<boolean>;
|
|
450
|
+
/**
|
|
451
|
+
* `confirmAsync` — global imperative confirm when ConfirmProvider is mounted.
|
|
452
|
+
* Call from any component without rendering a dialog yourself.
|
|
453
|
+
* / 全局命令式确认,需 ConfirmProvider 包裹
|
|
454
|
+
* @throws Error if called outside ConfirmProvider
|
|
455
|
+
*/
|
|
456
|
+
declare function confirmAsync(options: ConfirmOptions): Promise<boolean>;
|
|
457
|
+
interface ConfirmProviderProps {
|
|
458
|
+
children: React$1.ReactNode;
|
|
459
|
+
/** Default options merged into every call / 全局默认选项 */
|
|
460
|
+
defaultOptions?: ConfirmOptions;
|
|
461
|
+
}
|
|
462
|
+
declare function ConfirmProvider({ children, defaultOptions }: ConfirmProviderProps): React$1.JSX.Element;
|
|
463
|
+
declare function useConfirmAsync(): [
|
|
464
|
+
(options: ConfirmOptions) => Promise<boolean>,
|
|
465
|
+
() => React$1.ReactNode
|
|
466
|
+
];
|
|
467
|
+
declare function useConfirmContext(): ConfirmFn;
|
|
468
|
+
|
|
469
|
+
interface ValidationRule {
|
|
470
|
+
type: "required" | "min" | "max" | "pattern" | "custom";
|
|
471
|
+
message: string;
|
|
472
|
+
value?: number | RegExp | ((v: unknown) => boolean);
|
|
473
|
+
}
|
|
474
|
+
interface UseFieldValidationOptions {
|
|
475
|
+
rules?: ValidationRule[];
|
|
476
|
+
externalError?: string;
|
|
477
|
+
validateOnBlur?: boolean;
|
|
478
|
+
validateOnChange?: boolean;
|
|
479
|
+
}
|
|
480
|
+
declare function useFieldValidation(options?: UseFieldValidationOptions): {
|
|
481
|
+
error: string | undefined;
|
|
482
|
+
onBlur: (e: React$1.FocusEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => void;
|
|
483
|
+
onChange: (e: React$1.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => void;
|
|
484
|
+
validate: (value: unknown) => string | undefined;
|
|
485
|
+
reset: () => void;
|
|
486
|
+
touched: boolean;
|
|
487
|
+
};
|
|
488
|
+
|
|
489
|
+
interface NetworkState {
|
|
490
|
+
online: boolean;
|
|
491
|
+
downlink?: number | undefined;
|
|
492
|
+
effectiveType?: string | undefined;
|
|
493
|
+
rtt?: number | undefined;
|
|
494
|
+
saveData?: boolean | undefined;
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* Tracks browser online/offline status and network info via Navigator.connection API.
|
|
498
|
+
* @since 0.2.0
|
|
499
|
+
*/
|
|
500
|
+
declare function useNetworkStatus(): NetworkState;
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Tracks page visibility changes (tab focus/blur, minimize).
|
|
504
|
+
* @param onChange - Optional callback when visibility changes
|
|
505
|
+
* @returns Whether the page is currently visible
|
|
506
|
+
* @since 0.2.0
|
|
507
|
+
*/
|
|
508
|
+
declare function useVisibilityChange(onChange?: (visible: boolean) => void): boolean;
|
|
509
|
+
|
|
510
|
+
interface WindowSize {
|
|
511
|
+
width: number;
|
|
512
|
+
height: number;
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Reactive window dimensions, updated on resize (debounced).
|
|
516
|
+
* @param debounceMs - Debounce delay in ms (default 100)
|
|
517
|
+
* @since 0.2.0
|
|
518
|
+
*/
|
|
519
|
+
declare function useWindowSize(debounceMs?: number): WindowSize;
|
|
520
|
+
|
|
521
|
+
interface ScrollState {
|
|
522
|
+
x: number;
|
|
523
|
+
y: number;
|
|
524
|
+
isScrolled: boolean;
|
|
525
|
+
/** Scroll direction: 'up' | 'down' | null (initial) */
|
|
526
|
+
direction: "up" | "down" | null;
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Tracks scroll position and direction.
|
|
530
|
+
* @param throttleMs - Throttle interval in ms (default 50)
|
|
531
|
+
* @param target - Scroll target element ref (defaults to window)
|
|
532
|
+
* @since 0.2.0
|
|
533
|
+
*/
|
|
534
|
+
declare function useScroll(throttleMs?: number, target?: React$1.RefObject<HTMLElement | null>): ScrollState;
|
|
535
|
+
/**
|
|
536
|
+
* Convenience hook: returns just the scroll direction.
|
|
537
|
+
* @since 0.2.0
|
|
538
|
+
*/
|
|
539
|
+
declare function useScrollDirection(throttleMs?: number, target?: React$1.RefObject<HTMLElement | null>): "up" | "down" | null;
|
|
540
|
+
|
|
541
|
+
type Orientation = "portrait" | "landscape";
|
|
542
|
+
/**
|
|
543
|
+
* Tracks device screen orientation.
|
|
544
|
+
* @since 0.2.0
|
|
545
|
+
*/
|
|
546
|
+
declare function useOrientation(): Orientation;
|
|
547
|
+
|
|
548
|
+
interface UseClipboardReturn {
|
|
549
|
+
/** Copies text to clipboard */
|
|
550
|
+
copy: (text: string) => Promise<boolean>;
|
|
551
|
+
/** Whether a copy operation is in progress */
|
|
552
|
+
copying: boolean;
|
|
553
|
+
/** Whether the last copy was successful */
|
|
554
|
+
copied: boolean;
|
|
555
|
+
/** Recently copied text */
|
|
556
|
+
value: string | null;
|
|
557
|
+
/** Reset copied state */
|
|
558
|
+
reset: () => void;
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Copy text to clipboard with state tracking.
|
|
562
|
+
* Unifies the existing use-copy-to-clipboard under a standard API.
|
|
563
|
+
*
|
|
564
|
+
* @param timeout - How long "copied" stays true (ms, default 2000)
|
|
565
|
+
* @since 0.2.0
|
|
566
|
+
*/
|
|
567
|
+
declare function useClipboard(timeout?: number): UseClipboardReturn;
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* Enhanced form hook wrapping react-hook-form with enterprise defaults.
|
|
571
|
+
* - `mode: "onTouched"` by default (fewer re-renders)
|
|
572
|
+
* - `reValidateMode: "onChange"`
|
|
573
|
+
* - Standardized dirty/submit tracking
|
|
574
|
+
*
|
|
575
|
+
* @since 0.2.0
|
|
576
|
+
*/
|
|
577
|
+
declare function useForm<TFieldValues extends FieldValues = FieldValues, TContext = unknown>(props?: UseFormProps<TFieldValues, TContext>): react_hook_form.UseFormReturn<TFieldValues, TContext, TFieldValues>;
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* Schema-driven wrapper around {@link useForm}.
|
|
581
|
+
*
|
|
582
|
+
* - Accepts a zod schema and wires it through `zodResolver` automatically.
|
|
583
|
+
* - For yup / valibot / custom schema libraries, pass `resolver` directly
|
|
584
|
+
* (e.g. `yupResolver(schema)`); `schema` and custom resolvers are mutually
|
|
585
|
+
* exclusive — `resolver` wins when both are supplied.
|
|
586
|
+
* - When neither is supplied, behaves like plain {@link useForm} so the hook
|
|
587
|
+
* is safely composable inside mixed caller code paths.
|
|
588
|
+
*
|
|
589
|
+
* `zod` and `@hookform/resolvers` are declared as optional peer dependencies;
|
|
590
|
+
* consumers adopting schema-driven forms must install them.
|
|
591
|
+
*
|
|
592
|
+
* @since 1.1.0
|
|
593
|
+
* @example
|
|
594
|
+
* const form = useFormSchema({
|
|
595
|
+
* schema: loginSchema,
|
|
596
|
+
* defaultValues: { email: "", password: "" },
|
|
597
|
+
* })
|
|
598
|
+
*/
|
|
599
|
+
interface UseFormSchemaOptions<TFieldValues extends FieldValues = FieldValues, TContext = unknown> extends Omit<UseFormProps<TFieldValues, TContext>, "resolver"> {
|
|
600
|
+
/**
|
|
601
|
+
* Zod schema. Auto-detected via `zodResolver`; for other libraries use
|
|
602
|
+
* `resolver` instead. `z.infer<typeof schema>` must align with
|
|
603
|
+
* `TFieldValues` (the hook will infer it for you when omitted).
|
|
604
|
+
*
|
|
605
|
+
* Typed loosely (`unknown`) intentionally: zod v3/v4 surface slightly
|
|
606
|
+
* different generic arities and we pass the schema straight into
|
|
607
|
+
* `zodResolver`, which is the single source of truth for shape.
|
|
608
|
+
*/
|
|
609
|
+
schema?: unknown;
|
|
610
|
+
/**
|
|
611
|
+
* Explicit react-hook-form resolver. Takes precedence over `schema`.
|
|
612
|
+
* Pass `yupResolver` / `valibotResolver` / a custom resolver here.
|
|
613
|
+
*/
|
|
614
|
+
resolver?: Resolver<TFieldValues, TContext>;
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Infer field values from a zod schema.
|
|
618
|
+
*
|
|
619
|
+
* @example
|
|
620
|
+
* const form = useFormSchema({
|
|
621
|
+
* schema: z.object({ email: z.string() }),
|
|
622
|
+
* defaultValues: { email: "" },
|
|
623
|
+
* })
|
|
624
|
+
*/
|
|
625
|
+
declare function useFormSchema<TFieldValues extends FieldValues = FieldValues, TContext = unknown>(options?: UseFormSchemaOptions<TFieldValues, TContext>): react_hook_form.UseFormReturn<TFieldValues, TContext, TFieldValues>;
|
|
626
|
+
/**
|
|
627
|
+
* Convenience adapter mirroring `packages/chaos-design-ui` usage so consumers
|
|
628
|
+
* can write `const resolver = zodResolverAdapter(loginSchema)` without
|
|
629
|
+
* importing `@hookform/resolvers/zod` themselves.
|
|
630
|
+
*/
|
|
631
|
+
declare function zodResolverAdapter<TFieldValues extends FieldValues>(schema: unknown): Resolver<TFieldValues>;
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* @hook usePermission
|
|
635
|
+
* @category hooks/auth
|
|
636
|
+
* @since 0.7.0
|
|
637
|
+
* @description 权限校验 Hook,配合 PermissionProvider 使用。
|
|
638
|
+
* 提供当前用户权限列表和校验函数。
|
|
639
|
+
* / Permission hook — works with PermissionProvider to check user permissions.
|
|
640
|
+
* @keywords permission, auth, role, access, guard
|
|
641
|
+
* @example
|
|
642
|
+
* const { hasPermission, hasAny, hasAll } = usePermission();
|
|
643
|
+
* if (hasPermission("order:create")) { ... }
|
|
644
|
+
*/
|
|
645
|
+
type PermissionCheck = (permission: string) => boolean;
|
|
646
|
+
interface PermissionContextValue {
|
|
647
|
+
/** All permissions the current user holds / 当前用户拥有的权限列表 */
|
|
648
|
+
permissions: string[];
|
|
649
|
+
/** Check a single permission / 校验单个权限 */
|
|
650
|
+
hasPermission: PermissionCheck;
|
|
651
|
+
/** Check if user has ANY of the given permissions / 满足任一权限 */
|
|
652
|
+
hasAny: (permissions: string[]) => boolean;
|
|
653
|
+
/** Check if user has ALL of the given permissions / 满足全部权限 */
|
|
654
|
+
hasAll: (permissions: string[]) => boolean;
|
|
655
|
+
}
|
|
656
|
+
declare const PermissionContext: React$1.Context<PermissionContextValue>;
|
|
657
|
+
interface PermissionProviderProps {
|
|
658
|
+
/** Permission codes granted to the current user / 当前用户的权限码列表 */
|
|
659
|
+
permissions: string[];
|
|
660
|
+
children: React$1.ReactNode;
|
|
661
|
+
}
|
|
662
|
+
declare function PermissionProvider({ permissions, children, }: PermissionProviderProps): React$1.JSX.Element;
|
|
663
|
+
declare function usePermission(): PermissionContextValue;
|
|
664
|
+
|
|
665
|
+
/**
|
|
666
|
+
* @hook useApproval
|
|
667
|
+
* @category Data
|
|
668
|
+
* @since 1.0.0-beta.0
|
|
669
|
+
* @description Drives an approval action (approve/reject/transfer) with async state and result tracking.
|
|
670
|
+
* @param submit Async handler invoked with the action type and optional comment.
|
|
671
|
+
* @example
|
|
672
|
+
* const { submit, status, data, error, isLoading } = useApproval(async (action) => api.post(...));
|
|
673
|
+
*/
|
|
674
|
+
type ApprovalAction = "approve" | "reject" | "transfer";
|
|
675
|
+
interface UseApprovalResult<T> {
|
|
676
|
+
submit: (action: ApprovalAction, comment?: string) => Promise<T | undefined>;
|
|
677
|
+
status: "idle" | "pending" | "success" | "error";
|
|
678
|
+
data: T | undefined;
|
|
679
|
+
error: Error | undefined;
|
|
680
|
+
isLoading: boolean;
|
|
681
|
+
}
|
|
682
|
+
declare function useApproval<T = unknown>(handler: (action: ApprovalAction, comment?: string) => Promise<T>): UseApprovalResult<T>;
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* @hook useAsyncTask
|
|
686
|
+
* @category Data
|
|
687
|
+
* @since 1.0.0-beta.0
|
|
688
|
+
* @description Trigger a one-shot async task with progress, retry, and abort.
|
|
689
|
+
* @param task Async function returning a result.
|
|
690
|
+
* @example
|
|
691
|
+
* const { run, status, data, error, isLoading, abort } = useAsyncTask(async (signal) => {...});
|
|
692
|
+
*/
|
|
693
|
+
interface UseAsyncTaskResult<T> {
|
|
694
|
+
run: (...args: never[]) => Promise<T | undefined>;
|
|
695
|
+
status: "idle" | "pending" | "success" | "error";
|
|
696
|
+
data: T | undefined;
|
|
697
|
+
error: Error | undefined;
|
|
698
|
+
isLoading: boolean;
|
|
699
|
+
abort: () => void;
|
|
700
|
+
reset: () => void;
|
|
701
|
+
}
|
|
702
|
+
declare function useAsyncTask<T>(task: (signal: AbortSignal) => Promise<T>): UseAsyncTaskResult<T>;
|
|
703
|
+
|
|
704
|
+
/**
|
|
705
|
+
* @hook useBill
|
|
706
|
+
* @category Data
|
|
707
|
+
* @since 1.0.0-beta.0
|
|
708
|
+
* @description Tracks a bill/document's lifecycle state (draft → submitted → approved → paid → void) with transitions and history.
|
|
709
|
+
* @param initial Initial status.
|
|
710
|
+
* @example
|
|
711
|
+
* const { status, transition, history, can } = useBill("draft");
|
|
712
|
+
*/
|
|
713
|
+
type BillStatus = "draft" | "submitted" | "approved" | "rejected" | "paid" | "void";
|
|
714
|
+
interface UseBillState {
|
|
715
|
+
status: BillStatus;
|
|
716
|
+
transition: (next: BillStatus) => boolean;
|
|
717
|
+
can: (next: BillStatus) => boolean;
|
|
718
|
+
history: BillStatus[];
|
|
719
|
+
reset: (status?: BillStatus) => void;
|
|
720
|
+
}
|
|
721
|
+
declare function useBill(initial?: BillStatus): UseBillState;
|
|
722
|
+
|
|
723
|
+
/**
|
|
724
|
+
* @hook useDataScope
|
|
725
|
+
* @category Data
|
|
726
|
+
* @since 1.0.0-beta.0
|
|
727
|
+
* @description Tracks the active data scope (e.g. company/department/period) used to filter business queries, with persistence and change subscription.
|
|
728
|
+
* @param initial Initial scope.
|
|
729
|
+
* @param options storageKey to persist to localStorage.
|
|
730
|
+
* @example
|
|
731
|
+
* const { scope, setScope, subscribe } = useDataScope({ companyId: "1" });
|
|
732
|
+
*/
|
|
733
|
+
type DataScope = Record<string, string | number | boolean | undefined>;
|
|
734
|
+
interface UseDataScopeState<S extends DataScope> {
|
|
735
|
+
scope: S;
|
|
736
|
+
setScope: (next: S | ((prev: S) => S)) => void;
|
|
737
|
+
patch: (partial: Partial<S>) => void;
|
|
738
|
+
reset: () => void;
|
|
739
|
+
subscribe: (fn: (scope: S) => void) => () => void;
|
|
740
|
+
}
|
|
741
|
+
declare function useDataScope<S extends DataScope>(initial: S, options?: {
|
|
742
|
+
storageKey?: string;
|
|
743
|
+
}): UseDataScopeState<S>;
|
|
744
|
+
|
|
745
|
+
/**
|
|
746
|
+
* @hook useDict
|
|
747
|
+
* @category Data
|
|
748
|
+
* @since 1.0.0-beta.0
|
|
749
|
+
* @description Loads and caches a dictionary (key/label/code options) by dict type, with loading/error state and a label lookup helper.
|
|
750
|
+
* @param dictType Dictionary type key. Falsy skips loading.
|
|
751
|
+
* @param fetcher Returns the options for the given dict type.
|
|
752
|
+
* @example
|
|
753
|
+
* const { options, isLoading, getLabel } = useDict("gender", fetchDict);
|
|
754
|
+
*/
|
|
755
|
+
interface DictOption {
|
|
756
|
+
value: string;
|
|
757
|
+
label: string;
|
|
758
|
+
disabled?: boolean;
|
|
759
|
+
}
|
|
760
|
+
interface UseDictState {
|
|
761
|
+
options: DictOption[];
|
|
762
|
+
isLoading: boolean;
|
|
763
|
+
error: Error | undefined;
|
|
764
|
+
getLabel: (value: string) => string;
|
|
765
|
+
refresh: () => void;
|
|
766
|
+
}
|
|
767
|
+
declare function useDict(dictType: string | null, fetcher: (type: string) => Promise<DictOption[]>): UseDictState;
|
|
768
|
+
|
|
769
|
+
/**
|
|
770
|
+
* @hook useExport
|
|
771
|
+
* @category Data
|
|
772
|
+
* @since 1.0.0-beta.0
|
|
773
|
+
* @description Triggers a file export (download) with progress, abort, and blob/text support.
|
|
774
|
+
* @example
|
|
775
|
+
* const { exportFile, isLoading, error } = useExport();
|
|
776
|
+
* await exportFile(() => fetch("/api/export").then(r => r.blob()), "report.xlsx");
|
|
777
|
+
*/
|
|
778
|
+
interface UseExportResult {
|
|
779
|
+
exportFile: (source: () => Promise<Blob | string>, filename: string, mime?: string) => Promise<void>;
|
|
780
|
+
isLoading: boolean;
|
|
781
|
+
error: Error | undefined;
|
|
782
|
+
progress: number;
|
|
783
|
+
abort: () => void;
|
|
784
|
+
}
|
|
785
|
+
declare function useExport(): UseExportResult;
|
|
786
|
+
|
|
787
|
+
/**
|
|
788
|
+
* @hook useFetch
|
|
789
|
+
* @category Data
|
|
790
|
+
* @since 1.0.0-beta.0
|
|
791
|
+
* @description Lightweight fetch hook with abort, re-fetch, and manual trigger.
|
|
792
|
+
* @param input Request URL or Request object.
|
|
793
|
+
* @param init Fetch init options.
|
|
794
|
+
* @example
|
|
795
|
+
* const { data, error, isLoading, refetch } = useFetch("/api/users");
|
|
796
|
+
*/
|
|
797
|
+
interface UseFetchState<T> {
|
|
798
|
+
data: T | undefined;
|
|
799
|
+
error: Error | undefined;
|
|
800
|
+
isLoading: boolean;
|
|
801
|
+
}
|
|
802
|
+
declare function useFetch<T = unknown>(input: string | URL | Request, init?: RequestInit): UseFetchState<T> & {
|
|
803
|
+
refetch: () => void;
|
|
804
|
+
};
|
|
805
|
+
|
|
806
|
+
/**
|
|
807
|
+
* @hook useFormTable
|
|
808
|
+
* @category Data
|
|
809
|
+
* @since 1.0.0-beta.0
|
|
810
|
+
* @description Editable table rows backed by a form-like state: add/update/remove rows with field-level validation and dirty tracking.
|
|
811
|
+
* @param initial Initial rows.
|
|
812
|
+
* @param config validate, id generator.
|
|
813
|
+
* @example
|
|
814
|
+
* const { rows, addRow, updateRow, removeRow, errors, isValid, dirty } = useFormTable([{ id: "1", name: "" }]);
|
|
815
|
+
*/
|
|
816
|
+
interface UseFormTableConfig<T> {
|
|
817
|
+
validate?: (row: T, index: number) => Record<string, string>;
|
|
818
|
+
createId?: () => string;
|
|
819
|
+
}
|
|
820
|
+
interface UseFormTableResult<T> {
|
|
821
|
+
rows: T[];
|
|
822
|
+
addRow: (row: T) => void;
|
|
823
|
+
updateRow: (index: number, patch: Partial<T>) => void;
|
|
824
|
+
removeRow: (index: number) => void;
|
|
825
|
+
setRows: (rows: T[]) => void;
|
|
826
|
+
reset: (rows?: T[]) => void;
|
|
827
|
+
errors: Record<number, Record<string, string>>;
|
|
828
|
+
isValid: boolean;
|
|
829
|
+
dirty: boolean;
|
|
830
|
+
}
|
|
831
|
+
declare function useFormTable<T extends {
|
|
832
|
+
id?: string;
|
|
833
|
+
}>(initial: T[], config?: UseFormTableConfig<T>): UseFormTableResult<T>;
|
|
834
|
+
|
|
835
|
+
/**
|
|
836
|
+
* @hook useIdle
|
|
837
|
+
* @category Data
|
|
838
|
+
* @since 1.0.0-beta.0
|
|
839
|
+
* @description Tracks whether the user has been idle (no mouse/keyboard/touch/scroll) for a duration.
|
|
840
|
+
* @param timeout Idle threshold in ms (default 60_000).
|
|
841
|
+
* @param events Activity events to listen for.
|
|
842
|
+
* @example
|
|
843
|
+
* const isIdle = useIdle(30_000);
|
|
844
|
+
*/
|
|
845
|
+
declare function useIdle(timeout?: number, events?: string[]): boolean;
|
|
846
|
+
|
|
847
|
+
/**
|
|
848
|
+
* @hook useImport
|
|
849
|
+
* @category Data
|
|
850
|
+
* @since 1.0.0-beta.0
|
|
851
|
+
* @description Drive a file import: parse an uploaded file (text/json/csv), track progress, validation errors, and parsed rows.
|
|
852
|
+
* @example
|
|
853
|
+
* const { importFile, rows, errors, isLoading, progress } = useImport();
|
|
854
|
+
*/
|
|
855
|
+
interface ImportError {
|
|
856
|
+
row: number;
|
|
857
|
+
message: string;
|
|
858
|
+
}
|
|
859
|
+
interface UseImportResult<T> {
|
|
860
|
+
rows: T[];
|
|
861
|
+
errors: ImportError[];
|
|
862
|
+
isLoading: boolean;
|
|
863
|
+
progress: number;
|
|
864
|
+
importFile: (file: File, parser: (text: string, file: File) => T[] | Promise<T[]>) => Promise<T[]>;
|
|
865
|
+
reset: () => void;
|
|
866
|
+
}
|
|
867
|
+
declare function useImport<T = Record<string, unknown>>(): UseImportResult<T>;
|
|
868
|
+
|
|
869
|
+
/**
|
|
870
|
+
* @hook useLineEditor
|
|
871
|
+
* @category Data
|
|
872
|
+
* @since 1.0.0-beta.0
|
|
873
|
+
* @description Inline line editor: tracks edit/draft state for a single value, with commit/cancel, validation, and dirty flag. Used by editable table cells and inline-edit fields.
|
|
874
|
+
* @param value The committed value.
|
|
875
|
+
* @param options onCommit, validate, autoFocus.
|
|
876
|
+
* @example
|
|
877
|
+
* const { draft, setDraft, commit, cancel, isEditing, start, isValid } = useLineEditor("foo");
|
|
878
|
+
*/
|
|
879
|
+
interface UseLineEditorOptions<T> {
|
|
880
|
+
onCommit?: (value: T) => void | Promise<void>;
|
|
881
|
+
validate?: (value: T) => string | null;
|
|
882
|
+
autoFocus?: boolean;
|
|
883
|
+
}
|
|
884
|
+
interface UseLineEditorResult<T> {
|
|
885
|
+
value: T;
|
|
886
|
+
draft: T;
|
|
887
|
+
isEditing: boolean;
|
|
888
|
+
error: string | null;
|
|
889
|
+
isValid: boolean;
|
|
890
|
+
dirty: boolean;
|
|
891
|
+
start: () => void;
|
|
892
|
+
setDraft: (value: T) => void;
|
|
893
|
+
commit: () => Promise<void>;
|
|
894
|
+
cancel: () => void;
|
|
895
|
+
}
|
|
896
|
+
declare function useLineEditor<T>(value: T, options?: UseLineEditorOptions<T>): UseLineEditorResult<T>;
|
|
897
|
+
|
|
898
|
+
/**
|
|
899
|
+
* @hook useNetworkQuality
|
|
900
|
+
* @category Data
|
|
901
|
+
* @since 1.0.0-beta.0
|
|
902
|
+
* @description Estimates network quality via navigator.connection (effectiveType, downlink, rtt) plus online/offline status.
|
|
903
|
+
* @example
|
|
904
|
+
* const { online, effectiveType, downlink, rtt } = useNetworkQuality();
|
|
905
|
+
*/
|
|
906
|
+
interface UseNetworkQualityState {
|
|
907
|
+
online: boolean;
|
|
908
|
+
effectiveType: string | undefined;
|
|
909
|
+
downlink: number | undefined;
|
|
910
|
+
rtt: number | undefined;
|
|
911
|
+
saveData: boolean | undefined;
|
|
912
|
+
}
|
|
913
|
+
declare function useNetworkQuality(): UseNetworkQualityState;
|
|
914
|
+
|
|
915
|
+
/**
|
|
916
|
+
* @hook usePrint
|
|
917
|
+
* @category Data
|
|
918
|
+
* @since 1.0.0-beta.0
|
|
919
|
+
* @description Programmatic print helper: print a DOM node (via clone into a hidden iframe) or the whole window, with before/after hooks and cleanup.
|
|
920
|
+
* @example
|
|
921
|
+
* const { print, isPrinting } = usePrint();
|
|
922
|
+
* await print(ref.current, { title: "Invoice" });
|
|
923
|
+
*/
|
|
924
|
+
interface UsePrintOptions {
|
|
925
|
+
title?: string;
|
|
926
|
+
beforePrint?: () => void;
|
|
927
|
+
afterPrint?: () => void;
|
|
928
|
+
cssText?: string;
|
|
929
|
+
}
|
|
930
|
+
interface UsePrintResult {
|
|
931
|
+
print: (target?: HTMLElement | null, options?: UsePrintOptions) => Promise<void>;
|
|
932
|
+
isPrinting: boolean;
|
|
933
|
+
}
|
|
934
|
+
declare function usePrint(): UsePrintResult;
|
|
935
|
+
|
|
936
|
+
/**
|
|
937
|
+
* @hook useRedo
|
|
938
|
+
* @category Data
|
|
939
|
+
* @since 1.0.0-beta.0
|
|
940
|
+
* @description Tracks redo history for an externally-managed undo stack. Pair with {@link useUndo} when you need separate redo state, or use `useUndo` which includes both. This hook exposes the redo queue length and a way to push/peek/pop.
|
|
941
|
+
* @param initial Redo queue seed (default empty).
|
|
942
|
+
* @example
|
|
943
|
+
* const { redoCount, push, pop, peek } = useRedo<string>();
|
|
944
|
+
*/
|
|
945
|
+
interface UseRedoState<T> {
|
|
946
|
+
redoCount: number;
|
|
947
|
+
push: (value: T) => void;
|
|
948
|
+
pop: () => T | undefined;
|
|
949
|
+
peek: () => T | undefined;
|
|
950
|
+
clear: () => void;
|
|
951
|
+
}
|
|
952
|
+
declare function useRedo<T>(): UseRedoState<T>;
|
|
953
|
+
|
|
954
|
+
/**
|
|
955
|
+
* @hook useSse
|
|
956
|
+
* @category Data
|
|
957
|
+
* @since 1.0.0-beta.0
|
|
958
|
+
* @description Subscribe to a Server-Sent Events stream. Auto-reconnect and cleanup.
|
|
959
|
+
* @param url SSE endpoint URL. Falsy disables the connection.
|
|
960
|
+
* @param options onMessage handler, event name filter, withCredentials.
|
|
961
|
+
* @example
|
|
962
|
+
* const { readyState, lastEvent } = useSse("/api/stream", { onMessage: console.log });
|
|
963
|
+
*/
|
|
964
|
+
interface UseSseOptions {
|
|
965
|
+
onMessage?: (data: string, event: MessageEvent) => void;
|
|
966
|
+
event?: string;
|
|
967
|
+
withCredentials?: boolean;
|
|
968
|
+
}
|
|
969
|
+
interface UseSseState {
|
|
970
|
+
readyState: number;
|
|
971
|
+
lastEvent: string | undefined;
|
|
972
|
+
error: Event | undefined;
|
|
973
|
+
}
|
|
974
|
+
declare function useSse(url: string | null, options?: UseSseOptions): UseSseState;
|
|
975
|
+
|
|
976
|
+
/**
|
|
977
|
+
* Type-safe wrapper around TanStack Query's `useQuery`.
|
|
978
|
+
*
|
|
979
|
+
* Consumers must install `@tanstack/react-query` and wrap their app with
|
|
980
|
+
* `QueryClientProvider`. This hook is a thin pass-through that adds
|
|
981
|
+
* enterprise defaults (e.g. `staleTime: 30_000`) so teams can adopt
|
|
982
|
+
* query caching without boilerplate.
|
|
983
|
+
*
|
|
984
|
+
* @since 1.1.0
|
|
985
|
+
* @example
|
|
986
|
+
* const { data, isLoading } = useQuery({
|
|
987
|
+
* queryKey: ["users", userId],
|
|
988
|
+
* queryFn: () => fetchUser(userId),
|
|
989
|
+
* })
|
|
990
|
+
*/
|
|
991
|
+
declare function useQuery<TQueryFnData = unknown, TError = Error, TData = TQueryFnData, TQueryKey extends readonly unknown[] = readonly unknown[]>(options: UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>): UseQueryResult<TData, TError>;
|
|
992
|
+
|
|
993
|
+
/**
|
|
994
|
+
* Type-safe wrapper around TanStack Query's `useMutation`.
|
|
995
|
+
*
|
|
996
|
+
* @since 1.1.0
|
|
997
|
+
* @example
|
|
998
|
+
* const { mutate, isPending } = useMutation({
|
|
999
|
+
* mutationFn: (data: CreateUserInput) => createUser(data),
|
|
1000
|
+
* onSuccess: () => queryClient.invalidateQueries({ queryKey: ["users"] }),
|
|
1001
|
+
* })
|
|
1002
|
+
*/
|
|
1003
|
+
declare function useMutation<TData = unknown, TError = Error, TVariables = void, TContext = unknown>(options: UseMutationOptions<TData, TError, TVariables, TContext>): UseMutationResult<TData, TError, TVariables, TContext>;
|
|
1004
|
+
|
|
1005
|
+
/**
|
|
1006
|
+
* @hook useSwr
|
|
1007
|
+
* @category Data
|
|
1008
|
+
* @since 1.0.0-beta.0
|
|
1009
|
+
* @description SWR-style data fetching with revalidation on focus and interval.
|
|
1010
|
+
* @param key Cache key (falsy disables fetching).
|
|
1011
|
+
* @param fetcher Function that returns a Promise of data.
|
|
1012
|
+
* @param options revalidateOnFocus, dedupingInterval, refreshInterval.
|
|
1013
|
+
* @example
|
|
1014
|
+
* const { data, error, isLoading, mutate } = useSwr("/api/users", fetcher);
|
|
1015
|
+
*/
|
|
1016
|
+
interface UseSwrOptions {
|
|
1017
|
+
revalidateOnFocus?: boolean;
|
|
1018
|
+
refreshInterval?: number;
|
|
1019
|
+
dedupingInterval?: number;
|
|
1020
|
+
}
|
|
1021
|
+
interface UseSwrState<T> {
|
|
1022
|
+
data: T | undefined;
|
|
1023
|
+
error: Error | undefined;
|
|
1024
|
+
isLoading: boolean;
|
|
1025
|
+
mutate: (data?: T | ((prev: T | undefined) => T)) => void;
|
|
1026
|
+
}
|
|
1027
|
+
declare function useSwr<T>(key: string | null, fetcher: (key: string) => Promise<T>, options?: UseSwrOptions): UseSwrState<T>;
|
|
1028
|
+
|
|
1029
|
+
/**
|
|
1030
|
+
* @hook useTable
|
|
1031
|
+
* @category Data
|
|
1032
|
+
* @since 1.0.0-beta.0
|
|
1033
|
+
* @description Client-side table controller: sorting, filtering, pagination, and row selection over a flat data array.
|
|
1034
|
+
* @param data Source rows.
|
|
1035
|
+
* @param config initial sort, page size, filter predicate.
|
|
1036
|
+
* @example
|
|
1037
|
+
* const { rows, page, pageSize, totalPages, sort, setFilter, toggleRow, selected } = useTable(data, { pageSize: 20 });
|
|
1038
|
+
*/
|
|
1039
|
+
interface UseTableConfig<T> {
|
|
1040
|
+
pageSize?: number;
|
|
1041
|
+
initialSort?: {
|
|
1042
|
+
key: keyof T;
|
|
1043
|
+
direction?: "asc" | "desc";
|
|
1044
|
+
};
|
|
1045
|
+
filter?: (row: T, term: string) => boolean;
|
|
1046
|
+
getRowId?: (row: T, index: number) => string;
|
|
1047
|
+
}
|
|
1048
|
+
interface SortState<T> {
|
|
1049
|
+
key: keyof T | null;
|
|
1050
|
+
direction: "asc" | "desc";
|
|
1051
|
+
}
|
|
1052
|
+
interface UseTableResult<T> {
|
|
1053
|
+
rows: T[];
|
|
1054
|
+
page: number;
|
|
1055
|
+
pageSize: number;
|
|
1056
|
+
total: number;
|
|
1057
|
+
totalPages: number;
|
|
1058
|
+
sort: SortState<T>;
|
|
1059
|
+
setSort: (key: keyof T) => void;
|
|
1060
|
+
filterTerm: string;
|
|
1061
|
+
setFilter: (term: string) => void;
|
|
1062
|
+
setPage: (page: number) => void;
|
|
1063
|
+
setPageSize: (size: number) => void;
|
|
1064
|
+
selected: Set<string>;
|
|
1065
|
+
toggleRow: (id: string) => void;
|
|
1066
|
+
toggleAll: () => void;
|
|
1067
|
+
clearSelected: () => void;
|
|
1068
|
+
}
|
|
1069
|
+
declare function useTable<T>(data: T[], config?: UseTableConfig<T>): UseTableResult<T>;
|
|
1070
|
+
|
|
1071
|
+
interface UseTrackOptions {
|
|
1072
|
+
/** Event name sent to the telemetry adapter. */
|
|
1073
|
+
event: string;
|
|
1074
|
+
/** Additional properties merged into the event payload. */
|
|
1075
|
+
properties?: Record<string, unknown>;
|
|
1076
|
+
/** If true, fires the event on mount. Default false. */
|
|
1077
|
+
trackOnMount?: boolean;
|
|
1078
|
+
/** If true, fires the event on unmount. Default false. */
|
|
1079
|
+
trackOnUnmount?: boolean;
|
|
1080
|
+
}
|
|
1081
|
+
/**
|
|
1082
|
+
* Declarative tracking hook.
|
|
1083
|
+
*
|
|
1084
|
+
* Returns a `trackNow(extra?)` function for imperative use. Optionally
|
|
1085
|
+
* fires events on mount/unmount via `trackOnMount` / `trackOnUnmount`.
|
|
1086
|
+
*
|
|
1087
|
+
* @since 1.1.0
|
|
1088
|
+
* @example
|
|
1089
|
+
* // Track a page view on mount
|
|
1090
|
+
* useTrack({ event: "page_view", properties: { page: "dashboard" }, trackOnMount: true })
|
|
1091
|
+
*
|
|
1092
|
+
* // Track a button click
|
|
1093
|
+
* const { trackNow } = useTrack({ event: "export_csv" })
|
|
1094
|
+
* <Button onClick={() => trackNow({ rows: 142 })}>Export</Button>
|
|
1095
|
+
*/
|
|
1096
|
+
declare function useTrack(options: UseTrackOptions): {
|
|
1097
|
+
trackNow: (extra?: Record<string, unknown>) => void;
|
|
1098
|
+
};
|
|
1099
|
+
|
|
1100
|
+
/**
|
|
1101
|
+
* @hook useUndo
|
|
1102
|
+
* @category Data
|
|
1103
|
+
* @since 1.0.0-beta.0
|
|
1104
|
+
* @description Undo/redo history for a value. Returns value, setters, and can/clear flags.
|
|
1105
|
+
* @param initial Initial value.
|
|
1106
|
+
* @param limit Max history entries (default 100).
|
|
1107
|
+
* @example
|
|
1108
|
+
* const { value, set, undo, redo, canUndo, canRedo } = useUndo("");
|
|
1109
|
+
*/
|
|
1110
|
+
interface UseUndoState<T> {
|
|
1111
|
+
value: T;
|
|
1112
|
+
setValue: (next: T | ((prev: T) => T)) => void;
|
|
1113
|
+
undo: () => void;
|
|
1114
|
+
redo: () => void;
|
|
1115
|
+
clear: () => void;
|
|
1116
|
+
canUndo: boolean;
|
|
1117
|
+
canRedo: boolean;
|
|
1118
|
+
}
|
|
1119
|
+
declare function useUndo<T>(initial: T, limit?: number): UseUndoState<T>;
|
|
1120
|
+
|
|
1121
|
+
/**
|
|
1122
|
+
* @hook useWebsocket
|
|
1123
|
+
* @category Data
|
|
1124
|
+
* @since 1.0.0-beta.0
|
|
1125
|
+
* @description Manage a WebSocket connection with auto-reconnect, send helper, and last-message state.
|
|
1126
|
+
* @param url WebSocket URL. Falsy disables.
|
|
1127
|
+
* @param options onOpen/onMessage/onClose/onError callbacks, protocols, retry interval.
|
|
1128
|
+
* @example
|
|
1129
|
+
* const { send, readyState, lastMessage } = useWebsocket("wss://echo.example");
|
|
1130
|
+
*/
|
|
1131
|
+
interface UseWebsocketOptions {
|
|
1132
|
+
onOpen?: (e: Event) => void;
|
|
1133
|
+
onMessage?: (data: string, e: MessageEvent) => void;
|
|
1134
|
+
onClose?: (e: CloseEvent) => void;
|
|
1135
|
+
onError?: (e: Event) => void;
|
|
1136
|
+
protocols?: string | string[];
|
|
1137
|
+
retryInterval?: number;
|
|
1138
|
+
autoConnect?: boolean;
|
|
1139
|
+
}
|
|
1140
|
+
interface UseWebsocketState {
|
|
1141
|
+
readyState: number;
|
|
1142
|
+
lastMessage: string | undefined;
|
|
1143
|
+
send: (data: string | ArrayBuffer) => void;
|
|
1144
|
+
close: () => void;
|
|
1145
|
+
}
|
|
1146
|
+
declare function useWebsocket(url: string | null, options?: UseWebsocketOptions): UseWebsocketState;
|
|
1147
|
+
|
|
1148
|
+
export { type Breakpoint, type ConfirmOptions, ConfirmProvider, type ConfirmProviderProps, type KeyFilter, type KeyHandler, LocaleProvider, type MessageInstance, MessageOptions, type ModalInstance, type ModalOptions, ModalRenderer, type NotificationInstance, type NotificationOptions, PermissionContext, type PermissionContextValue, PermissionProvider, type PermissionProviderProps, type SupportedLocale, type UseCrudConfig, type UseCrudReturn, type UseFieldValidationOptions, type UseFormSchemaOptions, type UseKeyOptions, type UsePageTitleOptions, type UseTrackOptions, type ValidationRule, confirmAsync, getStoredLocale, supportedLocales, useApproval, useAsync, useAsyncTask, useBill, useBreakpoint, useClickOutside, useClipboard, useConfirmAsync, useConfirmContext, useCopyToClipboard, useCountdown, useCrud, useDataScope, useDebounce, useDict, useEventListener, useExport, useFetch, useFieldValidation, useForm, useFormSchema, useFormTable, useHotkeys, useIdle, useImport, useInView, useInfiniteScroll, useIntersectionObserver, useIsBreakpoint, useIsDesktop, useIsMobile, useIsTablet, useKey, useKeyCombo, useLineEditor, useLocalStorage, useLocale, useMediaQuery, useMessage, useModal, useMutation, useNetworkQuality, useNetworkStatus, useNotification, useOrientation, usePageTitle, usePagination, usePermission, usePrevious, usePrint, useQuery, useRedo, useScroll, useScrollDirection, useSse, useStep, useSwr, useTable, useThrottle, useToggle, useTrack, useUndo, useVisibilityChange, useWebsocket, useWindowSize, zodResolverAdapter };
|