@openway/ui 1.0.0 → 1.0.2
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.md +203 -181
- package/dist/chunk-X4LIYOS5.js +3 -0
- package/dist/chunk-X4LIYOS5.js.map +1 -0
- package/dist/index.cjs +5 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2740 -1473
- package/dist/index.d.ts +2740 -1473
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/query.cjs +3 -0
- package/dist/query.cjs.map +1 -0
- package/dist/query.d.cts +431 -0
- package/dist/query.d.ts +431 -0
- package/dist/query.js +3 -0
- package/dist/query.js.map +1 -0
- package/dist/useInfiniteScroll-D9AW6cQV.d.cts +598 -0
- package/dist/useInfiniteScroll-D9AW6cQV.d.ts +598 -0
- package/docs/AGENTS.md +144 -0
- package/docs/README.md +150 -0
- package/docs/SKILL.md +54 -0
- package/docs/components/alert.md +246 -0
- package/docs/components/badge.md +238 -0
- package/docs/components/button.md +262 -0
- package/docs/components/carousel.md +354 -0
- package/docs/components/checkbox.md +252 -0
- package/docs/components/collapse.md +318 -0
- package/docs/components/confirm.md +322 -0
- package/docs/components/datepicker.md +259 -0
- package/docs/components/daterangepicker.md +260 -0
- package/docs/components/datetimepicker.md +226 -0
- package/docs/components/datetimerangepicker.md +222 -0
- package/docs/components/dropdown.md +275 -0
- package/docs/components/empty.md +200 -0
- package/docs/components/file-preview.md +180 -0
- package/docs/components/input.md +559 -0
- package/docs/components/modal.md +293 -0
- package/docs/components/popover.md +255 -0
- package/docs/components/radio.md +245 -0
- package/docs/components/select.md +254 -0
- package/docs/components/skeleton.md +150 -0
- package/docs/components/slider.md +346 -0
- package/docs/components/table.md +316 -0
- package/docs/components/tabs.md +432 -0
- package/docs/components/textarea.md +193 -0
- package/docs/components/timepicker.md +242 -0
- package/docs/components/timerangepicker.md +210 -0
- package/docs/components/toast.md +282 -0
- package/docs/components/toggle.md +211 -0
- package/docs/components/tooltip.md +213 -0
- package/docs/components/upload-avatar.md +318 -0
- package/docs/components/upload-file.md +245 -0
- package/docs/components/upload-image.md +126 -0
- package/docs/hooks/useDebounce.md +92 -0
- package/docs/hooks/useInfiniteScroll.md +95 -0
- package/docs/hooks/useMutationApp.md +242 -0
- package/docs/hooks/useSelectInfiniteQuery.md +123 -0
- package/docs/hooks/useTableQuery.md +124 -0
- package/package.json +31 -12
package/dist/query.d.cts
ADDED
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
import { QueryFunctionContext, UseQueryOptions, UseQueryResult, UseInfiniteQueryOptions, InfiniteData, UseInfiniteQueryResult, QueryKey, InvalidateQueryFilters, DefaultError, UseMutationOptions, InvalidateOptions, UseMutationResult } from '@tanstack/react-query';
|
|
2
|
+
import { RowData, SortingState, ColumnFiltersState, PaginationState, OnChangeFn } from '@tanstack/react-table';
|
|
3
|
+
import { ReactNode } from 'react';
|
|
4
|
+
import { d as SelectOptionItem, U as UseInfiniteScrollOptions, a as ToastOptions, o as AlertVariant } from './useInfiniteScroll-D9AW6cQV.cjs';
|
|
5
|
+
import 'sonner';
|
|
6
|
+
import '@floating-ui/react';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Các tham số truy vấn chuẩn hóa gửi lên API máy chủ.
|
|
10
|
+
*/
|
|
11
|
+
interface TableQueryParams {
|
|
12
|
+
/**
|
|
13
|
+
* Số thứ tự trang (1-indexed: 1, 2, 3...)
|
|
14
|
+
*/
|
|
15
|
+
page: number;
|
|
16
|
+
/**
|
|
17
|
+
* Kích thước trang (số dòng trên 1 trang)
|
|
18
|
+
*/
|
|
19
|
+
pageSize: number;
|
|
20
|
+
/**
|
|
21
|
+
* ID cột được sắp xếp
|
|
22
|
+
*/
|
|
23
|
+
sortBy?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Chiều sắp xếp: "asc" (tăng dần) hoặc "desc" (giảm dần)
|
|
26
|
+
*/
|
|
27
|
+
sortOrder?: "asc" | "desc";
|
|
28
|
+
/**
|
|
29
|
+
* Danh sách bộ lọc cột dạng từ điển phẳng Record<cột, giá trị>
|
|
30
|
+
*/
|
|
31
|
+
filters?: Record<string, unknown>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Các tùy chọn cấu hình cho hook `useTableQuery`.
|
|
35
|
+
*/
|
|
36
|
+
interface UseTableQueryOptions<TData extends RowData = RowData, TResponse = unknown, TError = Error> {
|
|
37
|
+
/**
|
|
38
|
+
* Base query key cho TanStack Query.
|
|
39
|
+
* `queryParams` sẽ tự động được thêm vào cuối queryKey: `[...queryKey, queryParams]`.
|
|
40
|
+
*/
|
|
41
|
+
queryKey: readonly unknown[];
|
|
42
|
+
/**
|
|
43
|
+
* Hàm gọi API truy vấn dữ liệu từ máy chủ.
|
|
44
|
+
* Nhận vào `queryParams` đã chuẩn hóa và `context` của TanStack Query.
|
|
45
|
+
*/
|
|
46
|
+
queryFn: (params: TableQueryParams, context: QueryFunctionContext<readonly unknown[]>) => Promise<TResponse>;
|
|
47
|
+
/**
|
|
48
|
+
* Hàm trích xuất mảng dữ liệu các dòng (`TData[]`) từ kết quả API trả về.
|
|
49
|
+
* Mặc định tự động kiểm tra `response.data`, `response.items`, `response.rows`, `response.results` hoặc bản thân mảng response.
|
|
50
|
+
*/
|
|
51
|
+
selectData?: (response: TResponse) => TData[];
|
|
52
|
+
/**
|
|
53
|
+
* Hàm trích xuất tổng số lượng bản ghi (`rowCount` / `total`) từ kết quả API trả về.
|
|
54
|
+
* Mặc định tự động kiểm tra `response.total`, `response.rowCount`, `response.totalCount`, `response.count`.
|
|
55
|
+
*/
|
|
56
|
+
selectRowCount?: (response: TResponse) => number;
|
|
57
|
+
/**
|
|
58
|
+
* Cấu hình phân trang ban đầu
|
|
59
|
+
*/
|
|
60
|
+
initialPagination?: {
|
|
61
|
+
pageIndex?: number;
|
|
62
|
+
pageSize?: number;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Cấu hình sắp xếp ban đầu
|
|
66
|
+
*/
|
|
67
|
+
initialSorting?: SortingState;
|
|
68
|
+
/**
|
|
69
|
+
* Cấu hình bộ lọc cột ban đầu
|
|
70
|
+
*/
|
|
71
|
+
initialColumnFilters?: ColumnFiltersState;
|
|
72
|
+
/**
|
|
73
|
+
* Cấu hình từ khóa tìm kiếm ban đầu
|
|
74
|
+
*/
|
|
75
|
+
initialGlobalFilter?: string;
|
|
76
|
+
/**
|
|
77
|
+
* Tự động đưa về trang đầu (pageIndex = 0) khi thay đổi tìm kiếm, bộ lọc hoặc sắp xếp.
|
|
78
|
+
* @default true
|
|
79
|
+
*/
|
|
80
|
+
autoResetPageIndex?: boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Các tùy chọn nâng cao truyền trực tiếp cho hook `useQuery` của TanStack Query
|
|
83
|
+
* (ví dụ: `staleTime`, `gcTime`, `refetchOnWindowFocus`, `enabled`...).
|
|
84
|
+
*/
|
|
85
|
+
queryOptions?: Omit<UseQueryOptions<TResponse, TError, TResponse, readonly unknown[]>, "queryKey" | "queryFn">;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Kết quả trả về từ hook `useTableQuery`.
|
|
89
|
+
*/
|
|
90
|
+
interface UseTableQueryReturn<TData extends RowData = RowData, TResponse = unknown, TError = Error> {
|
|
91
|
+
/**
|
|
92
|
+
* Tập props trọn gói sẵn sàng truyền thẳng vào `<DataTable {...tableProps} />`
|
|
93
|
+
*/
|
|
94
|
+
tableProps: {
|
|
95
|
+
data: TData[];
|
|
96
|
+
rowCount: number;
|
|
97
|
+
isLoading: boolean;
|
|
98
|
+
isRefresh: boolean;
|
|
99
|
+
onRefresh: () => void;
|
|
100
|
+
manualPagination: true;
|
|
101
|
+
manualSorting: true;
|
|
102
|
+
manualFiltering: true;
|
|
103
|
+
pagination: PaginationState;
|
|
104
|
+
onPaginationChange: OnChangeFn<PaginationState>;
|
|
105
|
+
sorting: SortingState;
|
|
106
|
+
onSortingChange: OnChangeFn<SortingState>;
|
|
107
|
+
columnFilters: ColumnFiltersState;
|
|
108
|
+
onColumnFiltersChange: OnChangeFn<ColumnFiltersState>;
|
|
109
|
+
globalFilter: string;
|
|
110
|
+
onGlobalFilterChange: (filter: string) => void;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* Instance query đầy đủ từ TanStack Query
|
|
114
|
+
*/
|
|
115
|
+
query: UseQueryResult<TResponse, TError>;
|
|
116
|
+
/**
|
|
117
|
+
* Tham số truy vấn hiện tại (dùng để debug, ghi log, đồng bộ URL query string, hoặc xuất Excel)
|
|
118
|
+
*/
|
|
119
|
+
queryParams: TableQueryParams;
|
|
120
|
+
/**
|
|
121
|
+
* Đặt lại toàn bộ phân trang, sắp xếp, tìm kiếm và bộ lọc về giá trị mặc định ban đầu
|
|
122
|
+
*/
|
|
123
|
+
resetAll: () => void;
|
|
124
|
+
/**
|
|
125
|
+
* Đổi trang thủ công (1-indexed: 1, 2, 3...)
|
|
126
|
+
*/
|
|
127
|
+
setPage: (page: number) => void;
|
|
128
|
+
/**
|
|
129
|
+
* Đổi số dòng trên mỗi trang thủ công
|
|
130
|
+
*/
|
|
131
|
+
setPageSize: (pageSize: number) => void;
|
|
132
|
+
/**
|
|
133
|
+
* Đổi từ khóa tìm kiếm toàn bảng (lọc client-side)
|
|
134
|
+
*/
|
|
135
|
+
setGlobalFilter: (filter: string) => void;
|
|
136
|
+
/**
|
|
137
|
+
* Cập nhật trạng thái sắp xếp
|
|
138
|
+
*/
|
|
139
|
+
setSorting: (sorting: SortingState | ((prev: SortingState) => SortingState)) => void;
|
|
140
|
+
/**
|
|
141
|
+
* Cập nhật trạng thái bộ lọc cột
|
|
142
|
+
*/
|
|
143
|
+
setColumnFilters: (filters: ColumnFiltersState | ((prev: ColumnFiltersState) => ColumnFiltersState)) => void;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Hook Adapter `useTableQuery` tích hợp TanStack Table v9 và TanStack Query v5.
|
|
147
|
+
*
|
|
148
|
+
* Tính năng:
|
|
149
|
+
* - Đồng bộ hai chiều trạng thái bảng (Pagination, Sorting, Filtering, Search) với server API.
|
|
150
|
+
* - Tự động định dạng tham số `TableQueryParams`: `page` (1-indexed), `pageSize`, `search`, `sortBy`, `sortOrder`, `filters`.
|
|
151
|
+
* - Tự động gắn `queryParams` vào `queryKey` của TanStack Query để kích hoạt cache/refetch thông minh.
|
|
152
|
+
* - Hỗ trợ phân trang mượt mà bằng `placeholderData: keepPreviousData` (không bị nhấp nháy Skeleton khi chuyển trang).
|
|
153
|
+
* - Cung cấp `tableProps` dựng sẵn truyền trực tiếp vào `<DataTable {...tableProps} />`.
|
|
154
|
+
*/
|
|
155
|
+
declare function useTableQuery<TData extends RowData = RowData, TResponse = unknown, TError = Error>(options: UseTableQueryOptions<TData, TResponse, TError>): UseTableQueryReturn<TData, TResponse, TError>;
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Các tham số truy vấn chuẩn hóa được chuyển tới hàm `queryFn`.
|
|
159
|
+
*/
|
|
160
|
+
interface SelectQueryParams<TPageParam = number, TFilters extends Record<string, unknown> = Record<string, unknown>> {
|
|
161
|
+
/**
|
|
162
|
+
* Tham số phân trang hiện tại (trang hiện tại hoặc cursor).
|
|
163
|
+
*/
|
|
164
|
+
pageParam: TPageParam;
|
|
165
|
+
/**
|
|
166
|
+
* Từ khóa tìm kiếm từ ô Select.
|
|
167
|
+
*/
|
|
168
|
+
search: string;
|
|
169
|
+
/**
|
|
170
|
+
* Bộ lọc bổ sung từ menu filter của Select.
|
|
171
|
+
*/
|
|
172
|
+
filters: TFilters;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Các tùy chọn cấu hình cho hook `useSelectInfiniteQuery`.
|
|
176
|
+
*/
|
|
177
|
+
interface UseSelectInfiniteQueryOptions<TData = unknown, TResponse = unknown, TPageParam = number, TFilters extends Record<string, unknown> = Record<string, unknown>, TError = Error> {
|
|
178
|
+
/**
|
|
179
|
+
* Base query key cho TanStack Query.
|
|
180
|
+
* `[{ search, filters }]` sẽ tự động được thêm vào cuối queryKey:
|
|
181
|
+
* `[...queryKey, { search, filters }]`.
|
|
182
|
+
*/
|
|
183
|
+
queryKey: readonly unknown[];
|
|
184
|
+
/**
|
|
185
|
+
* Hàm gọi API truy vấn dữ liệu từ máy chủ theo từng trang.
|
|
186
|
+
* Nhận vào `SelectQueryParams` đã chuẩn hóa và `context` của TanStack Query.
|
|
187
|
+
*/
|
|
188
|
+
queryFn: (params: SelectQueryParams<TPageParam, TFilters>, context: QueryFunctionContext<readonly unknown[], TPageParam>) => Promise<TResponse>;
|
|
189
|
+
/**
|
|
190
|
+
* Giá trị tham số trang đầu tiên (initialPageParam).
|
|
191
|
+
* @default 1
|
|
192
|
+
*/
|
|
193
|
+
initialPageParam?: TPageParam;
|
|
194
|
+
/**
|
|
195
|
+
* Hàm xác định `pageParam` cho trang tiếp theo.
|
|
196
|
+
* Trả về `undefined` hoặc `null` khi không còn dữ liệu tiếp theo.
|
|
197
|
+
*/
|
|
198
|
+
getNextPageParam?: (lastPage: TResponse, allPages: TResponse[], lastPageParam: TPageParam, allPageParams: TPageParam[]) => TPageParam | undefined | null;
|
|
199
|
+
/**
|
|
200
|
+
* Hàm xác định `pageParam` cho trang trước đó (nếu có).
|
|
201
|
+
*/
|
|
202
|
+
getPreviousPageParam?: (firstPage: TResponse, allPages: TResponse[], firstPageParam: TPageParam, allPageParams: TPageParam[]) => TPageParam | undefined | null;
|
|
203
|
+
/**
|
|
204
|
+
* Hàm trích xuất danh sách options (`SelectOptionItem<TData>[]`) từ mỗi `response` trang.
|
|
205
|
+
* Nếu không truyền, mặc định sẽ kiểm tra `data`, `items`, `options`, `results`, `rows` hoặc chính `response`.
|
|
206
|
+
*/
|
|
207
|
+
selectOptions?: (response: TResponse) => SelectOptionItem<TData>[];
|
|
208
|
+
/**
|
|
209
|
+
* Hàm biến đổi từng phần tử thô (raw entity) thành `SelectOptionItem<TData>`.
|
|
210
|
+
*/
|
|
211
|
+
mapOption?: (item: unknown, index: number) => SelectOptionItem<TData>;
|
|
212
|
+
/**
|
|
213
|
+
* Thời gian debounce từ khóa tìm kiếm (tính theo ms).
|
|
214
|
+
* @default 300
|
|
215
|
+
*/
|
|
216
|
+
debounceMs?: number;
|
|
217
|
+
/**
|
|
218
|
+
* Từ khóa tìm kiếm ban đầu.
|
|
219
|
+
*/
|
|
220
|
+
initialSearch?: string;
|
|
221
|
+
/**
|
|
222
|
+
* Giá trị bộ lọc menu ban đầu.
|
|
223
|
+
*/
|
|
224
|
+
initialFilters?: TFilters;
|
|
225
|
+
/**
|
|
226
|
+
* Danh sách options ban đầu ghim sẵn (ví dụ các options đã chọn trước đó cần bảo lưu).
|
|
227
|
+
*/
|
|
228
|
+
initialOptions?: SelectOptionItem<TData>[];
|
|
229
|
+
/**
|
|
230
|
+
* Số dòng Skeleton hiển thị khi đang tải thêm trang tiếp theo.
|
|
231
|
+
* @default 2
|
|
232
|
+
*/
|
|
233
|
+
skeletonLines?: number;
|
|
234
|
+
/**
|
|
235
|
+
* Chiều cao của mỗi dòng Skeleton khi đang tải thêm trang.
|
|
236
|
+
* @default "1.75rem"
|
|
237
|
+
*/
|
|
238
|
+
skeletonHeight?: number | string;
|
|
239
|
+
/**
|
|
240
|
+
* Tùy biến render khi đang tải thêm trang tiếp theo (thay thế Skeleton mặc định).
|
|
241
|
+
*/
|
|
242
|
+
renderLoadingMore?: () => ReactNode;
|
|
243
|
+
/**
|
|
244
|
+
* Thông báo hiển thị khi đã tải hết toàn bộ dữ liệu ở đáy danh sách (tùy chọn).
|
|
245
|
+
*/
|
|
246
|
+
endMessage?: ReactNode;
|
|
247
|
+
/**
|
|
248
|
+
* Tùy chọn truyền trực tiếp cho hook `useInfiniteScroll`.
|
|
249
|
+
*/
|
|
250
|
+
scrollOptions?: Partial<Omit<UseInfiniteScrollOptions, "onLoadMore" | "hasMore" | "isLoading">>;
|
|
251
|
+
/**
|
|
252
|
+
* Các tùy chọn nâng cao truyền trực tiếp cho hook `useInfiniteQuery` của TanStack Query.
|
|
253
|
+
*/
|
|
254
|
+
queryOptions?: Omit<UseInfiniteQueryOptions<TResponse, TError, InfiniteData<TResponse>, readonly unknown[], TPageParam>, "queryKey" | "queryFn" | "initialPageParam" | "getNextPageParam" | "getPreviousPageParam">;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Kết quả trả về từ hook `useSelectInfiniteQuery`.
|
|
258
|
+
*/
|
|
259
|
+
interface UseSelectInfiniteQueryReturn<TData = unknown, TResponse = unknown, TFilters extends Record<string, unknown> = Record<string, unknown>, TError = Error> {
|
|
260
|
+
/**
|
|
261
|
+
* Bộ props trọn gói sẵn sàng truyền thẳng vào `<Select {...selectProps} />` hoặc `<MultiSelect {...selectProps} />`
|
|
262
|
+
*/
|
|
263
|
+
selectProps: {
|
|
264
|
+
options: SelectOptionItem<TData>[];
|
|
265
|
+
isLoading: boolean;
|
|
266
|
+
searchMode: "server";
|
|
267
|
+
debounceMs: number;
|
|
268
|
+
onSearch: (query: string, filters: TFilters) => void;
|
|
269
|
+
listFooter: ReactNode;
|
|
270
|
+
};
|
|
271
|
+
/**
|
|
272
|
+
* Instance query đầy đủ từ TanStack Query
|
|
273
|
+
*/
|
|
274
|
+
query: UseInfiniteQueryResult<InfiniteData<TResponse>, TError>;
|
|
275
|
+
/**
|
|
276
|
+
* Toàn bộ danh sách options đã gom tụ từ tất cả các trang
|
|
277
|
+
*/
|
|
278
|
+
options: SelectOptionItem<TData>[];
|
|
279
|
+
/**
|
|
280
|
+
* Từ khóa tìm kiếm hiện tại (đã được Select debounce qua onSearch)
|
|
281
|
+
*/
|
|
282
|
+
search: string;
|
|
283
|
+
/**
|
|
284
|
+
* Phương thức cập nhật từ khóa tìm kiếm
|
|
285
|
+
*/
|
|
286
|
+
setSearch: (search: string) => void;
|
|
287
|
+
/**
|
|
288
|
+
* Bộ lọc menu hiện tại
|
|
289
|
+
*/
|
|
290
|
+
filters: TFilters;
|
|
291
|
+
/**
|
|
292
|
+
* Phương thức cập nhật bộ lọc menu
|
|
293
|
+
*/
|
|
294
|
+
setFilters: (filters: TFilters | ((prev: TFilters) => TFilters)) => void;
|
|
295
|
+
/**
|
|
296
|
+
* Ref gắn vào phần tử sentinel (IntersectionObserver)
|
|
297
|
+
*/
|
|
298
|
+
sentinelRef: (node: HTMLElement | null) => void;
|
|
299
|
+
/**
|
|
300
|
+
* Đặt lại toàn bộ tìm kiếm, bộ lọc về giá trị ban đầu
|
|
301
|
+
*/
|
|
302
|
+
reset: () => void;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Hook `useSelectInfiniteQuery` kết hợp TanStack Query `useInfiniteQuery` với `useInfiniteScroll`
|
|
306
|
+
* dành riêng cho `<Select />` và `<MultiSelect />` ở chế độ máy chủ (`searchMode="server"`).
|
|
307
|
+
*/
|
|
308
|
+
declare function useSelectInfiniteQuery<TData = unknown, TResponse = unknown, TPageParam = number, TFilters extends Record<string, unknown> = Record<string, unknown>, TError = Error>({ queryKey, queryFn, initialPageParam, getNextPageParam, getPreviousPageParam, selectOptions, mapOption, debounceMs, initialSearch, initialFilters, initialOptions, skeletonLines, skeletonHeight, renderLoadingMore, endMessage, scrollOptions, queryOptions, }: UseSelectInfiniteQueryOptions<TData, TResponse, TPageParam, TFilters, TError>): UseSelectInfiniteQueryReturn<TData, TResponse, TFilters, TError>;
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Mục tiêu invalidate cache: có thể là QueryKey (readonly unknown[]) hoặc InvalidateQueryFilters.
|
|
312
|
+
*/
|
|
313
|
+
type InvalidateQueryTarget = QueryKey | InvalidateQueryFilters;
|
|
314
|
+
/**
|
|
315
|
+
* Tùy chọn cấu hình Toast cho hook `useMutationApp`.
|
|
316
|
+
*/
|
|
317
|
+
interface UseMutationAppToastOptions<TData, TError, TVariables> {
|
|
318
|
+
/**
|
|
319
|
+
* Nội dung thông báo khi đang thực thi mutation (loading spinner, không tự đóng).
|
|
320
|
+
* Có thể là ReactNode hoặc một hàm nhận vào `variables`.
|
|
321
|
+
*/
|
|
322
|
+
loading?: ReactNode | ((variables: TVariables) => ReactNode);
|
|
323
|
+
/**
|
|
324
|
+
* Nội dung thông báo khi mutation hoàn tất thành công.
|
|
325
|
+
* Có thể là ReactNode hoặc một hàm nhận vào `(data, variables)`.
|
|
326
|
+
*/
|
|
327
|
+
success?: ReactNode | ((data: TData, variables: TVariables) => ReactNode);
|
|
328
|
+
/**
|
|
329
|
+
* Nội dung thông báo khi mutation thất bại.
|
|
330
|
+
* - `true`: Tự động trích xuất thông điệp lỗi từ API/Error qua `extractErrorMessage`.
|
|
331
|
+
* - `false`: Không hiển thị toast lỗi.
|
|
332
|
+
* - `ReactNode`: Thông điệp lỗi cố định.
|
|
333
|
+
* - `(error, variables) => ReactNode`: Hàm tạo thông điệp lỗi linh hoạt.
|
|
334
|
+
* @default true
|
|
335
|
+
*/
|
|
336
|
+
error?: boolean | ReactNode | ((error: TError, variables: TVariables) => ReactNode);
|
|
337
|
+
/**
|
|
338
|
+
* Nội dung mô tả chi tiết (description) cho thông báo khi đang loading.
|
|
339
|
+
*/
|
|
340
|
+
loadingDescription?: ReactNode | ((variables: TVariables) => ReactNode);
|
|
341
|
+
/**
|
|
342
|
+
* Nội dung mô tả chi tiết (description) cho thông báo thành công.
|
|
343
|
+
*/
|
|
344
|
+
successDescription?: ReactNode | ((data: TData, variables: TVariables) => ReactNode);
|
|
345
|
+
/**
|
|
346
|
+
* Nội dung mô tả chi tiết (description) cho thông báo lỗi.
|
|
347
|
+
*/
|
|
348
|
+
errorDescription?: ReactNode | ((error: TError, variables: TVariables) => ReactNode);
|
|
349
|
+
/**
|
|
350
|
+
* Tùy chọn cấu hình bổ sung cho Toast (duration, position, size, radius, closable...).
|
|
351
|
+
*/
|
|
352
|
+
options?: ToastOptions;
|
|
353
|
+
/**
|
|
354
|
+
* Kiểu hiển thị Toast: "soft" | "solid" | "outline".
|
|
355
|
+
* @default "soft"
|
|
356
|
+
*/
|
|
357
|
+
variant?: AlertVariant;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Các tùy chọn cấu hình cho hook `useMutationApp`.
|
|
361
|
+
*/
|
|
362
|
+
interface UseMutationAppOptions<TData = unknown, TError = DefaultError, TVariables = void, TContext = unknown> extends Omit<UseMutationOptions<TData, TError, TVariables, TContext>, "mutationFn"> {
|
|
363
|
+
/**
|
|
364
|
+
* Hàm gọi API hoặc thực hiện tác vụ bất đồng bộ.
|
|
365
|
+
*/
|
|
366
|
+
mutationFn?: (variables: TVariables) => Promise<TData>;
|
|
367
|
+
/**
|
|
368
|
+
* Khóa truy vấn hoặc danh sách khóa truy vấn cần tự động làm mới (invalidate) khi mutation thành công.
|
|
369
|
+
* Hỗ trợ:
|
|
370
|
+
* - Một QueryKey đơn: `["teachers"]` hoặc `["users", 1]`
|
|
371
|
+
* - Danh sách nhiều QueryKey: `[["teachers"], ["classes"]]`
|
|
372
|
+
* - Bộ lọc nâng cao InvalidateQueryFilters: `{ queryKey: ["teachers"], exact: true }`
|
|
373
|
+
* - Danh sách bộ lọc: `[{ queryKey: ["teachers"] }, { queryKey: ["classes"] }]`
|
|
374
|
+
* - Hàm trả về động: `(data, variables) => [["teachers"], ["classes", variables.classId]]`
|
|
375
|
+
*/
|
|
376
|
+
invalidateQueries?: InvalidateQueryTarget | InvalidateQueryTarget[] | ((data: TData, variables: TVariables) => InvalidateQueryTarget | InvalidateQueryTarget[] | void | null | undefined);
|
|
377
|
+
/**
|
|
378
|
+
* Tùy chọn InvalidateOptions bổ sung truyền cho `queryClient.invalidateQueries`
|
|
379
|
+
* (ví dụ: `throwOnError`, `cancelRefetch`).
|
|
380
|
+
*/
|
|
381
|
+
invalidateOptions?: InvalidateOptions;
|
|
382
|
+
/**
|
|
383
|
+
* Cấu hình hiển thị thông báo Toast.
|
|
384
|
+
* - `false`: Tắt toàn bộ thông báo Toast.
|
|
385
|
+
* - `true`: Bật Toast với cấu hình mặc định (tự động báo lỗi nếu có).
|
|
386
|
+
* - `object`: Cấu hình chi tiết `loading`, `success`, `error`.
|
|
387
|
+
*/
|
|
388
|
+
toast?: boolean | UseMutationAppToastOptions<TData, TError, TVariables>;
|
|
389
|
+
/**
|
|
390
|
+
* Shortcut cấu hình nhanh thông báo thành công.
|
|
391
|
+
*/
|
|
392
|
+
successMessage?: ReactNode | ((data: TData, variables: TVariables) => ReactNode);
|
|
393
|
+
/**
|
|
394
|
+
* Shortcut cấu hình nhanh thông báo lỗi.
|
|
395
|
+
*/
|
|
396
|
+
errorMessage?: ReactNode | ((error: TError, variables: TVariables) => ReactNode);
|
|
397
|
+
/**
|
|
398
|
+
* Shortcut cấu hình nhanh thông báo loading.
|
|
399
|
+
*/
|
|
400
|
+
loadingMessage?: ReactNode | ((variables: TVariables) => ReactNode);
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Kết quả trả về từ hook `useMutationApp`.
|
|
404
|
+
*/
|
|
405
|
+
type UseMutationAppReturn<TData = unknown, TError = DefaultError, TVariables = void, TContext = unknown> = UseMutationResult<TData, TError, TVariables, TContext> & {
|
|
406
|
+
/**
|
|
407
|
+
* Bí danh (alias) của `isPending`, tương thích ngược với thói quen sử dụng `isLoading` của TanStack Query v4.
|
|
408
|
+
*/
|
|
409
|
+
isLoading: boolean;
|
|
410
|
+
};
|
|
411
|
+
/**
|
|
412
|
+
* Hàm hỗ trợ tự động trích xuất thông điệp lỗi (error message) từ nhiều định dạng lỗi phổ biến:
|
|
413
|
+
* - Axios Error response (`error.response?.data?.message`, `error.response?.data?.error`...)
|
|
414
|
+
* - Fetch API response / HTTP status
|
|
415
|
+
* - Standard JS Error (`error.message`)
|
|
416
|
+
* - String error
|
|
417
|
+
*/
|
|
418
|
+
declare function extractErrorMessage(error: unknown, fallback?: string): string;
|
|
419
|
+
/**
|
|
420
|
+
* Hook `useMutationApp` - Tối ưu hóa tác vụ Mutation cho ứng dụng với TanStack Query v5 & `@openway/ui`.
|
|
421
|
+
*
|
|
422
|
+
* Tính năng chính:
|
|
423
|
+
* - **Tự động hóa Toast**: Hiển thị Toast loading khi xử lý, tự động cập nhật Toast success/error mượt mà.
|
|
424
|
+
* - **Tự động bóc tách lỗi**: Bóc tách thông điệp lỗi chính xác từ Axios / API response qua `extractErrorMessage`.
|
|
425
|
+
* - **Tự động Invalidate Cache**: Refresh tự động các query liên quan (như DataTable, Select) khi hoàn tất.
|
|
426
|
+
* - **Bổ sung `isLoading`**: Cung cấp alias `isLoading` cho `isPending`, thuận tiện khi code giao diện.
|
|
427
|
+
* - **Giữ trọn vẹn sức mạnh của TanStack Query**: Hỗ trợ đầy đủ `onMutate`, `onSuccess`, `onError`, `onSettled`.
|
|
428
|
+
*/
|
|
429
|
+
declare function useMutationApp<TData = unknown, TError = DefaultError, TVariables = void, TContext = unknown>(options: UseMutationAppOptions<TData, TError, TVariables, TContext>): UseMutationAppReturn<TData, TError, TVariables, TContext>;
|
|
430
|
+
|
|
431
|
+
export { type InvalidateQueryTarget, type SelectQueryParams, type TableQueryParams, type UseMutationAppOptions, type UseMutationAppReturn, type UseMutationAppToastOptions, type UseSelectInfiniteQueryOptions, type UseSelectInfiniteQueryReturn, type UseTableQueryOptions, type UseTableQueryReturn, extractErrorMessage, useMutationApp, useSelectInfiniteQuery, useTableQuery };
|