@axenstudio/axen-form 0.1.16 → 0.1.18
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 +34 -3
- package/dist/adapters/yupAdapter.cjs +29 -10
- package/dist/adapters/yupAdapter.d.ts +1 -2
- package/dist/adapters/yupAdapter.js +29 -10
- package/dist/adapters/zodAdapter.cjs +29 -10
- package/dist/adapters/zodAdapter.d.ts +1 -2
- package/dist/adapters/zodAdapter.js +29 -10
- package/dist/core/dateUtils.d.ts +0 -1
- package/dist/core/formStore.cjs +127 -39
- package/dist/core/formStore.d.ts +2 -1
- package/dist/core/formStore.js +127 -39
- package/dist/core/numberUtils.d.ts +0 -1
- package/dist/core/pathUtils.d.ts +0 -1
- package/dist/core/payloadUtils.d.ts +0 -1
- package/dist/core/semanticValidation.cjs +69 -0
- package/dist/core/semanticValidation.d.ts +5 -0
- package/dist/core/semanticValidation.js +69 -0
- package/dist/core/validation.cjs +4 -3
- package/dist/core/validation.d.ts +0 -1
- package/dist/core/validation.js +4 -3
- package/dist/fields/AutocompleteField/AutocompleteField.d.ts +1 -2
- package/dist/fields/AutocompleteMultiField/AutocompleteMultiField.d.ts +1 -2
- package/dist/fields/AutocompletePredictField/AutocompletePredictField.d.ts +1 -2
- package/dist/fields/CheckboxField/CheckboxField.d.ts +1 -2
- package/dist/fields/ColorField/ColorField.d.ts +1 -2
- package/dist/fields/CurrencyField/CurrencyField.d.ts +1 -2
- package/dist/fields/DateField/DateField.d.ts +1 -2
- package/dist/fields/DateField/DatePicker.d.ts +1 -2
- package/dist/fields/DateTimeField/DateTimeField.d.ts +1 -2
- package/dist/fields/EmailField/EmailField.d.ts +1 -2
- package/dist/fields/NumberField/NumberField.d.ts +1 -2
- package/dist/fields/PasswordField/PasswordField.d.ts +1 -2
- package/dist/fields/PhoneField/PhoneField.d.ts +1 -2
- package/dist/fields/RadioField/RadioField.d.ts +1 -2
- package/dist/fields/SelectField/SelectField.d.ts +1 -2
- package/dist/fields/SliderField/SliderField.d.ts +1 -2
- package/dist/fields/SwitchField/SwitchField.d.ts +1 -2
- package/dist/fields/TextField/TextField.d.ts +1 -2
- package/dist/fields/TextareaField/TextareaField.d.ts +1 -2
- package/dist/fields/TimeField/TimeField.d.ts +1 -2
- package/dist/fields/TimeField/TimePicker.d.ts +1 -2
- package/dist/fields/defaultComponentMap.cjs +3 -0
- package/dist/fields/defaultComponentMap.d.ts +0 -1
- package/dist/fields/defaultComponentMap.js +3 -0
- package/dist/fields/defaultPlaceholders.d.ts +0 -1
- package/dist/fields/fieldBase.module.css.cjs +92 -70
- package/dist/fields/fieldBase.module.css.js +92 -70
- package/dist/fields/fieldUtils.d.ts +0 -1
- package/dist/fields/iconUtils.d.ts +0 -1
- package/dist/fields/icons.d.ts +3 -4
- package/dist/index.cjs +31 -22
- package/dist/index.d.ts +3 -2
- package/dist/index.js +32 -23
- package/dist/layout/Box/Box.d.ts +1 -2
- package/dist/layout/Divider/Divider.d.ts +1 -2
- package/dist/layout/Grid/Grid.d.ts +1 -2
- package/dist/layout/Spacer/Spacer.d.ts +1 -2
- package/dist/layout/Stack/Stack.d.ts +1 -2
- package/dist/layout/index.d.ts +0 -1
- package/dist/react/AxenArrayField.d.ts +1 -2
- package/dist/react/AxenField.d.ts +1 -2
- package/dist/react/AxenForm.cjs +33 -23
- package/dist/react/AxenForm.d.ts +0 -1
- package/dist/react/AxenForm.js +34 -24
- package/dist/react/FormContext.d.ts +0 -1
- package/dist/react/useAxenForm.cjs +11 -4
- package/dist/react/useAxenForm.d.ts +1 -2
- package/dist/react/useAxenForm.js +11 -4
- package/dist/react/useField.cjs +3 -0
- package/dist/react/useField.d.ts +0 -1
- package/dist/react/useField.js +3 -0
- package/dist/react/useFieldArray.cjs +19 -13
- package/dist/react/useFieldArray.d.ts +0 -1
- package/dist/react/useFieldArray.js +19 -13
- package/dist/react/useFormState.cjs +18 -0
- package/dist/react/useFormState.d.ts +5 -0
- package/dist/react/useFormState.js +18 -0
- package/dist/types.d.ts +19 -2
- package/package.json +5 -2
- package/dist/adapters/yupAdapter.d.ts.map +0 -1
- package/dist/adapters/zodAdapter.d.ts.map +0 -1
- package/dist/core/dateUtils.d.ts.map +0 -1
- package/dist/core/formStore.d.ts.map +0 -1
- package/dist/core/numberUtils.d.ts.map +0 -1
- package/dist/core/pathUtils.d.ts.map +0 -1
- package/dist/core/payloadUtils.d.ts.map +0 -1
- package/dist/core/validation.d.ts.map +0 -1
- package/dist/fields/AutocompleteField/AutocompleteField.d.ts.map +0 -1
- package/dist/fields/AutocompleteMultiField/AutocompleteMultiField.d.ts.map +0 -1
- package/dist/fields/AutocompletePredictField/AutocompletePredictField.d.ts.map +0 -1
- package/dist/fields/CheckboxField/CheckboxField.d.ts.map +0 -1
- package/dist/fields/ColorField/ColorField.d.ts.map +0 -1
- package/dist/fields/CurrencyField/CurrencyField.d.ts.map +0 -1
- package/dist/fields/DateField/DateField.d.ts.map +0 -1
- package/dist/fields/DateField/DatePicker.d.ts.map +0 -1
- package/dist/fields/DateTimeField/DateTimeField.d.ts.map +0 -1
- package/dist/fields/EmailField/EmailField.d.ts.map +0 -1
- package/dist/fields/NumberField/NumberField.d.ts.map +0 -1
- package/dist/fields/PasswordField/PasswordField.d.ts.map +0 -1
- package/dist/fields/PhoneField/PhoneField.d.ts.map +0 -1
- package/dist/fields/RadioField/RadioField.d.ts.map +0 -1
- package/dist/fields/SelectField/SelectField.d.ts.map +0 -1
- package/dist/fields/SliderField/SliderField.d.ts.map +0 -1
- package/dist/fields/SwitchField/SwitchField.d.ts.map +0 -1
- package/dist/fields/TextField/TextField.d.ts.map +0 -1
- package/dist/fields/TextareaField/TextareaField.d.ts.map +0 -1
- package/dist/fields/TimeField/TimeField.d.ts.map +0 -1
- package/dist/fields/TimeField/TimePicker.d.ts.map +0 -1
- package/dist/fields/defaultComponentMap.d.ts.map +0 -1
- package/dist/fields/defaultPlaceholders.d.ts.map +0 -1
- package/dist/fields/fieldUtils.d.ts.map +0 -1
- package/dist/fields/iconUtils.d.ts.map +0 -1
- package/dist/fields/icons.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/layout/Box/Box.d.ts.map +0 -1
- package/dist/layout/Divider/Divider.d.ts.map +0 -1
- package/dist/layout/Grid/Grid.d.ts.map +0 -1
- package/dist/layout/Spacer/Spacer.d.ts.map +0 -1
- package/dist/layout/Stack/Stack.d.ts.map +0 -1
- package/dist/layout/index.d.ts.map +0 -1
- package/dist/react/AxenArrayField.d.ts.map +0 -1
- package/dist/react/AxenField.d.ts.map +0 -1
- package/dist/react/AxenForm.d.ts.map +0 -1
- package/dist/react/FormContext.d.ts.map +0 -1
- package/dist/react/useAxenForm.d.ts.map +0 -1
- package/dist/react/useField.d.ts.map +0 -1
- package/dist/react/useFieldArray.d.ts.map +0 -1
- package/dist/types.d.ts.map +0 -1
package/dist/core/formStore.d.ts
CHANGED
|
@@ -27,13 +27,14 @@ export declare function createFormStore<TValues extends Record<string, unknown>>
|
|
|
27
27
|
setFieldError: (name: string, error: string | undefined) => void;
|
|
28
28
|
setValues: (values: TValues) => void;
|
|
29
29
|
setErrors: (errors: Record<string, string>) => void;
|
|
30
|
+
setFieldArrayValue: (name: string, items: unknown[], origins: Array<number | null>) => void;
|
|
30
31
|
resetForm: (nextValues?: Partial<TValues>) => void;
|
|
31
32
|
validateForm: () => Promise<Record<string, string>>;
|
|
32
33
|
validateField: (name: string) => Promise<string | undefined>;
|
|
33
34
|
submitForm: (onSubmit?: (values: TValues) => void | Promise<void>) => Promise<void>;
|
|
35
|
+
touchAllFields: () => void;
|
|
34
36
|
getFieldValue: (name: string) => unknown;
|
|
35
37
|
getFieldError: (name: string) => string | undefined;
|
|
36
38
|
getFieldTouched: (name: string) => boolean;
|
|
37
39
|
};
|
|
38
40
|
export type FormStore<TValues extends Record<string, unknown> = Record<string, unknown>> = ReturnType<typeof createFormStore<TValues>>;
|
|
39
|
-
//# sourceMappingURL=formStore.d.ts.map
|
package/dist/core/formStore.js
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
import { get, set } from "./pathUtils.js";
|
|
2
|
+
function valuesEqual(a, b) {
|
|
3
|
+
if (Object.is(a, b)) return true;
|
|
4
|
+
if (a instanceof Date || b instanceof Date) return a instanceof Date && b instanceof Date && a.getTime() === b.getTime();
|
|
5
|
+
if (a === null || b === null || typeof a !== "object" || typeof b !== "object") return false;
|
|
6
|
+
if (Array.isArray(a) !== Array.isArray(b)) return false;
|
|
7
|
+
const left = a;
|
|
8
|
+
const right = b;
|
|
9
|
+
const keys = Object.keys(left);
|
|
10
|
+
if (keys.length !== Object.keys(right).length) return false;
|
|
11
|
+
return keys.every((key) => Object.prototype.hasOwnProperty.call(right, key) && valuesEqual(left[key], right[key]));
|
|
12
|
+
}
|
|
2
13
|
function createFormStore(options) {
|
|
3
14
|
const {
|
|
4
15
|
initialValues,
|
|
@@ -18,6 +29,9 @@ function createFormStore(options) {
|
|
|
18
29
|
const subscribers = /* @__PURE__ */ new Set();
|
|
19
30
|
const fieldSubscribers = /* @__PURE__ */ new Map();
|
|
20
31
|
let validationSchema = options.validationSchema;
|
|
32
|
+
let valuesRevision = 0;
|
|
33
|
+
let formRequest = 0;
|
|
34
|
+
const fieldRequests = /* @__PURE__ */ new Map();
|
|
21
35
|
if (validationAdapter && options.fields && !validationSchema) {
|
|
22
36
|
validationSchema = validationAdapter.buildSchema(options.fields);
|
|
23
37
|
}
|
|
@@ -46,16 +60,30 @@ function createFormStore(options) {
|
|
|
46
60
|
var _a;
|
|
47
61
|
(_a = fieldSubscribers.get(name)) == null ? void 0 : _a.forEach((fn) => fn());
|
|
48
62
|
}
|
|
49
|
-
function
|
|
50
|
-
|
|
51
|
-
...state,
|
|
52
|
-
values: set(state.values, name, value),
|
|
53
|
-
dirty: true
|
|
54
|
-
};
|
|
55
|
-
notifyField(name);
|
|
63
|
+
function notifyAllFields() {
|
|
64
|
+
for (const name of fieldSubscribers.keys()) notifyField(name);
|
|
56
65
|
notify();
|
|
66
|
+
}
|
|
67
|
+
function notifyValuePath(path) {
|
|
68
|
+
const related = (key) => key === path || key.startsWith(`${path}.`) || key.startsWith(`${path}[`) || path.startsWith(`${key}.`) || path.startsWith(`${key}[`);
|
|
69
|
+
for (const key of fieldSubscribers.keys()) if (related(key)) notifyField(key);
|
|
70
|
+
notify();
|
|
71
|
+
}
|
|
72
|
+
function setFieldValue(name, value) {
|
|
73
|
+
const nextValues = set(state.values, name, value);
|
|
74
|
+
valuesRevision += 1;
|
|
75
|
+
state = { ...state, values: nextValues, dirty: !valuesEqual(nextValues, state.initialValues) };
|
|
76
|
+
for (const field of options.fields ?? []) {
|
|
77
|
+
if (field.hidden && state.errors[field.name] && (typeof field.hidden === "function" ? field.hidden(nextValues) : field.hidden)) {
|
|
78
|
+
setFieldError(field.name, void 0);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
notifyValuePath(name);
|
|
57
82
|
if (validateOnChange && validationAdapter && validationSchema) {
|
|
58
|
-
|
|
83
|
+
const revision = valuesRevision;
|
|
84
|
+
void runFieldValidation(name).catch((error) => {
|
|
85
|
+
if (revision === valuesRevision) setFieldError(name, error instanceof Error ? error.message : "Validation failed");
|
|
86
|
+
});
|
|
59
87
|
}
|
|
60
88
|
}
|
|
61
89
|
function setFieldTouched(name, touched = true) {
|
|
@@ -66,7 +94,10 @@ function createFormStore(options) {
|
|
|
66
94
|
notifyField(name);
|
|
67
95
|
notify();
|
|
68
96
|
if (validateOnBlur && touched && validationAdapter && validationSchema) {
|
|
69
|
-
|
|
97
|
+
const revision = valuesRevision;
|
|
98
|
+
void runFieldValidation(name).catch((error) => {
|
|
99
|
+
if (revision === valuesRevision) setFieldError(name, error instanceof Error ? error.message : "Validation failed");
|
|
100
|
+
});
|
|
70
101
|
}
|
|
71
102
|
}
|
|
72
103
|
function setFieldError(name, error) {
|
|
@@ -81,13 +112,47 @@ function createFormStore(options) {
|
|
|
81
112
|
notify();
|
|
82
113
|
}
|
|
83
114
|
function setValues(values) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
115
|
+
valuesRevision += 1;
|
|
116
|
+
state = { ...state, values, dirty: !valuesEqual(values, state.initialValues) };
|
|
117
|
+
notifyAllFields();
|
|
87
118
|
}
|
|
88
119
|
function setErrors(errors) {
|
|
89
120
|
state = { ...state, errors };
|
|
90
|
-
|
|
121
|
+
notifyAllFields();
|
|
122
|
+
}
|
|
123
|
+
function setFieldArrayValue(name, items, origins) {
|
|
124
|
+
const remap = (entries) => {
|
|
125
|
+
const result = {};
|
|
126
|
+
for (const [path, value] of Object.entries(entries)) {
|
|
127
|
+
if (!path.startsWith(name)) {
|
|
128
|
+
result[path] = value;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
const suffix = path.slice(name.length);
|
|
132
|
+
const match = /^(?:\.(\d+)|\[(\d+)\])(?=\.|\[|$)/.exec(suffix);
|
|
133
|
+
if (!match) {
|
|
134
|
+
result[path] = value;
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
const oldIndex = Number(match[1] ?? match[2]);
|
|
138
|
+
const tail = suffix.slice(match[0].length);
|
|
139
|
+
for (let i = 0; i < origins.length; i++) {
|
|
140
|
+
if (origins[i] !== oldIndex) continue;
|
|
141
|
+
result[`${name}${match[1] !== void 0 ? `.${i}` : `[${i}]`}${tail}`] = value;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return result;
|
|
145
|
+
};
|
|
146
|
+
const values = set(state.values, name, items);
|
|
147
|
+
valuesRevision += 1;
|
|
148
|
+
state = {
|
|
149
|
+
...state,
|
|
150
|
+
values,
|
|
151
|
+
dirty: !valuesEqual(values, state.initialValues),
|
|
152
|
+
errors: remap(state.errors),
|
|
153
|
+
touched: remap(state.touched)
|
|
154
|
+
};
|
|
155
|
+
notifyValuePath(name);
|
|
91
156
|
}
|
|
92
157
|
function resetForm(nextValues) {
|
|
93
158
|
const newValues = nextValues ? { ...state.initialValues, ...nextValues } : structuredClone(state.initialValues);
|
|
@@ -98,23 +163,40 @@ function createFormStore(options) {
|
|
|
98
163
|
dirty: false,
|
|
99
164
|
isSubmitting: false,
|
|
100
165
|
submitCount: state.submitCount,
|
|
101
|
-
initialValues: state.initialValues
|
|
166
|
+
initialValues: nextValues ? structuredClone(newValues) : state.initialValues
|
|
102
167
|
};
|
|
103
|
-
|
|
168
|
+
valuesRevision += 1;
|
|
169
|
+
notifyAllFields();
|
|
104
170
|
}
|
|
105
171
|
async function validateForm() {
|
|
106
172
|
if (!validationAdapter || !validationSchema) return {};
|
|
173
|
+
const revision = valuesRevision;
|
|
174
|
+
const request = ++formRequest;
|
|
107
175
|
const errors = await validationAdapter.validate(validationSchema, state.values);
|
|
176
|
+
if (revision !== valuesRevision || request !== formRequest) return state.errors;
|
|
108
177
|
state = { ...state, errors };
|
|
109
178
|
notify();
|
|
179
|
+
for (const name of fieldSubscribers.keys()) notifyField(name);
|
|
110
180
|
return errors;
|
|
111
181
|
}
|
|
112
182
|
async function validateField(name) {
|
|
183
|
+
var _a;
|
|
113
184
|
if (!(validationAdapter == null ? void 0 : validationAdapter.validateField) || !validationSchema) return void 0;
|
|
185
|
+
const revision = valuesRevision;
|
|
186
|
+
const request = (fieldRequests.get(name) ?? 0) + 1;
|
|
187
|
+
fieldRequests.set(name, request);
|
|
188
|
+
const config = (_a = options.fields) == null ? void 0 : _a.find((field) => field.name === name);
|
|
189
|
+
if ((config == null ? void 0 : config.hidden) && (typeof config.hidden === "function" ? config.hidden(state.values) : config.hidden)) {
|
|
190
|
+
setFieldError(name, void 0);
|
|
191
|
+
return void 0;
|
|
192
|
+
}
|
|
114
193
|
const fieldValue = get(state.values, name);
|
|
115
194
|
const error = await validationAdapter.validateField(validationSchema, name, fieldValue);
|
|
116
|
-
|
|
117
|
-
|
|
195
|
+
if (revision === valuesRevision && request === fieldRequests.get(name)) {
|
|
196
|
+
setFieldError(name, error);
|
|
197
|
+
return error;
|
|
198
|
+
}
|
|
199
|
+
return state.errors[name];
|
|
118
200
|
}
|
|
119
201
|
async function runFieldValidation(name) {
|
|
120
202
|
if (validationAdapter == null ? void 0 : validationAdapter.validateField) {
|
|
@@ -124,30 +206,18 @@ function createFormStore(options) {
|
|
|
124
206
|
}
|
|
125
207
|
}
|
|
126
208
|
async function submitForm(onSubmit) {
|
|
209
|
+
if (state.isSubmitting) return;
|
|
127
210
|
state = { ...state, isSubmitting: true, submitCount: state.submitCount + 1 };
|
|
128
211
|
notify();
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
state = { ...state, isSubmitting: false };
|
|
139
|
-
notify();
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
const handler = onSubmit ?? options.onSubmit;
|
|
143
|
-
if (handler) {
|
|
144
|
-
try {
|
|
145
|
-
await handler(state.values);
|
|
146
|
-
} finally {
|
|
147
|
-
state = { ...state, isSubmitting: false };
|
|
148
|
-
notify();
|
|
149
|
-
}
|
|
150
|
-
} else {
|
|
212
|
+
try {
|
|
213
|
+
touchAllFields();
|
|
214
|
+
const revision = valuesRevision;
|
|
215
|
+
const errors = await validateForm();
|
|
216
|
+
for (const name of Object.keys(state.touched)) notifyField(name);
|
|
217
|
+
if (revision !== valuesRevision || Object.keys(errors).length > 0) return;
|
|
218
|
+
const handler = onSubmit ?? options.onSubmit;
|
|
219
|
+
if (handler) await handler(state.values);
|
|
220
|
+
} finally {
|
|
151
221
|
state = { ...state, isSubmitting: false };
|
|
152
222
|
notify();
|
|
153
223
|
}
|
|
@@ -161,6 +231,22 @@ function createFormStore(options) {
|
|
|
161
231
|
function getFieldTouched(name) {
|
|
162
232
|
return state.touched[name] ?? false;
|
|
163
233
|
}
|
|
234
|
+
function touchAllFields() {
|
|
235
|
+
const allTouched = {};
|
|
236
|
+
if (options.fields) {
|
|
237
|
+
for (const field of options.fields) {
|
|
238
|
+
allTouched[field.name] = true;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
for (const name of fieldSubscribers.keys()) {
|
|
242
|
+
allTouched[name] = true;
|
|
243
|
+
}
|
|
244
|
+
state = { ...state, touched: { ...state.touched, ...allTouched } };
|
|
245
|
+
for (const name of Object.keys(allTouched)) {
|
|
246
|
+
notifyField(name);
|
|
247
|
+
}
|
|
248
|
+
notify();
|
|
249
|
+
}
|
|
164
250
|
return {
|
|
165
251
|
getState,
|
|
166
252
|
subscribe,
|
|
@@ -170,10 +256,12 @@ function createFormStore(options) {
|
|
|
170
256
|
setFieldError,
|
|
171
257
|
setValues,
|
|
172
258
|
setErrors,
|
|
259
|
+
setFieldArrayValue,
|
|
173
260
|
resetForm,
|
|
174
261
|
validateForm,
|
|
175
262
|
validateField,
|
|
176
263
|
submitForm,
|
|
264
|
+
touchAllFields,
|
|
177
265
|
getFieldValue,
|
|
178
266
|
getFieldError,
|
|
179
267
|
getFieldTouched
|
|
@@ -23,4 +23,3 @@ export declare function getGroupSeparator(locale?: string): string;
|
|
|
23
23
|
* then finds the same position in the formatted string.
|
|
24
24
|
*/
|
|
25
25
|
export declare function calculateCursorPosition(rawValue: string, formattedValue: string, cursorPos: number, locale?: string): number;
|
|
26
|
-
//# sourceMappingURL=numberUtils.d.ts.map
|
package/dist/core/pathUtils.d.ts
CHANGED
|
@@ -12,4 +12,3 @@ export declare function set<T extends Record<string, unknown>>(obj: T, path: str
|
|
|
12
12
|
export declare function toPathArray(path: string): string[];
|
|
13
13
|
/** Convert path segments back to dot-path string */
|
|
14
14
|
export declare function pathToString(segments: string[]): string;
|
|
15
|
-
//# sourceMappingURL=pathUtils.d.ts.map
|
|
@@ -19,4 +19,3 @@ export declare function pickFields<T extends Record<string, unknown>>(values: T,
|
|
|
19
19
|
* Useful for debugging / UI display.
|
|
20
20
|
*/
|
|
21
21
|
export declare function getStrippedFields<T extends Record<string, unknown>>(values: T, fieldMap: string[] | Record<string, string[]>, discriminatorKey?: string): string[];
|
|
22
|
-
//# sourceMappingURL=payloadUtils.d.ts.map
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const pathUtils = require("./pathUtils.cjs");
|
|
4
|
+
function isHidden(field, values) {
|
|
5
|
+
return typeof field.hidden === "function" ? Boolean(field.hidden(values)) : Boolean(field.hidden);
|
|
6
|
+
}
|
|
7
|
+
function validateSemanticValue(field, value, policy) {
|
|
8
|
+
var _a;
|
|
9
|
+
if (field.validation) return void 0;
|
|
10
|
+
const rules = field.rules;
|
|
11
|
+
const inferred = field.type === "tel" ? "phone" : field.type;
|
|
12
|
+
const format = (rules == null ? void 0 : rules.format) ?? ((policy == null ? void 0 : policy.mode) === "standard" && (inferred === "email" || inferred === "phone" || inferred === "url") ? inferred : void 0);
|
|
13
|
+
if (!format || value === void 0 || value === null || value === "") return void 0;
|
|
14
|
+
if (typeof value !== "string") return (rules == null ? void 0 : rules.message) ?? "Invalid value";
|
|
15
|
+
const input = value.trim();
|
|
16
|
+
if (!input) return void 0;
|
|
17
|
+
let valid = true;
|
|
18
|
+
if (format === "email") {
|
|
19
|
+
valid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/u.test(input) && input.length <= 254;
|
|
20
|
+
} else if (format === "url") {
|
|
21
|
+
try {
|
|
22
|
+
const parsed = new URL(input);
|
|
23
|
+
valid = (parsed.protocol === "http:" || parsed.protocol === "https:") && Boolean(parsed.hostname);
|
|
24
|
+
} catch {
|
|
25
|
+
valid = false;
|
|
26
|
+
}
|
|
27
|
+
} else if (format === "phone") {
|
|
28
|
+
const clean = input.replace(/[().\s-]/g, "");
|
|
29
|
+
const region = ((rules == null ? void 0 : rules.region) ?? "").toUpperCase();
|
|
30
|
+
valid = region === "ID" ? /^(?:\+62|62|0)8\d{7,11}$/u.test(clean) : /^\+[1-9]\d{7,14}$/u.test(clean);
|
|
31
|
+
} else if (format === "postalCode") {
|
|
32
|
+
const country = ((rules == null ? void 0 : rules.country) ?? "").toUpperCase();
|
|
33
|
+
const patterns = {
|
|
34
|
+
ID: /^\d{5}$/u,
|
|
35
|
+
US: /^\d{5}(?:-\d{4})?$/u,
|
|
36
|
+
SG: /^\d{6}$/u
|
|
37
|
+
};
|
|
38
|
+
valid = Boolean((_a = patterns[country]) == null ? void 0 : _a.test(input));
|
|
39
|
+
}
|
|
40
|
+
return valid ? void 0 : (rules == null ? void 0 : rules.message) ?? `Invalid ${format}`;
|
|
41
|
+
}
|
|
42
|
+
function withValidationPolicy(adapter, policy) {
|
|
43
|
+
return {
|
|
44
|
+
buildSchema(fields) {
|
|
45
|
+
return { base: adapter.buildSchema(fields), fields };
|
|
46
|
+
},
|
|
47
|
+
async validate(schema, values) {
|
|
48
|
+
const { base, fields } = schema;
|
|
49
|
+
const errors = { ...await adapter.validate(base, values) };
|
|
50
|
+
for (const field of fields) {
|
|
51
|
+
if (isHidden(field, values)) {
|
|
52
|
+
delete errors[field.name];
|
|
53
|
+
} else if (!errors[field.name]) {
|
|
54
|
+
const error = validateSemanticValue(field, pathUtils.get(values, field.name), policy);
|
|
55
|
+
if (error) errors[field.name] = error;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return errors;
|
|
59
|
+
},
|
|
60
|
+
async validateField(schema, name, value) {
|
|
61
|
+
var _a;
|
|
62
|
+
const { base, fields } = schema;
|
|
63
|
+
const error = await ((_a = adapter.validateField) == null ? void 0 : _a.call(adapter, base, name, value));
|
|
64
|
+
return error ?? validateSemanticValue(fields.find((f) => f.name === name) ?? { type: "text" }, value, policy);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
exports.validateSemanticValue = validateSemanticValue;
|
|
69
|
+
exports.withValidationPolicy = withValidationPolicy;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { FieldConfig, ValidationAdapter, ValidationPolicy } from '../types';
|
|
2
|
+
/** Optional semantics: custom Yup/Zod field schemas retain precedence. */
|
|
3
|
+
export declare function validateSemanticValue(field: FieldConfig, value: unknown, policy?: ValidationPolicy): string | undefined;
|
|
4
|
+
/** Adapter-independent policy wrapper. No mandatory Yup, Zod, or UI dependencies. */
|
|
5
|
+
export declare function withValidationPolicy(adapter: ValidationAdapter, policy?: ValidationPolicy): ValidationAdapter;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { get } from "./pathUtils.js";
|
|
2
|
+
function isHidden(field, values) {
|
|
3
|
+
return typeof field.hidden === "function" ? Boolean(field.hidden(values)) : Boolean(field.hidden);
|
|
4
|
+
}
|
|
5
|
+
function validateSemanticValue(field, value, policy) {
|
|
6
|
+
var _a;
|
|
7
|
+
if (field.validation) return void 0;
|
|
8
|
+
const rules = field.rules;
|
|
9
|
+
const inferred = field.type === "tel" ? "phone" : field.type;
|
|
10
|
+
const format = (rules == null ? void 0 : rules.format) ?? ((policy == null ? void 0 : policy.mode) === "standard" && (inferred === "email" || inferred === "phone" || inferred === "url") ? inferred : void 0);
|
|
11
|
+
if (!format || value === void 0 || value === null || value === "") return void 0;
|
|
12
|
+
if (typeof value !== "string") return (rules == null ? void 0 : rules.message) ?? "Invalid value";
|
|
13
|
+
const input = value.trim();
|
|
14
|
+
if (!input) return void 0;
|
|
15
|
+
let valid = true;
|
|
16
|
+
if (format === "email") {
|
|
17
|
+
valid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/u.test(input) && input.length <= 254;
|
|
18
|
+
} else if (format === "url") {
|
|
19
|
+
try {
|
|
20
|
+
const parsed = new URL(input);
|
|
21
|
+
valid = (parsed.protocol === "http:" || parsed.protocol === "https:") && Boolean(parsed.hostname);
|
|
22
|
+
} catch {
|
|
23
|
+
valid = false;
|
|
24
|
+
}
|
|
25
|
+
} else if (format === "phone") {
|
|
26
|
+
const clean = input.replace(/[().\s-]/g, "");
|
|
27
|
+
const region = ((rules == null ? void 0 : rules.region) ?? "").toUpperCase();
|
|
28
|
+
valid = region === "ID" ? /^(?:\+62|62|0)8\d{7,11}$/u.test(clean) : /^\+[1-9]\d{7,14}$/u.test(clean);
|
|
29
|
+
} else if (format === "postalCode") {
|
|
30
|
+
const country = ((rules == null ? void 0 : rules.country) ?? "").toUpperCase();
|
|
31
|
+
const patterns = {
|
|
32
|
+
ID: /^\d{5}$/u,
|
|
33
|
+
US: /^\d{5}(?:-\d{4})?$/u,
|
|
34
|
+
SG: /^\d{6}$/u
|
|
35
|
+
};
|
|
36
|
+
valid = Boolean((_a = patterns[country]) == null ? void 0 : _a.test(input));
|
|
37
|
+
}
|
|
38
|
+
return valid ? void 0 : (rules == null ? void 0 : rules.message) ?? `Invalid ${format}`;
|
|
39
|
+
}
|
|
40
|
+
function withValidationPolicy(adapter, policy) {
|
|
41
|
+
return {
|
|
42
|
+
buildSchema(fields) {
|
|
43
|
+
return { base: adapter.buildSchema(fields), fields };
|
|
44
|
+
},
|
|
45
|
+
async validate(schema, values) {
|
|
46
|
+
const { base, fields } = schema;
|
|
47
|
+
const errors = { ...await adapter.validate(base, values) };
|
|
48
|
+
for (const field of fields) {
|
|
49
|
+
if (isHidden(field, values)) {
|
|
50
|
+
delete errors[field.name];
|
|
51
|
+
} else if (!errors[field.name]) {
|
|
52
|
+
const error = validateSemanticValue(field, get(values, field.name), policy);
|
|
53
|
+
if (error) errors[field.name] = error;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return errors;
|
|
57
|
+
},
|
|
58
|
+
async validateField(schema, name, value) {
|
|
59
|
+
var _a;
|
|
60
|
+
const { base, fields } = schema;
|
|
61
|
+
const error = await ((_a = adapter.validateField) == null ? void 0 : _a.call(adapter, base, name, value));
|
|
62
|
+
return error ?? validateSemanticValue(fields.find((f) => f.name === name) ?? { type: "text" }, value, policy);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export {
|
|
67
|
+
validateSemanticValue,
|
|
68
|
+
withValidationPolicy
|
|
69
|
+
};
|
package/dist/core/validation.cjs
CHANGED
|
@@ -16,7 +16,7 @@ const simpleValidator = {
|
|
|
16
16
|
const isHidden = typeof rule.hidden === "function" ? rule.hidden(values) : rule.hidden;
|
|
17
17
|
if (isHidden) continue;
|
|
18
18
|
const value = getNestedValue(values, rule.name);
|
|
19
|
-
if (isEmpty(value)) {
|
|
19
|
+
if (isEmpty(value, rule.type)) {
|
|
20
20
|
errors[rule.name] = rule.message;
|
|
21
21
|
}
|
|
22
22
|
}
|
|
@@ -26,10 +26,11 @@ const simpleValidator = {
|
|
|
26
26
|
const rules = schema;
|
|
27
27
|
const rule = rules.find((r) => r.name === name);
|
|
28
28
|
if (!rule) return void 0;
|
|
29
|
-
return isEmpty(value) ? rule.message : void 0;
|
|
29
|
+
return isEmpty(value, rule.type) ? rule.message : void 0;
|
|
30
30
|
}
|
|
31
31
|
};
|
|
32
|
-
function isEmpty(value) {
|
|
32
|
+
function isEmpty(value, type) {
|
|
33
|
+
if (type === "checkbox" || type === "switch") return value !== true;
|
|
33
34
|
if (value == null) return true;
|
|
34
35
|
if (typeof value === "string") return value.trim() === "";
|
|
35
36
|
if (Array.isArray(value)) return value.length === 0;
|
package/dist/core/validation.js
CHANGED
|
@@ -14,7 +14,7 @@ const simpleValidator = {
|
|
|
14
14
|
const isHidden = typeof rule.hidden === "function" ? rule.hidden(values) : rule.hidden;
|
|
15
15
|
if (isHidden) continue;
|
|
16
16
|
const value = getNestedValue(values, rule.name);
|
|
17
|
-
if (isEmpty(value)) {
|
|
17
|
+
if (isEmpty(value, rule.type)) {
|
|
18
18
|
errors[rule.name] = rule.message;
|
|
19
19
|
}
|
|
20
20
|
}
|
|
@@ -24,10 +24,11 @@ const simpleValidator = {
|
|
|
24
24
|
const rules = schema;
|
|
25
25
|
const rule = rules.find((r) => r.name === name);
|
|
26
26
|
if (!rule) return void 0;
|
|
27
|
-
return isEmpty(value) ? rule.message : void 0;
|
|
27
|
+
return isEmpty(value, rule.type) ? rule.message : void 0;
|
|
28
28
|
}
|
|
29
29
|
};
|
|
30
|
-
function isEmpty(value) {
|
|
30
|
+
function isEmpty(value, type) {
|
|
31
|
+
if (type === "checkbox" || type === "switch") return value !== true;
|
|
31
32
|
if (value == null) return true;
|
|
32
33
|
if (typeof value === "string") return value.trim() === "";
|
|
33
34
|
if (Array.isArray(value)) return value.length === 0;
|
|
@@ -2,5 +2,4 @@ import { AutocompleteOption, FieldComponentProps } from '../../types';
|
|
|
2
2
|
export declare function AutocompleteField({ name, value, onChange: _onChange, onBlur, error, helperText, label, placeholder, disabled, readOnly, required, options: staticOptions, fetchOptions, optionLabel, icon, form, }: FieldComponentProps & {
|
|
3
3
|
fetchOptions?: (query: string, signal?: AbortSignal) => Promise<AutocompleteOption[]>;
|
|
4
4
|
optionLabel?: string;
|
|
5
|
-
}): import("react
|
|
6
|
-
//# sourceMappingURL=AutocompleteField.d.ts.map
|
|
5
|
+
}): import("react").JSX.Element;
|
|
@@ -2,5 +2,4 @@ import { AutocompleteOption, FieldComponentProps } from '../../types';
|
|
|
2
2
|
export declare function AutocompleteMultiField({ name, value, onChange: _onChange, onBlur, error, helperText, label, placeholder, disabled, readOnly, required, options: staticOptions, fetchOptions, optionLabel, icon, form, }: FieldComponentProps & {
|
|
3
3
|
fetchOptions?: (query: string, signal?: AbortSignal) => Promise<AutocompleteOption[]>;
|
|
4
4
|
optionLabel?: string;
|
|
5
|
-
}): import("react
|
|
6
|
-
//# sourceMappingURL=AutocompleteMultiField.d.ts.map
|
|
5
|
+
}): import("react").JSX.Element;
|
|
@@ -6,5 +6,4 @@ import { AutocompleteOption, FieldComponentProps } from '../../types';
|
|
|
6
6
|
export declare function AutocompletePredictField({ name, value, onChange: _onChange, onBlur, error, helperText, label, placeholder, disabled, readOnly, required, options: staticOptions, fetchOptions, optionLabel, icon, form, }: FieldComponentProps & {
|
|
7
7
|
fetchOptions?: (query: string, signal?: AbortSignal) => Promise<AutocompleteOption[]>;
|
|
8
8
|
optionLabel?: string;
|
|
9
|
-
}): import("react
|
|
10
|
-
//# sourceMappingURL=AutocompletePredictField.d.ts.map
|
|
9
|
+
}): import("react").JSX.Element;
|
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
import { FieldComponentProps } from '../../types';
|
|
2
|
-
export declare function CheckboxField({ name, value, onChange: _onChange, onBlur, error, helperText, label, disabled, readOnly, required, form, }: Readonly<FieldComponentProps>): import("react
|
|
3
|
-
//# sourceMappingURL=CheckboxField.d.ts.map
|
|
2
|
+
export declare function CheckboxField({ name, value, onChange: _onChange, onBlur, error, helperText, label, disabled, readOnly, required, form, }: Readonly<FieldComponentProps>): import("react").JSX.Element;
|
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
import { FieldComponentProps } from '../../types';
|
|
2
|
-
export declare function ColorField({ name, value, onChange: _onChange, onBlur, error, helperText, label, disabled, readOnly, required, form, }: Readonly<FieldComponentProps>): import("react
|
|
3
|
-
//# sourceMappingURL=ColorField.d.ts.map
|
|
2
|
+
export declare function ColorField({ name, value, onChange: _onChange, onBlur, error, helperText, label, disabled, readOnly, required, form, }: Readonly<FieldComponentProps>): import("react").JSX.Element;
|
|
@@ -6,6 +6,5 @@ interface DatePickerProps {
|
|
|
6
6
|
onApply: (isoDate: string) => void;
|
|
7
7
|
onClose: () => void;
|
|
8
8
|
}
|
|
9
|
-
export declare function DatePicker({ value, min, max, pickerId, onApply, onClose, }: Readonly<DatePickerProps>): import("react
|
|
9
|
+
export declare function DatePicker({ value, min, max, pickerId, onApply, onClose, }: Readonly<DatePickerProps>): import("react").JSX.Element;
|
|
10
10
|
export {};
|
|
11
|
-
//# sourceMappingURL=DatePicker.d.ts.map
|
|
@@ -5,5 +5,4 @@ export declare function DateTimeField({ name, value, onChange, onBlur, error, he
|
|
|
5
5
|
locale?: string;
|
|
6
6
|
ampm?: boolean;
|
|
7
7
|
showSeconds?: boolean;
|
|
8
|
-
}>): import("react
|
|
9
|
-
//# sourceMappingURL=DateTimeField.d.ts.map
|
|
8
|
+
}>): import("react").JSX.Element;
|
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
import { FieldComponentProps } from '../../types';
|
|
2
|
-
export declare function EmailField({ name, value, onChange, onBlur, error, helperText, label, placeholder, disabled, readOnly, required, icon, }: Readonly<FieldComponentProps>): import("react
|
|
3
|
-
//# sourceMappingURL=EmailField.d.ts.map
|
|
2
|
+
export declare function EmailField({ name, value, onChange, onBlur, error, helperText, label, placeholder, disabled, readOnly, required, icon, }: Readonly<FieldComponentProps>): import("react").JSX.Element;
|
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
import { FieldComponentProps } from '../../types';
|
|
2
|
-
export declare function PasswordField({ name, value, onChange, onBlur, error, helperText, label, placeholder, disabled, readOnly, required, icon, }: Readonly<FieldComponentProps>): import("react
|
|
3
|
-
//# sourceMappingURL=PasswordField.d.ts.map
|
|
2
|
+
export declare function PasswordField({ name, value, onChange, onBlur, error, helperText, label, placeholder, disabled, readOnly, required, icon, }: Readonly<FieldComponentProps>): import("react").JSX.Element;
|
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
import { FieldComponentProps } from '../../types';
|
|
2
|
-
export declare function PhoneField({ name, value, onChange, onBlur, error, helperText, label, placeholder, disabled, readOnly, required, icon, }: Readonly<FieldComponentProps>): import("react
|
|
3
|
-
//# sourceMappingURL=PhoneField.d.ts.map
|
|
2
|
+
export declare function PhoneField({ name, value, onChange, onBlur, error, helperText, label, placeholder, disabled, readOnly, required, icon, }: Readonly<FieldComponentProps>): import("react").JSX.Element;
|
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
import { FieldComponentProps } from '../../types';
|
|
2
|
-
export declare function RadioField({ name, value, onChange: _onChange, onBlur, error, helperText, label, disabled, readOnly, required, options, form, }: Readonly<FieldComponentProps>): import("react
|
|
3
|
-
//# sourceMappingURL=RadioField.d.ts.map
|
|
2
|
+
export declare function RadioField({ name, value, onChange: _onChange, onBlur, error, helperText, label, disabled, readOnly, required, options, form, }: Readonly<FieldComponentProps>): import("react").JSX.Element;
|
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
import { FieldComponentProps } from '../../types';
|
|
2
|
-
export declare function SelectField({ name, value, onChange, onBlur, error, helperText, label, placeholder, disabled, readOnly, required, options, }: Readonly<FieldComponentProps>): import("react
|
|
3
|
-
//# sourceMappingURL=SelectField.d.ts.map
|
|
2
|
+
export declare function SelectField({ name, value, onChange, onBlur, error, helperText, label, placeholder, disabled, readOnly, required, options, }: Readonly<FieldComponentProps>): import("react").JSX.Element;
|
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
import { FieldComponentProps } from '../../types';
|
|
2
|
-
export declare function SwitchField({ name, value, onChange: _onChange, onBlur, error, helperText, label, disabled, readOnly, required, form, }: Readonly<FieldComponentProps>): import("react
|
|
3
|
-
//# sourceMappingURL=SwitchField.d.ts.map
|
|
2
|
+
export declare function SwitchField({ name, value, onChange: _onChange, onBlur, error, helperText, label, disabled, readOnly, required, form, }: Readonly<FieldComponentProps>): import("react").JSX.Element;
|
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
import { FieldComponentProps } from '../../types';
|
|
2
|
-
export declare function TextField({ name, value, onChange, onBlur, error, helperText, label, placeholder, disabled, readOnly, required, icon, }: Readonly<FieldComponentProps>): import("react
|
|
3
|
-
//# sourceMappingURL=TextField.d.ts.map
|
|
2
|
+
export declare function TextField({ name, value, onChange, onBlur, error, helperText, label, placeholder, disabled, readOnly, required, icon, }: Readonly<FieldComponentProps>): import("react").JSX.Element;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { FieldComponentProps } from '../../types';
|
|
2
2
|
export declare function TextareaField({ name, value, onChange, onBlur, error, helperText, label, placeholder, disabled, readOnly, required, rows, }: FieldComponentProps & {
|
|
3
3
|
rows?: number;
|
|
4
|
-
}): import("react
|
|
5
|
-
//# sourceMappingURL=TextareaField.d.ts.map
|
|
4
|
+
}): import("react").JSX.Element;
|
|
@@ -6,6 +6,5 @@ interface TimePickerProps {
|
|
|
6
6
|
onApply: (isoTime: string) => void;
|
|
7
7
|
onClose: () => void;
|
|
8
8
|
}
|
|
9
|
-
export declare function TimePicker({ value, showSeconds, ampm, pickerId, onApply, onClose, }: Readonly<TimePickerProps>): import("react
|
|
9
|
+
export declare function TimePicker({ value, showSeconds, ampm, pickerId, onApply, onClose, }: Readonly<TimePickerProps>): import("react").JSX.Element;
|
|
10
10
|
export {};
|
|
11
|
-
//# sourceMappingURL=TimePicker.d.ts.map
|