@ram_28/kf-ai-sdk 2.0.14 → 2.0.16

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 (157) hide show
  1. package/README.md +10 -9
  2. package/dist/FileField-BWrSHNRq.js +296 -0
  3. package/dist/FileField-eDeuzln8.cjs +1 -0
  4. package/dist/api.cjs +1 -1
  5. package/dist/api.mjs +2 -2
  6. package/dist/auth.cjs +1 -1
  7. package/dist/auth.mjs +1 -1
  8. package/dist/bdo/core/BaseBdo.d.ts +1 -1
  9. package/dist/bdo.cjs +1 -1
  10. package/dist/bdo.mjs +230 -474
  11. package/dist/{client-DnO2KKrw.cjs → client-D5k4SYuw.cjs} +1 -1
  12. package/dist/{client-iQTqFDNI.js → client-_ayziI1d.js} +33 -32
  13. package/dist/components/hooks/index.d.ts +9 -3
  14. package/dist/components/hooks/index.d.ts.map +1 -1
  15. package/dist/{workflow/components → components/hooks}/useActivityForm/createActivityItemProxy.d.ts +9 -5
  16. package/dist/components/hooks/useActivityForm/createActivityItemProxy.d.ts.map +1 -0
  17. package/dist/components/hooks/useActivityForm/createActivityResolver.d.ts +23 -0
  18. package/dist/components/hooks/useActivityForm/createActivityResolver.d.ts.map +1 -0
  19. package/dist/components/hooks/useActivityForm/index.d.ts.map +1 -0
  20. package/dist/{workflow/components → components/hooks}/useActivityForm/types.d.ts +12 -8
  21. package/dist/components/hooks/useActivityForm/types.d.ts.map +1 -0
  22. package/dist/{workflow/components → components/hooks}/useActivityForm/useActivityForm.d.ts +2 -2
  23. package/dist/components/hooks/useActivityForm/useActivityForm.d.ts.map +1 -0
  24. package/dist/components/hooks/useActivityTable/index.d.ts +4 -0
  25. package/dist/components/hooks/useActivityTable/index.d.ts.map +1 -0
  26. package/dist/components/hooks/useActivityTable/types.d.ts +36 -0
  27. package/dist/components/hooks/useActivityTable/types.d.ts.map +1 -0
  28. package/dist/components/hooks/useActivityTable/useActivityTable.d.ts +4 -0
  29. package/dist/components/hooks/useActivityTable/useActivityTable.d.ts.map +1 -0
  30. package/dist/components/hooks/useBDOForm/createItemProxy.d.ts.map +1 -0
  31. package/dist/components/hooks/useBDOForm/createResolver.d.ts.map +1 -0
  32. package/dist/components/hooks/useBDOForm/index.d.ts +6 -0
  33. package/dist/components/hooks/useBDOForm/index.d.ts.map +1 -0
  34. package/dist/components/hooks/useBDOForm/shared.d.ts +50 -0
  35. package/dist/components/hooks/useBDOForm/shared.d.ts.map +1 -0
  36. package/dist/components/hooks/{useForm → useBDOForm}/types.d.ts +6 -6
  37. package/dist/components/hooks/useBDOForm/types.d.ts.map +1 -0
  38. package/dist/components/hooks/{useForm/useForm.d.ts → useBDOForm/useBDOForm.d.ts} +4 -4
  39. package/dist/components/hooks/useBDOForm/useBDOForm.d.ts.map +1 -0
  40. package/dist/components/hooks/useBDOTable/index.d.ts +3 -0
  41. package/dist/components/hooks/useBDOTable/index.d.ts.map +1 -0
  42. package/dist/components/hooks/useBDOTable/types.d.ts +24 -0
  43. package/dist/components/hooks/useBDOTable/types.d.ts.map +1 -0
  44. package/dist/components/hooks/useBDOTable/useBDOTable.d.ts +3 -0
  45. package/dist/components/hooks/useBDOTable/useBDOTable.d.ts.map +1 -0
  46. package/dist/components/hooks/useTable/index.d.ts +2 -2
  47. package/dist/components/hooks/useTable/index.d.ts.map +1 -1
  48. package/dist/components/hooks/useTable/types.d.ts +11 -10
  49. package/dist/components/hooks/useTable/types.d.ts.map +1 -1
  50. package/dist/components/hooks/useTable/useTable.d.ts +1 -1
  51. package/dist/components/hooks/useTable/useTable.d.ts.map +1 -1
  52. package/dist/form.cjs +1 -1
  53. package/dist/form.d.ts +1 -1
  54. package/dist/form.d.ts.map +1 -1
  55. package/dist/form.mjs +279 -344
  56. package/dist/form.types.d.ts +1 -1
  57. package/dist/form.types.d.ts.map +1 -1
  58. package/dist/{metadata-DpfI3zRN.js → metadata-Cc1mBcLS.js} +1 -1
  59. package/dist/{metadata-DgLSJkF5.cjs → metadata-DWXQPDav.cjs} +1 -1
  60. package/dist/shared-5a7UkED1.js +1180 -0
  61. package/dist/shared-nnmlRVs7.cjs +1 -0
  62. package/dist/table.cjs +1 -1
  63. package/dist/table.d.ts +1 -0
  64. package/dist/table.d.ts.map +1 -1
  65. package/dist/table.mjs +17 -192
  66. package/dist/table.types.d.ts +2 -1
  67. package/dist/table.types.d.ts.map +1 -1
  68. package/dist/types/base-fields.d.ts +4 -4
  69. package/dist/types/base-fields.d.ts.map +1 -1
  70. package/dist/types/constants.d.ts +3 -3
  71. package/dist/useTable-CeRklbdT.cjs +1 -0
  72. package/dist/useTable-DS0-WInw.js +203 -0
  73. package/dist/workflow/Activity.d.ts +19 -7
  74. package/dist/workflow/Activity.d.ts.map +1 -1
  75. package/dist/workflow/client.d.ts +2 -2
  76. package/dist/workflow/client.d.ts.map +1 -1
  77. package/dist/workflow/createFieldFromMeta.d.ts +29 -0
  78. package/dist/workflow/createFieldFromMeta.d.ts.map +1 -0
  79. package/dist/workflow/index.d.ts +1 -2
  80. package/dist/workflow/index.d.ts.map +1 -1
  81. package/dist/workflow/types.d.ts +16 -12
  82. package/dist/workflow/types.d.ts.map +1 -1
  83. package/dist/workflow.cjs +1 -1
  84. package/dist/workflow.d.ts +5 -2
  85. package/dist/workflow.d.ts.map +1 -1
  86. package/dist/workflow.mjs +687 -352
  87. package/dist/workflow.types.d.ts +1 -0
  88. package/dist/workflow.types.d.ts.map +1 -1
  89. package/docs/bdo.md +1 -1
  90. package/docs/gaps.md +360 -0
  91. package/docs/useActivityForm.md +393 -0
  92. package/docs/useActivityTable.md +418 -0
  93. package/docs/{useForm.md → useBDOForm.md} +24 -24
  94. package/docs/useBDOTable.md +284 -0
  95. package/docs/workflow.md +148 -297
  96. package/package.json +2 -2
  97. package/sdk/bdo/core/BaseBdo.ts +2 -2
  98. package/sdk/bdo/fields/UserField.ts +1 -1
  99. package/sdk/components/hooks/index.ts +28 -5
  100. package/sdk/components/hooks/useActivityForm/createActivityItemProxy.ts +400 -0
  101. package/sdk/components/hooks/useActivityForm/createActivityResolver.ts +87 -0
  102. package/sdk/{workflow/components → components/hooks}/useActivityForm/types.ts +24 -11
  103. package/sdk/components/hooks/useActivityForm/useActivityForm.ts +478 -0
  104. package/sdk/components/hooks/useActivityTable/index.ts +8 -0
  105. package/sdk/components/hooks/useActivityTable/types.ts +47 -0
  106. package/sdk/components/hooks/useActivityTable/useActivityTable.ts +40 -0
  107. package/sdk/components/hooks/{useForm → useBDOForm}/index.ts +4 -3
  108. package/sdk/components/hooks/useBDOForm/shared.ts +250 -0
  109. package/sdk/components/hooks/{useForm → useBDOForm}/types.ts +9 -9
  110. package/sdk/components/hooks/{useForm/useForm.ts → useBDOForm/useBDOForm.ts} +70 -96
  111. package/sdk/components/hooks/useBDOTable/index.ts +2 -0
  112. package/sdk/components/hooks/useBDOTable/types.ts +22 -0
  113. package/sdk/components/hooks/useBDOTable/useBDOTable.ts +16 -0
  114. package/sdk/components/hooks/useTable/index.ts +3 -3
  115. package/sdk/components/hooks/useTable/types.ts +16 -12
  116. package/sdk/components/hooks/useTable/useTable.ts +56 -49
  117. package/sdk/form.ts +2 -2
  118. package/sdk/form.types.ts +4 -4
  119. package/sdk/table.ts +4 -1
  120. package/sdk/table.types.ts +7 -4
  121. package/sdk/types/base-fields.ts +4 -4
  122. package/sdk/types/constants.ts +3 -3
  123. package/sdk/workflow/Activity.ts +36 -12
  124. package/sdk/workflow/client.ts +65 -12
  125. package/sdk/workflow/createFieldFromMeta.ts +110 -0
  126. package/sdk/workflow/index.ts +1 -6
  127. package/sdk/workflow/types.ts +20 -11
  128. package/sdk/workflow.ts +11 -2
  129. package/sdk/workflow.types.ts +7 -0
  130. package/dist/BaseField-B6da88U7.js +0 -40
  131. package/dist/BaseField-Drp0-OxL.cjs +0 -1
  132. package/dist/components/hooks/useForm/createItemProxy.d.ts.map +0 -1
  133. package/dist/components/hooks/useForm/createResolver.d.ts.map +0 -1
  134. package/dist/components/hooks/useForm/index.d.ts +0 -5
  135. package/dist/components/hooks/useForm/index.d.ts.map +0 -1
  136. package/dist/components/hooks/useForm/types.d.ts.map +0 -1
  137. package/dist/components/hooks/useForm/useForm.d.ts.map +0 -1
  138. package/dist/error-handling-CAoD0Kwb.cjs +0 -1
  139. package/dist/error-handling-CrhTtD88.js +0 -14
  140. package/dist/index.esm-Cj63v5ny.js +0 -1014
  141. package/dist/index.esm-DuwT11sx.cjs +0 -1
  142. package/dist/workflow/components/useActivityForm/createActivityItemProxy.d.ts.map +0 -1
  143. package/dist/workflow/components/useActivityForm/createActivityResolver.d.ts +0 -22
  144. package/dist/workflow/components/useActivityForm/createActivityResolver.d.ts.map +0 -1
  145. package/dist/workflow/components/useActivityForm/index.d.ts.map +0 -1
  146. package/dist/workflow/components/useActivityForm/types.d.ts.map +0 -1
  147. package/dist/workflow/components/useActivityForm/useActivityForm.d.ts.map +0 -1
  148. package/docs/useTable.md +0 -369
  149. package/sdk/workflow/components/useActivityForm/createActivityItemProxy.ts +0 -130
  150. package/sdk/workflow/components/useActivityForm/createActivityResolver.ts +0 -61
  151. package/sdk/workflow/components/useActivityForm/useActivityForm.ts +0 -386
  152. /package/dist/{workflow/components → components/hooks}/useActivityForm/index.d.ts +0 -0
  153. /package/dist/components/hooks/{useForm → useBDOForm}/createItemProxy.d.ts +0 -0
  154. /package/dist/components/hooks/{useForm → useBDOForm}/createResolver.d.ts +0 -0
  155. /package/sdk/{workflow/components → components/hooks}/useActivityForm/index.ts +0 -0
  156. /package/sdk/components/hooks/{useForm → useBDOForm}/createItemProxy.ts +0 -0
  157. /package/sdk/components/hooks/{useForm → useBDOForm}/createResolver.ts +0 -0
package/docs/workflow.md CHANGED
@@ -11,6 +11,8 @@ import {
11
11
  Activity,
12
12
  ActivityInstance,
13
13
  useActivityForm,
14
+ useActivityTable,
15
+ ActivityTableStatus,
14
16
  } from "@ram_28/kf-ai-sdk/workflow";
15
17
 
16
18
  // Type-only exports
@@ -20,6 +22,10 @@ import type {
20
22
  WorkflowStartResponseType,
21
23
  UseActivityFormOptions,
22
24
  UseActivityFormReturn,
25
+ UseActivityTableOptionsType,
26
+ UseActivityTableReturnType,
27
+ ActivityTableStatusType,
28
+ ActivityRowType,
23
29
  } from "@ram_28/kf-ai-sdk/workflow";
24
30
 
25
31
  // Field classes (for defining Activity fields)
@@ -31,7 +37,7 @@ import {
31
37
  DateTimeField,
32
38
  SelectField,
33
39
  ReferenceField,
34
- } from "@ram_28/kf-ai-sdk/bdo/fields";
40
+ } from '@ram_28/kf-ai-sdk/bdo/fields';
35
41
 
36
42
  // Field types (for entity type definitions)
37
43
  import type {
@@ -42,7 +48,7 @@ import type {
42
48
  DateTimeFieldType,
43
49
  SelectFieldType,
44
50
  ReferenceFieldType,
45
- } from "@ram_28/kf-ai-sdk/types";
51
+ } from '@ram_28/kf-ai-sdk/types';
46
52
  ```
47
53
 
48
54
  ---
@@ -82,64 +88,28 @@ System fields present on every activity instance. Returned alongside activity-sp
82
88
  type ActivityInstanceFieldsType = {
83
89
  _id: StringFieldType;
84
90
  Status: SelectFieldType<"InProgress" | "Completed">;
85
- AssignedTo: ReferenceFieldType<{ _id: StringFieldType; username: StringFieldType }>;
91
+ AssignedTo: UserFieldType[];
86
92
  CompletedAt: DateTimeFieldType;
87
93
  };
88
94
  ```
89
95
 
90
- ### UseActivityFormOptions\<A\>
96
+ ### Activity Table Types
91
97
 
92
- ```typescript
93
- interface UseActivityFormOptions<A extends Activity<any, any, any>> {
94
- /** Activity instance identifier (from wf.start() or getInProgressList()) */
95
- activity_instance_id: string;
98
+ See the dedicated [useActivityTable documentation](./useActivityTable.md) for `ActivityTableStatus`, `ActivityRowType`, `UseActivityTableOptionsType`, and `UseActivityTableReturnType`.
96
99
 
97
- /** Default form values */
98
- defaultValues?: Partial<ExtractActivityEditable<A>>;
100
+ Entity fields and system fields are flat at the top level, same as BDO tables. Access entity fields as `row.FieldName`.
99
101
 
100
- /** Validation mode (default: "onBlur") */
101
- mode?: "onBlur" | "onChange" | "onSubmit" | "onTouched" | "all";
102
102
 
103
- /** Whether to load activity data on mount (default: true) */
104
- enabled?: boolean;
105
- }
106
- ```
103
+ ### UseActivityFormOptions\<A\> / UseActivityFormReturn\<A\>
107
104
 
108
- ### UseActivityFormReturn\<A\>
105
+ See the dedicated [useActivityForm documentation](./useActivityForm.md) for the full type definitions.
109
106
 
110
- ```typescript
111
- interface UseActivityFormReturn<A extends Activity<any, any, any>> {
112
- // Core
113
- item: FormItemType<EditableFields, ReadonlyFields>;
114
- activity: A;
115
- register: FormRegisterType<EditableFields, ReadonlyFields>;
116
- handleSubmit: HandleSubmitType; // Save the activity form
117
- handleComplete: HandleSubmitType; // Complete the activity
118
-
119
- // RHF methods
120
- watch: UseFormWatch;
121
- setValue: UseFormSetValue;
122
- getValues: UseFormGetValues;
123
- reset: UseFormReset;
124
- trigger: UseFormTrigger;
125
- control: Control;
126
-
127
- // Form state
128
- errors: FieldErrors;
129
- isValid: boolean;
130
- isDirty: boolean;
131
- isSubmitting: boolean;
132
- isSubmitSuccessful: boolean;
133
-
134
- // Loading
135
- isLoading: boolean;
136
- loadError: Error | null;
137
- hasError: boolean;
138
-
139
- // Operations
140
- clearErrors: () => void;
141
- }
142
- ```
107
+ ### File & Image Types
108
+
109
+ Image accessor: `item.field.get()` returns `FileType | null`. Has `upload(file: File)`, `deleteAttachment()`, `getDownloadUrl()`.
110
+ File accessor: `item.field.get()` returns `FileType[]`. Has `upload(files: File[])`, `deleteAttachment(id)`, `getDownloadUrl(id)`.
111
+
112
+ Activity forms always have an instance ID, so attachment operations work immediately — no draft creation is needed.
143
113
 
144
114
  ---
145
115
 
@@ -250,21 +220,30 @@ Each Activity class provides methods to query and access activity instances. Lis
250
220
  const activity = wf.employeeInputActivity();
251
221
  ```
252
222
 
253
- ### getInProgressList()
223
+ ### getInProgressList(options?)
254
224
 
255
- List in-progress activity instances. Filtering and pagination are handled server-side automatically.
225
+ List in-progress activity instances. Accepts optional `ListOptionsType` payload for server-side filtering, sorting, and pagination.
256
226
 
257
227
  ```typescript
228
+ // No options — returns all in-progress items (default pagination)
258
229
  const result = await activity.getInProgressList();
259
230
 
260
231
  for (const item of result.Data) {
261
232
  console.log(item._id, item.Status, item.StartDate);
262
233
  }
234
+
235
+ // With options — server-side filter, sort, and pagination
236
+ const filtered = await activity.getInProgressList({
237
+ Filter: { Operator: 'And', Condition: [{ LHSField: 'Status', Operator: 'EQ', RHSValue: 'InProgress', RHSType: 'Constant' }] },
238
+ Sort: [{ '_created_at': 'DESC' }],
239
+ Page: 1,
240
+ PageSize: 10,
241
+ });
263
242
  ```
264
243
 
265
- ### getCompletedList()
244
+ ### getCompletedList(options?)
266
245
 
267
- List completed activity instances. Filtering and pagination are handled server-side automatically.
246
+ List completed activity instances. Same options as `getInProgressList`.
268
247
 
269
248
  ```typescript
270
249
  const result = await activity.getCompletedList();
@@ -274,20 +253,46 @@ for (const item of result.Data) {
274
253
  }
275
254
  ```
276
255
 
277
- ### inProgressMetrics()
256
+ ### inProgressCount(options?)
257
+
258
+ Get count of in-progress activity instances. Returns `number`.
259
+
260
+ ```typescript
261
+ const count = await activity.inProgressCount();
262
+ console.log('In-progress count:', count);
263
+ ```
264
+
265
+ ### completedCount(options?)
266
+
267
+ Get count of completed activity instances. Returns `number`.
268
+
269
+ ```typescript
270
+ const count = await activity.completedCount();
271
+ console.log('Completed count:', count);
272
+ ```
273
+
274
+ ### inProgressMetric(options)
278
275
 
279
- Get aggregated metrics for in-progress activity instances.
276
+ Get aggregated metrics for in-progress activity instances. Accepts `Omit<MetricOptionsType, 'Type'>` for custom aggregations (Sum, Avg, Count, etc.). Returns `MetricResponseType` (`{ Data: Record<string, any>[] }`).
280
277
 
281
278
  ```typescript
282
- const metrics = await activity.inProgressMetrics();
279
+ const result = await activity.inProgressMetric({
280
+ GroupBy: ['Status'],
281
+ Metric: [{ Field: '_id', Type: 'Count' }],
282
+ });
283
+ console.log(result.Data);
283
284
  ```
284
285
 
285
- ### completedMetrics()
286
+ ### completedMetric(options)
286
287
 
287
- Get aggregated metrics for completed activity instances.
288
+ Get aggregated metrics for completed activity instances. Same signature as `inProgressMetric`.
288
289
 
289
290
  ```typescript
290
- const metrics = await activity.completedMetrics();
291
+ const result = await activity.completedMetric({
292
+ GroupBy: [],
293
+ Metric: [{ Field: 'LeaveDays', Type: 'Sum' }],
294
+ });
295
+ console.log('Total leave days:', result.Data[0]?.sum_LeaveDays);
291
296
  ```
292
297
 
293
298
  ### getInstance(instanceId)
@@ -320,68 +325,19 @@ const progress = await instance.progress(); // get progress (ActivityP
320
325
 
321
326
  ## useActivityForm Hook
322
327
 
323
- React hook for building forms bound to workflow activity input fields. Integrates with `react-hook-form`.
324
-
325
- ### Options
328
+ See the dedicated [useActivityForm documentation](./useActivityForm.md) for the full API reference, type definitions, and examples.
326
329
 
327
- | Property | Type | Default | Description |
328
- |----------|------|---------|-------------|
329
- | `activity_instance_id` | `string` | *required* | Activity instance ID (from `wf.start()` or `getInProgressList()`) |
330
- | `defaultValues` | `Partial<Editable>` | `{}` | Initial form values |
331
- | `mode` | `"onBlur" \| "onChange" \| "onSubmit" \| "onTouched" \| "all"` | `"onBlur"` | Validation timing |
332
- | `enabled` | `boolean` | `true` | Whether to load activity data on mount |
330
+ ---
333
331
 
334
- ### Lifecycle
332
+ ## useActivityTable Hook
335
333
 
336
- ```
337
- Mount
338
- |
339
- |-> Load activity instance data -> populate form
340
- |
341
- v
342
- User edits field -> blurs
343
- |
344
- |-> Field validation (BaseField.validate)
345
- |-> If valid + readonly fields exist -> update computed fields
346
- |
347
- v
348
- User clicks Save
349
- |
350
- |-> handleSubmit -> save activity data
351
- |
352
- v
353
- User clicks Complete
354
- |
355
- |-> handleComplete -> complete activity
356
- ```
334
+ See the dedicated [useActivityTable documentation](./useActivityTable.md) for the full API reference, type definitions, and examples.
357
335
 
358
- ### Return Value
359
-
360
- | Property | Type | Description |
361
- |----------|------|-------------|
362
- | `item` | `FormItemType` | Proxy with typed field accessors (`.get()`, `.set()`, `.meta`) |
363
- | `activity` | `A` | The Activity instance |
364
- | `register` | `FormRegisterType` | Smart register (auto-disables readonly fields) |
365
- | `handleSubmit` | `HandleSubmitType` | Save activity data |
366
- | `handleComplete` | `HandleSubmitType` | Complete the activity |
367
- | `watch` | `UseFormWatch` | Watch field values |
368
- | `setValue` | `UseFormSetValue` | Set field value programmatically |
369
- | `getValues` | `UseFormGetValues` | Get current field values |
370
- | `reset` | `UseFormReset` | Reset form to default values |
371
- | `trigger` | `UseFormTrigger` | Trigger validation |
372
- | `control` | `Control` | RHF control (for Controller components) |
373
- | `errors` | `FieldErrors` | Validation errors |
374
- | `isValid` | `boolean` | Form is valid |
375
- | `isDirty` | `boolean` | Form has been modified |
376
- | `isSubmitting` | `boolean` | Currently submitting |
377
- | `isSubmitSuccessful` | `boolean` | Last submission succeeded |
378
- | `isLoading` | `boolean` | Loading activity data |
379
- | `loadError` | `Error \| null` | Load error |
380
- | `hasError` | `boolean` | Any error active |
381
- | `clearErrors` | `() => void` | Clear all form errors |
336
+ `useActivityTable` provides search, sort, filter, and pagination capabilities, same as `useBDOTable`. Entity fields are accessed at the top level (e.g., `row.FieldName`).
382
337
 
383
338
  ---
384
339
 
340
+
385
341
  ## Use Case: Employee Creating Leave
386
342
 
387
343
  ### Step 1 — Start the workflow
@@ -399,115 +355,7 @@ const progress = await wf.progress(BPInstanceId);
399
355
 
400
356
  ### Step 2 — React component with useActivityForm
401
357
 
402
- ```tsx
403
- import { useMemo } from "react";
404
- import { useActivityForm } from "@ram_28/kf-ai-sdk/workflow";
405
- import type { UseActivityFormOptions } from "@ram_28/kf-ai-sdk/workflow";
406
- import type { FieldErrors } from "react-hook-form";
407
- import { SimpleLeaveProcess, EmployeeInputActivity } from "@/bdo/workflows/SimpleLeaveProcess";
408
-
409
- interface LeaveRequestFormProps {
410
- activityInstanceId: string;
411
- onComplete: () => void;
412
- }
413
-
414
- function LeaveRequestForm({ activityInstanceId, onComplete }: LeaveRequestFormProps) {
415
- // 1. Get the typed activity from the workflow
416
- const activity = useMemo(() => new SimpleLeaveProcess().employeeInputActivity(), []);
417
-
418
- // 2. Hook options
419
- const options: UseActivityFormOptions<EmployeeInputActivity> = {
420
- activity_instance_id: activityInstanceId,
421
- defaultValues: {
422
- StartDate: undefined,
423
- EndDate: undefined,
424
- LeaveType: undefined,
425
- },
426
- mode: "onBlur",
427
- };
428
-
429
- // 3. Initialize hook
430
- const {
431
- register,
432
- handleSubmit,
433
- handleComplete,
434
- item,
435
- errors,
436
- isLoading,
437
- isSubmitting,
438
- loadError,
439
- } = useActivityForm(activity, options);
440
-
441
- if (isLoading) return <div>Loading...</div>;
442
- if (loadError) return <div>Error: {loadError.message}</div>;
443
-
444
- // 4. Handlers
445
- const onSaveSuccess = (): void => {
446
- console.log("Saved!");
447
- };
448
-
449
- const onCompleteSuccess = (): void => {
450
- console.log("Leave request submitted!");
451
- onComplete();
452
- };
453
-
454
- const onError = (error: FieldErrors | Error): void => {
455
- if (error instanceof Error) {
456
- console.error("API Error:", error.message);
457
- } else {
458
- console.error("Validation errors:", error);
459
- }
460
- };
461
-
462
- return (
463
- <form>
464
- <h2>Leave Request</h2>
465
-
466
- {/* Start Date */}
467
- <div>
468
- <label>{activity.StartDate.meta.label}</label>
469
- <input type="date" {...register(activity.StartDate.meta.id)} />
470
- {errors.StartDate && <span>{errors.StartDate.message}</span>}
471
- </div>
472
-
473
- {/* End Date */}
474
- <div>
475
- <label>{activity.EndDate.meta.label}</label>
476
- <input type="date" {...register(activity.EndDate.meta.id)} />
477
- {errors.EndDate && <span>{errors.EndDate.message}</span>}
478
- </div>
479
-
480
- {/* Leave Type */}
481
- <div>
482
- <label>{activity.LeaveType.meta.label}</label>
483
- <select {...register(activity.LeaveType.meta.id)}>
484
- <option value="">Select type</option>
485
- <option value="PTO">PTO</option>
486
- <option value="Sick">Sick</option>
487
- <option value="Parental">Parental</option>
488
- </select>
489
- {errors.LeaveType && <span>{errors.LeaveType.message}</span>}
490
- </div>
491
-
492
- {/* Leave Days (readonly — auto-disabled, computed by server) */}
493
- <div>
494
- <label>{activity.LeaveDays.meta.label}</label>
495
- <input type="number" {...register(activity.LeaveDays.meta.id)} />
496
- </div>
497
-
498
- {/* Actions */}
499
- <div>
500
- <button type="button" onClick={handleSubmit(onSaveSuccess, onError)}>
501
- {isSubmitting ? "Saving..." : "Save Draft"}
502
- </button>
503
- <button type="button" onClick={handleComplete(onCompleteSuccess, onError)}>
504
- {isSubmitting ? "Submitting..." : "Submit Leave Request"}
505
- </button>
506
- </div>
507
- </form>
508
- );
509
- }
510
- ```
358
+ See [useActivityForm](./useActivityForm.md) for the full form component example.
511
359
 
512
360
  ### Full flow orchestration
513
361
 
@@ -544,90 +392,80 @@ function LeaveRequestPage() {
544
392
 
545
393
  ### Step 1 — List in-progress items
546
394
 
547
- ```typescript
548
- import { SimpleLeaveProcess } from "@/bdo/workflows/SimpleLeaveProcess";
549
-
550
- const wf = new SimpleLeaveProcess();
551
- const activity = wf.managerApprovalActivity();
552
-
553
- const result = await activity.getInProgressList();
554
-
555
- for (const item of result.Data) {
556
- console.log(item._id, item.Status, item.AssignedTo.username);
557
- }
558
- ```
559
-
560
- ### Step 2 — Approval form component
561
-
562
395
  ```tsx
563
- import { useMemo } from "react";
564
- import { useActivityForm } from "@ram_28/kf-ai-sdk/workflow";
565
- import type { UseActivityFormOptions } from "@ram_28/kf-ai-sdk/workflow";
566
- import type { FieldErrors } from "react-hook-form";
396
+ import { useMemo, useState } from "react";
397
+ import { useActivityTable, ActivityTableStatus } from "@ram_28/kf-ai-sdk/workflow";
567
398
  import { SimpleLeaveProcess, ManagerApprovalActivity } from "@/bdo/workflows/SimpleLeaveProcess";
568
399
 
569
- interface ApprovalFormProps {
570
- activityInstanceId: string;
571
- onComplete: () => void;
572
- }
573
-
574
- function ApprovalForm({ activityInstanceId, onComplete }: ApprovalFormProps) {
575
- const activity = useMemo(() => new SimpleLeaveProcess().managerApprovalActivity(), []);
400
+ const wf = new SimpleLeaveProcess();
401
+ const activity = wf.managerApprovalActivity();
576
402
 
577
- const options: UseActivityFormOptions<ManagerApprovalActivity> = {
578
- activity_instance_id: activityInstanceId,
579
- defaultValues: {
580
- ManagerApproved: false,
581
- ManagerReason: "",
403
+ const { rows, totalItems, isLoading, error, pagination, refetch } = useActivityTable({
404
+ activity,
405
+ status: ActivityTableStatus.InProgress,
406
+ initialState: {
407
+ pagination: { pageNo: 1, pageSize: 10 },
582
408
  },
583
- mode: "onBlur",
584
- };
585
-
586
- const {
587
- register,
588
- handleComplete,
589
- errors,
590
- isLoading,
591
- isSubmitting,
592
- loadError,
593
- } = useActivityForm(activity, options);
409
+ });
594
410
 
595
411
  if (isLoading) return <div>Loading...</div>;
596
- if (loadError) return <div>Error: {loadError.message}</div>;
597
-
598
- const onSuccess = (): void => {
599
- console.log("Approval submitted!");
600
- onComplete();
601
- };
602
-
603
- const onError = (error: FieldErrors | Error): void => {
604
- if (error instanceof Error) console.error("API Error:", error.message);
605
- };
412
+ if (error) return <div>Error: {error.message}</div>;
413
+
414
+ if (selectedId) {
415
+ return (
416
+ <ApprovalForm
417
+ activityInstanceId={selectedId}
418
+ onComplete={() => {
419
+ setSelectedId(null);
420
+ refetch();
421
+ }}
422
+ />
423
+ );
424
+ }
606
425
 
607
426
  return (
608
- <form>
609
- <h2>Leave Approval</h2>
610
-
611
- <div>
612
- <label>
613
- <input type="checkbox" {...register(activity.ManagerApproved.meta.id)} />
614
- {activity.ManagerApproved.meta.label}
615
- </label>
616
- </div>
617
-
427
+ <div>
428
+ <h2>Pending Approvals ({totalItems})</h2>
429
+ <table>
430
+ <thead>
431
+ <tr>
432
+ <th>ID</th>
433
+ <th>Status</th>
434
+ <th>Assigned To</th>
435
+ <th>Approved</th>
436
+ <th>Reason</th>
437
+ <th>Action</th>
438
+ </tr>
439
+ </thead>
440
+ <tbody>
441
+ {rows.map((row) => (
442
+ <tr key={row._id}>
443
+ <td>{row._id}</td>
444
+ <td>{row.Status}</td>
445
+ <td>{row.AssignedTo.map((u) => u._name).join(", ")}</td>
446
+ <td>{row.ManagerApproved ? "Yes" : "No"}</td>
447
+ <td>{row.ManagerReason}</td>
448
+ <td>
449
+ <button onClick={() => setSelectedId(row._id)}>Review</button>
450
+ </td>
451
+ </tr>
452
+ ))}
453
+ </tbody>
454
+ </table>
618
455
  <div>
619
- <label>{activity.ManagerReason.meta.label}</label>
620
- <textarea {...register(activity.ManagerReason.meta.id)} rows={4} />
456
+ <button onClick={pagination.goToPrevious} disabled={!pagination.canGoPrevious}>Previous</button>
457
+ <span>Page {pagination.pageNo} of {pagination.totalPages}</span>
458
+ <button onClick={pagination.goToNext} disabled={!pagination.canGoNext}>Next</button>
621
459
  </div>
622
-
623
- <button type="button" onClick={handleComplete(onSuccess, onError)}>
624
- {isSubmitting ? "Submitting..." : "Submit Decision"}
625
- </button>
626
- </form>
460
+ </div>
627
461
  );
628
462
  }
629
463
  ```
630
464
 
465
+ ### Step 2 — Approval form component
466
+
467
+ See [useActivityForm](./useActivityForm.md) for the full approval form component example.
468
+
631
469
  ---
632
470
 
633
471
  ## Use Case: Programmatic ActivityInstance
@@ -653,7 +491,7 @@ instance.StartDate.set("2026-03-01");
653
491
  instance.EndDate.set("2026-03-05");
654
492
 
655
493
  // Field metadata
656
- console.log(instance.StartDate.meta.label); // "Start Date"
494
+ console.log(instance.StartDate.label); // "Start Date"
657
495
 
658
496
  // Persist changes
659
497
  await instance.update({ StartDate: "2026-03-01", EndDate: "2026-03-05" });
@@ -672,18 +510,31 @@ const progress = await instance.progress();
672
510
 
673
511
  ## Filtering Reference
674
512
 
675
- Status filtering is built into the method names (`getInProgressList` / `getCompletedList`). All filtering (by current user, activity status, and activity ID) and pagination are handled server-side automatically no client-side options are needed.
513
+ Status filtering is built into the method names (`getInProgressList` / `getCompletedList`). Internal filters (ActivityId, Status, AssignedTo) are **always applied** by the backend. Frontend filters passed via `ListOptionsType` are AND-merged with the internal filters.
514
+
515
+ All four list/metric endpoints now use **POST** with an optional `ListOptionsType` body (same shape as BDO list API: `{ Filter, Sort, Page, PageSize }`).
676
516
 
677
517
  ### In-progress items
678
518
 
679
519
  ```typescript
520
+ // No options — returns all (default pagination)
680
521
  const result = await activity.getInProgressList();
522
+
523
+ // With filter + pagination
524
+ const result = await activity.getInProgressList({
525
+ Sort: [{ '_created_at': 'DESC' }],
526
+ Page: 1,
527
+ PageSize: 25,
528
+ });
681
529
  ```
682
530
 
683
531
  ### Completed items
684
532
 
685
533
  ```typescript
686
- const result = await activity.getCompletedList();
534
+ const result = await activity.getCompletedList({
535
+ Page: 1,
536
+ PageSize: 25,
537
+ });
687
538
  ```
688
539
 
689
540
  ### Process progress
@@ -703,7 +554,7 @@ const progressList = await wf.progress(BPInstanceId);
703
554
  |-------|------|-------------|
704
555
  | `_id` | `StringFieldType` | Unique activity instance identifier |
705
556
  | `Status` | `SelectFieldType<"InProgress" \| "Completed">` | Current status |
706
- | `AssignedTo` | `ReferenceFieldType<UserRefType>` | Assigned user (has `._id` and `.username`) |
557
+ | `AssignedTo` | `UserFieldType[]` | Assigned users (each has `._id` and `._name`) |
707
558
  | `CompletedAt` | `DateTimeFieldType` | Completion timestamp (`"YYYY-MM-DDTHH:MM:SS"`) |
708
559
 
709
560
  ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ram_28/kf-ai-sdk",
3
- "version": "2.0.14",
3
+ "version": "2.0.16",
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",
@@ -189,7 +189,7 @@
189
189
  "react",
190
190
  "hooks",
191
191
  "typescript",
192
- "useForm",
192
+ "useBDOForm",
193
193
  "useTable",
194
194
  "useFilter",
195
195
  "bdo",
@@ -127,7 +127,7 @@ export abstract class BaseBdo<
127
127
  /**
128
128
  * Load backend metadata for expression-based validation
129
129
  *
130
- * Called by useForm after fetching schema from the backend.
130
+ * Called by useBDOForm after fetching schema from the backend.
131
131
  * This enables expression-based validation rules to be used
132
132
  * in addition to type validation.
133
133
  *
@@ -241,7 +241,7 @@ export abstract class BaseBdo<
241
241
  }
242
242
 
243
243
  // ============================================================
244
- // DRAFT OPERATIONS (for useForm integration)
244
+ // DRAFT OPERATIONS (for useBDOForm integration)
245
245
  // ============================================================
246
246
 
247
247
  /**
@@ -35,7 +35,7 @@ export class UserField extends BaseField<UserFieldType> {
35
35
  async fetchOptions(instanceId: string): Promise<UserFieldType[]> {
36
36
  if (!this._parentBoId) {
37
37
  throw new Error(
38
- `Field ${this.id} not bound to a BDO. Cannot fetch options.`
38
+ `Field ${this.id} not bound to a BDO. Cannot fetch options.`,
39
39
  );
40
40
  }
41
41
  return api(this._parentBoId).fetchField<UserFieldType>(instanceId, this.id);
@@ -1,10 +1,33 @@
1
- // Table hook
2
- export { useTable } from "./useTable";
1
+ // Table hook (base)
2
+ export { useTable } from './useTable';
3
3
  export type {
4
4
  UseTableOptionsType,
5
5
  UseTableReturnType,
6
- ColumnDefinitionType,
7
- } from "./useTable";
6
+ PaginationStateType,
7
+ } from './useTable';
8
+
9
+ // BDO table hook
10
+ export { useBDOTable } from './useBDOTable';
11
+ export type {
12
+ UseBDOTableOptionsType,
13
+ UseBDOTableReturnType,
14
+ } from './useBDOTable';
15
+
16
+ // Activity table hook
17
+ export { useActivityTable, ActivityTableStatus } from './useActivityTable';
18
+ export type {
19
+ UseActivityTableOptionsType,
20
+ UseActivityTableReturnType,
21
+ ActivityTableStatusType,
22
+ ActivityRowType,
23
+ } from './useActivityTable';
24
+
25
+ // Activity form hook
26
+ export { useActivityForm } from './useActivityForm';
27
+ export type {
28
+ UseActivityFormOptions,
29
+ UseActivityFormReturn,
30
+ } from './useActivityForm';
8
31
 
9
32
  // Filter hook
10
- export * from "./useFilter";
33
+ export * from './useFilter';