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.js
CHANGED
|
@@ -132,7 +132,6 @@ var runDefaultFieldValidator = (value, field, allValues) => {
|
|
|
132
132
|
if (!isTimeValueObject(value)) return `${errorPrefix} has an invalid time`;
|
|
133
133
|
break;
|
|
134
134
|
case "datetime": {
|
|
135
|
-
if (isDateValueObject(value)) break;
|
|
136
135
|
if (!isPlainObject(value)) return `${errorPrefix} has an invalid date/time`;
|
|
137
136
|
const hasDate = value.date !== void 0;
|
|
138
137
|
const hasTime = value.time !== void 0;
|
|
@@ -198,12 +197,14 @@ var collectAsyncValidatorPromises = (value, field, allValues, context) => {
|
|
|
198
197
|
};
|
|
199
198
|
var runValidators = (value, field, allValues, fieldTypes, options = {}) => {
|
|
200
199
|
const includeCustomValidators = options.includeCustomValidators !== false;
|
|
201
|
-
|
|
200
|
+
const msg = options.messages || {};
|
|
201
|
+
if (field.type === "display" || field.type === "crmPropertyList" || field.type === "crmAssociationPropertyList" || field.type === "fieldGroup") return null;
|
|
202
202
|
const isRequired = resolveRequired(field, allValues);
|
|
203
203
|
const plugin = fieldTypes && fieldTypes[field.type];
|
|
204
204
|
const empty = plugin && plugin.isEmpty ? plugin.isEmpty(value) : isValueEmpty(value, field);
|
|
205
205
|
if (isRequired && empty) {
|
|
206
|
-
|
|
206
|
+
const fn = msg.required || ((label) => `${label} is required`);
|
|
207
|
+
return typeof fn === "function" ? fn(field.label) : fn;
|
|
207
208
|
}
|
|
208
209
|
if (empty) return null;
|
|
209
210
|
if (field.useDefaultValidators !== false) {
|
|
@@ -212,23 +213,27 @@ var runValidators = (value, field, allValues, fieldTypes, options = {}) => {
|
|
|
212
213
|
}
|
|
213
214
|
if (field.pattern && typeof value === "string") {
|
|
214
215
|
if (!field.pattern.test(value)) {
|
|
215
|
-
return field.patternMessage || "Invalid format";
|
|
216
|
+
return field.patternMessage || msg.invalidFormat || "Invalid format";
|
|
216
217
|
}
|
|
217
218
|
}
|
|
218
219
|
if (typeof value === "string") {
|
|
219
220
|
if (field.minLength != null && value.length < field.minLength) {
|
|
220
|
-
|
|
221
|
+
const fn = msg.minLength || ((min) => `Must be at least ${min} characters`);
|
|
222
|
+
return typeof fn === "function" ? fn(field.minLength) : fn;
|
|
221
223
|
}
|
|
222
224
|
if (field.maxLength != null && value.length > field.maxLength) {
|
|
223
|
-
|
|
225
|
+
const fn = msg.maxLength || ((max) => `Must be no more than ${max} characters`);
|
|
226
|
+
return typeof fn === "function" ? fn(field.maxLength) : fn;
|
|
224
227
|
}
|
|
225
228
|
}
|
|
226
229
|
if (typeof value === "number") {
|
|
227
230
|
if (field.min != null && value < field.min) {
|
|
228
|
-
|
|
231
|
+
const fn = msg.minValue || ((min) => `Must be at least ${min}`);
|
|
232
|
+
return typeof fn === "function" ? fn(field.min) : fn;
|
|
229
233
|
}
|
|
230
234
|
if (field.max != null && value > field.max) {
|
|
231
|
-
|
|
235
|
+
const fn = msg.maxValue || ((max) => `Must be no more than ${max}`);
|
|
236
|
+
return typeof fn === "function" ? fn(field.max) : fn;
|
|
232
237
|
}
|
|
233
238
|
}
|
|
234
239
|
if (field.type === "date" && isDateValueObject(value)) {
|
|
@@ -340,6 +345,8 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
|
|
|
340
345
|
// (values, { reset, rawValues }) => void | Promise
|
|
341
346
|
transformValues,
|
|
342
347
|
// (values) => values — reshape before submit
|
|
348
|
+
transformInitialValues,
|
|
349
|
+
// (rawInitialValues) => values — reshape raw data on load
|
|
343
350
|
onBeforeSubmit,
|
|
344
351
|
// (values) => boolean | Promise<boolean> — intercept submit
|
|
345
352
|
onSubmitSuccess,
|
|
@@ -434,8 +441,18 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
|
|
|
434
441
|
// string — warning alert when readOnly
|
|
435
442
|
alerts,
|
|
436
443
|
// { addAlert, readOnlyTitle, errorTitle, successTitle }
|
|
437
|
-
errors: controlledErrors
|
|
444
|
+
errors: controlledErrors,
|
|
438
445
|
// controlled validation errors
|
|
446
|
+
showReadOnlyAlert = true,
|
|
447
|
+
// show warning Alert when readOnly is true
|
|
448
|
+
showInlineAlerts = true,
|
|
449
|
+
// show inline form-level error/success Alerts
|
|
450
|
+
renderReadOnlyAlert,
|
|
451
|
+
// (context: { title, message }) => ReactNode — custom readOnly alert renderer
|
|
452
|
+
renderFieldError,
|
|
453
|
+
// (error: string, field: object) => ReactNode — custom field error renderer
|
|
454
|
+
defaultCurrency = "USD"
|
|
455
|
+
// form-level default ISO 4217 currency code for currency fields
|
|
439
456
|
} = props;
|
|
440
457
|
const {
|
|
441
458
|
onDirtyChange,
|
|
@@ -447,6 +464,23 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
|
|
|
447
464
|
const cancelButtonLabel = (labels == null ? void 0 : labels.cancel) || "Cancel";
|
|
448
465
|
const backButtonLabel = (labels == null ? void 0 : labels.back) || "Back";
|
|
449
466
|
const nextButtonLabel = (labels == null ? void 0 : labels.next) || "Next";
|
|
467
|
+
const requiredMessage = (labels == null ? void 0 : labels.required) || ((label) => `${label} is required`);
|
|
468
|
+
const invalidFormatMessage = (labels == null ? void 0 : labels.invalidFormat) || "Invalid format";
|
|
469
|
+
const minLengthMessage = (labels == null ? void 0 : labels.minLength) || ((min) => `Must be at least ${min} characters`);
|
|
470
|
+
const maxLengthMessage = (labels == null ? void 0 : labels.maxLength) || ((max) => `Must be no more than ${max} characters`);
|
|
471
|
+
const minValueMessage = (labels == null ? void 0 : labels.minValue) || ((min) => `Must be at least ${min}`);
|
|
472
|
+
const maxValueMessage = (labels == null ? void 0 : labels.maxValue) || ((max) => `Must be no more than ${max}`);
|
|
473
|
+
const dependentPropertiesLabel = (labels == null ? void 0 : labels.dependentProperties) || "Dependent properties";
|
|
474
|
+
const repeaterAddLabel = (labels == null ? void 0 : labels.repeaterAdd) || "Add";
|
|
475
|
+
const repeaterRemoveLabel = (labels == null ? void 0 : labels.repeaterRemove) || "Remove";
|
|
476
|
+
const validationMessages = labels ? {
|
|
477
|
+
required: requiredMessage,
|
|
478
|
+
invalidFormat: invalidFormatMessage,
|
|
479
|
+
minLength: minLengthMessage,
|
|
480
|
+
maxLength: maxLengthMessage,
|
|
481
|
+
minValue: minValueMessage,
|
|
482
|
+
maxValue: maxValueMessage
|
|
483
|
+
} : void 0;
|
|
450
484
|
const addAlert = alerts == null ? void 0 : alerts.addAlert;
|
|
451
485
|
const readOnlyTitle = (alerts == null ? void 0 : alerts.readOnlyTitle) || "Read Only";
|
|
452
486
|
const errorTitle = (alerts == null ? void 0 : alerts.errorTitle) || "Error";
|
|
@@ -476,12 +510,27 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
|
|
|
476
510
|
prevSuccessRef.current = formSuccess;
|
|
477
511
|
}, [addAlert, formSuccess, successTitle]);
|
|
478
512
|
const computeInitialValues = () => {
|
|
513
|
+
const resolved = transformInitialValues && initialValues ? transformInitialValues(initialValues) : initialValues;
|
|
479
514
|
const vals = {};
|
|
480
515
|
for (const field of fields) {
|
|
481
516
|
if (field.type === "display" || field.type === "crmPropertyList" || field.type === "crmAssociationPropertyList") continue;
|
|
517
|
+
if (field.type === "fieldGroup" && field.items && field.fields) {
|
|
518
|
+
for (const item of field.items) {
|
|
519
|
+
const subFields = field.fields(item);
|
|
520
|
+
for (const sf of subFields) {
|
|
521
|
+
const plugin2 = fieldTypes && fieldTypes[sf.type];
|
|
522
|
+
const emptyValue2 = plugin2 && plugin2.getEmptyValue ? plugin2.getEmptyValue() : getEmptyValue(sf);
|
|
523
|
+
let init2 = resolved && resolved[sf.name] !== void 0 ? resolved[sf.name] : sf.defaultValue !== void 0 ? sf.defaultValue : emptyValue2;
|
|
524
|
+
if (sf.transformIn) init2 = sf.transformIn(init2);
|
|
525
|
+
vals[sf.name] = init2;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
continue;
|
|
529
|
+
}
|
|
482
530
|
const plugin = fieldTypes && fieldTypes[field.type];
|
|
483
531
|
const emptyValue = plugin && plugin.getEmptyValue ? plugin.getEmptyValue() : getEmptyValue(field);
|
|
484
|
-
|
|
532
|
+
let init = resolved && resolved[field.name] !== void 0 ? resolved[field.name] : field.defaultValue !== void 0 ? field.defaultValue : emptyValue;
|
|
533
|
+
if (field.transformIn) init = field.transformIn(init);
|
|
485
534
|
vals[field.name] = init;
|
|
486
535
|
}
|
|
487
536
|
return vals;
|
|
@@ -514,7 +563,14 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
|
|
|
514
563
|
formErrorsRef.current = formErrors;
|
|
515
564
|
const fieldByName = (0, import_react.useMemo)(() => {
|
|
516
565
|
const map = /* @__PURE__ */ new Map();
|
|
517
|
-
for (const field of fields)
|
|
566
|
+
for (const field of fields) {
|
|
567
|
+
map.set(field.name, field);
|
|
568
|
+
if (field.type === "fieldGroup" && field.items && field.fields) {
|
|
569
|
+
for (const item of field.items) {
|
|
570
|
+
for (const sf of field.fields(item)) map.set(sf.name, sf);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
}
|
|
518
574
|
return map;
|
|
519
575
|
}, [fields]);
|
|
520
576
|
const isDev = typeof process === "undefined" || !process.env || process.env.NODE_ENV !== "production";
|
|
@@ -685,7 +741,7 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
|
|
|
685
741
|
const rowValues = { ...allValues, [field.name]: rows };
|
|
686
742
|
subFields.forEach((subField) => {
|
|
687
743
|
if (subField.visible && !subField.visible(rowValues)) return;
|
|
688
|
-
const err = runValidators(row == null ? void 0 : row[subField.name], subField, rowValues, fieldTypes);
|
|
744
|
+
const err = runValidators(row == null ? void 0 : row[subField.name], subField, rowValues, fieldTypes, { messages: validationMessages });
|
|
689
745
|
if (!err) return;
|
|
690
746
|
const key = getRepeaterErrorKey(field.name, rowIdx, subField.name);
|
|
691
747
|
errors[key] = err;
|
|
@@ -712,9 +768,9 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
|
|
|
712
768
|
);
|
|
713
769
|
return repeaterResult.errors[name] || null;
|
|
714
770
|
}
|
|
715
|
-
return runValidators(value != null ? value : formValues[name], field, formValues, fieldTypes);
|
|
771
|
+
return runValidators(value != null ? value : formValues[name], field, formValues, fieldTypes, { messages: validationMessages });
|
|
716
772
|
},
|
|
717
|
-
[fieldByName, formValues, validateRepeaterField, fieldTypes]
|
|
773
|
+
[fieldByName, formValues, validateRepeaterField, fieldTypes, validationMessages]
|
|
718
774
|
);
|
|
719
775
|
const validateVisibleFields = (0, import_react.useCallback)(
|
|
720
776
|
(fieldSubset) => {
|
|
@@ -730,7 +786,7 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
|
|
|
730
786
|
}
|
|
731
787
|
continue;
|
|
732
788
|
}
|
|
733
|
-
const err = runValidators(formValues[field.name], field, formValues, fieldTypes);
|
|
789
|
+
const err = runValidators(formValues[field.name], field, formValues, fieldTypes, { messages: validationMessages });
|
|
734
790
|
if (err) {
|
|
735
791
|
errors[field.name] = err;
|
|
736
792
|
hasErrors = true;
|
|
@@ -738,14 +794,14 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
|
|
|
738
794
|
}
|
|
739
795
|
return { errors, hasErrors };
|
|
740
796
|
},
|
|
741
|
-
[visibleFields, formValues, validateRepeaterField, fieldTypes]
|
|
797
|
+
[visibleFields, formValues, validateRepeaterField, fieldTypes, validationMessages]
|
|
742
798
|
);
|
|
743
799
|
const runAsyncValidation = (0, import_react.useCallback)(
|
|
744
800
|
(name, value) => {
|
|
745
801
|
const field = fieldByName.get(name);
|
|
746
802
|
if (!field || field.type === "repeater") return null;
|
|
747
803
|
const val = value != null ? value : formValues[name];
|
|
748
|
-
const syncError = runValidators(val, field, formValues, fieldTypes, { includeCustomValidators: false });
|
|
804
|
+
const syncError = runValidators(val, field, formValues, fieldTypes, { includeCustomValidators: false, messages: validationMessages });
|
|
749
805
|
const prevController = asyncAbortRef.current.get(name);
|
|
750
806
|
if (prevController) prevController.abort();
|
|
751
807
|
asyncAbortRef.current.delete(name);
|
|
@@ -936,23 +992,27 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
|
|
|
936
992
|
);
|
|
937
993
|
const handleFieldInput = (0, import_react.useCallback)(
|
|
938
994
|
(name, value) => {
|
|
995
|
+
handleFieldChange(name, value);
|
|
939
996
|
if (!validateOnChange) return;
|
|
940
997
|
const err = validateField(name, value);
|
|
941
998
|
updateErrors({ [name]: err });
|
|
942
999
|
},
|
|
943
|
-
[validateOnChange, validateField, updateErrors]
|
|
1000
|
+
[validateOnChange, validateField, updateErrors, handleFieldChange]
|
|
944
1001
|
);
|
|
945
1002
|
const handleFieldBlur = (0, import_react.useCallback)(
|
|
946
1003
|
(name, value) => {
|
|
947
|
-
if (!validateOnBlur) return;
|
|
948
1004
|
const resolvedValue = value != null ? value : formValuesRef.current[name];
|
|
1005
|
+
if (value != null && value !== formValuesRef.current[name]) {
|
|
1006
|
+
handleFieldChange(name, value);
|
|
1007
|
+
}
|
|
1008
|
+
if (!validateOnBlur) return;
|
|
949
1009
|
const err = validateField(name, resolvedValue);
|
|
950
1010
|
updateErrors({ [name]: err });
|
|
951
1011
|
if (!err) {
|
|
952
1012
|
triggerAsyncValidation(name, resolvedValue);
|
|
953
1013
|
}
|
|
954
1014
|
},
|
|
955
|
-
[validateOnBlur, validateField, updateErrors, triggerAsyncValidation]
|
|
1015
|
+
[validateOnBlur, validateField, updateErrors, triggerAsyncValidation, handleFieldChange]
|
|
956
1016
|
);
|
|
957
1017
|
const handleSubmit = (0, import_react.useCallback)(
|
|
958
1018
|
async (e) => {
|
|
@@ -985,8 +1045,17 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
|
|
|
985
1045
|
const rawValues = {};
|
|
986
1046
|
for (const key of Object.keys(formValues)) {
|
|
987
1047
|
const f = fieldByName.get(key);
|
|
988
|
-
if (f && (f.type === "display" || f.type === "crmPropertyList" || f.type === "crmAssociationPropertyList")) continue;
|
|
989
|
-
rawValues[key] = formValues[key];
|
|
1048
|
+
if (f && (f.type === "display" || f.type === "crmPropertyList" || f.type === "crmAssociationPropertyList" || f.type === "fieldGroup")) continue;
|
|
1049
|
+
rawValues[key] = f && f.transformOut ? f.transformOut(formValues[key]) : formValues[key];
|
|
1050
|
+
}
|
|
1051
|
+
for (const f of fields) {
|
|
1052
|
+
if (f.type !== "fieldGroup" || !f.items || !f.fields) continue;
|
|
1053
|
+
for (const item of f.items) {
|
|
1054
|
+
for (const sf of f.fields(item)) {
|
|
1055
|
+
if (formValues[sf.name] === void 0) continue;
|
|
1056
|
+
rawValues[sf.name] = sf.transformOut ? sf.transformOut(formValues[sf.name]) : formValues[sf.name];
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
990
1059
|
}
|
|
991
1060
|
const submitValues = transformValues ? transformValues(rawValues) : rawValues;
|
|
992
1061
|
if (onBeforeSubmit) {
|
|
@@ -1114,6 +1183,12 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
|
|
|
1114
1183
|
[replaceErrors]
|
|
1115
1184
|
);
|
|
1116
1185
|
const renderField = (field) => {
|
|
1186
|
+
const fieldError = formErrors[field.name] || null;
|
|
1187
|
+
const rendered = renderFieldInner(field);
|
|
1188
|
+
if (!renderFieldError || !fieldError) return rendered;
|
|
1189
|
+
return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, rendered, renderFieldError(fieldError, field));
|
|
1190
|
+
};
|
|
1191
|
+
const renderFieldInner = (field) => {
|
|
1117
1192
|
const fieldValue = formValues[field.name];
|
|
1118
1193
|
const fieldError = formErrors[field.name] || null;
|
|
1119
1194
|
const hasError = !!fieldError;
|
|
@@ -1123,10 +1198,125 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
|
|
|
1123
1198
|
const fieldOnChange = field.debounce ? (v) => handleDebouncedFieldChange(field.name, v) : (v) => handleFieldChange(field.name, v);
|
|
1124
1199
|
if (field.type === "display") {
|
|
1125
1200
|
if (field.render) {
|
|
1126
|
-
return field.render({
|
|
1201
|
+
return field.render({
|
|
1202
|
+
allValues: formValues,
|
|
1203
|
+
setFieldValue: (name, value) => handleFieldChange(name, value),
|
|
1204
|
+
setFieldError: (name, message) => updateErrors({ [name]: message })
|
|
1205
|
+
});
|
|
1127
1206
|
}
|
|
1128
1207
|
return null;
|
|
1129
1208
|
}
|
|
1209
|
+
if (field.type === "fieldGroup") {
|
|
1210
|
+
const items = field.items || [];
|
|
1211
|
+
const fieldsFn = field.fields;
|
|
1212
|
+
if (!fieldsFn) return null;
|
|
1213
|
+
const groupColumns = field.columns || 1;
|
|
1214
|
+
const showItemLabel = field.showItemLabel !== false;
|
|
1215
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "column", gap: "xs" }, field.label && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Text, { format: { fontWeight: "demibold" } }, field.label), field.description && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Text, { variant: "microcopy" }, field.description), items.map((item, itemIdx) => {
|
|
1216
|
+
const subFields = fieldsFn(item);
|
|
1217
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { key: item.key || itemIdx, direction: "row", gap: "xs", align: "end" }, showItemLabel && item.label && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Box, { flex: 1 }, itemIdx === 0 ? /* @__PURE__ */ import_react.default.createElement(
|
|
1218
|
+
import_ui_extensions.Input,
|
|
1219
|
+
{
|
|
1220
|
+
name: `_fieldGroup-label-${field.name}-${itemIdx}`,
|
|
1221
|
+
label: "\xA0",
|
|
1222
|
+
value: item.label,
|
|
1223
|
+
readOnly: true,
|
|
1224
|
+
disabled: true
|
|
1225
|
+
}
|
|
1226
|
+
) : /* @__PURE__ */ import_react.default.createElement(
|
|
1227
|
+
import_ui_extensions.Input,
|
|
1228
|
+
{
|
|
1229
|
+
name: `_fieldGroup-label-${field.name}-${itemIdx}`,
|
|
1230
|
+
value: item.label,
|
|
1231
|
+
readOnly: true,
|
|
1232
|
+
disabled: true
|
|
1233
|
+
}
|
|
1234
|
+
)), subFields.map((sf) => {
|
|
1235
|
+
const sfValue = formValues[sf.name];
|
|
1236
|
+
const sfError = formErrors[sf.name] || null;
|
|
1237
|
+
const sfLabel = itemIdx === 0 ? sf.label : void 0;
|
|
1238
|
+
const sfReadOnly = sf.readOnly || formReadOnly;
|
|
1239
|
+
const sfDisabled = disabled || sf.disabled || formReadOnly;
|
|
1240
|
+
const sfOnChange = sf.debounce ? (v) => handleDebouncedFieldChange(sf.name, v) : (v) => handleFieldChange(sf.name, v);
|
|
1241
|
+
const sfProps = {
|
|
1242
|
+
name: sf.name,
|
|
1243
|
+
label: sfLabel,
|
|
1244
|
+
placeholder: sf.placeholder,
|
|
1245
|
+
description: itemIdx === 0 ? sf.description : void 0,
|
|
1246
|
+
readOnly: sfReadOnly,
|
|
1247
|
+
disabled: sfDisabled,
|
|
1248
|
+
error: !!sfError,
|
|
1249
|
+
validationMessage: sfError || void 0,
|
|
1250
|
+
...sf.fieldProps || {}
|
|
1251
|
+
};
|
|
1252
|
+
let sfElement;
|
|
1253
|
+
switch (sf.type) {
|
|
1254
|
+
case "select":
|
|
1255
|
+
sfElement = /* @__PURE__ */ import_react.default.createElement(
|
|
1256
|
+
import_ui_extensions.Select,
|
|
1257
|
+
{
|
|
1258
|
+
...sfProps,
|
|
1259
|
+
value: sfValue,
|
|
1260
|
+
options: resolveOptions(sf, formValues),
|
|
1261
|
+
onChange: sfOnChange
|
|
1262
|
+
}
|
|
1263
|
+
);
|
|
1264
|
+
break;
|
|
1265
|
+
case "number":
|
|
1266
|
+
sfElement = /* @__PURE__ */ import_react.default.createElement(
|
|
1267
|
+
import_ui_extensions.NumberInput,
|
|
1268
|
+
{
|
|
1269
|
+
...sfProps,
|
|
1270
|
+
value: sfValue,
|
|
1271
|
+
onChange: sfOnChange,
|
|
1272
|
+
onBlur: (v) => handleFieldBlur(sf.name, v)
|
|
1273
|
+
}
|
|
1274
|
+
);
|
|
1275
|
+
break;
|
|
1276
|
+
case "toggle":
|
|
1277
|
+
sfElement = /* @__PURE__ */ import_react.default.createElement(
|
|
1278
|
+
import_ui_extensions.Toggle,
|
|
1279
|
+
{
|
|
1280
|
+
name: sf.name,
|
|
1281
|
+
label: sfLabel || sf.label,
|
|
1282
|
+
checked: !!sfValue,
|
|
1283
|
+
size: sf.size || "md",
|
|
1284
|
+
labelDisplay: sf.labelDisplay || "top",
|
|
1285
|
+
readonly: sfReadOnly,
|
|
1286
|
+
disabled: sfDisabled,
|
|
1287
|
+
onChange: sfOnChange,
|
|
1288
|
+
...sf.fieldProps || {}
|
|
1289
|
+
}
|
|
1290
|
+
);
|
|
1291
|
+
break;
|
|
1292
|
+
case "time":
|
|
1293
|
+
sfElement = /* @__PURE__ */ import_react.default.createElement(
|
|
1294
|
+
import_ui_extensions.TimeInput,
|
|
1295
|
+
{
|
|
1296
|
+
...sfProps,
|
|
1297
|
+
value: sfValue,
|
|
1298
|
+
interval: sf.interval,
|
|
1299
|
+
onChange: sfOnChange,
|
|
1300
|
+
onBlur: (v) => handleFieldBlur(sf.name, v)
|
|
1301
|
+
}
|
|
1302
|
+
);
|
|
1303
|
+
break;
|
|
1304
|
+
default:
|
|
1305
|
+
sfElement = /* @__PURE__ */ import_react.default.createElement(
|
|
1306
|
+
import_ui_extensions.Input,
|
|
1307
|
+
{
|
|
1308
|
+
...sfProps,
|
|
1309
|
+
value: sfValue || "",
|
|
1310
|
+
onChange: sfOnChange,
|
|
1311
|
+
onInput: (v) => handleFieldInput(sf.name, v),
|
|
1312
|
+
onBlur: (v) => handleFieldBlur(sf.name, v)
|
|
1313
|
+
}
|
|
1314
|
+
);
|
|
1315
|
+
}
|
|
1316
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Box, { key: sf.name, flex: 1 }, sfElement);
|
|
1317
|
+
}));
|
|
1318
|
+
}));
|
|
1319
|
+
}
|
|
1130
1320
|
if (field.type === "crmPropertyList") {
|
|
1131
1321
|
return /* @__PURE__ */ import_react.default.createElement(
|
|
1132
1322
|
import_crm.CrmPropertyList,
|
|
@@ -1180,7 +1370,7 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
|
|
|
1180
1370
|
readOnly: isReadOnly,
|
|
1181
1371
|
disabled: isDisabled,
|
|
1182
1372
|
error: hasError,
|
|
1183
|
-
validationMessage: fieldError || void 0,
|
|
1373
|
+
validationMessage: renderFieldError ? void 0 : fieldError || void 0,
|
|
1184
1374
|
...field.loading || validatingFields[field.name] ? { loading: true } : {},
|
|
1185
1375
|
...field.fieldProps || {}
|
|
1186
1376
|
};
|
|
@@ -1250,7 +1440,7 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
|
|
|
1250
1440
|
import_ui_extensions.CurrencyInput,
|
|
1251
1441
|
{
|
|
1252
1442
|
...commonProps,
|
|
1253
|
-
currency: field.currency ||
|
|
1443
|
+
currency: field.currency || defaultCurrency,
|
|
1254
1444
|
value: fieldValue,
|
|
1255
1445
|
min: field.min,
|
|
1256
1446
|
max: field.max,
|
|
@@ -1428,8 +1618,8 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
|
|
|
1428
1618
|
const renderRemoveControl = repeaterProps.renderRemove;
|
|
1429
1619
|
const renderMoveUpControl = repeaterProps.renderMoveUp;
|
|
1430
1620
|
const renderMoveDownControl = repeaterProps.renderMoveDown;
|
|
1431
|
-
const addLabel = repeaterProps.addLabel ||
|
|
1432
|
-
const removeLabel = repeaterProps.removeLabel ||
|
|
1621
|
+
const addLabel = repeaterProps.addLabel || repeaterAddLabel;
|
|
1622
|
+
const removeLabel = repeaterProps.removeLabel || repeaterRemoveLabel;
|
|
1433
1623
|
const moveUpLabel = repeaterProps.moveUpLabel || "Up";
|
|
1434
1624
|
const moveDownLabel = repeaterProps.moveDownLabel || "Down";
|
|
1435
1625
|
const canEditRows = !isReadOnly && !isDisabled;
|
|
@@ -1463,7 +1653,7 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
|
|
|
1463
1653
|
};
|
|
1464
1654
|
const validateSubField = (rowIdx, subField, subValue, nextRows) => {
|
|
1465
1655
|
const rowValues = { ...formValues, [field.name]: nextRows };
|
|
1466
|
-
const err = runValidators(subValue, subField, rowValues, fieldTypes);
|
|
1656
|
+
const err = runValidators(subValue, subField, rowValues, fieldTypes, { messages: validationMessages });
|
|
1467
1657
|
setRepeaterSubFieldError(field.name, rowIdx, subField.name, err);
|
|
1468
1658
|
};
|
|
1469
1659
|
const handleSubFieldChange = (rowIdx, subField, subValue) => {
|
|
@@ -1581,7 +1771,7 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
|
|
|
1581
1771
|
const renderDependentGroup = (parentField, dependents) => {
|
|
1582
1772
|
const firstWithLabel = dependents.find((f) => getDependsOnLabel(f)) || dependents[0];
|
|
1583
1773
|
const firstWithMessage = dependents.find((f) => getDependsOnMessage(f)) || dependents[0];
|
|
1584
|
-
const groupLabel = getDependsOnLabel(firstWithLabel) ||
|
|
1774
|
+
const groupLabel = getDependsOnLabel(firstWithLabel) || dependentPropertiesLabel;
|
|
1585
1775
|
const rawMessage = getDependsOnMessage(firstWithMessage);
|
|
1586
1776
|
const tooltipMessage = typeof rawMessage === "function" ? rawMessage(parentField.label) : rawMessage || "";
|
|
1587
1777
|
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Tile, { key: `dep-${parentField.name}`, compact: true }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "column", gap }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", align: "center", gap: "xs" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Text, { format: { fontWeight: "demibold" } }, groupLabel, " ", tooltipMessage && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Link, { inline: true, variant: "dark", overlay: /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Tooltip, null, tooltipMessage) }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Icon, { name: "info" })))), renderFieldSubset(dependents)));
|
|
@@ -1671,38 +1861,19 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
|
|
|
1671
1861
|
}
|
|
1672
1862
|
return elements;
|
|
1673
1863
|
};
|
|
1674
|
-
const
|
|
1864
|
+
const renderSingleColumnLayout = (fieldSubset) => {
|
|
1675
1865
|
const fieldList = fieldSubset || visibleFields;
|
|
1676
|
-
const rows = [];
|
|
1677
|
-
let i = 0;
|
|
1678
|
-
while (i < fieldList.length) {
|
|
1679
|
-
const field = fieldList[i];
|
|
1680
|
-
if (field.width === "half" && i + 1 < fieldList.length && fieldList[i + 1].width === "half" && !getDependsOnName(field)) {
|
|
1681
|
-
rows.push({ type: "pair", fields: [fieldList[i], fieldList[i + 1]] });
|
|
1682
|
-
i += 2;
|
|
1683
|
-
} else {
|
|
1684
|
-
rows.push({ type: "single", field });
|
|
1685
|
-
i++;
|
|
1686
|
-
}
|
|
1687
|
-
}
|
|
1688
1866
|
const elements = [];
|
|
1689
1867
|
const processedDeps = /* @__PURE__ */ new Set();
|
|
1690
|
-
for (const
|
|
1691
|
-
if (
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
elements.push(
|
|
1699
|
-
/* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, { key: field.name }, renderField(field))
|
|
1700
|
-
);
|
|
1701
|
-
const dependents = getDependents(field);
|
|
1702
|
-
if (dependents.length > 0) {
|
|
1703
|
-
for (const dep of dependents) processedDeps.add(dep.name);
|
|
1704
|
-
elements.push(renderDependentGroup(field, dependents));
|
|
1705
|
-
}
|
|
1868
|
+
for (const field of fieldList) {
|
|
1869
|
+
if (processedDeps.has(field.name)) continue;
|
|
1870
|
+
elements.push(
|
|
1871
|
+
/* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, { key: field.name }, renderField(field))
|
|
1872
|
+
);
|
|
1873
|
+
const dependents = getDependents(field);
|
|
1874
|
+
if (dependents.length > 0) {
|
|
1875
|
+
for (const dep of dependents) processedDeps.add(dep.name);
|
|
1876
|
+
elements.push(renderDependentGroup(field, dependents));
|
|
1706
1877
|
}
|
|
1707
1878
|
}
|
|
1708
1879
|
return elements;
|
|
@@ -1713,10 +1884,20 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
|
|
|
1713
1884
|
let batch = [];
|
|
1714
1885
|
const flushBatch = () => {
|
|
1715
1886
|
if (batch.length === 0) return;
|
|
1716
|
-
|
|
1717
|
-
|
|
1887
|
+
if (maxColumns) {
|
|
1888
|
+
const chunks = Array.from(
|
|
1889
|
+
{ length: Math.ceil(batch.length / maxColumns) },
|
|
1890
|
+
(_, i) => batch.slice(i * maxColumns, i * maxColumns + maxColumns)
|
|
1891
|
+
);
|
|
1892
|
+
for (const chunk of chunks) {
|
|
1893
|
+
const remainder = maxColumns - chunk.length;
|
|
1894
|
+
elements.push(
|
|
1895
|
+
/* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { key: `ag-${chunk[0].name}`, direction: "row", gap }, chunk.map((f) => /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Box, { key: f.name, flex: 1 }, renderField(f))), remainder > 0 && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Box, { flex: remainder }))
|
|
1896
|
+
);
|
|
1897
|
+
}
|
|
1898
|
+
} else {
|
|
1718
1899
|
elements.push(
|
|
1719
|
-
/* @__PURE__ */ import_react.default.createElement(import_ui_extensions.AutoGrid, { key: `ag-${
|
|
1900
|
+
/* @__PURE__ */ import_react.default.createElement(import_ui_extensions.AutoGrid, { key: `ag-${batch[0].name}`, columnWidth, flexible: true, gap }, batch.map((f) => /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, { key: f.name }, renderField(f))))
|
|
1720
1901
|
);
|
|
1721
1902
|
}
|
|
1722
1903
|
batch = [];
|
|
@@ -1775,7 +1956,7 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
|
|
|
1775
1956
|
if (layout && fieldSubset === visibleFields) return renderExplicitLayout();
|
|
1776
1957
|
if (columnWidth) return renderAutoGridLayout(fieldSubset);
|
|
1777
1958
|
if (columns > 1) return renderGridLayout(fieldSubset);
|
|
1778
|
-
return
|
|
1959
|
+
return renderSingleColumnLayout(fieldSubset);
|
|
1779
1960
|
};
|
|
1780
1961
|
const renderSections = () => {
|
|
1781
1962
|
const hasSections = Array.isArray(sections) && sections.length > 0;
|
|
@@ -1788,7 +1969,8 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
|
|
|
1788
1969
|
for (const sec of sections) {
|
|
1789
1970
|
const sectionFields = sec.fields ? visibleFields.filter((f) => sec.fields.includes(f.name)) : [];
|
|
1790
1971
|
if (sectionFields.length === 0) continue;
|
|
1791
|
-
const
|
|
1972
|
+
const sectionContext = { values: formValues, errors: formErrors };
|
|
1973
|
+
const accordionContent = /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "column", gap }, sec.renderBefore && sec.renderBefore(sectionContext), renderFieldSubset(sectionFields), sec.renderAfter && sec.renderAfter(sectionContext));
|
|
1792
1974
|
const accordion = /* @__PURE__ */ import_react.default.createElement(
|
|
1793
1975
|
import_ui_extensions.Accordion,
|
|
1794
1976
|
{
|
|
@@ -1881,7 +2063,7 @@ var FormBuilder = (0, import_react.forwardRef)(function FormBuilder2(props, ref)
|
|
|
1881
2063
|
currentStep,
|
|
1882
2064
|
stepNames: steps.map((s) => s.title)
|
|
1883
2065
|
}
|
|
1884
|
-
), formReadOnly && readOnlyMessage && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Alert, { title: readOnlyTitle, variant: "warning" }, readOnlyMessage), !addAlert && formError && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Alert, { title: errorTitle, variant: "danger" }, typeof formError === "string" ? formError : void 0), !addAlert && formSuccess && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Alert, { title: successTitle, variant: "success" }, formSuccess), isMultiStep && steps[currentStep] && steps[currentStep].render ? steps[currentStep].render({
|
|
2066
|
+
), showReadOnlyAlert && formReadOnly && readOnlyMessage && (renderReadOnlyAlert ? renderReadOnlyAlert({ title: readOnlyTitle, message: readOnlyMessage }) : /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Alert, { title: readOnlyTitle, variant: "warning" }, readOnlyMessage)), showInlineAlerts && !addAlert && formError && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Alert, { title: errorTitle, variant: "danger" }, typeof formError === "string" ? formError : void 0), showInlineAlerts && !addAlert && formSuccess && /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Alert, { title: successTitle, variant: "success" }, formSuccess), isMultiStep && steps[currentStep] && steps[currentStep].render ? steps[currentStep].render({
|
|
1885
2067
|
values: formValues,
|
|
1886
2068
|
goNext: handleNext,
|
|
1887
2069
|
goBack: handleBack,
|