@ram_28/kf-ai-sdk 2.0.15 → 2.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -14
- package/dist/api.cjs +1 -1
- package/dist/api.mjs +1 -1
- package/dist/auth/authConfig.d.ts +1 -1
- package/dist/auth/types.d.ts +1 -1
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/auth.cjs +1 -1
- package/dist/auth.mjs +1 -1
- package/dist/bdo/core/BaseBdo.d.ts +1 -1
- package/dist/bdo.cjs +1 -1
- package/dist/bdo.mjs +3 -3
- package/dist/components/hooks/useActivityForm/createActivityItemProxy.d.ts +1 -1
- package/dist/components/hooks/useActivityForm/createActivityItemProxy.d.ts.map +1 -1
- package/dist/components/hooks/useActivityForm/types.d.ts +6 -7
- package/dist/components/hooks/useActivityForm/types.d.ts.map +1 -1
- package/dist/components/hooks/useActivityForm/useActivityForm.d.ts.map +1 -1
- package/dist/components/hooks/useActivityTable/types.d.ts +7 -6
- package/dist/components/hooks/useActivityTable/types.d.ts.map +1 -1
- package/dist/components/hooks/useActivityTable/useActivityTable.d.ts +1 -1
- package/dist/components/hooks/useActivityTable/useActivityTable.d.ts.map +1 -1
- package/dist/components/hooks/useBDOForm/createItemProxy.d.ts.map +1 -0
- package/dist/components/hooks/useBDOForm/createResolver.d.ts.map +1 -0
- package/dist/components/hooks/useBDOForm/index.d.ts +6 -0
- package/dist/components/hooks/useBDOForm/index.d.ts.map +1 -0
- package/dist/components/hooks/useBDOForm/shared.d.ts +50 -0
- package/dist/components/hooks/useBDOForm/shared.d.ts.map +1 -0
- package/dist/components/hooks/{useForm → useBDOForm}/types.d.ts +6 -6
- package/dist/components/hooks/useBDOForm/types.d.ts.map +1 -0
- package/dist/components/hooks/{useForm/useForm.d.ts → useBDOForm/useBDOForm.d.ts} +4 -4
- package/dist/components/hooks/useBDOForm/useBDOForm.d.ts.map +1 -0
- package/dist/components/hooks/useBDOTable/types.d.ts +20 -14
- package/dist/components/hooks/useBDOTable/types.d.ts.map +1 -1
- package/dist/components/hooks/useBDOTable/useBDOTable.d.ts +2 -2
- package/dist/components/hooks/useBDOTable/useBDOTable.d.ts.map +1 -1
- package/dist/{constants-ConHc1oS.js → constants-Cyi942Yr.js} +5 -5
- package/dist/constants-DEmYwKfC.cjs +1 -0
- package/dist/filter.cjs +1 -1
- package/dist/filter.mjs +1 -1
- package/dist/form.cjs +1 -1
- package/dist/form.d.ts +1 -1
- package/dist/form.d.ts.map +1 -1
- package/dist/form.mjs +250 -253
- package/dist/form.types.d.ts +1 -1
- package/dist/form.types.d.ts.map +1 -1
- package/dist/shared-5a7UkED1.js +1180 -0
- package/dist/shared-nnmlRVs7.cjs +1 -0
- package/dist/table.cjs +1 -1
- package/dist/table.mjs +14 -14
- package/dist/table.types.d.ts +1 -1
- package/dist/table.types.d.ts.map +1 -1
- package/dist/types/constants.d.ts +4 -4
- package/dist/workflow/Activity.d.ts +22 -7
- package/dist/workflow/Activity.d.ts.map +1 -1
- package/dist/workflow/client.d.ts +2 -2
- package/dist/workflow/client.d.ts.map +1 -1
- package/dist/workflow/types.d.ts +7 -3
- package/dist/workflow/types.d.ts.map +1 -1
- package/dist/workflow.cjs +1 -1
- package/dist/workflow.mjs +518 -576
- package/docs/README.md +51 -0
- package/docs/bdo/README.md +161 -0
- package/docs/bdo/api_reference.md +281 -0
- package/docs/examples/bdo/create-product.md +69 -0
- package/docs/examples/bdo/edit-product-dialog.md +95 -0
- package/docs/examples/bdo/filtered-product-table.md +100 -0
- package/docs/examples/bdo/product-listing.md +73 -0
- package/docs/examples/bdo/supplier-dropdown.md +60 -0
- package/docs/examples/workflow/approve-leave-request.md +76 -0
- package/docs/examples/workflow/filtered-activity-table.md +101 -0
- package/docs/examples/workflow/my-pending-requests.md +90 -0
- package/docs/examples/workflow/start-new-workflow.md +47 -0
- package/docs/examples/workflow/submit-leave-request.md +72 -0
- package/docs/examples/workflow/workflow-progress.md +49 -0
- package/docs/useActivityForm/README.md +241 -0
- package/docs/useActivityForm/api_reference.md +279 -0
- package/docs/useActivityTable/README.md +263 -0
- package/docs/useActivityTable/api_reference.md +294 -0
- package/docs/useBDOForm/README.md +172 -0
- package/docs/useBDOForm/api_reference.md +244 -0
- package/docs/useBDOTable/README.md +242 -0
- package/docs/useBDOTable/api_reference.md +253 -0
- package/docs/useFilter/README.md +323 -0
- package/docs/useFilter/api_reference.md +228 -0
- package/docs/workflow/README.md +158 -0
- package/docs/workflow/api_reference.md +161 -0
- package/package.json +2 -2
- package/sdk/auth/authConfig.ts +1 -1
- package/sdk/auth/types.ts +1 -1
- package/sdk/bdo/core/BaseBdo.ts +2 -2
- package/sdk/components/hooks/useActivityForm/createActivityItemProxy.ts +1 -1
- package/sdk/components/hooks/useActivityForm/createActivityResolver.ts +1 -1
- package/sdk/components/hooks/useActivityForm/types.ts +8 -10
- package/sdk/components/hooks/useActivityForm/useActivityForm.ts +52 -265
- package/sdk/components/hooks/useActivityTable/types.ts +6 -5
- package/sdk/components/hooks/useActivityTable/useActivityTable.ts +14 -43
- package/sdk/components/hooks/{useForm → useBDOForm}/index.ts +4 -3
- package/sdk/components/hooks/useBDOForm/shared.ts +250 -0
- package/sdk/components/hooks/{useForm → useBDOForm}/types.ts +9 -9
- package/sdk/components/hooks/{useForm/useForm.ts → useBDOForm/useBDOForm.ts} +70 -96
- package/sdk/components/hooks/useBDOTable/types.ts +20 -12
- package/sdk/components/hooks/useBDOTable/useBDOTable.ts +12 -7
- package/sdk/form.ts +2 -2
- package/sdk/form.types.ts +4 -4
- package/sdk/table.types.ts +2 -0
- package/sdk/types/constants.ts +4 -4
- package/sdk/workflow/Activity.ts +68 -13
- package/sdk/workflow/client.ts +65 -25
- package/sdk/workflow/types.ts +10 -2
- package/dist/components/hooks/useForm/createItemProxy.d.ts.map +0 -1
- package/dist/components/hooks/useForm/createResolver.d.ts.map +0 -1
- package/dist/components/hooks/useForm/index.d.ts +0 -5
- package/dist/components/hooks/useForm/index.d.ts.map +0 -1
- package/dist/components/hooks/useForm/types.d.ts.map +0 -1
- package/dist/components/hooks/useForm/useForm.d.ts.map +0 -1
- package/dist/constants-QX2RX-wu.cjs +0 -1
- package/dist/createResolver-AIgUwoS6.cjs +0 -1
- package/dist/createResolver-ZHXQ7QMa.js +0 -1078
- package/docs/api.md +0 -95
- package/docs/bdo.md +0 -224
- package/docs/gaps.md +0 -410
- package/docs/useActivityTable.md +0 -481
- package/docs/useBDOTable.md +0 -317
- package/docs/useFilter.md +0 -188
- package/docs/useForm.md +0 -376
- package/docs/workflow.md +0 -818
- /package/dist/components/hooks/{useForm → useBDOForm}/createItemProxy.d.ts +0 -0
- /package/dist/components/hooks/{useForm → useBDOForm}/createResolver.d.ts +0 -0
- /package/docs/{useAuth.md → useAuth/README.md} +0 -0
- /package/sdk/components/hooks/{useForm → useBDOForm}/createItemProxy.ts +0 -0
- /package/sdk/components/hooks/{useForm → useBDOForm}/createResolver.ts +0 -0
package/docs/useForm.md
DELETED
|
@@ -1,376 +0,0 @@
|
|
|
1
|
-
# Form SDK API
|
|
2
|
-
|
|
3
|
-
React hook for forms with validation, API integration, and typed field handling.
|
|
4
|
-
|
|
5
|
-
## Imports
|
|
6
|
-
|
|
7
|
-
```typescript
|
|
8
|
-
import { useForm } from "@ram_28/kf-ai-sdk/form";
|
|
9
|
-
import { ValidationMode, FormOperation } from "@ram_28/kf-ai-sdk/form";
|
|
10
|
-
import type { UseFormOptionsType, UseFormReturnType, FormItemType, FormRegisterType, HandleSubmitType } from "@ram_28/kf-ai-sdk/form/types";
|
|
11
|
-
import type { CreateUpdateResponseType } from "@ram_28/kf-ai-sdk/api/types";
|
|
12
|
-
|
|
13
|
-
// Pre-built components for special field types
|
|
14
|
-
import { ReferenceSelect } from "@/components/ui/reference-select";
|
|
15
|
-
import { ImageUpload } from "@/components/ui/image-upload";
|
|
16
|
-
import { FileUpload } from "@/components/ui/file-upload";
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
## Common Mistakes (READ FIRST)
|
|
22
|
-
|
|
23
|
-
### 1. Missing `operation` in useForm options (TS2345)
|
|
24
|
-
|
|
25
|
-
ALWAYS include `operation`. Without it, TypeScript cannot resolve the union type.
|
|
26
|
-
|
|
27
|
-
```typescript
|
|
28
|
-
// ❌ WRONG — missing operation (TS2345)
|
|
29
|
-
useForm({ bdo: product, mode: ValidationMode.OnBlur });
|
|
30
|
-
|
|
31
|
-
// ✅ CORRECT — always include operation
|
|
32
|
-
useForm({ bdo: product, operation: FormOperation.Create, mode: ValidationMode.OnBlur });
|
|
33
|
-
useForm({ bdo: product, operation: FormOperation.Update, recordId: id, mode: ValidationMode.OnBlur });
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
### 2. Annotating ternary with UseFormOptionsType (TS2322)
|
|
37
|
-
|
|
38
|
-
`UseFormOptionsType` is a discriminated union. Type-annotating a variable prevents TS narrowing. NEVER annotate — call useForm inline in each branch.
|
|
39
|
-
|
|
40
|
-
```typescript
|
|
41
|
-
// ❌ WRONG — type annotation prevents union narrowing (TS2322)
|
|
42
|
-
const options: UseFormOptionsType<typeof bdo> = id
|
|
43
|
-
? { bdo, operation: FormOperation.Update, recordId: id, mode: ValidationMode.OnBlur }
|
|
44
|
-
: { bdo, operation: FormOperation.Create, mode: ValidationMode.OnBlur };
|
|
45
|
-
const formResult = useForm(options);
|
|
46
|
-
|
|
47
|
-
// ✅ CORRECT — call useForm inline, no type annotation
|
|
48
|
-
const formResult = id
|
|
49
|
-
? useForm({ bdo, operation: FormOperation.Update, recordId: id, mode: ValidationMode.OnBlur })
|
|
50
|
-
: useForm({ bdo, operation: FormOperation.Create, mode: ValidationMode.OnBlur });
|
|
51
|
-
const { register, handleSubmit, watch, setValue, item, formState: { errors, isSubmitting }, isLoading } = formResult;
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
### 3. Using `.options` on StringField (TS2339)
|
|
55
|
-
|
|
56
|
-
ONLY `SelectField` has `.options` getter. `StringField` with `Constraint.Enum` does NOT — use hardcoded `<option>` values from the BDO file.
|
|
57
|
-
|
|
58
|
-
```tsx
|
|
59
|
-
// Check the BDO class to determine field type:
|
|
60
|
-
// new SelectField({...}) → has .options → use bdo.field.options.map()
|
|
61
|
-
// new StringField({..."Constraint": {"Enum": [...]}}) → NO .options → hardcode from Enum array
|
|
62
|
-
|
|
63
|
-
// ❌ WRONG — StringField has no .options (TS2339)
|
|
64
|
-
// Given: readonly status = new StringField({... "Constraint": { "Enum": ["Active", "Discontinued"] }})
|
|
65
|
-
<select {...register(bdo.status.id)}>
|
|
66
|
-
{bdo.status.options.map((opt) => ( // TS2339: Property 'options' does not exist on StringField
|
|
67
|
-
<option key={opt.value} value={opt.value}>{opt.label}</option>
|
|
68
|
-
))}
|
|
69
|
-
</select>
|
|
70
|
-
|
|
71
|
-
// ✅ CORRECT for StringField with Enum — hardcode options from BDO Constraint.Enum array
|
|
72
|
-
<select {...register(bdo.status.id)}>
|
|
73
|
-
<option value="">Select {bdo.status.label}</option>
|
|
74
|
-
<option value="Active">Active</option>
|
|
75
|
-
<option value="Discontinued">Discontinued</option>
|
|
76
|
-
</select>
|
|
77
|
-
|
|
78
|
-
// ✅ CORRECT for SelectField — use .options getter
|
|
79
|
-
// Given: readonly status = new SelectField({...})
|
|
80
|
-
<select {...register(bdo.status.id)}>
|
|
81
|
-
<option value="">Select {bdo.status.label}</option>
|
|
82
|
-
{bdo.status.options.map((opt) => (
|
|
83
|
-
<option key={opt.value} value={opt.value}>{opt.label}</option>
|
|
84
|
-
))}
|
|
85
|
-
</select>
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### 4. Using register() for BooleanField
|
|
89
|
-
|
|
90
|
-
HTML checkboxes don't work with register(). Use watch/setValue.
|
|
91
|
-
|
|
92
|
-
```tsx
|
|
93
|
-
// ❌ WRONG
|
|
94
|
-
<input type="checkbox" {...register(bdo.is_active.id)} />
|
|
95
|
-
|
|
96
|
-
// ✅ CORRECT
|
|
97
|
-
<Checkbox
|
|
98
|
-
checked={Boolean(watch(bdo.is_active.id))}
|
|
99
|
-
onCheckedChange={(v) => setValue(bdo.is_active.id, v as boolean, { shouldDirty: true })}
|
|
100
|
-
/>
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
### 5. Using `<input>` for ReferenceField (should use `<ReferenceSelect>`)
|
|
104
|
-
|
|
105
|
-
ReferenceField stores an object `{ _id, _name, ... }`, not a string. Use the pre-built component.
|
|
106
|
-
|
|
107
|
-
```tsx
|
|
108
|
-
// ❌ WRONG — text input for reference field
|
|
109
|
-
<input {...register(bdo.category.id)} />
|
|
110
|
-
|
|
111
|
-
// ✅ CORRECT
|
|
112
|
-
<ReferenceSelect
|
|
113
|
-
bdoField={bdo.category}
|
|
114
|
-
instanceId={id || String(watch("_id") ?? "")}
|
|
115
|
-
value={watch(bdo.category.id)}
|
|
116
|
-
onChange={(val) => setValue(bdo.category.id, val, { shouldDirty: true })}
|
|
117
|
-
/>
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
### 6. Using custom Image/File upload (should use template components)
|
|
121
|
-
|
|
122
|
-
Use `<ImageUpload>` and `<FileUpload>`. CRITICAL: `instanceId` must work for BOTH edit and create mode.
|
|
123
|
-
|
|
124
|
-
```tsx
|
|
125
|
-
// ❌ WRONG — instanceId={id} is undefined in create mode
|
|
126
|
-
<ImageUpload field={item.icon} value={watch(bdo.icon.id)} boId={bdo.meta._id} instanceId={id} fieldId={bdo.icon.id} />
|
|
127
|
-
|
|
128
|
-
// ✅ CORRECT — ImageUpload (single image)
|
|
129
|
-
<ImageUpload
|
|
130
|
-
field={item.product_image}
|
|
131
|
-
value={watch(bdo.product_image.id)}
|
|
132
|
-
boId={bdo.meta._id}
|
|
133
|
-
instanceId={id || String(watch("_id") ?? "")}
|
|
134
|
-
fieldId={bdo.product_image.id}
|
|
135
|
-
/>
|
|
136
|
-
|
|
137
|
-
// ✅ CORRECT — FileUpload (multi-file)
|
|
138
|
-
<FileUpload
|
|
139
|
-
field={item.specification_document}
|
|
140
|
-
value={watch(bdo.specification_document.id)}
|
|
141
|
-
boId={bdo.meta._id}
|
|
142
|
-
instanceId={id || String(watch("_id") ?? "")}
|
|
143
|
-
fieldId={bdo.specification_document.id}
|
|
144
|
-
/>
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
Props: `field` = item accessor (`item.fieldName`), `value` = `watch(bdo.field.id)`, `boId` = `bdo.meta._id`, `instanceId` = `id || String(watch("_id") ?? "")`, `fieldId` = `bdo.field.id`. Parent component MUST have `"use no memo"` directive.
|
|
148
|
-
|
|
149
|
-
### 7. Wrong handleSubmit onSuccess type
|
|
150
|
-
|
|
151
|
-
```typescript
|
|
152
|
-
// ❌ WRONG
|
|
153
|
-
const onSuccess = (data: unknown) => { ... };
|
|
154
|
-
|
|
155
|
-
// ✅ CORRECT — CreateUpdateResponseType = { _id: string }
|
|
156
|
-
import type { CreateUpdateResponseType } from "@ram_28/kf-ai-sdk/api/types";
|
|
157
|
-
const onSuccess = (data: CreateUpdateResponseType) => { toast.success("Saved"); navigate("/list"); };
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
### 8. Passing FieldType instead of BDO instance
|
|
161
|
-
|
|
162
|
-
```typescript
|
|
163
|
-
// ❌ WRONG
|
|
164
|
-
useForm<ProductFieldType>({ ... });
|
|
165
|
-
|
|
166
|
-
// ✅ CORRECT — pass BDO class instance
|
|
167
|
-
const product = useMemo(() => new SellerProduct(), []);
|
|
168
|
-
useForm({ bdo: product, operation: FormOperation.Create, mode: ValidationMode.OnBlur });
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
### 9. Wrong default values for date fields
|
|
172
|
-
|
|
173
|
-
```typescript
|
|
174
|
-
// ❌ WRONG — empty string causes type errors
|
|
175
|
-
defaultValues: { start_date: "" }
|
|
176
|
-
|
|
177
|
-
// ✅ CORRECT
|
|
178
|
-
defaultValues: { start_date: undefined }
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
---
|
|
182
|
-
|
|
183
|
-
## Complete Form Example (Create + Edit)
|
|
184
|
-
|
|
185
|
-
```tsx
|
|
186
|
-
"use no memo";
|
|
187
|
-
|
|
188
|
-
import { useMemo } from "react";
|
|
189
|
-
import { useNavigate, useParams } from "react-router-dom";
|
|
190
|
-
import { useForm, ValidationMode, FormOperation } from "@ram_28/kf-ai-sdk/form";
|
|
191
|
-
import type { CreateUpdateResponseType } from "@ram_28/kf-ai-sdk/api/types";
|
|
192
|
-
import { AdminProduct } from "@/bdo/admin/Product";
|
|
193
|
-
import { ReferenceSelect } from "@/components/ui/reference-select";
|
|
194
|
-
import { ImageUpload } from "@/components/ui/image-upload";
|
|
195
|
-
import { FileUpload } from "@/components/ui/file-upload";
|
|
196
|
-
import { Checkbox } from "@/components/ui/checkbox";
|
|
197
|
-
import { toast } from "sonner";
|
|
198
|
-
|
|
199
|
-
export default function ProductForm() {
|
|
200
|
-
const { id } = useParams<{ id: string }>();
|
|
201
|
-
const navigate = useNavigate();
|
|
202
|
-
const bdo = useMemo(() => new AdminProduct(), []);
|
|
203
|
-
|
|
204
|
-
// Create/Edit ternary — NO type annotation on result
|
|
205
|
-
const formResult = id
|
|
206
|
-
? useForm({ bdo, operation: FormOperation.Update, recordId: id, mode: ValidationMode.OnBlur })
|
|
207
|
-
: useForm({ bdo, operation: FormOperation.Create, mode: ValidationMode.OnBlur });
|
|
208
|
-
|
|
209
|
-
const { register, handleSubmit, watch, setValue, item, formState: { errors, isSubmitting }, isLoading } = formResult;
|
|
210
|
-
|
|
211
|
-
// Loading guard AFTER all hooks
|
|
212
|
-
if (isLoading) return <div className="flex items-center justify-center h-full"><div className="animate-spin w-8 h-8 border-4 border-primary border-t-transparent rounded-full" /></div>;
|
|
213
|
-
|
|
214
|
-
const onSuccess = (data: CreateUpdateResponseType) => {
|
|
215
|
-
toast.success(id ? "Updated" : "Created");
|
|
216
|
-
navigate("/products");
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
const onError = (error: any) => {
|
|
220
|
-
toast.error(error instanceof Error ? error.message : "Please fix errors above");
|
|
221
|
-
};
|
|
222
|
-
|
|
223
|
-
return (
|
|
224
|
-
<form onSubmit={handleSubmit(onSuccess, onError)} className="space-y-6">
|
|
225
|
-
{/* StringField — register */}
|
|
226
|
-
<div>
|
|
227
|
-
<label>{bdo.product_name.label}{bdo.product_name.required && <span className="text-red-500"> *</span>}</label>
|
|
228
|
-
<input {...register(bdo.product_name.id)} className="w-full border rounded px-3 py-2" />
|
|
229
|
-
{errors.product_name && <p className="text-red-600 text-sm">{errors.product_name.message}</p>}
|
|
230
|
-
</div>
|
|
231
|
-
|
|
232
|
-
{/* NumberField — register */}
|
|
233
|
-
<div>
|
|
234
|
-
<label>{bdo.unit_price.label}</label>
|
|
235
|
-
<input type="number" step="0.01" {...register(bdo.unit_price.id)} className="w-full border rounded px-3 py-2" />
|
|
236
|
-
{errors.unit_price && <p className="text-red-600 text-sm">{errors.unit_price.message}</p>}
|
|
237
|
-
</div>
|
|
238
|
-
|
|
239
|
-
{/* StringField with Constraint.Enum — hardcoded options (NO .options getter) */}
|
|
240
|
-
<div>
|
|
241
|
-
<label>{bdo.status.label}</label>
|
|
242
|
-
<select {...register(bdo.status.id)} className="w-full border rounded px-3 py-2">
|
|
243
|
-
<option value="">Select {bdo.status.label}</option>
|
|
244
|
-
<option value="Active">Active</option>
|
|
245
|
-
<option value="Discontinued">Discontinued</option>
|
|
246
|
-
</select>
|
|
247
|
-
{errors.status && <p className="text-red-600 text-sm">{errors.status.message}</p>}
|
|
248
|
-
</div>
|
|
249
|
-
|
|
250
|
-
{/* ReferenceField — ReferenceSelect component */}
|
|
251
|
-
<div>
|
|
252
|
-
<label>{bdo.category.label}</label>
|
|
253
|
-
<ReferenceSelect
|
|
254
|
-
bdoField={bdo.category}
|
|
255
|
-
instanceId={id || String(watch("_id") ?? "")}
|
|
256
|
-
value={watch(bdo.category.id)}
|
|
257
|
-
onChange={(val) => setValue(bdo.category.id, val, { shouldDirty: true })}
|
|
258
|
-
/>
|
|
259
|
-
{errors.category && <p className="text-red-600 text-sm">{String(errors.category.message ?? "")}</p>}
|
|
260
|
-
</div>
|
|
261
|
-
|
|
262
|
-
{/* BooleanField — watch + setValue */}
|
|
263
|
-
<div className="flex items-center gap-2">
|
|
264
|
-
<Checkbox
|
|
265
|
-
checked={Boolean(watch(bdo.is_active.id))}
|
|
266
|
-
onCheckedChange={(v) => setValue(bdo.is_active.id, v as boolean, { shouldDirty: true })}
|
|
267
|
-
/>
|
|
268
|
-
<label>{bdo.is_active.label}</label>
|
|
269
|
-
</div>
|
|
270
|
-
|
|
271
|
-
{/* ImageField — ImageUpload component */}
|
|
272
|
-
<div>
|
|
273
|
-
<label>{bdo.product_image.label}</label>
|
|
274
|
-
<ImageUpload
|
|
275
|
-
field={item.product_image}
|
|
276
|
-
value={watch(bdo.product_image.id)}
|
|
277
|
-
boId={bdo.meta._id}
|
|
278
|
-
instanceId={id || String(watch("_id") ?? "")}
|
|
279
|
-
fieldId={bdo.product_image.id}
|
|
280
|
-
/>
|
|
281
|
-
</div>
|
|
282
|
-
|
|
283
|
-
{/* FileField — FileUpload component */}
|
|
284
|
-
<div>
|
|
285
|
-
<label>{bdo.specification_document.label}</label>
|
|
286
|
-
<FileUpload
|
|
287
|
-
field={item.specification_document}
|
|
288
|
-
value={watch(bdo.specification_document.id)}
|
|
289
|
-
boId={bdo.meta._id}
|
|
290
|
-
instanceId={id || String(watch("_id") ?? "")}
|
|
291
|
-
fieldId={bdo.specification_document.id}
|
|
292
|
-
/>
|
|
293
|
-
</div>
|
|
294
|
-
|
|
295
|
-
{/* TextField — textarea with register */}
|
|
296
|
-
<div>
|
|
297
|
-
<label>{bdo.description.label}</label>
|
|
298
|
-
<textarea {...register(bdo.description.id)} rows={4} className="w-full border rounded px-3 py-2" />
|
|
299
|
-
</div>
|
|
300
|
-
|
|
301
|
-
<button type="submit" disabled={isSubmitting} className="px-4 py-2 bg-primary text-white rounded">
|
|
302
|
-
{isSubmitting ? "Saving..." : id ? "Update" : "Create"}
|
|
303
|
-
</button>
|
|
304
|
-
</form>
|
|
305
|
-
);
|
|
306
|
-
}
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
---
|
|
310
|
-
|
|
311
|
-
## Type Definitions
|
|
312
|
-
|
|
313
|
-
### UseFormOptionsType (Discriminated Union)
|
|
314
|
-
|
|
315
|
-
```typescript
|
|
316
|
-
type UseFormOptionsType<B extends BaseBdo<any, any, any>> =
|
|
317
|
-
| { bdo: B; operation: "create"; defaultValues?: Partial<EditableFieldType>; mode?: ValidationModeType; }
|
|
318
|
-
| { bdo: B; operation: "update"; recordId: string; mode?: ValidationModeType; }
|
|
319
|
-
| { bdo: B; recordId?: string; defaultValues?: Partial<EditableFieldType>; mode?: ValidationModeType; };
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
### UseFormReturnType
|
|
323
|
-
|
|
324
|
-
```typescript
|
|
325
|
-
interface UseFormReturnType<B> {
|
|
326
|
-
item: FormItemType<EditableFieldType, ReadonlyFieldType>; // Field accessors (.get(), .set(), .upload())
|
|
327
|
-
register: FormRegisterType; // Auto-disables readonly fields
|
|
328
|
-
handleSubmit: HandleSubmitType; // Auto-calls bdo.create() or bdo.update()
|
|
329
|
-
watch: UseFormWatch; // Watch field values by bdo.field.id
|
|
330
|
-
setValue: UseFormSetValue; // Set field values by bdo.field.id
|
|
331
|
-
getValues: UseFormGetValues;
|
|
332
|
-
control: Control;
|
|
333
|
-
formState: FormState;
|
|
334
|
-
errors: FieldErrors;
|
|
335
|
-
isLoading: boolean; // Fetching record data (edit mode)
|
|
336
|
-
isSubmitting: boolean;
|
|
337
|
-
isDirty: boolean;
|
|
338
|
-
loadError: Error | null;
|
|
339
|
-
}
|
|
340
|
-
```
|
|
341
|
-
|
|
342
|
-
### File & Image Types
|
|
343
|
-
|
|
344
|
-
```typescript
|
|
345
|
-
interface FileType { _id: string; _name: string; FileName: string; FileExtension: string; Size: number; ContentType: string; }
|
|
346
|
-
type ImageFieldType = FileType | null; // Single image, nullable
|
|
347
|
-
type FileFieldType = FileType[]; // Array of files
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
Image accessor: `item.field.get()` returns `FileType | null`. Has `upload(file: File)`, `deleteAttachment()`, `getDownloadUrl()`.
|
|
351
|
-
File accessor: `item.field.get()` returns `FileType[]`. Has `upload(files: File[])`, `deleteAttachment(id)`, `getDownloadUrl(id)`.
|
|
352
|
-
|
|
353
|
-
### Constants
|
|
354
|
-
|
|
355
|
-
```typescript
|
|
356
|
-
FormOperation.Create // "create"
|
|
357
|
-
FormOperation.Update // "update"
|
|
358
|
-
ValidationMode.OnBlur / .OnChange / .OnSubmit / .OnTouched / .All
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
### Field-Type to UI Component Mapping
|
|
362
|
-
|
|
363
|
-
| BDO Field Class | UI Pattern |
|
|
364
|
-
|---|---|
|
|
365
|
-
| `StringField` | `<input {...register(bdo.field.id)} />` |
|
|
366
|
-
| `StringField` with `Constraint.Enum` | `<select {...register(bdo.field.id)}>` with hardcoded `<option>` from Enum array |
|
|
367
|
-
| `SelectField` | `<select {...register(bdo.field.id)}>` with `bdo.field.options.map()` |
|
|
368
|
-
| `TextField` | `<textarea {...register(bdo.field.id)} />` |
|
|
369
|
-
| `NumberField` | `<input type="number" {...register(bdo.field.id)} />` |
|
|
370
|
-
| `BooleanField` | `<Checkbox checked={watch()} onCheckedChange={v => setValue()} />` |
|
|
371
|
-
| `DateField` | `<input type="date" {...register(bdo.field.id)} />` |
|
|
372
|
-
| `DateTimeField` | `<input type="datetime-local" {...register(bdo.field.id)} />` |
|
|
373
|
-
| `ReferenceField` | `<ReferenceSelect bdoField={bdo.field} instanceId={id \|\| String(watch("_id") ?? "")} value={watch()} onChange={...} />` |
|
|
374
|
-
| `UserField` | `<ReferenceSelect bdoField={bdo.field} instanceId={id \|\| String(watch("_id") ?? "")} value={watch()} onChange={...} />` |
|
|
375
|
-
| `ImageField` | `<ImageUpload field={item.field} value={watch()} boId={} instanceId={} fieldId={} />` |
|
|
376
|
-
| `FileField` | `<FileUpload field={item.field} value={watch()} boId={} instanceId={} fieldId={} />` |
|