@dynamic-field-kit/react 1.0.0 → 1.0.2

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 (2) hide show
  1. package/README.md +299 -0
  2. package/package.json +3 -3
package/README.md ADDED
@@ -0,0 +1,299 @@
1
+ # Dynamic Field Kit
2
+
3
+ A lightweight, extensible **dynamic form engine** for React, built for scalable applications and design systems.
4
+
5
+ `dynamic-field-kit` lets you define forms using **configuration objects** instead of hard-coded UI, and allows applications to **freely extend field types** (`text`, `number`, `checkbox`, `select`, `date`, `custom`, …) without modifying the library.
6
+
7
+ ---
8
+
9
+ ## ✨ Features
10
+
11
+ - Schema-driven dynamic forms
12
+ - Extensible field types (no enums, no hard-coded unions)
13
+ - Pluggable field renderers via registry
14
+ - Runtime conditional fields (`appearCondition`)
15
+ - Clean TypeScript declarations (DTS-safe)
16
+ - Core logic separated from React rendering
17
+ - Ideal for form builders & design systems
18
+
19
+ ---
20
+
21
+ ## 📦 Packages
22
+
23
+ | Package | Description |
24
+ |------|------------|
25
+ | `@dynamic-field-kit/core` | Core types and field registry |
26
+ | `@dynamic-field-kit/react` | React components (FieldInput, MultiFieldInput, DynamicInput) |
27
+
28
+ ---
29
+
30
+ ## 📥 Installation
31
+
32
+ ```bash
33
+ npm install @dynamic-field-kit/core @dynamic-field-kit/react
34
+ ```
35
+
36
+ **Peer dependency**
37
+
38
+ ```txt
39
+ react >= 17
40
+ ```
41
+
42
+ ---
43
+
44
+ ## 🧱 Core Concepts
45
+
46
+ The library **does NOT define field types** like:
47
+ ```ts
48
+ "text" | "number"
49
+ ```
50
+
51
+ Instead, it exposes an **extendable interface** that applications can augment:
52
+ ```ts
53
+ export interface FieldTypeMap {}
54
+ ```
55
+
56
+ This allows:
57
+ - Unlimited custom field types
58
+ - Strong typing without locking consumers
59
+ - No need to rebuild the library
60
+
61
+ This pattern is used by mature libraries like **MUI, React Hook Form,** and **Redux Toolkit**.
62
+
63
+ ## 🧩 Defining Field Types (App Side)
64
+
65
+ Create a `.d.ts` file in your app (e.g. src/types/dynamic-field.d.ts):
66
+
67
+ ```ts
68
+ import "@dynamic-field-kit/core"
69
+
70
+ declare module "@dynamic-field-kit/core" {
71
+ interface FieldTypeMap {
72
+ text: string
73
+ number: number
74
+ checkbox: boolean
75
+ select: string
76
+ }
77
+ }
78
+ ```
79
+ ⚠️ Make sure this file is included in tsconfig.json.
80
+
81
+ ---
82
+
83
+ ## FieldRendererProps
84
+
85
+ ```ts
86
+ export interface FieldRendererProps<T = any> {
87
+ value?: T
88
+ onValueChange?: (value: T) => void
89
+ label?: string
90
+ }
91
+ ```
92
+ 👉 A common contract for all field renderers
93
+
94
+ ---
95
+
96
+ ### FieldDescription
97
+
98
+ A `FieldDescription` defines **what a field is**, not **how it looks**.
99
+
100
+ ```ts
101
+ import { FieldDescription } from "@dynamic-field-kit/core"
102
+
103
+ const fields: FieldDescription[] = [
104
+ {
105
+ name: "username",
106
+ type: "text",
107
+ label: "Username"
108
+ },
109
+ {
110
+ name: "age",
111
+ type: "number",
112
+ label: "Age",
113
+ appearCondition: (data) => data.username !== ""
114
+ }
115
+ ]
116
+ ```
117
+
118
+ **Common Properties**
119
+ | Property | Description |
120
+ |------|------------|
121
+ | name | Field key in form data |
122
+ | type | Field renderer key |
123
+ | label | UI label |
124
+ | value | Default value |
125
+ | appearCondition | Runtime visibility condition |
126
+
127
+ **Field Registry (Render Layer)**
128
+ The library does **not** ship UI components.
129
+
130
+ Instead, applications register their own renderers.
131
+
132
+ ```ts
133
+ import { fieldRegistry } from "@dynamic-field-kit/core"
134
+
135
+ fieldRegistry.register("text", ({ value, onValueChange, label }) => (
136
+ <div>
137
+ <label>{label}</label>
138
+ <input
139
+ value={value ?? ""}
140
+ onChange={(e) => onValueChange?.(e.target.value)}
141
+ />
142
+ </div>
143
+ ))
144
+
145
+ fieldRegistry.register("checkbox", ({ value, onValueChange, label }) => (
146
+ <label>
147
+ <input
148
+ type="checkbox"
149
+ checked={!!value}
150
+ onChange={(e) => onValueChange?.(e.target.checked)}
151
+ />
152
+ {label}
153
+ </label>
154
+ ))
155
+
156
+ ```
157
+
158
+ ---
159
+
160
+ ## ⚛️ React Usage
161
+
162
+ **MultiFieldInput (Main Form Engine)**
163
+
164
+ ```tsx
165
+ import { MultiFieldInput } from "@dynamic-field-kit/react"
166
+ import { FieldDescription } from "@dynamic-field-kit/core"
167
+
168
+ const fields: FieldDescription[] = [
169
+ { name: "email", type: "text", label: "Email" },
170
+ { name: "age", type: "number", label: "Age" }
171
+ ]
172
+
173
+ const Example = () => {
174
+ return (
175
+ <MultiFieldInput
176
+ fieldDescriptions={fields}
177
+ onChange={(data) => {
178
+ console.log("Form data:", data)
179
+ }}
180
+ />
181
+ )
182
+ }
183
+ ```
184
+
185
+ **Controlled Form**
186
+ ```tsx
187
+ const [formData, setFormData] = useState({})
188
+
189
+ <MultiFieldInput
190
+ fieldDescriptions={fields}
191
+ properties={formData}
192
+ onChange={setFormData}
193
+ />
194
+ ```
195
+
196
+ ---
197
+
198
+ ## ➕ Adding a New Field Type
199
+
200
+ You **do not** need to modify the library.
201
+
202
+ Just extend `FieldTypeMap`:
203
+
204
+ ```ts
205
+ declare module "@dynamic-field-kit/react" {
206
+ interface FieldTypeMap {
207
+ date: Date
208
+ }
209
+ }
210
+ ```
211
+
212
+ Then register a renderer:
213
+
214
+ ```ts
215
+ fieldRegistry.register("date", ({ value, onValueChange }) => (
216
+ <input
217
+ type="date"
218
+ value={value ? value.toISOString().slice(0, 10) : ""}
219
+ onChange={(e) =>
220
+ onValueChange?.(new Date(e.target.value))
221
+ }
222
+ />
223
+ ))
224
+ ```
225
+
226
+ Now `"date"` is fully type-safe everywhere.
227
+
228
+ ---
229
+ ## 🧠 Domain Typing (Optional)
230
+ The library intentionally avoids enforcing domain types.
231
+ If you want strict typing, cast inside your app:
232
+
233
+ ```ts
234
+ interface UserForm {
235
+ age: number
236
+ }
237
+
238
+ const fields: FieldDescription[] = [
239
+ {
240
+ name: "age",
241
+ type: "number",
242
+ appearCondition: (data) =>
243
+ (data as UserForm).age > 18
244
+ }
245
+ ]
246
+ ```
247
+ This keeps the library generic while allowing strict typing in the app.
248
+
249
+ ---
250
+
251
+ ## 🧩 Components API
252
+
253
+ **<DynamicInput />**
254
+
255
+ Resolves and renders a field based on its type.
256
+
257
+ ```tsx
258
+ <DynamicInput type="text" value="hello" />
259
+ ```
260
+ ---
261
+
262
+ **<FieldInput />**
263
+
264
+ Renders a single field with value binding.
265
+
266
+ ```tsx
267
+ <FieldInput
268
+ fieldDescription={field}
269
+ renderInfos={formData}
270
+ onChange={(value, key) => {}}
271
+ />
272
+ ```
273
+
274
+ ## Demo
275
+ - [Examples](https://github.com/vannt-dev/dynamic-field-kit-demo)
276
+
277
+ ---
278
+
279
+ ## 🏗 Architecture
280
+
281
+ ```
282
+ dynamic-field-kit
283
+ ├─ packages/
284
+ │ ├─ core # framework-agnostic types
285
+ │ └─ react # React renderer + registry
286
+ ```
287
+
288
+ ---
289
+
290
+ ## 🚫 Non-Goals
291
+ This library intentionally does not include:
292
+ -Built-in UI components
293
+ -Built-in UI components
294
+ -Form state management library
295
+
296
+ It is a **form engine**, not a full form framework.
297
+
298
+ ## 📄 License
299
+ MIT © vannt-dev
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dynamic-field-kit/react",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "React renderer for dynamic-field-kit",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.cjs",
@@ -14,7 +14,7 @@
14
14
  "react": ">=17"
15
15
  },
16
16
  "dependencies": {
17
- "@dynamic-field-kit/core": "^1.0.0"
17
+ "@dynamic-field-kit/core": "^1.0.2"
18
18
  },
19
19
  "exports": {
20
20
  ".": {
@@ -27,4 +27,4 @@
27
27
  "build": "tsup",
28
28
  "clean": "rm -rf dist"
29
29
  }
30
- }
30
+ }