@classytic/formkit 1.3.1 → 1.4.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.
- package/CHANGELOG.md +12 -0
- package/README.md +31 -12
- package/dist/index.d.mts +447 -161
- package/dist/index.mjs +665 -179
- package/dist/server.d.mts +393 -150
- package/dist/server.mjs +385 -92
- package/package.json +115 -113
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.4.0] - 2026-05-26
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- New schema helpers exported from `./schema`: `extractDefaultValuesAsync`, field-type predicates (`isChoiceField`, `isTextField`, `isNumericField`, `isDateField`, `isContainerField`, `isArrayField`, `isDynamicField`, `isConditionalField`), schema composition (`mergeSchemas`, `extendSection`, `pickFields`, `omitFields`, `flattenSchema`), and `applyServerErrors`.
|
|
13
|
+
- New exported types: `SectionRendererProps`, `GridRendererProps`, `FieldWrapperProps`, `ValidationRuleObject`, `PatternRuleObject`.
|
|
14
|
+
- Conditional package exports add `module-sync` condition for better React Server Components / sync-import interop.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- `main` / `module` fields removed from `package.json` in favor of pure conditional `exports`.
|
|
19
|
+
|
|
8
20
|
## [1.3.0] - 2026-02-27
|
|
9
21
|
|
|
10
22
|
### Added
|
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ Headless, type-safe form generation engine for React 19. Schema-driven with full
|
|
|
20
20
|
- **Responsive layouts** - Multi-column grid layouts
|
|
21
21
|
- **Accessibility** - Auto-generated `fieldId`, `error`, and `fieldState` props
|
|
22
22
|
- **Validation helpers** - `buildValidationRules` generates RHF rules from schema props
|
|
23
|
-
- **Lightweight** - ~
|
|
23
|
+
- **Lightweight** - ~12KB gzipped (peer deps excluded), tree-shakeable
|
|
24
24
|
|
|
25
25
|
## Requirements
|
|
26
26
|
|
|
@@ -54,28 +54,41 @@ import { Label } from "@/components/ui/label";
|
|
|
54
54
|
|
|
55
55
|
export function FormInput({
|
|
56
56
|
control,
|
|
57
|
-
|
|
57
|
+
name,
|
|
58
|
+
rules, // pre-computed RHF rules from schema (required, minLength, pattern, validate…)
|
|
58
59
|
label,
|
|
59
60
|
placeholder,
|
|
60
61
|
required,
|
|
62
|
+
fieldId, // use as id on <input> and htmlFor on <Label>
|
|
63
|
+
errorId, // use as id on error <p> and aria-errormessage on <input>
|
|
64
|
+
shouldShowError, // true only after touch/submit — mirrors :user-invalid timing
|
|
61
65
|
error,
|
|
62
|
-
fieldId,
|
|
63
66
|
}: FieldComponentProps) {
|
|
64
67
|
return (
|
|
65
68
|
<Controller
|
|
66
|
-
name={
|
|
69
|
+
name={name}
|
|
67
70
|
control={control}
|
|
68
|
-
|
|
71
|
+
rules={rules}
|
|
72
|
+
render={({ field }) => (
|
|
69
73
|
<div className="space-y-2">
|
|
70
74
|
{label && (
|
|
71
75
|
<Label htmlFor={fieldId}>
|
|
72
76
|
{label}
|
|
73
|
-
{required && <span className="text-red-500 ml-1">*</span>}
|
|
77
|
+
{required && <span aria-hidden="true" className="text-red-500 ml-1">*</span>}
|
|
74
78
|
</Label>
|
|
75
79
|
)}
|
|
76
|
-
<Input
|
|
77
|
-
|
|
78
|
-
|
|
80
|
+
<Input
|
|
81
|
+
{...field}
|
|
82
|
+
id={fieldId}
|
|
83
|
+
placeholder={placeholder}
|
|
84
|
+
aria-required={required || undefined}
|
|
85
|
+
aria-invalid={shouldShowError || undefined}
|
|
86
|
+
aria-errormessage={shouldShowError ? errorId : undefined}
|
|
87
|
+
/>
|
|
88
|
+
{shouldShowError && (
|
|
89
|
+
<p id={errorId} role="alert" className="text-sm text-red-500">
|
|
90
|
+
{error?.message}
|
|
91
|
+
</p>
|
|
79
92
|
)}
|
|
80
93
|
</div>
|
|
81
94
|
)}
|
|
@@ -277,7 +290,11 @@ interface Section<T> {
|
|
|
277
290
|
|
|
278
291
|
```ts
|
|
279
292
|
interface BaseField<T> {
|
|
280
|
-
name
|
|
293
|
+
// name accepts Path<T> or any string.
|
|
294
|
+
// Use field.for<T>() builders for call-site enforcement of valid paths.
|
|
295
|
+
// Relative names are correct for nameSpace sections and itemFields children —
|
|
296
|
+
// FormGenerator prefixes them at render time (e.g. "street" → "address.street").
|
|
297
|
+
name: Path<T> | string; // Field name (required)
|
|
281
298
|
type: FieldType; // Field type (required)
|
|
282
299
|
label?: string; // Field label
|
|
283
300
|
placeholder?: string; // Placeholder text
|
|
@@ -298,8 +315,10 @@ interface BaseField<T> {
|
|
|
298
315
|
loadOptions?: (formValues: Partial<T>) => Promise<FieldOption[]> | FieldOption[];
|
|
299
316
|
debounceMs?: number;
|
|
300
317
|
|
|
301
|
-
//
|
|
302
|
-
|
|
318
|
+
// Sub-fields for group and array types.
|
|
319
|
+
// Children use relative names ("street") — FormGenerator prefixes with parent name.
|
|
320
|
+
// Intentionally untyped to T because they resolve at render time, not authoring time.
|
|
321
|
+
itemFields?: BaseField[];
|
|
303
322
|
|
|
304
323
|
// For select/radio/checkbox
|
|
305
324
|
options?: FieldOption[];
|