@ram_28/kf-ai-sdk 2.0.19 → 2.0.20-beta.1
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 +8 -16
- 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/Item.d.ts.map +1 -1
- package/dist/bdo.cjs +1 -1
- package/dist/bdo.mjs +32 -32
- package/dist/components/hooks/useActivityForm/types.d.ts +5 -4
- 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 +4 -5
- package/dist/components/hooks/useActivityTable/types.d.ts.map +1 -1
- package/dist/components/hooks/useActivityTable/useActivityTable.d.ts.map +1 -1
- package/dist/components/hooks/useBDOForm/createItemProxy.d.ts +2 -2
- package/dist/components/hooks/useBDOForm/createItemProxy.d.ts.map +1 -1
- package/dist/components/hooks/useBDOTable/types.d.ts +12 -20
- 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-Cyi942Yr.js → constants-ConHc1oS.js} +5 -5
- package/dist/constants-QX2RX-wu.cjs +1 -0
- package/dist/filter.cjs +1 -1
- package/dist/filter.mjs +1 -1
- package/dist/form.cjs +1 -1
- package/dist/form.mjs +1 -1
- package/dist/table.cjs +1 -1
- package/dist/table.mjs +16 -15
- package/dist/table.types.d.ts +1 -1
- package/dist/table.types.d.ts.map +1 -1
- package/dist/types/constants.d.ts +1 -1
- package/dist/workflow/Activity.d.ts +5 -8
- package/dist/workflow/Activity.d.ts.map +1 -1
- package/dist/workflow.cjs +1 -1
- package/dist/workflow.mjs +476 -461
- package/docs/api.md +95 -0
- package/docs/bdo.md +224 -0
- package/docs/gaps.md +360 -0
- package/docs/useActivityForm.md +393 -0
- package/docs/useActivityTable.md +418 -0
- package/docs/useBDOForm.md +498 -0
- package/docs/useBDOTable.md +284 -0
- package/docs/useFilter.md +188 -0
- package/docs/workflow.md +560 -0
- package/package.json +14 -15
- package/sdk/auth/authConfig.ts +1 -1
- package/sdk/auth/types.ts +1 -1
- package/sdk/bdo/core/Item.ts +1 -2
- package/sdk/components/hooks/useActivityForm/types.ts +6 -4
- package/sdk/components/hooks/useActivityForm/useActivityForm.ts +73 -10
- package/sdk/components/hooks/useActivityTable/types.ts +5 -4
- package/sdk/components/hooks/useActivityTable/useActivityTable.ts +8 -10
- package/sdk/components/hooks/useBDOForm/createItemProxy.ts +5 -9
- package/sdk/components/hooks/useBDOTable/types.ts +10 -20
- package/sdk/components/hooks/useBDOTable/useBDOTable.ts +8 -12
- package/sdk/table.types.ts +0 -2
- package/sdk/types/constants.ts +1 -1
- package/sdk/workflow/Activity.ts +7 -39
- package/dist/constants-DEmYwKfC.cjs +0 -1
- package/docs/README.md +0 -57
- package/docs/bdo/README.md +0 -161
- package/docs/bdo/api_reference.md +0 -281
- package/docs/examples/bdo/create-product.md +0 -69
- package/docs/examples/bdo/edit-product-dialog.md +0 -95
- package/docs/examples/bdo/filtered-product-table.md +0 -100
- package/docs/examples/bdo/product-listing.md +0 -73
- package/docs/examples/bdo/supplier-dropdown.md +0 -60
- package/docs/examples/fields/complex-fields.md +0 -248
- package/docs/examples/fields/primitive-fields.md +0 -217
- package/docs/examples/workflow/approve-leave-request.md +0 -76
- package/docs/examples/workflow/filtered-activity-table.md +0 -101
- package/docs/examples/workflow/my-pending-requests.md +0 -90
- package/docs/examples/workflow/start-new-workflow.md +0 -47
- package/docs/examples/workflow/submit-leave-request.md +0 -72
- package/docs/examples/workflow/workflow-progress.md +0 -49
- package/docs/fields/README.md +0 -141
- package/docs/fields/api_reference.md +0 -134
- package/docs/useActivityForm/README.md +0 -244
- package/docs/useActivityForm/api_reference.md +0 -279
- package/docs/useActivityTable/README.md +0 -263
- package/docs/useActivityTable/api_reference.md +0 -294
- package/docs/useBDOForm/README.md +0 -175
- package/docs/useBDOForm/api_reference.md +0 -244
- package/docs/useBDOTable/README.md +0 -242
- package/docs/useBDOTable/api_reference.md +0 -253
- package/docs/useFilter/README.md +0 -323
- package/docs/useFilter/api_reference.md +0 -228
- package/docs/workflow/README.md +0 -158
- package/docs/workflow/api_reference.md +0 -161
- /package/docs/{useAuth/README.md → useAuth.md} +0 -0
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
# My Pending Requests
|
|
2
|
-
|
|
3
|
-
> Employee views leave requests in In Progress / Completed tabs using `useActivityTable`.
|
|
4
|
-
|
|
5
|
-
```tsx
|
|
6
|
-
import { useState, useMemo } from "react";
|
|
7
|
-
import { useActivityTable, ActivityTableStatus } from "@ram_28/kf-ai-sdk/workflow";
|
|
8
|
-
import type { UseActivityTableReturnType } from "@ram_28/kf-ai-sdk/workflow";
|
|
9
|
-
import { EmployeeInputActivity } from "@/workflow/leave";
|
|
10
|
-
|
|
11
|
-
export default function MyPendingRequests({ onOpenForm }: { onOpenForm: (instanceId: string, bpInstanceId: string) => void }) {
|
|
12
|
-
const [status, setStatus] = useState(ActivityTableStatus.InProgress);
|
|
13
|
-
const activity = useMemo(() => new EmployeeInputActivity(), []);
|
|
14
|
-
|
|
15
|
-
const table: UseActivityTableReturnType<EmployeeInputActivity> = useActivityTable({
|
|
16
|
-
activity,
|
|
17
|
-
status,
|
|
18
|
-
initialState: { sort: [{ StartDate: "DESC" }], pagination: { pageNo: 1, pageSize: 10 } },
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
if (table.isLoading) return <p>Loading...</p>;
|
|
22
|
-
if (table.error) return <p>Error: {table.error.message}</p>;
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
<div>
|
|
26
|
-
{/* Tab switcher */}
|
|
27
|
-
<div>
|
|
28
|
-
<button onClick={() => setStatus(ActivityTableStatus.InProgress)}
|
|
29
|
-
style={{ fontWeight: status === ActivityTableStatus.InProgress ? "bold" : "normal" }}>
|
|
30
|
-
My Requests
|
|
31
|
-
</button>
|
|
32
|
-
<button onClick={() => setStatus(ActivityTableStatus.Completed)}
|
|
33
|
-
style={{ fontWeight: status === ActivityTableStatus.Completed ? "bold" : "normal" }}>
|
|
34
|
-
Completed
|
|
35
|
-
</button>
|
|
36
|
-
</div>
|
|
37
|
-
|
|
38
|
-
<table>
|
|
39
|
-
<thead>
|
|
40
|
-
<tr>
|
|
41
|
-
<th onClick={() => table.sort.toggle(activity.StartDate.id)} style={{ cursor: "pointer" }}>
|
|
42
|
-
{activity.StartDate.label}
|
|
43
|
-
</th>
|
|
44
|
-
<th>{activity.EndDate.label}</th>
|
|
45
|
-
<th>{activity.LeaveType.label}</th>
|
|
46
|
-
<th>{activity.LeaveDays.label}</th>
|
|
47
|
-
<th>Status</th>
|
|
48
|
-
{status === ActivityTableStatus.Completed && <th>Completed At</th>}
|
|
49
|
-
</tr>
|
|
50
|
-
</thead>
|
|
51
|
-
<tbody>
|
|
52
|
-
{table.rows.map((row) => (
|
|
53
|
-
<tr
|
|
54
|
-
key={row._id}
|
|
55
|
-
style={{ cursor: status === ActivityTableStatus.InProgress ? "pointer" : "default" }}
|
|
56
|
-
onClick={() => {
|
|
57
|
-
if (status === ActivityTableStatus.InProgress) {
|
|
58
|
-
onOpenForm(row._id, row.BPInstanceId.get());
|
|
59
|
-
}
|
|
60
|
-
}}
|
|
61
|
-
>
|
|
62
|
-
<td>{row.StartDate.get()}</td>
|
|
63
|
-
<td>{row.EndDate.get()}</td>
|
|
64
|
-
<td>{row.LeaveType.get()}</td>
|
|
65
|
-
<td>{row.LeaveDays.get()}</td>
|
|
66
|
-
<td>{row.Status.get()}</td>
|
|
67
|
-
{status === ActivityTableStatus.Completed && <td>{row.CompletedAt.get()}</td>}
|
|
68
|
-
</tr>
|
|
69
|
-
))}
|
|
70
|
-
</tbody>
|
|
71
|
-
</table>
|
|
72
|
-
|
|
73
|
-
{/* Pagination */}
|
|
74
|
-
<div>
|
|
75
|
-
<button onClick={table.pagination.goToPrevious} disabled={!table.pagination.canGoPrevious}>Previous</button>
|
|
76
|
-
<span>Page {table.pagination.pageNo} of {table.pagination.totalPages}</span>
|
|
77
|
-
<button onClick={table.pagination.goToNext} disabled={!table.pagination.canGoNext}>Next</button>
|
|
78
|
-
</div>
|
|
79
|
-
</div>
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
## Key Patterns
|
|
85
|
-
|
|
86
|
-
- **`ActivityTableStatus.InProgress` / `Completed`** -- changing `status` state triggers an automatic refetch
|
|
87
|
-
- **Activity system fields** -- `row.Status.get()`, `row.CompletedAt.get()`, `row.BPInstanceId.get()` are available on every row
|
|
88
|
-
- **Conditional `CompletedAt` column** -- only rendered in the Completed tab
|
|
89
|
-
- **Clickable rows only in InProgress** -- completed rows are read-only and don't open a form dialog
|
|
90
|
-
- **`row.BPInstanceId.get()`** -- passed along when opening a form, needed for workflow progress tracking
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
# Start New Workflow
|
|
2
|
-
|
|
3
|
-
> "New Request" button calls `workflow.start()` and opens the form with the returned instance ID.
|
|
4
|
-
|
|
5
|
-
```tsx
|
|
6
|
-
import { useState, useMemo, useCallback } from "react";
|
|
7
|
-
import { Workflow } from "@ram_28/kf-ai-sdk/workflow";
|
|
8
|
-
import type { WorkflowStartResponseType } from "@ram_28/kf-ai-sdk/workflow";
|
|
9
|
-
import type { EmployeeInputEntityType } from "@/workflow/leave";
|
|
10
|
-
|
|
11
|
-
export default function StartNewWorkflow({ onOpenForm }: { onOpenForm: (instanceId: string, bpInstanceId: string) => void }) {
|
|
12
|
-
const [isStarting, setIsStarting] = useState(false);
|
|
13
|
-
const [error, setError] = useState<string | null>(null);
|
|
14
|
-
|
|
15
|
-
const workflow = useMemo(() => new Workflow<EmployeeInputEntityType>("SimpleLeaveProcess"), []);
|
|
16
|
-
|
|
17
|
-
const handleNewRequest = useCallback(async () => {
|
|
18
|
-
try {
|
|
19
|
-
setIsStarting(true);
|
|
20
|
-
setError(null);
|
|
21
|
-
const result: WorkflowStartResponseType = await workflow.start();
|
|
22
|
-
// result: { BPInstanceId, ActivityId, _id }
|
|
23
|
-
onOpenForm(result._id, result.BPInstanceId);
|
|
24
|
-
} catch (err) {
|
|
25
|
-
setError(err instanceof Error ? err.message : "Failed to start workflow");
|
|
26
|
-
} finally {
|
|
27
|
-
setIsStarting(false);
|
|
28
|
-
}
|
|
29
|
-
}, [workflow, onOpenForm]);
|
|
30
|
-
|
|
31
|
-
return (
|
|
32
|
-
<div>
|
|
33
|
-
<button onClick={handleNewRequest} disabled={isStarting}>
|
|
34
|
-
{isStarting ? "Starting..." : "New Request"}
|
|
35
|
-
</button>
|
|
36
|
-
{error && <p>{error}</p>}
|
|
37
|
-
</div>
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
## Key Patterns
|
|
43
|
-
|
|
44
|
-
- **`workflow.start()`** -- creates a new process instance and returns `{ BPInstanceId, ActivityId, _id }`
|
|
45
|
-
- **`BPInstanceId`** -- identifies the workflow instance; used for `workflow.progress()`
|
|
46
|
-
- **`_id`** -- the first activity instance ID; passed to `useActivityForm` as `activity_instance_id`
|
|
47
|
-
- **Workflow constructor** -- `new Workflow<TEntity>("BusinessProcessId")` takes the process ID string
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
# Submit Leave Request
|
|
2
|
-
|
|
3
|
-
> Employee fills in dates, leave type, and reason, then submits using `useActivityForm`.
|
|
4
|
-
|
|
5
|
-
```tsx
|
|
6
|
-
import { useMemo } from "react";
|
|
7
|
-
import { useActivityForm } from "@ram_28/kf-ai-sdk/workflow";
|
|
8
|
-
import type { UseActivityFormReturn } from "@ram_28/kf-ai-sdk/workflow";
|
|
9
|
-
import { EmployeeInputActivity } from "@/workflow/leave";
|
|
10
|
-
|
|
11
|
-
export default function LeaveRequestForm({ instanceId, onClose }: { instanceId: string; onClose: () => void }) {
|
|
12
|
-
const activity = useMemo(() => new EmployeeInputActivity(), []);
|
|
13
|
-
|
|
14
|
-
const { register, handleSubmit, errors, isLoading, isSubmitting, watch, setValue }: UseActivityFormReturn<EmployeeInputActivity> =
|
|
15
|
-
useActivityForm(activity, { activity_instance_id: instanceId, mode: "onBlur" });
|
|
16
|
-
|
|
17
|
-
if (isLoading) return <p>Loading...</p>;
|
|
18
|
-
|
|
19
|
-
return (
|
|
20
|
-
<form>
|
|
21
|
-
<div>
|
|
22
|
-
<label>{activity.StartDate.label} {activity.StartDate.required && <span>*</span>}</label>
|
|
23
|
-
<input type="date" {...register(activity.StartDate.id)} />
|
|
24
|
-
{errors.StartDate && <p>{errors.StartDate.message}</p>}
|
|
25
|
-
</div>
|
|
26
|
-
|
|
27
|
-
<div>
|
|
28
|
-
<label>{activity.EndDate.label} {activity.EndDate.required && <span>*</span>}</label>
|
|
29
|
-
<input type="date" {...register(activity.EndDate.id)} />
|
|
30
|
-
{errors.EndDate && <p>{errors.EndDate.message}</p>}
|
|
31
|
-
</div>
|
|
32
|
-
|
|
33
|
-
{/* Select field — watch/setValue, not register */}
|
|
34
|
-
<div>
|
|
35
|
-
<label>{activity.LeaveType.label} {activity.LeaveType.required && <span>*</span>}</label>
|
|
36
|
-
<select value={watch(activity.LeaveType.id) ?? ""} onChange={(e) => setValue(activity.LeaveType.id, e.target.value)}>
|
|
37
|
-
<option value="">Select leave type</option>
|
|
38
|
-
{activity.LeaveType.options.map((opt) => (
|
|
39
|
-
<option key={opt.value} value={opt.value}>{opt.label}</option>
|
|
40
|
-
))}
|
|
41
|
-
</select>
|
|
42
|
-
{errors.LeaveType && <p>{errors.LeaveType.message}</p>}
|
|
43
|
-
</div>
|
|
44
|
-
|
|
45
|
-
<div>
|
|
46
|
-
<label>{activity.Reason.label}</label>
|
|
47
|
-
<textarea {...register(activity.Reason.id)} rows={3} placeholder="Reason for leave..." />
|
|
48
|
-
{errors.Reason && <p>{errors.Reason.message}</p>}
|
|
49
|
-
</div>
|
|
50
|
-
|
|
51
|
-
{/* Readonly computed field — auto-disabled by register() */}
|
|
52
|
-
<div>
|
|
53
|
-
<label>{activity.LeaveDays.label} (computed)</label>
|
|
54
|
-
<input type="number" {...register(activity.LeaveDays.id)} />
|
|
55
|
-
</div>
|
|
56
|
-
|
|
57
|
-
<button type="button" onClick={onClose}>Cancel</button>
|
|
58
|
-
<button type="button" disabled={isSubmitting} onClick={handleSubmit(() => onClose(), console.error)}>
|
|
59
|
-
Submit Request
|
|
60
|
-
</button>
|
|
61
|
-
</form>
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
## Key Patterns
|
|
67
|
-
|
|
68
|
-
- **`useActivityForm(activity, { activity_instance_id })`** -- the instance ID comes from `workflow.start()` or a table row
|
|
69
|
-
- **`handleSubmit` completes the activity** -- validates, sends dirty fields, then completes to advance the workflow
|
|
70
|
-
- **Readonly fields auto-disabled** -- `LeaveDays` has `ReadOnly: true`, so `register()` returns `{ disabled: true }`
|
|
71
|
-
- **`watch()` + `setValue()` for selects** -- custom components that don't fire native change events
|
|
72
|
-
- **Per-field sync** -- changes are auto-saved on blur/change; no manual save button needed
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
# Workflow Progress
|
|
2
|
-
|
|
3
|
-
> Display progress badges for each activity in a workflow instance using `workflow.progress()`.
|
|
4
|
-
|
|
5
|
-
```tsx
|
|
6
|
-
import { useMemo } from "react";
|
|
7
|
-
import { useQuery } from "@tanstack/react-query";
|
|
8
|
-
import { Workflow } from "@ram_28/kf-ai-sdk/workflow";
|
|
9
|
-
import type { ActivityProgressType } from "@ram_28/kf-ai-sdk/workflow";
|
|
10
|
-
import type { EmployeeInputEntityType } from "@/workflow/leave";
|
|
11
|
-
|
|
12
|
-
export default function WorkflowProgressBadges({ bpInstanceId }: { bpInstanceId: string }) {
|
|
13
|
-
const workflow = useMemo(() => new Workflow<EmployeeInputEntityType>("SimpleLeaveProcess"), []);
|
|
14
|
-
|
|
15
|
-
const { data: progress } = useQuery<ActivityProgressType[]>({
|
|
16
|
-
queryKey: ["workflow-progress", bpInstanceId],
|
|
17
|
-
queryFn: () => workflow.progress(bpInstanceId),
|
|
18
|
-
staleTime: 0,
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
if (!progress) return null;
|
|
22
|
-
|
|
23
|
-
return (
|
|
24
|
-
<div style={{ display: "flex", gap: "8px" }}>
|
|
25
|
-
{progress.map((entry: ActivityProgressType) => (
|
|
26
|
-
<span
|
|
27
|
-
key={entry.ActivityId}
|
|
28
|
-
style={{
|
|
29
|
-
padding: "4px 12px",
|
|
30
|
-
borderRadius: "12px",
|
|
31
|
-
fontSize: "12px",
|
|
32
|
-
backgroundColor: entry.Status === "COMPLETED" ? "#dcfce7" : "#fef9c3",
|
|
33
|
-
color: entry.Status === "COMPLETED" ? "#166534" : "#854d0e",
|
|
34
|
-
}}
|
|
35
|
-
>
|
|
36
|
-
{entry._name} — {entry.Status === "COMPLETED" ? "Done" : "In Progress"}
|
|
37
|
-
</span>
|
|
38
|
-
))}
|
|
39
|
-
</div>
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
## Key Patterns
|
|
45
|
-
|
|
46
|
-
- **`workflow.progress(bpInstanceId)`** -- returns `ActivityProgressType[]`, one entry per activity in the process
|
|
47
|
-
- **`ActivityProgressType`** -- each entry has `ActivityId`, `_name`, `Status` (`"COMPLETED"` or `"IN_PROGRESS"`), `CompletedAt`, `CompletedBy`
|
|
48
|
-
- **`BPInstanceId`** -- comes from `workflow.start()` (new requests) or `row.BPInstanceId.get()` (existing table rows)
|
|
49
|
-
- **`staleTime: 0`** -- always refetch progress when the component mounts (progress changes as activities complete)
|
package/docs/fields/README.md
DELETED
|
@@ -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
|