@ram_28/kf-ai-sdk 1.0.16 → 1.0.18

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.
@@ -0,0 +1,372 @@
1
+ # useTable
2
+
3
+ ## Brief Description
4
+
5
+ - Provides complete table state management including data fetching, sorting, filtering, search, and pagination
6
+ - Integrates with `useFilter` for advanced filtering capabilities with nested condition groups
7
+ - Handles API interactions automatically using React Query for caching and background refetching
8
+ - Returns flattened state accessors (`sort.field`, `pagination.currentPage`) for easy component integration
9
+
10
+ ## Type Reference
11
+
12
+ ```typescript
13
+ import { useTable } from "@ram_28/kf-ai-sdk/table";
14
+ import { isCondition, isConditionGroup } from "@ram_28/kf-ai-sdk/filter";
15
+ import type {
16
+ UseTableOptionsType,
17
+ UseTableReturnType,
18
+ ColumnDefinitionType,
19
+ } from "@ram_28/kf-ai-sdk/table/types";
20
+ import type {
21
+ ConditionType,
22
+ ConditionGroupType,
23
+ ConditionOperatorType,
24
+ ConditionGroupOperatorType,
25
+ FilterType,
26
+ UseFilterReturnType,
27
+ } from "@ram_28/kf-ai-sdk/filter/types";
28
+ import type { ListResponseType } from "@ram_28/kf-ai-sdk/api/types";
29
+
30
+ // Condition operators for comparing field values
31
+ type ConditionOperatorType =
32
+ | "EQ" | "NE" | "GT" | "GTE" | "LT" | "LTE"
33
+ | "Between" | "NotBetween"
34
+ | "IN" | "NIN"
35
+ | "Empty" | "NotEmpty"
36
+ | "Contains" | "NotContains"
37
+ | "MinLength" | "MaxLength";
38
+
39
+ // Group operators for combining conditions
40
+ type ConditionGroupOperatorType = "And" | "Or" | "Not";
41
+
42
+ // Column configuration
43
+ interface ColumnDefinitionType<T> {
44
+ fieldId: keyof T;
45
+ label?: string;
46
+ enableSorting?: boolean;
47
+ enableFiltering?: boolean;
48
+ transform?: (value: any, row: T) => React.ReactNode;
49
+ }
50
+
51
+ // Hook options
52
+ interface UseTableOptionsType<T> {
53
+ source: string;
54
+ columns: ColumnDefinitionType<T>[];
55
+ enableSorting?: boolean;
56
+ enableFiltering?: boolean;
57
+ enablePagination?: boolean;
58
+ initialState?: {
59
+ pagination?: { pageNo: number; pageSize: number };
60
+ sorting?: { field: keyof T; direction: "asc" | "desc" };
61
+ filters?: Array<ConditionType | ConditionGroupType>;
62
+ filterOperator?: ConditionGroupOperatorType;
63
+ };
64
+ onError?: (error: Error) => void;
65
+ onSuccess?: (data: T[]) => void;
66
+ }
67
+
68
+ // Hook return type
69
+ interface UseTableReturnType<T> {
70
+ // Data
71
+ rows: T[];
72
+ totalItems: number;
73
+
74
+ // Loading states
75
+ isLoading: boolean;
76
+ isFetching: boolean;
77
+ error: Error | null;
78
+
79
+ // Search
80
+ search: {
81
+ query: string;
82
+ setQuery: (value: string) => void;
83
+ clear: () => void;
84
+ };
85
+
86
+ // Sort
87
+ sort: {
88
+ field: keyof T | null;
89
+ direction: "asc" | "desc" | null;
90
+ toggle: (field: keyof T) => void;
91
+ clear: () => void;
92
+ set: (field: keyof T, direction: "asc" | "desc") => void;
93
+ };
94
+
95
+ // Filter (uses useFilter internally)
96
+ filter: UseFilterReturnType;
97
+
98
+ // Pagination
99
+ pagination: {
100
+ currentPage: number;
101
+ pageSize: number;
102
+ totalPages: number;
103
+ totalItems: number;
104
+ canGoNext: boolean;
105
+ canGoPrevious: boolean;
106
+ goToNext: () => void;
107
+ goToPrevious: () => void;
108
+ goToPage: (page: number) => void;
109
+ setPageSize: (size: number) => void;
110
+ };
111
+
112
+ // Operations
113
+ refetch: () => Promise<ListResponseType<T>>;
114
+ }
115
+
116
+ // API response structure
117
+ interface ListResponseType<T> {
118
+ Data: T[];
119
+ }
120
+ ```
121
+
122
+ ## Usage Example
123
+
124
+ ```tsx
125
+ import { useTable } from "@ram_28/kf-ai-sdk/table";
126
+ import { isCondition, isConditionGroup } from "@ram_28/kf-ai-sdk/filter";
127
+ import type {
128
+ UseTableOptionsType,
129
+ UseTableReturnType,
130
+ ColumnDefinitionType,
131
+ } from "@ram_28/kf-ai-sdk/table/types";
132
+ import type {
133
+ ConditionType,
134
+ ConditionGroupType,
135
+ ConditionOperatorType,
136
+ ConditionGroupOperatorType,
137
+ FilterType,
138
+ UseFilterReturnType,
139
+ } from "@ram_28/kf-ai-sdk/filter/types";
140
+ import type { ListResponseType } from "@ram_28/kf-ai-sdk/api/types";
141
+ import { Product, ProductType } from "../sources";
142
+ import { Roles } from "../sources/roles";
143
+
144
+ // Get the typed product for the Buyer role
145
+ type BuyerProduct = ProductType<typeof Roles.Buyer>;
146
+
147
+ function ProductsPage() {
148
+ // Instantiate the Product source with role
149
+ const product = new Product(Roles.Buyer);
150
+
151
+ // Column definitions with type safety
152
+ const columns: ColumnDefinitionType<BuyerProduct>[] = [
153
+ { fieldId: "Title", label: "Name", enableSorting: true },
154
+ {
155
+ fieldId: "Price",
156
+ label: "Price",
157
+ enableSorting: true,
158
+ transform: (value) => `$${value.toFixed(2)}`,
159
+ },
160
+ { fieldId: "Category", label: "Category", enableSorting: true, enableFiltering: true },
161
+ { fieldId: "Stock", label: "Stock", enableSorting: true },
162
+ ];
163
+
164
+ // Hook configuration with full options
165
+ const options: UseTableOptionsType<BuyerProduct> = {
166
+ source: product._id, // Use the Business Object ID from the Product class
167
+ columns,
168
+ enableSorting: true,
169
+ enableFiltering: true,
170
+ enablePagination: true,
171
+ initialState: {
172
+ pagination: { pageNo: 1, pageSize: 10 },
173
+ sorting: { field: "_created_at", direction: "desc" },
174
+ filterOperator: "And",
175
+ },
176
+ onError: (error: Error) => console.error("Table error:", error.message),
177
+ onSuccess: (data: BuyerProduct[]) => console.log("Loaded", data.length, "products"),
178
+ };
179
+
180
+ const table: UseTableReturnType<BuyerProduct> = useTable<BuyerProduct>(options);
181
+
182
+ // Access filter functionality (UseFilterReturnType)
183
+ const filterState: UseFilterReturnType = table.filter;
184
+
185
+ // Add a filter with dynamic operator selection
186
+ const addFilter = (field: keyof BuyerProduct, operator: ConditionOperatorType, value: any) => {
187
+ table.filter.addCondition({
188
+ Operator: operator,
189
+ LHSField: field as string,
190
+ RHSValue: value,
191
+ });
192
+ };
193
+
194
+ // Add a simple filter condition
195
+ const filterByCategory = (category: string) => {
196
+ table.filter.clearAllConditions();
197
+ addFilter("Category", "EQ", category);
198
+ };
199
+
200
+ // Add a complex nested filter (Price > 100 OR Stock < 10)
201
+ const addComplexFilter = () => {
202
+ const groupId = table.filter.addConditionGroup("Or");
203
+ table.filter.addCondition({ Operator: "GT", LHSField: "Price", RHSValue: 100 }, groupId);
204
+ table.filter.addCondition({ Operator: "LT", LHSField: "Stock", RHSValue: 10 }, groupId);
205
+ };
206
+
207
+ // Display active filters using type guards
208
+ const renderActiveFilters = () => (
209
+ <div className="active-filters">
210
+ {table.filter.items.map((item) => {
211
+ if (isCondition(item)) {
212
+ return (
213
+ <span key={item.id} className="filter-tag">
214
+ {item.LHSField} {item.Operator} {String(item.RHSValue)}
215
+ <button onClick={() => table.filter.removeCondition(item.id!)}>×</button>
216
+ </span>
217
+ );
218
+ }
219
+ if (isConditionGroup(item)) {
220
+ return (
221
+ <span key={item.id} className="filter-group-tag">
222
+ {item.Operator} Group ({item.Condition.length} conditions)
223
+ <button onClick={() => table.filter.removeCondition(item.id!)}>×</button>
224
+ </span>
225
+ );
226
+ }
227
+ return null;
228
+ })}
229
+ </div>
230
+ );
231
+
232
+ // Toggle filter logic operator
233
+ const toggleFilterLogic = () => {
234
+ const next: ConditionGroupOperatorType = table.filter.operator === "And" ? "Or" : "And";
235
+ table.filter.setRootOperator(next);
236
+ };
237
+
238
+ // Refetch data manually
239
+ const handleRefresh = async () => {
240
+ const response: ListResponseType<BuyerProduct> = await table.refetch();
241
+ console.log(`Refreshed: ${response.Data.length} items`);
242
+ };
243
+
244
+ // Access filter payload for debugging
245
+ const getFilterPayload = (): FilterType | undefined => {
246
+ return table.filter.payload;
247
+ };
248
+
249
+ if (table.isLoading) {
250
+ return <div>Loading products...</div>;
251
+ }
252
+
253
+ if (table.error) {
254
+ return <div>Error: {table.error.message}</div>;
255
+ }
256
+
257
+ return (
258
+ <div className="products-page">
259
+ {/* Search */}
260
+ <div className="search-bar">
261
+ <input
262
+ type="text"
263
+ placeholder="Search products..."
264
+ value={table.search.query}
265
+ onChange={(e) => table.search.setQuery(e.target.value)}
266
+ />
267
+ <button onClick={table.search.clear}>Clear</button>
268
+ </div>
269
+
270
+ {/* Filter Controls */}
271
+ <div className="filter-controls">
272
+ <button onClick={() => filterByCategory("Electronics")}>Electronics</button>
273
+ <button onClick={() => filterByCategory("Books")}>Books</button>
274
+ <button onClick={addComplexFilter}>Add Complex Filter</button>
275
+ <button onClick={toggleFilterLogic}>
276
+ Logic: {table.filter.operator}
277
+ </button>
278
+ {table.filter.hasConditions && (
279
+ <button onClick={() => table.filter.clearAllConditions()}>Clear All Filters</button>
280
+ )}
281
+ </div>
282
+
283
+ {/* Active Filters */}
284
+ {renderActiveFilters()}
285
+
286
+ {/* Table */}
287
+ <table>
288
+ <thead>
289
+ <tr>
290
+ {columns.map((col) => (
291
+ <th
292
+ key={String(col.fieldId)}
293
+ onClick={() => col.enableSorting && table.sort.toggle(col.fieldId)}
294
+ style={{ cursor: col.enableSorting ? "pointer" : "default" }}
295
+ >
296
+ {col.label || String(col.fieldId)}
297
+ {table.sort.field === col.fieldId && (
298
+ <span>{table.sort.direction === "asc" ? " ↑" : " ↓"}</span>
299
+ )}
300
+ </th>
301
+ ))}
302
+ </tr>
303
+ </thead>
304
+ <tbody>
305
+ {table.rows.map((row: BuyerProduct) => (
306
+ <tr key={row._id}>
307
+ <td>{row.Title}</td>
308
+ <td>${row.Price.toFixed(2)}</td>
309
+ <td>{row.Category}</td>
310
+ <td>{row.Stock}</td>
311
+ </tr>
312
+ ))}
313
+ </tbody>
314
+ </table>
315
+
316
+ {/* Pagination */}
317
+ <div className="pagination">
318
+ <button
319
+ onClick={table.pagination.goToPrevious}
320
+ disabled={!table.pagination.canGoPrevious}
321
+ >
322
+ Previous
323
+ </button>
324
+ <span>
325
+ Page {table.pagination.currentPage} of {table.pagination.totalPages}
326
+ ({table.pagination.totalItems} total)
327
+ </span>
328
+ <button
329
+ onClick={table.pagination.goToNext}
330
+ disabled={!table.pagination.canGoNext}
331
+ >
332
+ Next
333
+ </button>
334
+ <select
335
+ value={table.pagination.pageSize}
336
+ onChange={(e) => table.pagination.setPageSize(Number(e.target.value))}
337
+ >
338
+ <option value={10}>10 per page</option>
339
+ <option value={25}>25 per page</option>
340
+ <option value={50}>50 per page</option>
341
+ </select>
342
+ <input
343
+ type="number"
344
+ min={1}
345
+ max={table.pagination.totalPages}
346
+ placeholder="Go to page"
347
+ onKeyDown={(e) => {
348
+ if (e.key === "Enter") {
349
+ table.pagination.goToPage(Number((e.target as HTMLInputElement).value));
350
+ }
351
+ }}
352
+ />
353
+ </div>
354
+
355
+ {/* Actions */}
356
+ <div className="table-actions">
357
+ <button onClick={handleRefresh} disabled={table.isFetching}>
358
+ {table.isFetching ? "Refreshing..." : "Refresh"}
359
+ </button>
360
+ <button onClick={() => table.sort.clear()}>Clear Sort</button>
361
+ <button onClick={() => table.sort.set("Price", "desc")}>Sort by Price (desc)</button>
362
+ </div>
363
+
364
+ {/* Debug: Filter payload */}
365
+ <details>
366
+ <summary>Filter Payload (Debug)</summary>
367
+ <pre>{JSON.stringify(getFilterPayload(), null, 2)}</pre>
368
+ </details>
369
+ </div>
370
+ );
371
+ }
372
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ram_28/kf-ai-sdk",
3
- "version": "1.0.16",
3
+ "version": "1.0.18",
4
4
  "description": "Type-safe, AI-driven SDK for building modern web applications with role-based access control",
5
5
  "author": "Ramprasad",
6
6
  "license": "MIT",
@@ -156,11 +156,13 @@
156
156
  "types": "./dist/base-types.d.ts",
157
157
  "default": "./dist/types.cjs"
158
158
  }
159
- }
159
+ },
160
+ "./docs/*": "./docs/*"
160
161
  },
161
162
  "files": [
162
163
  "dist",
163
164
  "sdk",
165
+ "docs",
164
166
  "README.md",
165
167
  "LICENSE"
166
168
  ],