@ram_28/kf-ai-sdk 2.0.19 → 2.0.20-beta.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 (105) hide show
  1. package/README.md +8 -16
  2. package/dist/{FileField-CZjS2uLh.js → FileField-BWrSHNRq.js} +3 -3
  3. package/dist/{FileField-DU4UWo_t.cjs → FileField-eDeuzln8.cjs} +1 -1
  4. package/dist/api.cjs +1 -1
  5. package/dist/api.mjs +1 -1
  6. package/dist/auth/authConfig.d.ts +1 -1
  7. package/dist/auth/types.d.ts +1 -1
  8. package/dist/auth/types.d.ts.map +1 -1
  9. package/dist/auth.cjs +1 -1
  10. package/dist/auth.mjs +1 -1
  11. package/dist/bdo/core/Item.d.ts +4 -0
  12. package/dist/bdo/core/Item.d.ts.map +1 -1
  13. package/dist/bdo/fields/ReferenceField.d.ts +1 -1
  14. package/dist/bdo/fields/ReferenceField.d.ts.map +1 -1
  15. package/dist/bdo/fields/SelectField.d.ts +1 -1
  16. package/dist/bdo/fields/SelectField.d.ts.map +1 -1
  17. package/dist/bdo/fields/UserField.d.ts +1 -1
  18. package/dist/bdo/fields/UserField.d.ts.map +1 -1
  19. package/dist/bdo.cjs +1 -1
  20. package/dist/bdo.mjs +62 -53
  21. package/dist/components/hooks/useActivityForm/types.d.ts +5 -4
  22. package/dist/components/hooks/useActivityForm/types.d.ts.map +1 -1
  23. package/dist/components/hooks/useActivityForm/useActivityForm.d.ts.map +1 -1
  24. package/dist/components/hooks/useActivityTable/types.d.ts +4 -5
  25. package/dist/components/hooks/useActivityTable/types.d.ts.map +1 -1
  26. package/dist/components/hooks/useActivityTable/useActivityTable.d.ts.map +1 -1
  27. package/dist/components/hooks/useBDOForm/createItemProxy.d.ts +3 -2
  28. package/dist/components/hooks/useBDOForm/createItemProxy.d.ts.map +1 -1
  29. package/dist/components/hooks/useBDOTable/types.d.ts +12 -20
  30. package/dist/components/hooks/useBDOTable/types.d.ts.map +1 -1
  31. package/dist/components/hooks/useBDOTable/useBDOTable.d.ts +2 -2
  32. package/dist/components/hooks/useBDOTable/useBDOTable.d.ts.map +1 -1
  33. package/dist/{constants-Cyi942Yr.js → constants-ConHc1oS.js} +5 -5
  34. package/dist/constants-QX2RX-wu.cjs +1 -0
  35. package/dist/filter.cjs +1 -1
  36. package/dist/filter.mjs +1 -1
  37. package/dist/form.cjs +1 -1
  38. package/dist/form.mjs +243 -226
  39. package/dist/table.cjs +1 -1
  40. package/dist/table.mjs +16 -15
  41. package/dist/table.types.d.ts +1 -1
  42. package/dist/table.types.d.ts.map +1 -1
  43. package/dist/types/constants.d.ts +1 -1
  44. package/dist/workflow/Activity.d.ts +5 -8
  45. package/dist/workflow/Activity.d.ts.map +1 -1
  46. package/dist/workflow.cjs +1 -1
  47. package/dist/workflow.mjs +476 -461
  48. package/docs/api.md +95 -0
  49. package/docs/bdo.md +224 -0
  50. package/docs/gaps.md +360 -0
  51. package/docs/useActivityForm.md +393 -0
  52. package/docs/useActivityTable.md +418 -0
  53. package/docs/useBDOForm.md +498 -0
  54. package/docs/useBDOTable.md +284 -0
  55. package/docs/useFilter.md +188 -0
  56. package/docs/workflow.md +560 -0
  57. package/package.json +14 -15
  58. package/sdk/auth/authConfig.ts +1 -1
  59. package/sdk/auth/types.ts +1 -1
  60. package/sdk/bdo/core/Item.ts +10 -1
  61. package/sdk/bdo/fields/ReferenceField.ts +1 -1
  62. package/sdk/bdo/fields/SelectField.ts +1 -1
  63. package/sdk/bdo/fields/UserField.ts +1 -1
  64. package/sdk/components/hooks/useActivityForm/types.ts +6 -4
  65. package/sdk/components/hooks/useActivityForm/useActivityForm.ts +73 -10
  66. package/sdk/components/hooks/useActivityTable/types.ts +5 -4
  67. package/sdk/components/hooks/useActivityTable/useActivityTable.ts +8 -10
  68. package/sdk/components/hooks/useBDOForm/createItemProxy.ts +58 -17
  69. package/sdk/components/hooks/useBDOTable/types.ts +10 -20
  70. package/sdk/components/hooks/useBDOTable/useBDOTable.ts +8 -12
  71. package/sdk/table.types.ts +0 -2
  72. package/sdk/types/constants.ts +1 -1
  73. package/sdk/workflow/Activity.ts +7 -39
  74. package/dist/constants-DEmYwKfC.cjs +0 -1
  75. package/docs/README.md +0 -57
  76. package/docs/bdo/README.md +0 -161
  77. package/docs/bdo/api_reference.md +0 -281
  78. package/docs/examples/bdo/create-product.md +0 -69
  79. package/docs/examples/bdo/edit-product-dialog.md +0 -95
  80. package/docs/examples/bdo/filtered-product-table.md +0 -100
  81. package/docs/examples/bdo/product-listing.md +0 -73
  82. package/docs/examples/bdo/supplier-dropdown.md +0 -60
  83. package/docs/examples/fields/complex-fields.md +0 -248
  84. package/docs/examples/fields/primitive-fields.md +0 -217
  85. package/docs/examples/workflow/approve-leave-request.md +0 -76
  86. package/docs/examples/workflow/filtered-activity-table.md +0 -101
  87. package/docs/examples/workflow/my-pending-requests.md +0 -90
  88. package/docs/examples/workflow/start-new-workflow.md +0 -47
  89. package/docs/examples/workflow/submit-leave-request.md +0 -72
  90. package/docs/examples/workflow/workflow-progress.md +0 -49
  91. package/docs/fields/README.md +0 -141
  92. package/docs/fields/api_reference.md +0 -134
  93. package/docs/useActivityForm/README.md +0 -244
  94. package/docs/useActivityForm/api_reference.md +0 -279
  95. package/docs/useActivityTable/README.md +0 -263
  96. package/docs/useActivityTable/api_reference.md +0 -294
  97. package/docs/useBDOForm/README.md +0 -175
  98. package/docs/useBDOForm/api_reference.md +0 -244
  99. package/docs/useBDOTable/README.md +0 -242
  100. package/docs/useBDOTable/api_reference.md +0 -253
  101. package/docs/useFilter/README.md +0 -323
  102. package/docs/useFilter/api_reference.md +0 -228
  103. package/docs/workflow/README.md +0 -158
  104. package/docs/workflow/api_reference.md +0 -161
  105. /package/docs/{useAuth/README.md → useAuth.md} +0 -0
@@ -1,141 +0,0 @@
1
- # Fields
2
-
3
- Field classes are the typed metadata layer for BDO properties. 13 classes extend `BaseField<T>`, each storing raw backend meta and exposing getters + `validate()`.
4
-
5
- ## Imports
6
-
7
- ```typescript
8
- import {
9
- StringField,
10
- NumberField,
11
- BooleanField,
12
- DateField,
13
- DateTimeField,
14
- TextField,
15
- SelectField,
16
- ReferenceField,
17
- UserField,
18
- FileField,
19
- ImageField,
20
- ArrayField,
21
- ObjectField,
22
- } from "@ram_28/kf-ai-sdk/bdo";
23
- import type {
24
- StringFieldType,
25
- NumberFieldType,
26
- BooleanFieldType,
27
- DateFieldType,
28
- DateTimeFieldType,
29
- TextFieldType,
30
- SelectFieldType,
31
- ReferenceFieldType,
32
- UserFieldType,
33
- FileFieldType,
34
- ImageFieldType,
35
- FileType,
36
- ArrayFieldType,
37
- ObjectFieldType,
38
- } from "@ram_28/kf-ai-sdk/types";
39
- ```
40
-
41
- ## Common Mistakes (READ FIRST)
42
-
43
- 1. **`item.Title` is not the value** — Use `item.Title.get()` to read, `.set()` to write.
44
- 2. **Don't confuse `StringField` (class) with `StringFieldType` (type alias)** — Different modules.
45
- 3. **`fetchOptions()` requires a parent BDO** — Standalone fields will throw.
46
- 4. **SelectField meta `Type` is `"String"`** — `Constraint.Enum` differentiates it.
47
- 5. **Always use pre-built components for File/Image** — `<FileUpload>`, `<ImageUpload>`, `<FilePreview>`, `<ImageThumbnail>`.
48
-
49
- ## Quick Start
50
-
51
- ```typescript
52
- // Declare on a BDO class
53
- readonly Title = new StringField({
54
- _id: "Title", Name: "Title", Type: "String",
55
- Constraint: { Required: true, Length: 255 },
56
- });
57
-
58
- // Access metadata
59
- bdo.Title.id; // "Title"
60
- bdo.Title.label; // "Title"
61
- bdo.Title.required; // true
62
- bdo.Title.length; // 255
63
-
64
- // Read/write via Item proxy
65
- const item = await bdo.get("abc123");
66
- item.Title.get(); // "My Product"
67
- item.Title.set("New"); // update
68
-
69
- // Form binding
70
- <input {...register(bdo.Title.id)} />
71
- ```
72
-
73
- ## BaseField Contract
74
-
75
- All fields share these getters: `id`, `label`, `readOnly`, `required`, `defaultValue`, `primaryKey`, `meta`.
76
-
77
- Abstract method: `validate(value: T | undefined): ValidationResultType` → `{ valid, errors }`.
78
-
79
- ## Quick Reference
80
-
81
- | Class | Value Type | Extra Getters | Async |
82
- | ---------------------- | ------------------ | ------------------------------------------------- | ---------------- |
83
- | `StringField` | `string` | `length` | — |
84
- | `NumberField` | `number` | `integerPart`, `fractionPart` | — |
85
- | `BooleanField` | `boolean` | — | — |
86
- | `DateField` | `YYYY-MM-DD` | — | — |
87
- | `DateTimeField` | ISO string | `precision` | — |
88
- | `TextField` | `string` | `format` | — |
89
- | `SelectField<T>` | `T` | `options` | `fetchOptions()` |
90
- | `ReferenceField<TRef>` | `TRef` | `referenceBdo`, `referenceFields`, `searchFields` | `fetchOptions()` |
91
- | `UserField` | `{ _id, _name }` | `businessEntity` | `fetchOptions()` |
92
- | `FileField` | `FileType[]` | — | — |
93
- | `ImageField` | `FileType \| null` | — | — |
94
- | `ArrayField<T>` | `T[]` | `elementType` | — |
95
- | `ObjectField<T>` | `T` | `properties` | — |
96
-
97
- ## Form Binding Patterns
98
-
99
- | Field Type | Pattern | Key Detail |
100
- | ---------- | ----------------------------------------- | ------------------------------------------------------------------------------ |
101
- | String | `register()` | `maxLength={field.length}` |
102
- | Number | `register()` with `type="number"` | `step` from `fractionPart` (e.g. `2` → `"0.01"`, none → `"1"`) |
103
- | Boolean | `watch()` + `setValue()` | Checkboxes don't fire native change — never use `register()` |
104
- | Date | `register()` with `type="date"` | Strict `YYYY-MM-DD` — never default to `""` |
105
- | DateTime | `register()` with `type="datetime-local"` | `step="0.001"` for `"Millisecond"` precision — never default to `""` |
106
- | Text | `register()` with `<textarea>` | Check `field.format` (`"Plain"` \| `"Markdown"`) for conditional rendering |
107
- | Select | `watch()` + `setValue()` | Static `field.options` from `Constraint.Enum`, or dynamic via `fetchOptions()` |
108
- | Reference | `watch()` + `setValue()` | Stores **full object**, not just ID — use `<ReferenceSelect>` component |
109
- | User | `watch()` + `setValue()` | `{ _id, _name }` shape — use `fetchOptions()` + dropdown |
110
- | File | Component only | `<FileUpload>` (edit) / `<FilePreview>` (read-only) |
111
- | Image | Component only | `<ImageUpload>` (edit) / `<ImageThumbnail>` (read-only) |
112
-
113
- ## fetchOptions() Pattern
114
-
115
- SelectField, ReferenceField, and UserField share this pattern:
116
-
117
- ```tsx
118
- const [dropdownOpen, setDropdownOpen] = useState(false);
119
- const { data: options = [] } = useQuery({
120
- queryKey: ["options", bdo.meta._id, field.id, item._id],
121
- queryFn: () => field.fetchOptions(item._id!),
122
- enabled: dropdownOpen && !!item._id,
123
- staleTime: Infinity,
124
- });
125
- ```
126
-
127
- ## UI Components
128
-
129
- | Component | Field | Mode | Key Props |
130
- | ------------------- | --------- | --------- | ------------------------------------------------- |
131
- | `<ReferenceSelect>` | Reference | Edit | `bdoField`, `instanceId`, `value`, `onChange` |
132
- | `<FileUpload>` | File | Edit | `field`, `value`, `boId`, `instanceId`, `fieldId` |
133
- | `<ImageUpload>` | Image | Edit | `field`, `value`, `boId`, `instanceId`, `fieldId` |
134
- | `<FilePreview>` | File | Read-only | `boId`, `instanceId`, `fieldId`, `value` |
135
- | `<ImageThumbnail>` | Image | Read-only | `boId`, `instanceId`, `fieldId`, `value` |
136
-
137
- ## Further Reading
138
-
139
- - [API Reference](./api_reference.md) — Type signatures for BaseField and all 13 classes
140
- - [Primitive Fields](../examples/fields/primitive-fields.md) · [Complex Fields](../examples/fields/complex-fields.md)
141
- - [BDO](../bdo/README.md) · [useBDOForm](../useBDOForm/README.md)
@@ -1,134 +0,0 @@
1
- # Fields API Reference
2
-
3
- ```typescript
4
- import { StringField, NumberField, BooleanField, DateField, DateTimeField,
5
- TextField, SelectField, ReferenceField, UserField,
6
- FileField, ImageField, ArrayField, ObjectField } from "@ram_28/kf-ai-sdk/bdo";
7
- import type { BaseFieldMetaType, ValidationResultType, SelectOptionType,
8
- EditableFieldAccessorType, ReadonlyFieldAccessorType } from "@ram_28/kf-ai-sdk/bdo/types";
9
- import type { StringFieldType, NumberFieldType, BooleanFieldType,
10
- DateFieldType, DateTimeFieldType, TextFieldType, SelectFieldType,
11
- ReferenceFieldType, UserFieldType, FileFieldType, ImageFieldType, FileType,
12
- ArrayFieldType, ObjectFieldType } from "@ram_28/kf-ai-sdk/types";
13
- ```
14
-
15
- ## BaseField\<T\>
16
-
17
- Abstract base class for all field definitions. Constructor: `new(meta: BaseFieldMetaType)`.
18
-
19
- | Property | Type | Description |
20
- |----------|------|-------------|
21
- | `id` | `string` | `meta._id` |
22
- | `label` | `string` | `meta.Name` (falls back to `id`) |
23
- | `readOnly` | `boolean` | `meta.ReadOnly ?? false` |
24
- | `required` | `boolean` | `meta.Constraint?.Required ?? meta.Required ?? false` |
25
- | `defaultValue` | `unknown` | `meta.DefaultValue ?? meta.Constraint?.DefaultValue` |
26
- | `primaryKey` | `boolean` | `meta.Constraint?.PrimaryKey ?? false` |
27
- | `meta` | `BaseFieldMetaType` | Full raw backend meta |
28
- | `validate()` | `(value: T \| undefined) => ValidationResultType` | Abstract — overridden per subclass |
29
-
30
- ## All Fields
31
-
32
- | Class | Meta Type | Extra Properties | validate() |
33
- |-------|-----------|-----------------|------------|
34
- | `StringField` | `StringFieldMetaType` | `length: number \| undefined` | Rejects non-string |
35
- | `NumberField` | `NumberFieldMetaType` | `integerPart: number` (default 9), `fractionPart: number \| undefined` | Rejects NaN, non-number |
36
- | `BooleanField` | `BooleanFieldMetaType` | — | Rejects non-boolean |
37
- | `DateField` | `DateFieldMetaType` | — | Rejects non-`YYYY-MM-DD`, invalid dates |
38
- | `DateTimeField` | `DateTimeFieldMetaType` | `precision: "Second" \| "Millisecond"` | Rejects unparseable date strings |
39
- | `TextField` | `TextFieldMetaType` | `format: "Plain" \| "Markdown"` | Rejects non-string |
40
- | `SelectField<T>` | `SelectFieldMetaType` | `options: readonly SelectOptionType<T>[]` | Rejects values not in options (skipped if empty) |
41
- | `ReferenceField<TRef>` | `ReferenceFieldMetaType` | `referenceBdo: string`, `referenceFields: readonly string[]`, `searchFields: readonly string[]` | Rejects non-object, missing `_id` |
42
- | `UserField` | `UserFieldMetaType` | `businessEntity: string \| undefined` | Rejects non-object, missing `_id` |
43
- | `FileField` | `FileFieldMetaType` | — | Rejects non-array, items without `_id` |
44
- | `ImageField` | `ImageFieldMetaType` | — | Rejects non-object, missing `_id`/`FileName` |
45
- | `ArrayField<T>` | `ArrayFieldMetaType` | `elementType: BaseFieldMetaType \| undefined` | Rejects non-array |
46
- | `ObjectField<T>` | `ObjectFieldMetaType` | `properties: Record<string, unknown> \| undefined` | Rejects non-object, arrays |
47
-
48
- All validate() methods accept `undefined` and `null`.
49
-
50
- ## Async Methods
51
-
52
- | Class | Method | Signature |
53
- |-------|--------|-----------|
54
- | `SelectField<T>` | `fetchOptions` | `(instanceId?: string) => Promise<SelectOptionType<T>[]>` |
55
- | `ReferenceField<TRef>` | `fetchOptions` | `(instanceId?: string) => Promise<TRef[]>` |
56
- | `UserField` | `fetchOptions` | `(instanceId?: string) => Promise<UserFieldType[]>` |
57
-
58
- `instanceId` defaults to `"draft"`. Requires field to be bound to a parent BDO.
59
-
60
- ## Types
61
-
62
- ### SelectOptionType\<T\>
63
-
64
- ```typescript
65
- interface SelectOptionType<T = string> {
66
- value: T;
67
- label: string;
68
- disabled?: boolean;
69
- }
70
- ```
71
-
72
- ### FileType
73
-
74
- ```typescript
75
- interface FileType {
76
- _id: string;
77
- _name: string;
78
- FileName: string;
79
- FileExtension: string;
80
- Size: number;
81
- ContentType: string;
82
- }
83
- ```
84
-
85
- ### ValidationResultType
86
-
87
- ```typescript
88
- interface ValidationResultType {
89
- valid: boolean;
90
- errors: string[];
91
- }
92
- ```
93
-
94
- ### Runtime Accessor Types
95
-
96
- ```typescript
97
- interface EditableFieldAccessorType<T> {
98
- get(): T | undefined;
99
- getOrDefault(fallback: T): T;
100
- set(value: T): void;
101
- validate(): ValidationResultType;
102
- readonly label: string;
103
- readonly required: boolean;
104
- readonly readOnly: boolean;
105
- readonly defaultValue: unknown;
106
- readonly meta: BaseFieldMetaType;
107
- }
108
-
109
- // ReadonlyFieldAccessorType<T> — same but no set()
110
- ```
111
-
112
- ### Value Type Aliases
113
-
114
- | Type | Resolves To |
115
- |------|-------------|
116
- | `StringFieldType` | `string` |
117
- | `TextFieldType` | `string` |
118
- | `NumberFieldType` | `number` |
119
- | `BooleanFieldType` | `boolean` |
120
- | `DateFieldType` | `YYYY-MM-DD` (template literal) |
121
- | `DateTimeFieldType` | `YYYY-MM-DDThh:mm:ssZ` (template literal) |
122
- | `SelectFieldType<T>` | `T` |
123
- | `ReferenceFieldType<TRef>` | `TRef` |
124
- | `UserFieldType` | `{ _id: string; _name: string }` |
125
- | `ImageFieldType` | `FileType \| null` |
126
- | `FileFieldType` | `FileType[]` |
127
- | `ArrayFieldType<T>` | `T[]` |
128
- | `ObjectFieldType<T>` | `T` |
129
-
130
- ### Supported File Extensions
131
-
132
- **Image fields** — jpg, jpeg, png, gif, webp, bmp, tiff, tif, heic, heif
133
-
134
- **File fields** — all image extensions plus: mp4, mov, avi, webm, mkv, m4v, wmv, flv, pdf, doc, docx, xls, xlsx, ppt, pptx, txt, csv, zip
@@ -1,244 +0,0 @@
1
- # useActivityForm
2
-
3
- Form hook for workflow activities with automatic per-field sync and a single `handleSubmit` to complete the activity and advance the workflow.
4
-
5
- ## When to Use
6
-
7
- **Use `useActivityForm` when:**
8
-
9
- - Building a form for a workflow activity (employee leave request, manager approval, etc.)
10
- - You need `handleSubmit` to complete the activity and advance the workflow
11
- - Fields from prior activities should appear as readonly context
12
-
13
- **Use something else when:**
14
-
15
- - Building a BDO record form — use [`useBDOForm`](../useBDOForm/README.md) instead
16
- - Listing activity instances in a table — use [`useActivityTable`](../useActivityTable/README.md) instead
17
-
18
- ## Imports
19
-
20
- ```tsx
21
- import { useActivityForm } from "@ram_28/kf-ai-sdk/workflow";
22
- ```
23
-
24
- ## Quick Start
25
-
26
- ```tsx
27
- import { useMemo } from "react";
28
- import { useActivityForm } from "@ram_28/kf-ai-sdk/workflow";
29
- import { EmployeeInputActivity } from "@/workflow/leave";
30
-
31
- function LeaveRequestForm({ instanceId }: { instanceId: string }) {
32
- const activity = useMemo(() => new EmployeeInputActivity(), []);
33
-
34
- const { register, handleSubmit, errors, isLoading, isSubmitting } =
35
- useActivityForm(activity, { activity_instance_id: instanceId });
36
-
37
- if (isLoading) return <p>Loading...</p>;
38
-
39
- return (
40
- <form>
41
- <label>{activity.StartDate.label}</label>
42
- <input type="date" {...register(activity.StartDate.id)} />
43
- {errors.StartDate && <p>{errors.StartDate.message}</p>}
44
-
45
- <label>{activity.EndDate.label}</label>
46
- <input type="date" {...register(activity.EndDate.id)} />
47
- {errors.EndDate && <p>{errors.EndDate.message}</p>}
48
-
49
- <button type="button" disabled={isSubmitting}
50
- onClick={handleSubmit(() => {}, console.error)}>
51
- Submit Request
52
- </button>
53
- </form>
54
- );
55
- }
56
- ```
57
-
58
- ## Usage Guide
59
-
60
- ### Registering Fields
61
-
62
- Use the Activity instance's field to get the field ID, label, and metadata — never hardcode field names as strings.
63
-
64
- ```tsx
65
- <label>{activity.StartDate.label} {activity.StartDate.required && <span>*</span>}</label>
66
- <input type="date" {...register(activity.StartDate.id)} />
67
- {errors.StartDate && <p>{errors.StartDate.message}</p>}
68
- ```
69
-
70
- For **select, reference, boolean, and other custom components** that don't fire native change events, use `watch()` + `setValue()` instead of `register()` (see [Fields — Selection & Reference](../fields/README.md#selection--reference-fields) for full patterns):
71
-
72
- ```tsx
73
- <Select
74
- value={watch(activity.LeaveType.id) ?? ""}
75
- onValueChange={(v) => setValue(activity.LeaveType.id, v)}
76
- >
77
- <SelectTrigger>
78
- <SelectValue placeholder="Select leave type" />
79
- </SelectTrigger>
80
- <SelectContent>
81
- {activity.LeaveType.options.map((opt) => (
82
- <SelectItem key={opt.value} value={opt.value}>
83
- {opt.label}
84
- </SelectItem>
85
- ))}
86
- </SelectContent>
87
- </Select>
88
- ```
89
-
90
- Readonly fields are auto-disabled by `register()` — no manual disable needed.
91
-
92
- ### Context-Derived Readonly Fields
93
-
94
- When a workflow has multiple activities, fields from prior activities appear as readonly context. The hook discovers them automatically from BP metadata, and `register()` returns `{ disabled: true }` for them.
95
-
96
- In a manager approval form, the employee's StartDate, EndDate, LeaveType, and LeaveDays are readonly context, while ManagerApproved and ManagerReason are editable:
97
-
98
- ```tsx
99
- import { useMemo } from "react";
100
- import { useActivityForm } from "@ram_28/kf-ai-sdk/workflow";
101
- import { ManagerApprovalActivity } from "@/workflow/leave";
102
-
103
- function ManagerApprovalForm({ instanceId }: { instanceId: string }) {
104
- const activity = useMemo(() => new ManagerApprovalActivity(), []);
105
-
106
- const { register, handleSubmit, errors, isLoading, isSubmitting, watch, setValue } =
107
- useActivityForm(activity, { activity_instance_id: instanceId });
108
-
109
- if (isLoading) return <p>Loading...</p>;
110
-
111
- return (
112
- <div>
113
- {/* Readonly context from employee's activity — auto-disabled */}
114
- <label>{activity.StartDate.label}</label>
115
- <input type="date" {...register(activity.StartDate.id)} className="bg-gray-100" />
116
-
117
- <label>{activity.EndDate.label}</label>
118
- <input type="date" {...register(activity.EndDate.id)} className="bg-gray-100" />
119
-
120
- <label>{activity.LeaveDays.label}</label>
121
- <input type="number" {...register(activity.LeaveDays.id)} className="bg-gray-100" />
122
-
123
- {/* Editable manager decision fields */}
124
- <div>
125
- <input
126
- type="checkbox"
127
- checked={watch(activity.ManagerApproved.id) ?? false}
128
- onChange={(e) => setValue(activity.ManagerApproved.id, e.target.checked)}
129
- />
130
- <label>
131
- {activity.ManagerApproved.label}
132
- {activity.ManagerApproved.required && <span> *</span>}
133
- </label>
134
- {errors.ManagerApproved && <p>{errors.ManagerApproved.message}</p>}
135
- </div>
136
-
137
- <label>{activity.ManagerReason.label}</label>
138
- <textarea {...register(activity.ManagerReason.id)} rows={3} />
139
- {errors.ManagerReason && <p>{errors.ManagerReason.message}</p>}
140
-
141
- <button type="button" disabled={isSubmitting}
142
- onClick={handleSubmit(() => {}, console.error)}>
143
- Complete Review
144
- </button>
145
- </div>
146
- );
147
- }
148
- ```
149
-
150
- ### Validation
151
-
152
- Validation happens automatically. The hook validates field types, constraints (required, length, integerPart/fractionPart), and backend expression rules — all without any manual configuration.
153
-
154
- Errors appear in `errors.FieldName.message`:
155
-
156
- ```tsx
157
- {errors.StartDate && <p>{errors.StartDate.message}</p>}
158
- ```
159
-
160
- ### Handling Submit
161
-
162
- Per-field sync automatically saves changes on blur/change via `activity.update()`, so there's no need for a manual save button. When the user is ready, `handleSubmit` validates the form, sends any remaining dirty fields, then completes the activity to advance the workflow.
163
-
164
- `handleSubmit` is curried: `(onSuccess?, onError?) => (event?) => Promise<void>`.
165
-
166
- - **`onSuccess(result)`** — Called with `CreateUpdateResponseType` (`{ _id: string }`) after the activity is completed.
167
- - **`onError(error)`** — Called with `FieldErrors` (validation failure) or `Error` (API failure).
168
-
169
- ```tsx
170
- <button type="button" disabled={isSubmitting}
171
- onClick={handleSubmit(() => { toast.success("Submitted"); onClose(); }, console.error)}>
172
- Submit Request
173
- </button>
174
- ```
175
-
176
- To validate before showing a confirmation dialog, use `trigger()`:
177
-
178
- ```tsx
179
- const handleSubmitWithConfirm = async () => {
180
- const valid = await trigger();
181
- if (!valid) return;
182
- // Show confirmation UI, then invoke:
183
- handleSubmit(onSuccess, onError)(); // note the double invocation — curried
184
- };
185
- ```
186
-
187
- > **Don't** call `activity.update()` or `activity.complete()` manually — `handleSubmit` does it for you.
188
-
189
- ### Working with `item`
190
-
191
- `item` represents the current activity instance. Each field on `item` is an accessor with methods to read, write, and validate that field's value.
192
-
193
- **Instance-level members:**
194
-
195
- ```tsx
196
- const { item } = useActivityForm(activity, { activity_instance_id: instanceId });
197
-
198
- item._id; // current activity instance ID
199
- item.toJSON(); // all form values as plain object
200
- await item.validate(); // trigger validation for all fields
201
- ```
202
-
203
- **Field-level accessors** (`item.FieldName`):
204
-
205
- ```tsx
206
- // Read/write
207
- item.StartDate.get(); // current value
208
- item.LeaveDays.getOrDefault(0); // value or fallback
209
- item.StartDate.set("2026-03-01"); // update value
210
-
211
- // Validate
212
- item.StartDate.validate(); // { valid: boolean, errors: string[] }
213
-
214
- // Metadata
215
- item.StartDate.label; // display label
216
- item.StartDate.required; // is required?
217
- item.StartDate.readOnly; // is readonly?
218
- ```
219
-
220
- **When to use `item` vs `register`/`watch`/`setValue`:**
221
-
222
- - Use `register()` for standard HTML inputs (text, number, date)
223
- - Use `watch()` + `setValue()` for custom components (select, checkbox, reference)
224
- - Use `item.Field.get()` / `item.Field.set()` for programmatic read/write (event handlers, computed logic)
225
-
226
- ## Further Reading
227
-
228
- - [API Reference](./api_reference.md) — All options, return values, and type definitions
229
- - [Fields](../fields/README.md) — All 13 field classes, constraint getters, and attachment methods
230
- - [Submit Leave Request](../examples/workflow/submit-leave-request.md) — Employee form submission
231
- - [Approve Leave Request](../examples/workflow/approve-leave-request.md) — Manager approval with readonly context
232
- - [Start New Workflow](../examples/workflow/start-new-workflow.md) — `workflow.start()` flow
233
- - [Primitive Fields](../examples/fields/primitive-fields.md) — Form with String, Number, Boolean, Date, DateTime, Text
234
- - [Complex Fields](../examples/fields/complex-fields.md) — Form with Select, Reference, User, File, Image
235
-
236
- ## Common Mistakes
237
-
238
- - **Don't forget `useMemo` on the Activity.** `new ActivityClass()` must be wrapped in `useMemo(() => ..., [])`. Re-creating the instance on every render breaks the hook.
239
- - **Don't create a manual save button.** Per-field sync handles auto-saving on blur/change. `handleSubmit` is for completing the activity, not saving drafts.
240
- - **Don't set date `defaultValues` to empty string.** Use `undefined` instead. Empty strings cause type validation errors for Date and DateTime fields.
241
- - **Don't use `register()` for select, checkbox, or reference components.** They don't fire native change events. Use `watch()` + `setValue()`.
242
- - **Don't call `activity.update()` or `activity.complete()` manually.** `handleSubmit` handles the API calls. Calling them yourself will double-submit.
243
- - **Don't render the form before `isLoading` is false.** The activity data and metadata are being fetched. Guard with `if (isLoading) return <Loading />`.
244
- - **Don't forget `activity_instance_id` is required.** This is the activity instance ID (from `workflow.start()` or `getInProgressList()`), not a BDO record ID.