@ram_28/kf-ai-sdk 1.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.
Files changed (126) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +840 -0
  3. package/dist/api/client.d.ts +78 -0
  4. package/dist/api/client.d.ts.map +1 -0
  5. package/dist/api/datetime.d.ts +21 -0
  6. package/dist/api/datetime.d.ts.map +1 -0
  7. package/dist/api/index.d.ts +7 -0
  8. package/dist/api/index.d.ts.map +1 -0
  9. package/dist/api/metadata.d.ts +75 -0
  10. package/dist/api/metadata.d.ts.map +1 -0
  11. package/dist/components/hooks/index.d.ts +8 -0
  12. package/dist/components/hooks/index.d.ts.map +1 -0
  13. package/dist/components/hooks/useFilter/index.d.ts +5 -0
  14. package/dist/components/hooks/useFilter/index.d.ts.map +1 -0
  15. package/dist/components/hooks/useFilter/payloadBuilder.utils.d.ts +33 -0
  16. package/dist/components/hooks/useFilter/payloadBuilder.utils.d.ts.map +1 -0
  17. package/dist/components/hooks/useFilter/types.d.ts +137 -0
  18. package/dist/components/hooks/useFilter/types.d.ts.map +1 -0
  19. package/dist/components/hooks/useFilter/useFilter.d.ts +3 -0
  20. package/dist/components/hooks/useFilter/useFilter.d.ts.map +1 -0
  21. package/dist/components/hooks/useFilter/validation.utils.d.ts +38 -0
  22. package/dist/components/hooks/useFilter/validation.utils.d.ts.map +1 -0
  23. package/dist/components/hooks/useForm/apiClient.d.ts +71 -0
  24. package/dist/components/hooks/useForm/apiClient.d.ts.map +1 -0
  25. package/dist/components/hooks/useForm/expressionValidator.utils.d.ts +28 -0
  26. package/dist/components/hooks/useForm/expressionValidator.utils.d.ts.map +1 -0
  27. package/dist/components/hooks/useForm/index.d.ts +6 -0
  28. package/dist/components/hooks/useForm/index.d.ts.map +1 -0
  29. package/dist/components/hooks/useForm/optimizedExpressionValidator.utils.d.ts +88 -0
  30. package/dist/components/hooks/useForm/optimizedExpressionValidator.utils.d.ts.map +1 -0
  31. package/dist/components/hooks/useForm/ruleClassifier.utils.d.ts +28 -0
  32. package/dist/components/hooks/useForm/ruleClassifier.utils.d.ts.map +1 -0
  33. package/dist/components/hooks/useForm/schemaParser.utils.d.ts +29 -0
  34. package/dist/components/hooks/useForm/schemaParser.utils.d.ts.map +1 -0
  35. package/dist/components/hooks/useForm/types.d.ts +412 -0
  36. package/dist/components/hooks/useForm/types.d.ts.map +1 -0
  37. package/dist/components/hooks/useForm/useForm.d.ts +3 -0
  38. package/dist/components/hooks/useForm/useForm.d.ts.map +1 -0
  39. package/dist/components/hooks/useKanban/apiClient.d.ts +99 -0
  40. package/dist/components/hooks/useKanban/apiClient.d.ts.map +1 -0
  41. package/dist/components/hooks/useKanban/context.d.ts +4 -0
  42. package/dist/components/hooks/useKanban/context.d.ts.map +1 -0
  43. package/dist/components/hooks/useKanban/dragDropManager.d.ts +27 -0
  44. package/dist/components/hooks/useKanban/dragDropManager.d.ts.map +1 -0
  45. package/dist/components/hooks/useKanban/index.d.ts +6 -0
  46. package/dist/components/hooks/useKanban/index.d.ts.map +1 -0
  47. package/dist/components/hooks/useKanban/types.d.ts +438 -0
  48. package/dist/components/hooks/useKanban/types.d.ts.map +1 -0
  49. package/dist/components/hooks/useKanban/useKanban.d.ts +3 -0
  50. package/dist/components/hooks/useKanban/useKanban.d.ts.map +1 -0
  51. package/dist/components/hooks/useKanban/useKanbanSimple.d.ts +62 -0
  52. package/dist/components/hooks/useKanban/useKanbanSimple.d.ts.map +1 -0
  53. package/dist/components/hooks/useTable/index.d.ts +3 -0
  54. package/dist/components/hooks/useTable/index.d.ts.map +1 -0
  55. package/dist/components/hooks/useTable/types.d.ts +107 -0
  56. package/dist/components/hooks/useTable/types.d.ts.map +1 -0
  57. package/dist/components/hooks/useTable/useTable.d.ts +8 -0
  58. package/dist/components/hooks/useTable/useTable.d.ts.map +1 -0
  59. package/dist/components/index.d.ts +3 -0
  60. package/dist/components/index.d.ts.map +1 -0
  61. package/dist/components/ui/index.d.ts +2 -0
  62. package/dist/components/ui/index.d.ts.map +1 -0
  63. package/dist/components/ui/kanban/Kanban.d.ts +12 -0
  64. package/dist/components/ui/kanban/Kanban.d.ts.map +1 -0
  65. package/dist/components/ui/kanban/index.d.ts +2 -0
  66. package/dist/components/ui/kanban/index.d.ts.map +1 -0
  67. package/dist/index.cjs +45 -0
  68. package/dist/index.d.ts +5 -0
  69. package/dist/index.d.ts.map +1 -0
  70. package/dist/index.mjs +6522 -0
  71. package/dist/types/base-fields.d.ts +182 -0
  72. package/dist/types/base-fields.d.ts.map +1 -0
  73. package/dist/types/common.d.ts +238 -0
  74. package/dist/types/common.d.ts.map +1 -0
  75. package/dist/types/index.d.ts +3 -0
  76. package/dist/types/index.d.ts.map +1 -0
  77. package/dist/utils/cn.d.ts +7 -0
  78. package/dist/utils/cn.d.ts.map +1 -0
  79. package/dist/utils/formatting.d.ts +52 -0
  80. package/dist/utils/formatting.d.ts.map +1 -0
  81. package/dist/utils/index.d.ts +3 -0
  82. package/dist/utils/index.d.ts.map +1 -0
  83. package/package.json +98 -0
  84. package/sdk/api/client.ts +447 -0
  85. package/sdk/api/datetime.ts +33 -0
  86. package/sdk/api/index.ts +61 -0
  87. package/sdk/api/metadata.ts +148 -0
  88. package/sdk/components/hooks/index.ts +34 -0
  89. package/sdk/components/hooks/useFilter/index.ts +37 -0
  90. package/sdk/components/hooks/useFilter/payloadBuilder.utils.ts +298 -0
  91. package/sdk/components/hooks/useFilter/types.ts +158 -0
  92. package/sdk/components/hooks/useFilter/useFilter.llm.txt +497 -0
  93. package/sdk/components/hooks/useFilter/useFilter.ts +494 -0
  94. package/sdk/components/hooks/useFilter/validation.utils.ts +401 -0
  95. package/sdk/components/hooks/useForm/apiClient.ts +441 -0
  96. package/sdk/components/hooks/useForm/expressionValidator.utils.ts +444 -0
  97. package/sdk/components/hooks/useForm/index.ts +64 -0
  98. package/sdk/components/hooks/useForm/optimizedExpressionValidator.utils.ts +482 -0
  99. package/sdk/components/hooks/useForm/ruleClassifier.utils.ts +424 -0
  100. package/sdk/components/hooks/useForm/schemaParser.utils.ts +519 -0
  101. package/sdk/components/hooks/useForm/types.ts +630 -0
  102. package/sdk/components/hooks/useForm/useForm.llm.txt +340 -0
  103. package/sdk/components/hooks/useForm/useForm.ts +821 -0
  104. package/sdk/components/hooks/useKanban/apiClient.ts +494 -0
  105. package/sdk/components/hooks/useKanban/context.ts +14 -0
  106. package/sdk/components/hooks/useKanban/dragDropManager.ts +529 -0
  107. package/sdk/components/hooks/useKanban/index.ts +63 -0
  108. package/sdk/components/hooks/useKanban/types.ts +606 -0
  109. package/sdk/components/hooks/useKanban/useKanban.llm.txt +482 -0
  110. package/sdk/components/hooks/useKanban/useKanban.ts +725 -0
  111. package/sdk/components/hooks/useKanban/useKanbanSimple.ts +389 -0
  112. package/sdk/components/hooks/useTable/index.ts +5 -0
  113. package/sdk/components/hooks/useTable/types.ts +154 -0
  114. package/sdk/components/hooks/useTable/useTable.llm.txt +344 -0
  115. package/sdk/components/hooks/useTable/useTable.ts +413 -0
  116. package/sdk/components/index.ts +15 -0
  117. package/sdk/components/ui/index.ts +2 -0
  118. package/sdk/components/ui/kanban/Kanban.tsx +134 -0
  119. package/sdk/components/ui/kanban/index.ts +11 -0
  120. package/sdk/index.ts +13 -0
  121. package/sdk/types/base-fields.ts +221 -0
  122. package/sdk/types/common.ts +306 -0
  123. package/sdk/types/index.ts +5 -0
  124. package/sdk/utils/cn.ts +10 -0
  125. package/sdk/utils/formatting.ts +212 -0
  126. package/sdk/utils/index.ts +5 -0
@@ -0,0 +1,389 @@
1
+ // ============================================================
2
+ // USE KANBAN HOOK - Simplified Implementation
3
+ // ============================================================
4
+ // Clean hook following useTable pattern for API integration
5
+
6
+ import { useState, useMemo, useCallback, useRef } from "react";
7
+ import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
8
+ import { api } from "../../../api";
9
+ import type { ListOptions, ListResponse } from "../../../types/common";
10
+
11
+ // ============================================================
12
+ // TYPE DEFINITIONS
13
+ // ============================================================
14
+
15
+ export interface KanbanCard<T = Record<string, any>> {
16
+ _id: string;
17
+ title: string;
18
+ description?: string;
19
+ columnId: string;
20
+ position: number;
21
+ data?: T; // Custom fields
22
+ _created_at?: Date;
23
+ _modified_at?: Date;
24
+ }
25
+
26
+ export interface KanbanColumn<T = Record<string, any>> {
27
+ _id: string;
28
+ title: string;
29
+ position: number;
30
+ color?: string;
31
+ cards: KanbanCard<T>[];
32
+ }
33
+
34
+ export interface ColumnDefinition {
35
+ id: string;
36
+ title: string;
37
+ position: number;
38
+ color?: string;
39
+ }
40
+
41
+ export interface UseKanbanOptions<T = Record<string, any>> {
42
+ /** Data source identifier for API calls */
43
+ source: string;
44
+ /** Column configurations */
45
+ columns: ColumnDefinition[];
46
+ /** Enable drag and drop functionality */
47
+ enableDragDrop?: boolean;
48
+ /** Initial search query */
49
+ initialSearch?: string;
50
+ /** Error callback */
51
+ onError?: (error: Error) => void;
52
+ /** Custom card data type validator (optional) */
53
+ validateCardData?: (data: T) => boolean;
54
+ }
55
+
56
+ export interface UseKanbanReturn<T> {
57
+ // Data
58
+ columns: KanbanColumn<T>[];
59
+ totalCards: number;
60
+
61
+ // Loading States
62
+ isLoading: boolean;
63
+ isFetching: boolean;
64
+ isUpdating: boolean;
65
+
66
+ // Error Handling
67
+ error: Error | null;
68
+
69
+ // Search
70
+ searchQuery: string;
71
+ setSearchQuery: (query: string) => void;
72
+ clearSearch: () => void;
73
+
74
+ // Card Operations
75
+ createCard: (card: Partial<KanbanCard<T>> & { columnId: string }) => Promise<void>;
76
+ updateCard: (id: string, updates: Partial<KanbanCard<T>>) => Promise<void>;
77
+ deleteCard: (id: string) => Promise<void>;
78
+ moveCard: (cardId: string, toColumnId: string, position?: number) => Promise<void>;
79
+
80
+ // Drag Drop State (if enabled)
81
+ isDragging: boolean;
82
+ draggedCard: KanbanCard<T> | null;
83
+ handleDragStart: (card: KanbanCard<T>) => void;
84
+ handleDragEnd: () => void;
85
+ handleKeyboardMove: (cardId: string, direction: "left" | "right") => Promise<void>;
86
+
87
+ // Utilities
88
+ refresh: () => Promise<void>;
89
+ }
90
+
91
+ // ============================================================
92
+ // MAIN HOOK IMPLEMENTATION
93
+ // ============================================================
94
+
95
+ export function useKanban<T extends Record<string, any> = Record<string, any>>(
96
+ options: UseKanbanOptions<T>
97
+ ): UseKanbanReturn<T> {
98
+ const {
99
+ source,
100
+ columns: columnConfigs,
101
+ enableDragDrop = false,
102
+ initialSearch = "",
103
+ onError,
104
+ } = options;
105
+
106
+ // ============================================================
107
+ // STATE MANAGEMENT
108
+ // ============================================================
109
+
110
+ const [searchQuery, setSearchQuery] = useState(initialSearch);
111
+ const [dragState, setDragState] = useState({
112
+ isDragging: false,
113
+ draggedCard: null as KanbanCard<T> | null,
114
+ });
115
+
116
+ // Query client for cache management
117
+ const queryClient = useQueryClient();
118
+ const onErrorRef = useRef(onError);
119
+
120
+ // ============================================================
121
+ // API OPTIONS
122
+ // ============================================================
123
+
124
+ const apiOptions = useMemo((): ListOptions => {
125
+ const opts: ListOptions = {};
126
+
127
+ // Default sorting by column and position - using correct API format
128
+ opts.Sort = [
129
+ { columnId: "ASC" },
130
+ { position: "ASC" },
131
+ ];
132
+
133
+ // Add search query
134
+ if (searchQuery) {
135
+ opts.Search = searchQuery;
136
+ }
137
+
138
+ return opts;
139
+ }, [searchQuery]);
140
+
141
+ // ============================================================
142
+ // DATA FETCHING
143
+ // ============================================================
144
+
145
+ // Fetch cards
146
+ const {
147
+ data: cardsResponse,
148
+ isLoading: isLoadingCards,
149
+ isFetching: isFetchingCards,
150
+ error: cardsError,
151
+ refetch: refetchCards,
152
+ } = useQuery({
153
+ queryKey: ["kanban-cards", source, apiOptions],
154
+ queryFn: async (): Promise<ListResponse<KanbanCard<T>>> => {
155
+ try {
156
+ return await api<KanbanCard<T>>(source).list(apiOptions);
157
+ } catch (err) {
158
+ onErrorRef.current?.(err as Error);
159
+ throw err;
160
+ }
161
+ },
162
+ staleTime: 30 * 1000,
163
+ });
164
+
165
+ // Get total card count
166
+ const {
167
+ data: countData,
168
+ isLoading: isLoadingCount,
169
+ error: countError,
170
+ } = useQuery({
171
+ queryKey: ["kanban-count", source, apiOptions],
172
+ queryFn: async () => {
173
+ try {
174
+ return await api<KanbanCard<T>>(source).count(apiOptions);
175
+ } catch (err) {
176
+ onErrorRef.current?.(err as Error);
177
+ throw err;
178
+ }
179
+ },
180
+ staleTime: 30 * 1000,
181
+ });
182
+
183
+ // ============================================================
184
+ // CARD MUTATIONS
185
+ // ============================================================
186
+
187
+ const createCardMutation = useMutation({
188
+ mutationFn: async (card: Partial<KanbanCard<T>> & { columnId: string }) => {
189
+ // Calculate position
190
+ const currentCards = cardsResponse?.Data?.filter((c) => c.columnId === card.columnId) || [];
191
+ const position = card.position ?? currentCards.length;
192
+
193
+ return await api<KanbanCard<T>>(source).create({
194
+ ...card,
195
+ position,
196
+ });
197
+ },
198
+ onSuccess: () => refetchCards(),
199
+ onError: (error) => onErrorRef.current?.(error as Error),
200
+ });
201
+
202
+ const updateCardMutation = useMutation({
203
+ mutationFn: async ({ id, updates }: { id: string; updates: Partial<KanbanCard<T>> }) => {
204
+ return await api<KanbanCard<T>>(source).update(id, updates);
205
+ },
206
+ onSuccess: () => refetchCards(),
207
+ onError: (error) => onErrorRef.current?.(error as Error),
208
+ });
209
+
210
+ const deleteCardMutation = useMutation({
211
+ mutationFn: async (id: string) => {
212
+ return await api(source).delete(id);
213
+ },
214
+ onSuccess: () => refetchCards(),
215
+ onError: (error) => onErrorRef.current?.(error as Error),
216
+ });
217
+
218
+ const moveCardMutation = useMutation({
219
+ mutationFn: async ({ cardId, toColumnId, position }: {
220
+ cardId: string;
221
+ toColumnId: string;
222
+ position?: number;
223
+ }) => {
224
+ const updates: any = { columnId: toColumnId };
225
+ if (position !== undefined) {
226
+ updates.position = position;
227
+ }
228
+ return await api<KanbanCard<T>>(source).update(cardId, updates);
229
+ },
230
+ onSuccess: () => refetchCards(),
231
+ onError: (error) => onErrorRef.current?.(error as Error),
232
+ });
233
+
234
+ // ============================================================
235
+ // OPERATIONS
236
+ // ============================================================
237
+
238
+ const clearSearch = useCallback(() => {
239
+ setSearchQuery("");
240
+ }, []);
241
+
242
+ const handleDragStart = useCallback((card: KanbanCard<T>) => {
243
+ if (!enableDragDrop) return;
244
+ setDragState({
245
+ isDragging: true,
246
+ draggedCard: card,
247
+ });
248
+ }, [enableDragDrop]);
249
+
250
+ const handleDragEnd = useCallback(() => {
251
+ setDragState({
252
+ isDragging: false,
253
+ draggedCard: null,
254
+ });
255
+ }, []);
256
+
257
+ const handleKeyboardMove = useCallback(async (
258
+ cardId: string,
259
+ direction: "left" | "right"
260
+ ) => {
261
+ if (!enableDragDrop) return;
262
+
263
+ const card = cardsResponse?.Data?.find(c => c._id === cardId);
264
+ if (!card) return;
265
+
266
+ const currentColumnIndex = columnConfigs.findIndex(col => col.id === card.columnId);
267
+ if (currentColumnIndex === -1) return;
268
+
269
+ let targetColumnIndex = currentColumnIndex;
270
+
271
+ if (direction === "left") {
272
+ targetColumnIndex = Math.max(0, currentColumnIndex - 1);
273
+ } else if (direction === "right") {
274
+ targetColumnIndex = Math.min(columnConfigs.length - 1, currentColumnIndex + 1);
275
+ }
276
+
277
+ if (targetColumnIndex !== currentColumnIndex) {
278
+ const targetColumn = columnConfigs[targetColumnIndex];
279
+ await moveCardMutation.mutateAsync({
280
+ cardId,
281
+ toColumnId: targetColumn.id,
282
+ });
283
+ }
284
+ }, [enableDragDrop, cardsResponse?.Data, columnConfigs, moveCardMutation]);
285
+
286
+ // ============================================================
287
+ // COMPUTED VALUES
288
+ // ============================================================
289
+
290
+ const processedColumns = useMemo(() => {
291
+ const cards = cardsResponse?.Data || [];
292
+
293
+ // Group cards by columnId
294
+ const cardsByColumn = cards.reduce(
295
+ (acc, card) => {
296
+ if (!acc[card.columnId]) {
297
+ acc[card.columnId] = [];
298
+ }
299
+ acc[card.columnId].push(card);
300
+ return acc;
301
+ },
302
+ {} as Record<string, KanbanCard<T>[]>
303
+ );
304
+
305
+ // Map column configs to columns with cards
306
+ return columnConfigs
307
+ .sort((a, b) => a.position - b.position)
308
+ .map((config) => ({
309
+ _id: config.id,
310
+ title: config.title,
311
+ position: config.position,
312
+ color: config.color,
313
+ cards: (cardsByColumn[config.id] || []).sort(
314
+ (a, b) => a.position - b.position
315
+ ),
316
+ }));
317
+ }, [columnConfigs, cardsResponse]);
318
+
319
+ const refresh = useCallback(async () => {
320
+ await queryClient.invalidateQueries({
321
+ predicate: (query) =>
322
+ query.queryKey[0] === "kanban-cards" ||
323
+ query.queryKey[0] === "kanban-count",
324
+ });
325
+ }, [queryClient]);
326
+
327
+ // ============================================================
328
+ // RETURN VALUES
329
+ // ============================================================
330
+
331
+ return {
332
+ // Data
333
+ columns: processedColumns,
334
+ totalCards: countData?.Count || 0,
335
+
336
+ // Loading States
337
+ isLoading: isLoadingCards || isLoadingCount,
338
+ isFetching: isFetchingCards,
339
+ isUpdating:
340
+ createCardMutation.isPending ||
341
+ updateCardMutation.isPending ||
342
+ deleteCardMutation.isPending ||
343
+ moveCardMutation.isPending,
344
+
345
+ // Error Handling
346
+ error: (cardsError || countError) as Error | null,
347
+
348
+ // Search
349
+ searchQuery,
350
+ setSearchQuery,
351
+ clearSearch,
352
+
353
+ // Card Operations
354
+ createCard: useCallback(
355
+ async (card: Partial<KanbanCard<T>> & { columnId: string }) => {
356
+ await createCardMutation.mutateAsync(card);
357
+ },
358
+ [createCardMutation]
359
+ ),
360
+ updateCard: useCallback(
361
+ async (id: string, updates: Partial<KanbanCard<T>>) => {
362
+ await updateCardMutation.mutateAsync({ id, updates });
363
+ },
364
+ [updateCardMutation]
365
+ ),
366
+ deleteCard: useCallback(
367
+ async (id: string) => {
368
+ await deleteCardMutation.mutateAsync(id);
369
+ },
370
+ [deleteCardMutation]
371
+ ),
372
+ moveCard: useCallback(
373
+ async (cardId: string, toColumnId: string, position?: number) => {
374
+ await moveCardMutation.mutateAsync({ cardId, toColumnId, position });
375
+ },
376
+ [moveCardMutation]
377
+ ),
378
+
379
+ // Drag Drop
380
+ isDragging: dragState.isDragging,
381
+ draggedCard: dragState.draggedCard,
382
+ handleDragStart,
383
+ handleDragEnd,
384
+ handleKeyboardMove,
385
+
386
+ // Utilities
387
+ refresh,
388
+ };
389
+ }
@@ -0,0 +1,5 @@
1
+ // Main hook
2
+ export { useTable } from "./useTable";
3
+
4
+ // Types
5
+ export type { ColumnDefinition, UseTableOptions, UseTableReturn } from "./types";
@@ -0,0 +1,154 @@
1
+ import type { ListResponse, LogicalOperator } from "../../../types/common";
2
+ import type {
3
+ FilterConditionWithId,
4
+ TypedFilterConditionInput,
5
+ ValidationError,
6
+ FieldDefinition,
7
+ } from "../useFilter";
8
+
9
+ // ============================================================
10
+ // TYPE DEFINITIONS
11
+ // ============================================================
12
+
13
+ export interface ColumnDefinition<T> {
14
+ /** Field name from the data type */
15
+ fieldId: keyof T;
16
+ /** Display label (optional, defaults to fieldId) */
17
+ label?: string;
18
+ /** Enable sorting for this column */
19
+ enableSorting?: boolean;
20
+ /** Enable filtering for this column */
21
+ enableFiltering?: boolean;
22
+ /** Custom transform function (overrides auto-formatting) */
23
+ transform?: (value: any, row: T) => React.ReactNode;
24
+ }
25
+
26
+ export interface UseTableOptions<T> {
27
+ /** Data source identifier */
28
+ source: string;
29
+ /** Column configurations */
30
+ columns: ColumnDefinition<T>[];
31
+ /** Enable sorting functionality */
32
+ enableSorting?: boolean;
33
+ /** Enable filtering functionality */
34
+ enableFiltering?: boolean;
35
+ /** Enable pagination */
36
+ enablePagination?: boolean;
37
+ /** Field definitions for filter validation */
38
+ fieldDefinitions?: Record<keyof T, FieldDefinition>;
39
+ /** Initial state */
40
+ initialState?: {
41
+ pagination?: {
42
+ pageNo: number; // 1-indexed page number
43
+ pageSize: number;
44
+ };
45
+ sorting?: {
46
+ field: keyof T;
47
+ direction: "asc" | "desc";
48
+ };
49
+ globalFilter?: string;
50
+ filters?: FilterConditionWithId[];
51
+ filterOperator?: LogicalOperator;
52
+ };
53
+ /** Error callback */
54
+ onError?: (error: Error) => void;
55
+ /** Success callback */
56
+ onSuccess?: (data: T[]) => void;
57
+ /** Filter error callback */
58
+ onFilterError?: (errors: ValidationError[]) => void;
59
+ }
60
+
61
+ export interface UseTableReturn<T> {
62
+ // Data
63
+ rows: T[];
64
+ totalItems: number;
65
+
66
+ // Loading States
67
+ isLoading: boolean;
68
+ isFetching: boolean;
69
+
70
+ // Error Handling
71
+ error: Error | null;
72
+
73
+ // Search (Flat Access)
74
+ search: {
75
+ query: string;
76
+ setQuery: (value: string) => void;
77
+ clear: () => void;
78
+ };
79
+
80
+ // Sorting (Flat Access)
81
+ sort: {
82
+ field: keyof T | null;
83
+ direction: "asc" | "desc" | null;
84
+ toggle: (field: keyof T) => void;
85
+ clear: () => void;
86
+ set: (field: keyof T, direction: "asc" | "desc") => void;
87
+ };
88
+
89
+ // Legacy Global Filtering (Flat Access)
90
+ globalFilter: {
91
+ value: string;
92
+ setValue: (value: string) => void;
93
+ clear: () => void;
94
+ };
95
+
96
+ // Advanced Filtering (Filter Conditions) - Type-safe: lhsField constrained to keyof T
97
+ filter: {
98
+ // State
99
+ conditions: FilterConditionWithId[];
100
+ logicalOperator: LogicalOperator;
101
+ isValid: boolean;
102
+ validationErrors: ValidationError[];
103
+ hasConditions: boolean;
104
+
105
+ // Condition Management (type-safe)
106
+ addCondition: (condition: TypedFilterConditionInput<T>) => string;
107
+ updateCondition: (
108
+ id: string,
109
+ updates: Partial<TypedFilterConditionInput<T>>
110
+ ) => boolean;
111
+ removeCondition: (id: string) => boolean;
112
+ clearConditions: () => void;
113
+ getCondition: (id: string) => FilterConditionWithId | undefined;
114
+
115
+ // Logical Operator
116
+ setLogicalOperator: (operator: LogicalOperator) => void;
117
+
118
+ // Bulk Operations
119
+ setConditions: (conditions: FilterConditionWithId[]) => void;
120
+ replaceCondition: (
121
+ id: string,
122
+ newCondition: TypedFilterConditionInput<T>
123
+ ) => boolean;
124
+
125
+ // Validation
126
+ validateCondition: (condition: Partial<FilterConditionWithId>) => any;
127
+ validateAllConditions: () => any;
128
+
129
+ // State Management
130
+ exportState: () => any;
131
+ importState: (state: any) => void;
132
+ resetToInitial: () => void;
133
+
134
+ // Utilities
135
+ getConditionCount: () => number;
136
+ };
137
+
138
+ // Pagination (Flat Access)
139
+ pagination: {
140
+ currentPage: number;
141
+ pageSize: number;
142
+ totalPages: number;
143
+ totalItems: number;
144
+ canGoNext: boolean;
145
+ canGoPrevious: boolean;
146
+ goToNext: () => void;
147
+ goToPrevious: () => void;
148
+ goToPage: (page: number) => void;
149
+ setPageSize: (size: number) => void;
150
+ };
151
+
152
+ // Operations
153
+ refetch: () => Promise<ListResponse<T>>;
154
+ }