hs-uix 1.0.4 → 1.2.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/README.md +7 -4
- package/dist/datatable.js +89 -22
- package/dist/datatable.mjs +89 -22
- package/dist/form.js +246 -64
- package/dist/form.mjs +246 -64
- package/dist/index.js +335 -86
- package/dist/index.mjs +335 -86
- package/form.d.ts +1 -0
- package/index.d.ts +1 -0
- package/package.json +1 -1
package/dist/form.mjs
CHANGED
|
@@ -136,7 +136,6 @@ var runDefaultFieldValidator = (value, field, allValues) => {
|
|
|
136
136
|
if (!isTimeValueObject(value)) return `${errorPrefix} has an invalid time`;
|
|
137
137
|
break;
|
|
138
138
|
case "datetime": {
|
|
139
|
-
if (isDateValueObject(value)) break;
|
|
140
139
|
if (!isPlainObject(value)) return `${errorPrefix} has an invalid date/time`;
|
|
141
140
|
const hasDate = value.date !== void 0;
|
|
142
141
|
const hasTime = value.time !== void 0;
|
|
@@ -202,12 +201,14 @@ var collectAsyncValidatorPromises = (value, field, allValues, context) => {
|
|
|
202
201
|
};
|
|
203
202
|
var runValidators = (value, field, allValues, fieldTypes, options = {}) => {
|
|
204
203
|
const includeCustomValidators = options.includeCustomValidators !== false;
|
|
205
|
-
|
|
204
|
+
const msg = options.messages || {};
|
|
205
|
+
if (field.type === "display" || field.type === "crmPropertyList" || field.type === "crmAssociationPropertyList" || field.type === "fieldGroup") return null;
|
|
206
206
|
const isRequired = resolveRequired(field, allValues);
|
|
207
207
|
const plugin = fieldTypes && fieldTypes[field.type];
|
|
208
208
|
const empty = plugin && plugin.isEmpty ? plugin.isEmpty(value) : isValueEmpty(value, field);
|
|
209
209
|
if (isRequired && empty) {
|
|
210
|
-
|
|
210
|
+
const fn = msg.required || ((label) => `${label} is required`);
|
|
211
|
+
return typeof fn === "function" ? fn(field.label) : fn;
|
|
211
212
|
}
|
|
212
213
|
if (empty) return null;
|
|
213
214
|
if (field.useDefaultValidators !== false) {
|
|
@@ -216,23 +217,27 @@ var runValidators = (value, field, allValues, fieldTypes, options = {}) => {
|
|
|
216
217
|
}
|
|
217
218
|
if (field.pattern && typeof value === "string") {
|
|
218
219
|
if (!field.pattern.test(value)) {
|
|
219
|
-
return field.patternMessage || "Invalid format";
|
|
220
|
+
return field.patternMessage || msg.invalidFormat || "Invalid format";
|
|
220
221
|
}
|
|
221
222
|
}
|
|
222
223
|
if (typeof value === "string") {
|
|
223
224
|
if (field.minLength != null && value.length < field.minLength) {
|
|
224
|
-
|
|
225
|
+
const fn = msg.minLength || ((min) => `Must be at least ${min} characters`);
|
|
226
|
+
return typeof fn === "function" ? fn(field.minLength) : fn;
|
|
225
227
|
}
|
|
226
228
|
if (field.maxLength != null && value.length > field.maxLength) {
|
|
227
|
-
|
|
229
|
+
const fn = msg.maxLength || ((max) => `Must be no more than ${max} characters`);
|
|
230
|
+
return typeof fn === "function" ? fn(field.maxLength) : fn;
|
|
228
231
|
}
|
|
229
232
|
}
|
|
230
233
|
if (typeof value === "number") {
|
|
231
234
|
if (field.min != null && value < field.min) {
|
|
232
|
-
|
|
235
|
+
const fn = msg.minValue || ((min) => `Must be at least ${min}`);
|
|
236
|
+
return typeof fn === "function" ? fn(field.min) : fn;
|
|
233
237
|
}
|
|
234
238
|
if (field.max != null && value > field.max) {
|
|
235
|
-
|
|
239
|
+
const fn = msg.maxValue || ((max) => `Must be no more than ${max}`);
|
|
240
|
+
return typeof fn === "function" ? fn(field.max) : fn;
|
|
236
241
|
}
|
|
237
242
|
}
|
|
238
243
|
if (field.type === "date" && isDateValueObject(value)) {
|
|
@@ -344,6 +349,8 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
|
|
|
344
349
|
// (values, { reset, rawValues }) => void | Promise
|
|
345
350
|
transformValues,
|
|
346
351
|
// (values) => values — reshape before submit
|
|
352
|
+
transformInitialValues,
|
|
353
|
+
// (rawInitialValues) => values — reshape raw data on load
|
|
347
354
|
onBeforeSubmit,
|
|
348
355
|
// (values) => boolean | Promise<boolean> — intercept submit
|
|
349
356
|
onSubmitSuccess,
|
|
@@ -438,8 +445,18 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
|
|
|
438
445
|
// string — warning alert when readOnly
|
|
439
446
|
alerts,
|
|
440
447
|
// { addAlert, readOnlyTitle, errorTitle, successTitle }
|
|
441
|
-
errors: controlledErrors
|
|
448
|
+
errors: controlledErrors,
|
|
442
449
|
// controlled validation errors
|
|
450
|
+
showReadOnlyAlert = true,
|
|
451
|
+
// show warning Alert when readOnly is true
|
|
452
|
+
showInlineAlerts = true,
|
|
453
|
+
// show inline form-level error/success Alerts
|
|
454
|
+
renderReadOnlyAlert,
|
|
455
|
+
// (context: { title, message }) => ReactNode — custom readOnly alert renderer
|
|
456
|
+
renderFieldError,
|
|
457
|
+
// (error: string, field: object) => ReactNode — custom field error renderer
|
|
458
|
+
defaultCurrency = "USD"
|
|
459
|
+
// form-level default ISO 4217 currency code for currency fields
|
|
443
460
|
} = props;
|
|
444
461
|
const {
|
|
445
462
|
onDirtyChange,
|
|
@@ -451,6 +468,23 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
|
|
|
451
468
|
const cancelButtonLabel = (labels == null ? void 0 : labels.cancel) || "Cancel";
|
|
452
469
|
const backButtonLabel = (labels == null ? void 0 : labels.back) || "Back";
|
|
453
470
|
const nextButtonLabel = (labels == null ? void 0 : labels.next) || "Next";
|
|
471
|
+
const requiredMessage = (labels == null ? void 0 : labels.required) || ((label) => `${label} is required`);
|
|
472
|
+
const invalidFormatMessage = (labels == null ? void 0 : labels.invalidFormat) || "Invalid format";
|
|
473
|
+
const minLengthMessage = (labels == null ? void 0 : labels.minLength) || ((min) => `Must be at least ${min} characters`);
|
|
474
|
+
const maxLengthMessage = (labels == null ? void 0 : labels.maxLength) || ((max) => `Must be no more than ${max} characters`);
|
|
475
|
+
const minValueMessage = (labels == null ? void 0 : labels.minValue) || ((min) => `Must be at least ${min}`);
|
|
476
|
+
const maxValueMessage = (labels == null ? void 0 : labels.maxValue) || ((max) => `Must be no more than ${max}`);
|
|
477
|
+
const dependentPropertiesLabel = (labels == null ? void 0 : labels.dependentProperties) || "Dependent properties";
|
|
478
|
+
const repeaterAddLabel = (labels == null ? void 0 : labels.repeaterAdd) || "Add";
|
|
479
|
+
const repeaterRemoveLabel = (labels == null ? void 0 : labels.repeaterRemove) || "Remove";
|
|
480
|
+
const validationMessages = labels ? {
|
|
481
|
+
required: requiredMessage,
|
|
482
|
+
invalidFormat: invalidFormatMessage,
|
|
483
|
+
minLength: minLengthMessage,
|
|
484
|
+
maxLength: maxLengthMessage,
|
|
485
|
+
minValue: minValueMessage,
|
|
486
|
+
maxValue: maxValueMessage
|
|
487
|
+
} : void 0;
|
|
454
488
|
const addAlert = alerts == null ? void 0 : alerts.addAlert;
|
|
455
489
|
const readOnlyTitle = (alerts == null ? void 0 : alerts.readOnlyTitle) || "Read Only";
|
|
456
490
|
const errorTitle = (alerts == null ? void 0 : alerts.errorTitle) || "Error";
|
|
@@ -480,12 +514,27 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
|
|
|
480
514
|
prevSuccessRef.current = formSuccess;
|
|
481
515
|
}, [addAlert, formSuccess, successTitle]);
|
|
482
516
|
const computeInitialValues = () => {
|
|
517
|
+
const resolved = transformInitialValues && initialValues ? transformInitialValues(initialValues) : initialValues;
|
|
483
518
|
const vals = {};
|
|
484
519
|
for (const field of fields) {
|
|
485
520
|
if (field.type === "display" || field.type === "crmPropertyList" || field.type === "crmAssociationPropertyList") continue;
|
|
521
|
+
if (field.type === "fieldGroup" && field.items && field.fields) {
|
|
522
|
+
for (const item of field.items) {
|
|
523
|
+
const subFields = field.fields(item);
|
|
524
|
+
for (const sf of subFields) {
|
|
525
|
+
const plugin2 = fieldTypes && fieldTypes[sf.type];
|
|
526
|
+
const emptyValue2 = plugin2 && plugin2.getEmptyValue ? plugin2.getEmptyValue() : getEmptyValue(sf);
|
|
527
|
+
let init2 = resolved && resolved[sf.name] !== void 0 ? resolved[sf.name] : sf.defaultValue !== void 0 ? sf.defaultValue : emptyValue2;
|
|
528
|
+
if (sf.transformIn) init2 = sf.transformIn(init2);
|
|
529
|
+
vals[sf.name] = init2;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
continue;
|
|
533
|
+
}
|
|
486
534
|
const plugin = fieldTypes && fieldTypes[field.type];
|
|
487
535
|
const emptyValue = plugin && plugin.getEmptyValue ? plugin.getEmptyValue() : getEmptyValue(field);
|
|
488
|
-
|
|
536
|
+
let init = resolved && resolved[field.name] !== void 0 ? resolved[field.name] : field.defaultValue !== void 0 ? field.defaultValue : emptyValue;
|
|
537
|
+
if (field.transformIn) init = field.transformIn(init);
|
|
489
538
|
vals[field.name] = init;
|
|
490
539
|
}
|
|
491
540
|
return vals;
|
|
@@ -518,7 +567,14 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
|
|
|
518
567
|
formErrorsRef.current = formErrors;
|
|
519
568
|
const fieldByName = useMemo(() => {
|
|
520
569
|
const map = /* @__PURE__ */ new Map();
|
|
521
|
-
for (const field of fields)
|
|
570
|
+
for (const field of fields) {
|
|
571
|
+
map.set(field.name, field);
|
|
572
|
+
if (field.type === "fieldGroup" && field.items && field.fields) {
|
|
573
|
+
for (const item of field.items) {
|
|
574
|
+
for (const sf of field.fields(item)) map.set(sf.name, sf);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
}
|
|
522
578
|
return map;
|
|
523
579
|
}, [fields]);
|
|
524
580
|
const isDev = typeof process === "undefined" || !process.env || process.env.NODE_ENV !== "production";
|
|
@@ -689,7 +745,7 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
|
|
|
689
745
|
const rowValues = { ...allValues, [field.name]: rows };
|
|
690
746
|
subFields.forEach((subField) => {
|
|
691
747
|
if (subField.visible && !subField.visible(rowValues)) return;
|
|
692
|
-
const err = runValidators(row == null ? void 0 : row[subField.name], subField, rowValues, fieldTypes);
|
|
748
|
+
const err = runValidators(row == null ? void 0 : row[subField.name], subField, rowValues, fieldTypes, { messages: validationMessages });
|
|
693
749
|
if (!err) return;
|
|
694
750
|
const key = getRepeaterErrorKey(field.name, rowIdx, subField.name);
|
|
695
751
|
errors[key] = err;
|
|
@@ -716,9 +772,9 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
|
|
|
716
772
|
);
|
|
717
773
|
return repeaterResult.errors[name] || null;
|
|
718
774
|
}
|
|
719
|
-
return runValidators(value != null ? value : formValues[name], field, formValues, fieldTypes);
|
|
775
|
+
return runValidators(value != null ? value : formValues[name], field, formValues, fieldTypes, { messages: validationMessages });
|
|
720
776
|
},
|
|
721
|
-
[fieldByName, formValues, validateRepeaterField, fieldTypes]
|
|
777
|
+
[fieldByName, formValues, validateRepeaterField, fieldTypes, validationMessages]
|
|
722
778
|
);
|
|
723
779
|
const validateVisibleFields = useCallback(
|
|
724
780
|
(fieldSubset) => {
|
|
@@ -734,7 +790,7 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
|
|
|
734
790
|
}
|
|
735
791
|
continue;
|
|
736
792
|
}
|
|
737
|
-
const err = runValidators(formValues[field.name], field, formValues, fieldTypes);
|
|
793
|
+
const err = runValidators(formValues[field.name], field, formValues, fieldTypes, { messages: validationMessages });
|
|
738
794
|
if (err) {
|
|
739
795
|
errors[field.name] = err;
|
|
740
796
|
hasErrors = true;
|
|
@@ -742,14 +798,14 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
|
|
|
742
798
|
}
|
|
743
799
|
return { errors, hasErrors };
|
|
744
800
|
},
|
|
745
|
-
[visibleFields, formValues, validateRepeaterField, fieldTypes]
|
|
801
|
+
[visibleFields, formValues, validateRepeaterField, fieldTypes, validationMessages]
|
|
746
802
|
);
|
|
747
803
|
const runAsyncValidation = useCallback(
|
|
748
804
|
(name, value) => {
|
|
749
805
|
const field = fieldByName.get(name);
|
|
750
806
|
if (!field || field.type === "repeater") return null;
|
|
751
807
|
const val = value != null ? value : formValues[name];
|
|
752
|
-
const syncError = runValidators(val, field, formValues, fieldTypes, { includeCustomValidators: false });
|
|
808
|
+
const syncError = runValidators(val, field, formValues, fieldTypes, { includeCustomValidators: false, messages: validationMessages });
|
|
753
809
|
const prevController = asyncAbortRef.current.get(name);
|
|
754
810
|
if (prevController) prevController.abort();
|
|
755
811
|
asyncAbortRef.current.delete(name);
|
|
@@ -940,23 +996,27 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
|
|
|
940
996
|
);
|
|
941
997
|
const handleFieldInput = useCallback(
|
|
942
998
|
(name, value) => {
|
|
999
|
+
handleFieldChange(name, value);
|
|
943
1000
|
if (!validateOnChange) return;
|
|
944
1001
|
const err = validateField(name, value);
|
|
945
1002
|
updateErrors({ [name]: err });
|
|
946
1003
|
},
|
|
947
|
-
[validateOnChange, validateField, updateErrors]
|
|
1004
|
+
[validateOnChange, validateField, updateErrors, handleFieldChange]
|
|
948
1005
|
);
|
|
949
1006
|
const handleFieldBlur = useCallback(
|
|
950
1007
|
(name, value) => {
|
|
951
|
-
if (!validateOnBlur) return;
|
|
952
1008
|
const resolvedValue = value != null ? value : formValuesRef.current[name];
|
|
1009
|
+
if (value != null && value !== formValuesRef.current[name]) {
|
|
1010
|
+
handleFieldChange(name, value);
|
|
1011
|
+
}
|
|
1012
|
+
if (!validateOnBlur) return;
|
|
953
1013
|
const err = validateField(name, resolvedValue);
|
|
954
1014
|
updateErrors({ [name]: err });
|
|
955
1015
|
if (!err) {
|
|
956
1016
|
triggerAsyncValidation(name, resolvedValue);
|
|
957
1017
|
}
|
|
958
1018
|
},
|
|
959
|
-
[validateOnBlur, validateField, updateErrors, triggerAsyncValidation]
|
|
1019
|
+
[validateOnBlur, validateField, updateErrors, triggerAsyncValidation, handleFieldChange]
|
|
960
1020
|
);
|
|
961
1021
|
const handleSubmit = useCallback(
|
|
962
1022
|
async (e) => {
|
|
@@ -989,8 +1049,17 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
|
|
|
989
1049
|
const rawValues = {};
|
|
990
1050
|
for (const key of Object.keys(formValues)) {
|
|
991
1051
|
const f = fieldByName.get(key);
|
|
992
|
-
if (f && (f.type === "display" || f.type === "crmPropertyList" || f.type === "crmAssociationPropertyList")) continue;
|
|
993
|
-
rawValues[key] = formValues[key];
|
|
1052
|
+
if (f && (f.type === "display" || f.type === "crmPropertyList" || f.type === "crmAssociationPropertyList" || f.type === "fieldGroup")) continue;
|
|
1053
|
+
rawValues[key] = f && f.transformOut ? f.transformOut(formValues[key]) : formValues[key];
|
|
1054
|
+
}
|
|
1055
|
+
for (const f of fields) {
|
|
1056
|
+
if (f.type !== "fieldGroup" || !f.items || !f.fields) continue;
|
|
1057
|
+
for (const item of f.items) {
|
|
1058
|
+
for (const sf of f.fields(item)) {
|
|
1059
|
+
if (formValues[sf.name] === void 0) continue;
|
|
1060
|
+
rawValues[sf.name] = sf.transformOut ? sf.transformOut(formValues[sf.name]) : formValues[sf.name];
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
994
1063
|
}
|
|
995
1064
|
const submitValues = transformValues ? transformValues(rawValues) : rawValues;
|
|
996
1065
|
if (onBeforeSubmit) {
|
|
@@ -1118,6 +1187,12 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
|
|
|
1118
1187
|
[replaceErrors]
|
|
1119
1188
|
);
|
|
1120
1189
|
const renderField = (field) => {
|
|
1190
|
+
const fieldError = formErrors[field.name] || null;
|
|
1191
|
+
const rendered = renderFieldInner(field);
|
|
1192
|
+
if (!renderFieldError || !fieldError) return rendered;
|
|
1193
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, rendered, renderFieldError(fieldError, field));
|
|
1194
|
+
};
|
|
1195
|
+
const renderFieldInner = (field) => {
|
|
1121
1196
|
const fieldValue = formValues[field.name];
|
|
1122
1197
|
const fieldError = formErrors[field.name] || null;
|
|
1123
1198
|
const hasError = !!fieldError;
|
|
@@ -1127,10 +1202,125 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
|
|
|
1127
1202
|
const fieldOnChange = field.debounce ? (v) => handleDebouncedFieldChange(field.name, v) : (v) => handleFieldChange(field.name, v);
|
|
1128
1203
|
if (field.type === "display") {
|
|
1129
1204
|
if (field.render) {
|
|
1130
|
-
return field.render({
|
|
1205
|
+
return field.render({
|
|
1206
|
+
allValues: formValues,
|
|
1207
|
+
setFieldValue: (name, value) => handleFieldChange(name, value),
|
|
1208
|
+
setFieldError: (name, message) => updateErrors({ [name]: message })
|
|
1209
|
+
});
|
|
1131
1210
|
}
|
|
1132
1211
|
return null;
|
|
1133
1212
|
}
|
|
1213
|
+
if (field.type === "fieldGroup") {
|
|
1214
|
+
const items = field.items || [];
|
|
1215
|
+
const fieldsFn = field.fields;
|
|
1216
|
+
if (!fieldsFn) return null;
|
|
1217
|
+
const groupColumns = field.columns || 1;
|
|
1218
|
+
const showItemLabel = field.showItemLabel !== false;
|
|
1219
|
+
return /* @__PURE__ */ React.createElement(Flex, { direction: "column", gap: "xs" }, field.label && /* @__PURE__ */ React.createElement(Text, { format: { fontWeight: "demibold" } }, field.label), field.description && /* @__PURE__ */ React.createElement(Text, { variant: "microcopy" }, field.description), items.map((item, itemIdx) => {
|
|
1220
|
+
const subFields = fieldsFn(item);
|
|
1221
|
+
return /* @__PURE__ */ React.createElement(Flex, { key: item.key || itemIdx, direction: "row", gap: "xs", align: "end" }, showItemLabel && item.label && /* @__PURE__ */ React.createElement(Box, { flex: 1 }, itemIdx === 0 ? /* @__PURE__ */ React.createElement(
|
|
1222
|
+
Input,
|
|
1223
|
+
{
|
|
1224
|
+
name: `_fieldGroup-label-${field.name}-${itemIdx}`,
|
|
1225
|
+
label: "\xA0",
|
|
1226
|
+
value: item.label,
|
|
1227
|
+
readOnly: true,
|
|
1228
|
+
disabled: true
|
|
1229
|
+
}
|
|
1230
|
+
) : /* @__PURE__ */ React.createElement(
|
|
1231
|
+
Input,
|
|
1232
|
+
{
|
|
1233
|
+
name: `_fieldGroup-label-${field.name}-${itemIdx}`,
|
|
1234
|
+
value: item.label,
|
|
1235
|
+
readOnly: true,
|
|
1236
|
+
disabled: true
|
|
1237
|
+
}
|
|
1238
|
+
)), subFields.map((sf) => {
|
|
1239
|
+
const sfValue = formValues[sf.name];
|
|
1240
|
+
const sfError = formErrors[sf.name] || null;
|
|
1241
|
+
const sfLabel = itemIdx === 0 ? sf.label : void 0;
|
|
1242
|
+
const sfReadOnly = sf.readOnly || formReadOnly;
|
|
1243
|
+
const sfDisabled = disabled || sf.disabled || formReadOnly;
|
|
1244
|
+
const sfOnChange = sf.debounce ? (v) => handleDebouncedFieldChange(sf.name, v) : (v) => handleFieldChange(sf.name, v);
|
|
1245
|
+
const sfProps = {
|
|
1246
|
+
name: sf.name,
|
|
1247
|
+
label: sfLabel,
|
|
1248
|
+
placeholder: sf.placeholder,
|
|
1249
|
+
description: itemIdx === 0 ? sf.description : void 0,
|
|
1250
|
+
readOnly: sfReadOnly,
|
|
1251
|
+
disabled: sfDisabled,
|
|
1252
|
+
error: !!sfError,
|
|
1253
|
+
validationMessage: sfError || void 0,
|
|
1254
|
+
...sf.fieldProps || {}
|
|
1255
|
+
};
|
|
1256
|
+
let sfElement;
|
|
1257
|
+
switch (sf.type) {
|
|
1258
|
+
case "select":
|
|
1259
|
+
sfElement = /* @__PURE__ */ React.createElement(
|
|
1260
|
+
Select,
|
|
1261
|
+
{
|
|
1262
|
+
...sfProps,
|
|
1263
|
+
value: sfValue,
|
|
1264
|
+
options: resolveOptions(sf, formValues),
|
|
1265
|
+
onChange: sfOnChange
|
|
1266
|
+
}
|
|
1267
|
+
);
|
|
1268
|
+
break;
|
|
1269
|
+
case "number":
|
|
1270
|
+
sfElement = /* @__PURE__ */ React.createElement(
|
|
1271
|
+
NumberInput,
|
|
1272
|
+
{
|
|
1273
|
+
...sfProps,
|
|
1274
|
+
value: sfValue,
|
|
1275
|
+
onChange: sfOnChange,
|
|
1276
|
+
onBlur: (v) => handleFieldBlur(sf.name, v)
|
|
1277
|
+
}
|
|
1278
|
+
);
|
|
1279
|
+
break;
|
|
1280
|
+
case "toggle":
|
|
1281
|
+
sfElement = /* @__PURE__ */ React.createElement(
|
|
1282
|
+
Toggle,
|
|
1283
|
+
{
|
|
1284
|
+
name: sf.name,
|
|
1285
|
+
label: sfLabel || sf.label,
|
|
1286
|
+
checked: !!sfValue,
|
|
1287
|
+
size: sf.size || "md",
|
|
1288
|
+
labelDisplay: sf.labelDisplay || "top",
|
|
1289
|
+
readonly: sfReadOnly,
|
|
1290
|
+
disabled: sfDisabled,
|
|
1291
|
+
onChange: sfOnChange,
|
|
1292
|
+
...sf.fieldProps || {}
|
|
1293
|
+
}
|
|
1294
|
+
);
|
|
1295
|
+
break;
|
|
1296
|
+
case "time":
|
|
1297
|
+
sfElement = /* @__PURE__ */ React.createElement(
|
|
1298
|
+
TimeInput,
|
|
1299
|
+
{
|
|
1300
|
+
...sfProps,
|
|
1301
|
+
value: sfValue,
|
|
1302
|
+
interval: sf.interval,
|
|
1303
|
+
onChange: sfOnChange,
|
|
1304
|
+
onBlur: (v) => handleFieldBlur(sf.name, v)
|
|
1305
|
+
}
|
|
1306
|
+
);
|
|
1307
|
+
break;
|
|
1308
|
+
default:
|
|
1309
|
+
sfElement = /* @__PURE__ */ React.createElement(
|
|
1310
|
+
Input,
|
|
1311
|
+
{
|
|
1312
|
+
...sfProps,
|
|
1313
|
+
value: sfValue || "",
|
|
1314
|
+
onChange: sfOnChange,
|
|
1315
|
+
onInput: (v) => handleFieldInput(sf.name, v),
|
|
1316
|
+
onBlur: (v) => handleFieldBlur(sf.name, v)
|
|
1317
|
+
}
|
|
1318
|
+
);
|
|
1319
|
+
}
|
|
1320
|
+
return /* @__PURE__ */ React.createElement(Box, { key: sf.name, flex: 1 }, sfElement);
|
|
1321
|
+
}));
|
|
1322
|
+
}));
|
|
1323
|
+
}
|
|
1134
1324
|
if (field.type === "crmPropertyList") {
|
|
1135
1325
|
return /* @__PURE__ */ React.createElement(
|
|
1136
1326
|
CrmPropertyList,
|
|
@@ -1184,7 +1374,7 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
|
|
|
1184
1374
|
readOnly: isReadOnly,
|
|
1185
1375
|
disabled: isDisabled,
|
|
1186
1376
|
error: hasError,
|
|
1187
|
-
validationMessage: fieldError || void 0,
|
|
1377
|
+
validationMessage: renderFieldError ? void 0 : fieldError || void 0,
|
|
1188
1378
|
...field.loading || validatingFields[field.name] ? { loading: true } : {},
|
|
1189
1379
|
...field.fieldProps || {}
|
|
1190
1380
|
};
|
|
@@ -1254,7 +1444,7 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
|
|
|
1254
1444
|
CurrencyInput,
|
|
1255
1445
|
{
|
|
1256
1446
|
...commonProps,
|
|
1257
|
-
currency: field.currency ||
|
|
1447
|
+
currency: field.currency || defaultCurrency,
|
|
1258
1448
|
value: fieldValue,
|
|
1259
1449
|
min: field.min,
|
|
1260
1450
|
max: field.max,
|
|
@@ -1432,8 +1622,8 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
|
|
|
1432
1622
|
const renderRemoveControl = repeaterProps.renderRemove;
|
|
1433
1623
|
const renderMoveUpControl = repeaterProps.renderMoveUp;
|
|
1434
1624
|
const renderMoveDownControl = repeaterProps.renderMoveDown;
|
|
1435
|
-
const addLabel = repeaterProps.addLabel ||
|
|
1436
|
-
const removeLabel = repeaterProps.removeLabel ||
|
|
1625
|
+
const addLabel = repeaterProps.addLabel || repeaterAddLabel;
|
|
1626
|
+
const removeLabel = repeaterProps.removeLabel || repeaterRemoveLabel;
|
|
1437
1627
|
const moveUpLabel = repeaterProps.moveUpLabel || "Up";
|
|
1438
1628
|
const moveDownLabel = repeaterProps.moveDownLabel || "Down";
|
|
1439
1629
|
const canEditRows = !isReadOnly && !isDisabled;
|
|
@@ -1467,7 +1657,7 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
|
|
|
1467
1657
|
};
|
|
1468
1658
|
const validateSubField = (rowIdx, subField, subValue, nextRows) => {
|
|
1469
1659
|
const rowValues = { ...formValues, [field.name]: nextRows };
|
|
1470
|
-
const err = runValidators(subValue, subField, rowValues, fieldTypes);
|
|
1660
|
+
const err = runValidators(subValue, subField, rowValues, fieldTypes, { messages: validationMessages });
|
|
1471
1661
|
setRepeaterSubFieldError(field.name, rowIdx, subField.name, err);
|
|
1472
1662
|
};
|
|
1473
1663
|
const handleSubFieldChange = (rowIdx, subField, subValue) => {
|
|
@@ -1585,7 +1775,7 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
|
|
|
1585
1775
|
const renderDependentGroup = (parentField, dependents) => {
|
|
1586
1776
|
const firstWithLabel = dependents.find((f) => getDependsOnLabel(f)) || dependents[0];
|
|
1587
1777
|
const firstWithMessage = dependents.find((f) => getDependsOnMessage(f)) || dependents[0];
|
|
1588
|
-
const groupLabel = getDependsOnLabel(firstWithLabel) ||
|
|
1778
|
+
const groupLabel = getDependsOnLabel(firstWithLabel) || dependentPropertiesLabel;
|
|
1589
1779
|
const rawMessage = getDependsOnMessage(firstWithMessage);
|
|
1590
1780
|
const tooltipMessage = typeof rawMessage === "function" ? rawMessage(parentField.label) : rawMessage || "";
|
|
1591
1781
|
return /* @__PURE__ */ React.createElement(Tile, { key: `dep-${parentField.name}`, compact: true }, /* @__PURE__ */ React.createElement(Flex, { direction: "column", gap }, /* @__PURE__ */ React.createElement(Flex, { direction: "row", align: "center", gap: "xs" }, /* @__PURE__ */ React.createElement(Text, { format: { fontWeight: "demibold" } }, groupLabel, " ", tooltipMessage && /* @__PURE__ */ React.createElement(Link, { inline: true, variant: "dark", overlay: /* @__PURE__ */ React.createElement(Tooltip, null, tooltipMessage) }, /* @__PURE__ */ React.createElement(Icon, { name: "info" })))), renderFieldSubset(dependents)));
|
|
@@ -1675,38 +1865,19 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
|
|
|
1675
1865
|
}
|
|
1676
1866
|
return elements;
|
|
1677
1867
|
};
|
|
1678
|
-
const
|
|
1868
|
+
const renderSingleColumnLayout = (fieldSubset) => {
|
|
1679
1869
|
const fieldList = fieldSubset || visibleFields;
|
|
1680
|
-
const rows = [];
|
|
1681
|
-
let i = 0;
|
|
1682
|
-
while (i < fieldList.length) {
|
|
1683
|
-
const field = fieldList[i];
|
|
1684
|
-
if (field.width === "half" && i + 1 < fieldList.length && fieldList[i + 1].width === "half" && !getDependsOnName(field)) {
|
|
1685
|
-
rows.push({ type: "pair", fields: [fieldList[i], fieldList[i + 1]] });
|
|
1686
|
-
i += 2;
|
|
1687
|
-
} else {
|
|
1688
|
-
rows.push({ type: "single", field });
|
|
1689
|
-
i++;
|
|
1690
|
-
}
|
|
1691
|
-
}
|
|
1692
1870
|
const elements = [];
|
|
1693
1871
|
const processedDeps = /* @__PURE__ */ new Set();
|
|
1694
|
-
for (const
|
|
1695
|
-
if (
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
elements.push(
|
|
1703
|
-
/* @__PURE__ */ React.createElement(React.Fragment, { key: field.name }, renderField(field))
|
|
1704
|
-
);
|
|
1705
|
-
const dependents = getDependents(field);
|
|
1706
|
-
if (dependents.length > 0) {
|
|
1707
|
-
for (const dep of dependents) processedDeps.add(dep.name);
|
|
1708
|
-
elements.push(renderDependentGroup(field, dependents));
|
|
1709
|
-
}
|
|
1872
|
+
for (const field of fieldList) {
|
|
1873
|
+
if (processedDeps.has(field.name)) continue;
|
|
1874
|
+
elements.push(
|
|
1875
|
+
/* @__PURE__ */ React.createElement(React.Fragment, { key: field.name }, renderField(field))
|
|
1876
|
+
);
|
|
1877
|
+
const dependents = getDependents(field);
|
|
1878
|
+
if (dependents.length > 0) {
|
|
1879
|
+
for (const dep of dependents) processedDeps.add(dep.name);
|
|
1880
|
+
elements.push(renderDependentGroup(field, dependents));
|
|
1710
1881
|
}
|
|
1711
1882
|
}
|
|
1712
1883
|
return elements;
|
|
@@ -1717,10 +1888,20 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
|
|
|
1717
1888
|
let batch = [];
|
|
1718
1889
|
const flushBatch = () => {
|
|
1719
1890
|
if (batch.length === 0) return;
|
|
1720
|
-
|
|
1721
|
-
|
|
1891
|
+
if (maxColumns) {
|
|
1892
|
+
const chunks = Array.from(
|
|
1893
|
+
{ length: Math.ceil(batch.length / maxColumns) },
|
|
1894
|
+
(_, i) => batch.slice(i * maxColumns, i * maxColumns + maxColumns)
|
|
1895
|
+
);
|
|
1896
|
+
for (const chunk of chunks) {
|
|
1897
|
+
const remainder = maxColumns - chunk.length;
|
|
1898
|
+
elements.push(
|
|
1899
|
+
/* @__PURE__ */ React.createElement(Flex, { key: `ag-${chunk[0].name}`, direction: "row", gap }, chunk.map((f) => /* @__PURE__ */ React.createElement(Box, { key: f.name, flex: 1 }, renderField(f))), remainder > 0 && /* @__PURE__ */ React.createElement(Box, { flex: remainder }))
|
|
1900
|
+
);
|
|
1901
|
+
}
|
|
1902
|
+
} else {
|
|
1722
1903
|
elements.push(
|
|
1723
|
-
/* @__PURE__ */ React.createElement(AutoGrid, { key: `ag-${
|
|
1904
|
+
/* @__PURE__ */ React.createElement(AutoGrid, { key: `ag-${batch[0].name}`, columnWidth, flexible: true, gap }, batch.map((f) => /* @__PURE__ */ React.createElement(React.Fragment, { key: f.name }, renderField(f))))
|
|
1724
1905
|
);
|
|
1725
1906
|
}
|
|
1726
1907
|
batch = [];
|
|
@@ -1779,7 +1960,7 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
|
|
|
1779
1960
|
if (layout && fieldSubset === visibleFields) return renderExplicitLayout();
|
|
1780
1961
|
if (columnWidth) return renderAutoGridLayout(fieldSubset);
|
|
1781
1962
|
if (columns > 1) return renderGridLayout(fieldSubset);
|
|
1782
|
-
return
|
|
1963
|
+
return renderSingleColumnLayout(fieldSubset);
|
|
1783
1964
|
};
|
|
1784
1965
|
const renderSections = () => {
|
|
1785
1966
|
const hasSections = Array.isArray(sections) && sections.length > 0;
|
|
@@ -1792,7 +1973,8 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
|
|
|
1792
1973
|
for (const sec of sections) {
|
|
1793
1974
|
const sectionFields = sec.fields ? visibleFields.filter((f) => sec.fields.includes(f.name)) : [];
|
|
1794
1975
|
if (sectionFields.length === 0) continue;
|
|
1795
|
-
const
|
|
1976
|
+
const sectionContext = { values: formValues, errors: formErrors };
|
|
1977
|
+
const accordionContent = /* @__PURE__ */ React.createElement(Flex, { direction: "column", gap }, sec.renderBefore && sec.renderBefore(sectionContext), renderFieldSubset(sectionFields), sec.renderAfter && sec.renderAfter(sectionContext));
|
|
1796
1978
|
const accordion = /* @__PURE__ */ React.createElement(
|
|
1797
1979
|
Accordion,
|
|
1798
1980
|
{
|
|
@@ -1885,7 +2067,7 @@ var FormBuilder = forwardRef(function FormBuilder2(props, ref) {
|
|
|
1885
2067
|
currentStep,
|
|
1886
2068
|
stepNames: steps.map((s) => s.title)
|
|
1887
2069
|
}
|
|
1888
|
-
), formReadOnly && readOnlyMessage && /* @__PURE__ */ React.createElement(Alert, { title: readOnlyTitle, variant: "warning" }, readOnlyMessage), !addAlert && formError && /* @__PURE__ */ React.createElement(Alert, { title: errorTitle, variant: "danger" }, typeof formError === "string" ? formError : void 0), !addAlert && formSuccess && /* @__PURE__ */ React.createElement(Alert, { title: successTitle, variant: "success" }, formSuccess), isMultiStep && steps[currentStep] && steps[currentStep].render ? steps[currentStep].render({
|
|
2070
|
+
), showReadOnlyAlert && formReadOnly && readOnlyMessage && (renderReadOnlyAlert ? renderReadOnlyAlert({ title: readOnlyTitle, message: readOnlyMessage }) : /* @__PURE__ */ React.createElement(Alert, { title: readOnlyTitle, variant: "warning" }, readOnlyMessage)), showInlineAlerts && !addAlert && formError && /* @__PURE__ */ React.createElement(Alert, { title: errorTitle, variant: "danger" }, typeof formError === "string" ? formError : void 0), showInlineAlerts && !addAlert && formSuccess && /* @__PURE__ */ React.createElement(Alert, { title: successTitle, variant: "success" }, formSuccess), isMultiStep && steps[currentStep] && steps[currentStep].render ? steps[currentStep].render({
|
|
1889
2071
|
values: formValues,
|
|
1890
2072
|
goNext: handleNext,
|
|
1891
2073
|
goBack: handleBack,
|