hs-uix 1.4.0 → 1.5.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 +20 -2
- package/common-components.d.ts +55 -0
- package/dist/common-components.js +260 -0
- package/dist/common-components.mjs +221 -0
- package/dist/datatable.js +74 -38
- package/dist/datatable.mjs +74 -38
- package/dist/form.js +204 -76
- package/dist/form.mjs +204 -76
- package/dist/index.js +486 -114
- package/dist/index.mjs +481 -114
- package/dist/utils.js +269 -0
- package/dist/utils.mjs +230 -0
- package/index.d.ts +21 -0
- package/package.json +14 -2
- package/utils.d.ts +59 -0
package/dist/index.js
CHANGED
|
@@ -29,8 +29,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
29
29
|
// src/index.js
|
|
30
30
|
var src_exports = {};
|
|
31
31
|
__export(src_exports, {
|
|
32
|
+
AutoStatusTag: () => AutoStatusTag,
|
|
33
|
+
AutoTag: () => AutoTag,
|
|
32
34
|
DataTable: () => DataTable,
|
|
33
35
|
FormBuilder: () => FormBuilder,
|
|
36
|
+
createStatusTagSortComparator: () => createStatusTagSortComparator,
|
|
37
|
+
getAutoStatusTagVariant: () => getAutoStatusTagVariant,
|
|
38
|
+
getAutoTagVariant: () => getAutoTagVariant,
|
|
34
39
|
useFormPrefill: () => useFormPrefill
|
|
35
40
|
});
|
|
36
41
|
module.exports = __toCommonJS(src_exports);
|
|
@@ -311,7 +316,9 @@ var DataTable = ({
|
|
|
311
316
|
const initialSortState = (0, import_react.useMemo)(() => {
|
|
312
317
|
return normalizeSortState(columns, defaultSort);
|
|
313
318
|
}, [columns, defaultSort]);
|
|
314
|
-
const [internalSearchTerm, setInternalSearchTerm] = (0, import_react.useState)(
|
|
319
|
+
const [internalSearchTerm, setInternalSearchTerm] = (0, import_react.useState)(
|
|
320
|
+
() => serverSide && searchValue != null ? searchValue : ""
|
|
321
|
+
);
|
|
315
322
|
const [internalFilterValues, setInternalFilterValues] = (0, import_react.useState)(() => {
|
|
316
323
|
const init = {};
|
|
317
324
|
filters.forEach((f) => {
|
|
@@ -322,7 +329,16 @@ var DataTable = ({
|
|
|
322
329
|
const [internalSortState, setInternalSortState] = (0, import_react.useState)(initialSortState);
|
|
323
330
|
const [currentPage, setCurrentPage] = (0, import_react.useState)(1);
|
|
324
331
|
const [showMoreFilters, setShowMoreFilters] = (0, import_react.useState)(false);
|
|
332
|
+
const lastAppliedSearchRef = (0, import_react.useRef)(
|
|
333
|
+
serverSide && searchValue != null ? searchValue : ""
|
|
334
|
+
);
|
|
325
335
|
const searchTerm = serverSide && searchValue != null ? searchValue : internalSearchTerm;
|
|
336
|
+
(0, import_react.useEffect)(() => {
|
|
337
|
+
if (!serverSide || searchValue == null) return;
|
|
338
|
+
if (searchValue === lastAppliedSearchRef.current) return;
|
|
339
|
+
lastAppliedSearchRef.current = searchValue;
|
|
340
|
+
setInternalSearchTerm(searchValue);
|
|
341
|
+
}, [serverSide, searchValue]);
|
|
326
342
|
const filterValues = serverSide && externalFilterValues != null ? externalFilterValues : internalFilterValues;
|
|
327
343
|
const externalSortState = (0, import_react.useMemo)(
|
|
328
344
|
() => normalizeSortState(columns, externalSort),
|
|
@@ -356,15 +372,16 @@ var DataTable = ({
|
|
|
356
372
|
const handleSearchChange = (0, import_react.useCallback)((term) => {
|
|
357
373
|
setInternalSearchTerm(term);
|
|
358
374
|
resetPage();
|
|
375
|
+
const dispatch = () => {
|
|
376
|
+
lastAppliedSearchRef.current = term;
|
|
377
|
+
fireSearchCallback(term);
|
|
378
|
+
fireParamsChange({ search: term, page: resetPageOnChange ? 1 : void 0 });
|
|
379
|
+
};
|
|
359
380
|
if (searchDebounce > 0) {
|
|
360
381
|
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
361
|
-
debounceRef.current = setTimeout(
|
|
362
|
-
fireSearchCallback(term);
|
|
363
|
-
fireParamsChange({ search: term, page: resetPageOnChange ? 1 : void 0 });
|
|
364
|
-
}, searchDebounce);
|
|
382
|
+
debounceRef.current = setTimeout(dispatch, searchDebounce);
|
|
365
383
|
} else {
|
|
366
|
-
|
|
367
|
-
fireParamsChange({ search: term, page: resetPageOnChange ? 1 : void 0 });
|
|
384
|
+
dispatch();
|
|
368
385
|
}
|
|
369
386
|
}, [searchDebounce, fireSearchCallback, fireParamsChange, resetPage, resetPageOnChange]);
|
|
370
387
|
(0, import_react.useEffect)(() => () => {
|
|
@@ -446,10 +463,23 @@ var DataTable = ({
|
|
|
446
463
|
if (serverSide) return filteredData;
|
|
447
464
|
const activeField = Object.keys(sortState).find((k) => sortState[k] !== "none");
|
|
448
465
|
if (!activeField) return filteredData;
|
|
466
|
+
const activeCol = columns.find((c) => c.field === activeField);
|
|
467
|
+
const sortOrder = Array.isArray(activeCol == null ? void 0 : activeCol.sortOrder) ? activeCol.sortOrder : null;
|
|
468
|
+
const sortOrderIndex = (val) => {
|
|
469
|
+
const idx = sortOrder.indexOf(val);
|
|
470
|
+
return idx === -1 ? sortOrder.length : idx;
|
|
471
|
+
};
|
|
449
472
|
return [...filteredData].sort((a, b) => {
|
|
450
473
|
const dir = sortState[activeField] === "ascending" ? 1 : -1;
|
|
451
474
|
const aVal = a[activeField];
|
|
452
475
|
const bVal = b[activeField];
|
|
476
|
+
if (typeof (activeCol == null ? void 0 : activeCol.sortComparator) === "function") {
|
|
477
|
+
return dir * activeCol.sortComparator(aVal, bVal, a, b);
|
|
478
|
+
}
|
|
479
|
+
if (sortOrder) {
|
|
480
|
+
const diff = sortOrderIndex(aVal) - sortOrderIndex(bVal);
|
|
481
|
+
if (diff !== 0) return dir * diff;
|
|
482
|
+
}
|
|
453
483
|
if (aVal == null && bVal == null) return 0;
|
|
454
484
|
if (aVal == null) return 1;
|
|
455
485
|
if (bVal == null) return -1;
|
|
@@ -457,7 +487,7 @@ var DataTable = ({
|
|
|
457
487
|
if (aVal > bVal) return dir;
|
|
458
488
|
return 0;
|
|
459
489
|
});
|
|
460
|
-
}, [filteredData, sortState, serverSide]);
|
|
490
|
+
}, [filteredData, sortState, serverSide, columns]);
|
|
461
491
|
const groupedData = (0, import_react.useMemo)(() => {
|
|
462
492
|
if (!groupBy) return null;
|
|
463
493
|
const source = serverSide ? data : sortedData;
|
|
@@ -509,28 +539,33 @@ var DataTable = ({
|
|
|
509
539
|
return next;
|
|
510
540
|
});
|
|
511
541
|
}, []);
|
|
512
|
-
const
|
|
513
|
-
if (!groupedData) return
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
if (expandedGroups.has(group.key)) {
|
|
518
|
-
group.rows.forEach((row) => flat.push({ type: "data", row }));
|
|
519
|
-
}
|
|
520
|
-
});
|
|
521
|
-
return flat;
|
|
522
|
-
}, [groupedData, sortedData, data, serverSide, expandedGroups]);
|
|
523
|
-
const totalItems = serverSide ? totalCount || data.length : flatRows.length;
|
|
542
|
+
const datasetRows = (0, import_react.useMemo)(() => {
|
|
543
|
+
if (!groupedData) return serverSide ? data : sortedData;
|
|
544
|
+
return groupedData.flatMap((group) => group.rows);
|
|
545
|
+
}, [groupedData, sortedData, data, serverSide]);
|
|
546
|
+
const totalItems = serverSide ? totalCount || data.length : datasetRows.length;
|
|
524
547
|
const pageCount = Math.ceil(totalItems / pageSize);
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
} else {
|
|
529
|
-
displayRows = flatRows.slice(
|
|
548
|
+
const paginatedRows = (0, import_react.useMemo)(() => {
|
|
549
|
+
if (serverSide) return datasetRows;
|
|
550
|
+
return datasetRows.slice(
|
|
530
551
|
(activePage - 1) * pageSize,
|
|
531
552
|
activePage * pageSize
|
|
532
553
|
);
|
|
533
|
-
}
|
|
554
|
+
}, [serverSide, datasetRows, activePage, pageSize]);
|
|
555
|
+
const displayRows = (0, import_react.useMemo)(() => {
|
|
556
|
+
if (!groupedData) return paginatedRows.map((row) => ({ type: "data", row }));
|
|
557
|
+
const pageRows = new Set(paginatedRows);
|
|
558
|
+
const rows = [];
|
|
559
|
+
groupedData.forEach((group) => {
|
|
560
|
+
const groupPageRows = group.rows.filter((row) => pageRows.has(row));
|
|
561
|
+
if (groupPageRows.length === 0) return;
|
|
562
|
+
rows.push({ type: "group-header", group });
|
|
563
|
+
if (expandedGroups.has(group.key)) {
|
|
564
|
+
groupPageRows.forEach((row) => rows.push({ type: "data", row }));
|
|
565
|
+
}
|
|
566
|
+
});
|
|
567
|
+
return rows;
|
|
568
|
+
}, [groupedData, paginatedRows, expandedGroups]);
|
|
534
569
|
const footerData = serverSide ? data : filteredData;
|
|
535
570
|
const activeChips = (0, import_react.useMemo)(() => {
|
|
536
571
|
const chips = [];
|
|
@@ -641,8 +676,8 @@ var DataTable = ({
|
|
|
641
676
|
return displayRows.filter((r) => r.type === "data").map((r) => r.row[rowIdField]).filter((id) => id != null);
|
|
642
677
|
}, [serverSide, data, displayRows, rowIdField]);
|
|
643
678
|
const allRowIds = (0, import_react.useMemo)(
|
|
644
|
-
() =>
|
|
645
|
-
[
|
|
679
|
+
() => datasetRows.map((row) => row[rowIdField]).filter((id) => id != null),
|
|
680
|
+
[datasetRows, rowIdField]
|
|
646
681
|
);
|
|
647
682
|
const handleSelectRow = (0, import_react.useCallback)((rowId, checked) => {
|
|
648
683
|
const next = new Set(selectedIds);
|
|
@@ -689,19 +724,25 @@ var DataTable = ({
|
|
|
689
724
|
if (row) onEditStart(row, field, currentValue);
|
|
690
725
|
}
|
|
691
726
|
}, [onEditStart, data, rowIdField]);
|
|
692
|
-
const commitEdit = (0, import_react.useCallback)((row, field, value) => {
|
|
727
|
+
const commitEdit = (0, import_react.useCallback)((row, field, value, options = {}) => {
|
|
728
|
+
const { keepEditing = false } = options;
|
|
693
729
|
const col = columns.find((c) => c.field === field);
|
|
694
730
|
if (col == null ? void 0 : col.editValidate) {
|
|
695
731
|
const result = col.editValidate(value, row);
|
|
696
732
|
if (result !== true && result !== void 0 && result !== null) {
|
|
697
733
|
setEditError(typeof result === "string" ? result : "Invalid value");
|
|
698
|
-
return;
|
|
734
|
+
return false;
|
|
699
735
|
}
|
|
700
736
|
}
|
|
701
737
|
if (onRowEdit) onRowEdit(row, field, value);
|
|
702
|
-
|
|
703
|
-
|
|
738
|
+
if (!keepEditing) {
|
|
739
|
+
setEditingCell(null);
|
|
740
|
+
setEditValue(null);
|
|
741
|
+
} else {
|
|
742
|
+
setEditValue(value);
|
|
743
|
+
}
|
|
704
744
|
setEditError(null);
|
|
745
|
+
return true;
|
|
705
746
|
}, [onRowEdit, columns]);
|
|
706
747
|
const renderEditControl = (col, row) => {
|
|
707
748
|
const type = col.editType || "text";
|
|
@@ -760,12 +801,12 @@ var DataTable = ({
|
|
|
760
801
|
case "datetime":
|
|
761
802
|
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", align: "center", gap: "xs", wrap: "nowrap" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.DateInput, { ...extra, name: `${fieldName}-date`, label: "", value: editValue == null ? void 0 : editValue.date, onChange: (val) => {
|
|
762
803
|
const next = { ...editValue, date: val };
|
|
763
|
-
|
|
764
|
-
|
|
804
|
+
handleInput(next);
|
|
805
|
+
commitEdit(row, col.field, next, { keepEditing: true });
|
|
765
806
|
}, onBlur: maybeExitDatetimeEdit }), /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.TimeInput, { ...extra.timeProps || {}, name: `${fieldName}-time`, label: "", value: editValue == null ? void 0 : editValue.time, onChange: (val) => {
|
|
766
807
|
const next = { ...editValue, time: val };
|
|
767
|
-
|
|
768
|
-
|
|
808
|
+
handleInput(next);
|
|
809
|
+
commitEdit(row, col.field, next, { keepEditing: true });
|
|
769
810
|
}, onBlur: maybeExitDatetimeEdit }));
|
|
770
811
|
case "toggle":
|
|
771
812
|
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Toggle, { ...extra, name: fieldName, label: "", checked: !!editValue, onChange: commit });
|
|
@@ -970,12 +1011,12 @@ var DataTable = ({
|
|
|
970
1011
|
}
|
|
971
1012
|
);
|
|
972
1013
|
};
|
|
973
|
-
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "column", gap: "xs" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", gap: "sm" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Box, { flex: 3 }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "column", gap: "sm" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", align: "
|
|
1014
|
+
return /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "column", gap: "xs" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", gap: "sm" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Box, { flex: 3 }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "column", gap: "sm" }, /* @__PURE__ */ import_react.default.createElement(import_ui_extensions.Flex, { direction: "row", align: "end", gap: "sm", wrap: "wrap" }, showSearch && searchFields.length > 0 && /* @__PURE__ */ import_react.default.createElement(
|
|
974
1015
|
import_ui_extensions.SearchInput,
|
|
975
1016
|
{
|
|
976
1017
|
name: "datatable-search",
|
|
977
1018
|
placeholder: searchPlaceholder,
|
|
978
|
-
value:
|
|
1019
|
+
value: internalSearchTerm,
|
|
979
1020
|
onChange: handleSearchChange
|
|
980
1021
|
}
|
|
981
1022
|
), filters.slice(0, filterInlineLimit).map(renderFilterControl), filters.length > filterInlineLimit && /* @__PURE__ */ import_react.default.createElement(
|
|
@@ -1738,9 +1779,10 @@ var FormBuilder = (0, import_react2.forwardRef)(function FormBuilder2(props, ref
|
|
|
1738
1779
|
const inputDebounceRef = (0, import_react2.useRef)(/* @__PURE__ */ new Map());
|
|
1739
1780
|
const rowKeyRef = (0, import_react2.useRef)(/* @__PURE__ */ new WeakMap());
|
|
1740
1781
|
const rowKeyCounterRef = (0, import_react2.useRef)(0);
|
|
1782
|
+
const controlledBaselineLockedRef = (0, import_react2.useRef)(false);
|
|
1741
1783
|
const initialSnapshot = (0, import_react2.useRef)(null);
|
|
1742
1784
|
if (initialSnapshot.current === null) {
|
|
1743
|
-
initialSnapshot.current = deepClone(computeInitialValues());
|
|
1785
|
+
initialSnapshot.current = deepClone(values != null ? values : computeInitialValues());
|
|
1744
1786
|
}
|
|
1745
1787
|
const formValues = values != null ? values : internalValues;
|
|
1746
1788
|
const formErrors = controlledErrors != null ? controlledErrors : internalErrors;
|
|
@@ -1752,6 +1794,10 @@ var FormBuilder = (0, import_react2.forwardRef)(function FormBuilder2(props, ref
|
|
|
1752
1794
|
const draftValuesRef = (0, import_react2.useRef)(null);
|
|
1753
1795
|
formValuesRef.current = formValues;
|
|
1754
1796
|
formErrorsRef.current = formErrors;
|
|
1797
|
+
const syncDirtyBaseline = (0, import_react2.useCallback)((nextValues) => {
|
|
1798
|
+
initialSnapshot.current = deepClone(nextValues || {});
|
|
1799
|
+
prevAutoSaveValues.current = deepClone(nextValues || {});
|
|
1800
|
+
}, []);
|
|
1755
1801
|
const fieldByName = (0, import_react2.useMemo)(() => {
|
|
1756
1802
|
const map = /* @__PURE__ */ new Map();
|
|
1757
1803
|
for (const field of fields) {
|
|
@@ -1828,6 +1874,11 @@ var FormBuilder = (0, import_react2.forwardRef)(function FormBuilder2(props, ref
|
|
|
1828
1874
|
if (autoSaveTimerRef.current) clearTimeout(autoSaveTimerRef.current);
|
|
1829
1875
|
};
|
|
1830
1876
|
}, []);
|
|
1877
|
+
(0, import_react2.useEffect)(() => {
|
|
1878
|
+
if (values == null) return;
|
|
1879
|
+
if (controlledBaselineLockedRef.current) return;
|
|
1880
|
+
syncDirtyBaseline(values);
|
|
1881
|
+
}, [values, syncDirtyBaseline]);
|
|
1831
1882
|
const isDirty = (0, import_react2.useMemo)(() => {
|
|
1832
1883
|
return !deepEqual(formValues, initialSnapshot.current);
|
|
1833
1884
|
}, [formValues]);
|
|
@@ -1946,6 +1997,50 @@ var FormBuilder = (0, import_react2.forwardRef)(function FormBuilder2(props, ref
|
|
|
1946
1997
|
},
|
|
1947
1998
|
[fieldTypes]
|
|
1948
1999
|
);
|
|
2000
|
+
const setRepeaterSubFieldError = (0, import_react2.useCallback)(
|
|
2001
|
+
(fieldName, rowIdx, subFieldName, errorMessage) => {
|
|
2002
|
+
const key = getRepeaterErrorKey(fieldName, rowIdx, subFieldName);
|
|
2003
|
+
const merged = { ...formErrorsRef.current };
|
|
2004
|
+
if (errorMessage) {
|
|
2005
|
+
merged[key] = errorMessage;
|
|
2006
|
+
} else {
|
|
2007
|
+
delete merged[key];
|
|
2008
|
+
}
|
|
2009
|
+
const subErrors = Object.keys(merged).filter((k) => k.startsWith(`${fieldName}[`)).map((k) => {
|
|
2010
|
+
const match = k.match(/\[(\d+)\]\./);
|
|
2011
|
+
const row = match ? Number(match[1]) : Number.MAX_SAFE_INTEGER;
|
|
2012
|
+
return { key: k, row };
|
|
2013
|
+
}).sort((a, b) => a.row - b.row);
|
|
2014
|
+
if (subErrors.length > 0) {
|
|
2015
|
+
const first = subErrors[0];
|
|
2016
|
+
merged[fieldName] = `Row ${first.row + 1}: ${merged[first.key]}`;
|
|
2017
|
+
} else if (!merged[fieldName] || merged[fieldName].startsWith("Row ")) {
|
|
2018
|
+
delete merged[fieldName];
|
|
2019
|
+
}
|
|
2020
|
+
replaceErrors(merged);
|
|
2021
|
+
},
|
|
2022
|
+
[replaceErrors]
|
|
2023
|
+
);
|
|
2024
|
+
const expandValidationFields = (0, import_react2.useCallback)(
|
|
2025
|
+
(fieldSubset) => {
|
|
2026
|
+
const toValidate = fieldSubset || visibleFields;
|
|
2027
|
+
const expanded = [];
|
|
2028
|
+
for (const field of toValidate) {
|
|
2029
|
+
if (field.type === "fieldGroup" && field.items && field.fields) {
|
|
2030
|
+
for (const item of field.items) {
|
|
2031
|
+
for (const subField of field.fields(item)) {
|
|
2032
|
+
if (subField.visible && !subField.visible(formValues)) continue;
|
|
2033
|
+
expanded.push(subField);
|
|
2034
|
+
}
|
|
2035
|
+
}
|
|
2036
|
+
continue;
|
|
2037
|
+
}
|
|
2038
|
+
expanded.push(field);
|
|
2039
|
+
}
|
|
2040
|
+
return expanded;
|
|
2041
|
+
},
|
|
2042
|
+
[visibleFields, formValues]
|
|
2043
|
+
);
|
|
1949
2044
|
const validateField = (0, import_react2.useCallback)(
|
|
1950
2045
|
(name, value) => {
|
|
1951
2046
|
const field = fieldByName.get(name);
|
|
@@ -1965,7 +2060,7 @@ var FormBuilder = (0, import_react2.forwardRef)(function FormBuilder2(props, ref
|
|
|
1965
2060
|
);
|
|
1966
2061
|
const validateVisibleFields = (0, import_react2.useCallback)(
|
|
1967
2062
|
(fieldSubset) => {
|
|
1968
|
-
const toValidate = fieldSubset
|
|
2063
|
+
const toValidate = expandValidationFields(fieldSubset);
|
|
1969
2064
|
const errors = {};
|
|
1970
2065
|
let hasErrors = false;
|
|
1971
2066
|
for (const field of toValidate) {
|
|
@@ -1985,52 +2080,54 @@ var FormBuilder = (0, import_react2.forwardRef)(function FormBuilder2(props, ref
|
|
|
1985
2080
|
}
|
|
1986
2081
|
return { errors, hasErrors };
|
|
1987
2082
|
},
|
|
1988
|
-
[
|
|
2083
|
+
[expandValidationFields, formValues, validateRepeaterField, fieldTypes, validationMessages]
|
|
1989
2084
|
);
|
|
1990
|
-
const
|
|
1991
|
-
(
|
|
1992
|
-
const field =
|
|
1993
|
-
if (!field || field.type === "repeater") return null;
|
|
1994
|
-
const
|
|
1995
|
-
|
|
1996
|
-
|
|
2085
|
+
const runAsyncValidationTarget = (0, import_react2.useCallback)(
|
|
2086
|
+
(target) => {
|
|
2087
|
+
const { validationKey, field, value, allValues, applyError } = target || {};
|
|
2088
|
+
if (!field || !validationKey || field.type === "repeater" || field.type === "fieldGroup") return null;
|
|
2089
|
+
const syncError = runValidators(value, field, allValues, fieldTypes, {
|
|
2090
|
+
includeCustomValidators: false,
|
|
2091
|
+
messages: validationMessages
|
|
2092
|
+
});
|
|
2093
|
+
const prevController = asyncAbortRef.current.get(validationKey);
|
|
1997
2094
|
if (prevController) prevController.abort();
|
|
1998
|
-
asyncAbortRef.current.delete(
|
|
2095
|
+
asyncAbortRef.current.delete(validationKey);
|
|
1999
2096
|
setValidatingFields((prev) => {
|
|
2000
|
-
if (!prev[
|
|
2097
|
+
if (!prev[validationKey]) return prev;
|
|
2001
2098
|
const next = { ...prev };
|
|
2002
|
-
delete next[
|
|
2099
|
+
delete next[validationKey];
|
|
2003
2100
|
return next;
|
|
2004
2101
|
});
|
|
2005
2102
|
if (syncError) return null;
|
|
2006
|
-
const version = (asyncValidationVersionRef.current.get(
|
|
2007
|
-
asyncValidationVersionRef.current.set(
|
|
2103
|
+
const version = (asyncValidationVersionRef.current.get(validationKey) || 0) + 1;
|
|
2104
|
+
asyncValidationVersionRef.current.set(validationKey, version);
|
|
2008
2105
|
const controller = typeof AbortController !== "undefined" ? new AbortController() : null;
|
|
2009
|
-
if (controller) asyncAbortRef.current.set(
|
|
2106
|
+
if (controller) asyncAbortRef.current.set(validationKey, controller);
|
|
2010
2107
|
let asyncPromises;
|
|
2011
2108
|
try {
|
|
2012
2109
|
asyncPromises = collectAsyncValidatorPromises(
|
|
2013
|
-
|
|
2110
|
+
value,
|
|
2014
2111
|
field,
|
|
2015
|
-
|
|
2112
|
+
allValues,
|
|
2016
2113
|
controller ? { signal: controller.signal } : void 0
|
|
2017
2114
|
);
|
|
2018
2115
|
} catch (err) {
|
|
2019
|
-
|
|
2116
|
+
applyError((err == null ? void 0 : err.message) || "Validation failed");
|
|
2020
2117
|
return null;
|
|
2021
2118
|
}
|
|
2022
2119
|
if (asyncPromises.length === 0) {
|
|
2023
|
-
asyncAbortRef.current.delete(
|
|
2120
|
+
asyncAbortRef.current.delete(validationKey);
|
|
2024
2121
|
return null;
|
|
2025
2122
|
}
|
|
2026
2123
|
const validationPromise = Promise.all(asyncPromises).then(
|
|
2027
2124
|
(results) => {
|
|
2028
|
-
if (asyncValidationVersionRef.current.get(
|
|
2029
|
-
asyncValidationRef.current.delete(
|
|
2030
|
-
asyncAbortRef.current.delete(
|
|
2125
|
+
if (asyncValidationVersionRef.current.get(validationKey) !== version) return;
|
|
2126
|
+
asyncValidationRef.current.delete(validationKey);
|
|
2127
|
+
asyncAbortRef.current.delete(validationKey);
|
|
2031
2128
|
setValidatingFields((prev) => {
|
|
2032
2129
|
const next = { ...prev };
|
|
2033
|
-
delete next[
|
|
2130
|
+
delete next[validationKey];
|
|
2034
2131
|
return next;
|
|
2035
2132
|
});
|
|
2036
2133
|
let err = null;
|
|
@@ -2041,50 +2138,128 @@ var FormBuilder = (0, import_react2.forwardRef)(function FormBuilder2(props, ref
|
|
|
2041
2138
|
break;
|
|
2042
2139
|
}
|
|
2043
2140
|
}
|
|
2044
|
-
|
|
2141
|
+
applyError(err);
|
|
2045
2142
|
},
|
|
2046
2143
|
(rejection) => {
|
|
2047
|
-
if (asyncValidationVersionRef.current.get(
|
|
2048
|
-
asyncValidationRef.current.delete(
|
|
2049
|
-
asyncAbortRef.current.delete(
|
|
2144
|
+
if (asyncValidationVersionRef.current.get(validationKey) !== version) return;
|
|
2145
|
+
asyncValidationRef.current.delete(validationKey);
|
|
2146
|
+
asyncAbortRef.current.delete(validationKey);
|
|
2050
2147
|
setValidatingFields((prev) => {
|
|
2051
2148
|
const next = { ...prev };
|
|
2052
|
-
delete next[
|
|
2149
|
+
delete next[validationKey];
|
|
2053
2150
|
return next;
|
|
2054
2151
|
});
|
|
2055
2152
|
if (rejection && rejection.name === "AbortError") return;
|
|
2056
|
-
|
|
2153
|
+
applyError((rejection == null ? void 0 : rejection.message) || "Validation failed");
|
|
2057
2154
|
}
|
|
2058
2155
|
);
|
|
2059
|
-
asyncValidationRef.current.set(
|
|
2060
|
-
setValidatingFields((prev) => ({ ...prev, [
|
|
2156
|
+
asyncValidationRef.current.set(validationKey, validationPromise);
|
|
2157
|
+
setValidatingFields((prev) => ({ ...prev, [validationKey]: true }));
|
|
2061
2158
|
return validationPromise;
|
|
2062
2159
|
},
|
|
2063
|
-
[
|
|
2160
|
+
[fieldTypes, validationMessages]
|
|
2064
2161
|
);
|
|
2065
|
-
const
|
|
2162
|
+
const runAsyncValidation = (0, import_react2.useCallback)(
|
|
2066
2163
|
(name, value) => {
|
|
2067
2164
|
const field = fieldByName.get(name);
|
|
2068
|
-
if (!field || field.type === "repeater") return;
|
|
2069
|
-
|
|
2165
|
+
if (!field || field.type === "repeater" || field.type === "fieldGroup") return null;
|
|
2166
|
+
return runAsyncValidationTarget({
|
|
2167
|
+
validationKey: name,
|
|
2168
|
+
field,
|
|
2169
|
+
value: value != null ? value : formValues[name],
|
|
2170
|
+
allValues: formValues,
|
|
2171
|
+
applyError: (errorMessage) => updateErrors({ [name]: errorMessage })
|
|
2172
|
+
});
|
|
2173
|
+
},
|
|
2174
|
+
[fieldByName, formValues, runAsyncValidationTarget, updateErrors]
|
|
2175
|
+
);
|
|
2176
|
+
const triggerAsyncValidationTarget = (0, import_react2.useCallback)(
|
|
2177
|
+
(target) => {
|
|
2178
|
+
if (!(target == null ? void 0 : target.field) || !target.validationKey) return;
|
|
2179
|
+
const debounceMs = target.field.validateDebounce;
|
|
2070
2180
|
if (debounceMs && debounceMs > 0) {
|
|
2071
|
-
const existing = debounceTimersRef.current.get(
|
|
2181
|
+
const existing = debounceTimersRef.current.get(target.validationKey);
|
|
2072
2182
|
if (existing) clearTimeout(existing);
|
|
2073
2183
|
const timer = setTimeout(() => {
|
|
2074
|
-
debounceTimersRef.current.delete(
|
|
2075
|
-
|
|
2184
|
+
debounceTimersRef.current.delete(target.validationKey);
|
|
2185
|
+
runAsyncValidationTarget(target);
|
|
2076
2186
|
}, debounceMs);
|
|
2077
|
-
debounceTimersRef.current.set(
|
|
2187
|
+
debounceTimersRef.current.set(target.validationKey, timer);
|
|
2078
2188
|
} else {
|
|
2079
|
-
|
|
2189
|
+
runAsyncValidationTarget(target);
|
|
2190
|
+
}
|
|
2191
|
+
},
|
|
2192
|
+
[runAsyncValidationTarget]
|
|
2193
|
+
);
|
|
2194
|
+
const triggerAsyncValidation = (0, import_react2.useCallback)(
|
|
2195
|
+
(name, value) => {
|
|
2196
|
+
const field = fieldByName.get(name);
|
|
2197
|
+
if (!field || field.type === "repeater" || field.type === "fieldGroup") return;
|
|
2198
|
+
triggerAsyncValidationTarget({
|
|
2199
|
+
validationKey: name,
|
|
2200
|
+
field,
|
|
2201
|
+
value: value != null ? value : formValuesRef.current[name],
|
|
2202
|
+
allValues: formValuesRef.current,
|
|
2203
|
+
applyError: (errorMessage) => updateErrors({ [name]: errorMessage })
|
|
2204
|
+
});
|
|
2205
|
+
},
|
|
2206
|
+
[fieldByName, triggerAsyncValidationTarget, updateErrors]
|
|
2207
|
+
);
|
|
2208
|
+
const getAsyncValidationTargets = (0, import_react2.useCallback)(
|
|
2209
|
+
(fieldSubset) => {
|
|
2210
|
+
const toValidate = fieldSubset || visibleFields;
|
|
2211
|
+
const targets = [];
|
|
2212
|
+
for (const field of toValidate) {
|
|
2213
|
+
if (field.type === "fieldGroup" && field.items && field.fields) {
|
|
2214
|
+
for (const item of field.items) {
|
|
2215
|
+
for (const subField of field.fields(item)) {
|
|
2216
|
+
if (subField.visible && !subField.visible(formValues)) continue;
|
|
2217
|
+
targets.push({
|
|
2218
|
+
validationKey: subField.name,
|
|
2219
|
+
field: subField,
|
|
2220
|
+
value: formValues[subField.name],
|
|
2221
|
+
allValues: formValues,
|
|
2222
|
+
applyError: (errorMessage) => updateErrors({ [subField.name]: errorMessage })
|
|
2223
|
+
});
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
continue;
|
|
2227
|
+
}
|
|
2228
|
+
if (field.type === "repeater") {
|
|
2229
|
+
const rows = Array.isArray(formValues[field.name]) ? formValues[field.name] : [];
|
|
2230
|
+
const subFields = field.fields || [];
|
|
2231
|
+
rows.forEach((row, rowIdx) => {
|
|
2232
|
+
const rowValues = { ...formValues, [field.name]: rows };
|
|
2233
|
+
subFields.forEach((subField) => {
|
|
2234
|
+
if (subField.visible && !subField.visible(rowValues)) return;
|
|
2235
|
+
targets.push({
|
|
2236
|
+
validationKey: getRepeaterErrorKey(field.name, rowIdx, subField.name),
|
|
2237
|
+
field: subField,
|
|
2238
|
+
value: row == null ? void 0 : row[subField.name],
|
|
2239
|
+
allValues: rowValues,
|
|
2240
|
+
applyError: (errorMessage) => setRepeaterSubFieldError(field.name, rowIdx, subField.name, errorMessage)
|
|
2241
|
+
});
|
|
2242
|
+
});
|
|
2243
|
+
});
|
|
2244
|
+
continue;
|
|
2245
|
+
}
|
|
2246
|
+
targets.push({
|
|
2247
|
+
validationKey: field.name,
|
|
2248
|
+
field,
|
|
2249
|
+
value: formValues[field.name],
|
|
2250
|
+
allValues: formValues,
|
|
2251
|
+
applyError: (errorMessage) => updateErrors({ [field.name]: errorMessage })
|
|
2252
|
+
});
|
|
2080
2253
|
}
|
|
2254
|
+
return targets;
|
|
2081
2255
|
},
|
|
2082
|
-
[
|
|
2256
|
+
[visibleFields, formValues, setRepeaterSubFieldError, updateErrors]
|
|
2083
2257
|
);
|
|
2084
2258
|
const commitValues = (0, import_react2.useCallback)(
|
|
2085
2259
|
(nextValues) => {
|
|
2086
2260
|
formValuesRef.current = nextValues;
|
|
2087
2261
|
if (values != null) {
|
|
2262
|
+
controlledBaselineLockedRef.current = true;
|
|
2088
2263
|
if (onChange) onChange(nextValues);
|
|
2089
2264
|
} else {
|
|
2090
2265
|
setInternalValues(nextValues);
|
|
@@ -2102,7 +2277,8 @@ var FormBuilder = (0, import_react2.forwardRef)(function FormBuilder2(props, ref
|
|
|
2102
2277
|
[commitValues]
|
|
2103
2278
|
);
|
|
2104
2279
|
const handleFieldChange = (0, import_react2.useCallback)(
|
|
2105
|
-
(name, value) => {
|
|
2280
|
+
(name, value, options = {}) => {
|
|
2281
|
+
const { clearNestedErrors = true } = options;
|
|
2106
2282
|
const newValues = { ...formValuesRef.current, [name]: value };
|
|
2107
2283
|
const queue = [name];
|
|
2108
2284
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -2143,9 +2319,11 @@ var FormBuilder = (0, import_react2.forwardRef)(function FormBuilder2(props, ref
|
|
|
2143
2319
|
if (formErrorsRef.current[name] != null) {
|
|
2144
2320
|
clearedErrors[name] = null;
|
|
2145
2321
|
}
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2322
|
+
if (clearNestedErrors) {
|
|
2323
|
+
for (const key of Object.keys(formErrorsRef.current)) {
|
|
2324
|
+
if (key.startsWith(`${name}[`)) {
|
|
2325
|
+
clearedErrors[key] = null;
|
|
2326
|
+
}
|
|
2149
2327
|
}
|
|
2150
2328
|
}
|
|
2151
2329
|
draftValuesRef.current = newValues;
|
|
@@ -2214,7 +2392,7 @@ var FormBuilder = (0, import_react2.forwardRef)(function FormBuilder2(props, ref
|
|
|
2214
2392
|
replaceErrors(errors);
|
|
2215
2393
|
return;
|
|
2216
2394
|
}
|
|
2217
|
-
const asyncSubmitValidations = allVisibleFields.map((
|
|
2395
|
+
const asyncSubmitValidations = getAsyncValidationTargets(allVisibleFields).map((target) => runAsyncValidationTarget(target)).filter(Boolean);
|
|
2218
2396
|
if (asyncSubmitValidations.length > 0 || asyncValidationRef.current.size > 0) {
|
|
2219
2397
|
const pendingValidations = [
|
|
2220
2398
|
.../* @__PURE__ */ new Set([
|
|
@@ -2229,6 +2407,7 @@ var FormBuilder = (0, import_react2.forwardRef)(function FormBuilder2(props, ref
|
|
|
2229
2407
|
const reset = () => {
|
|
2230
2408
|
const fresh = computeInitialValues();
|
|
2231
2409
|
if (values == null) setInternalValues(fresh);
|
|
2410
|
+
controlledBaselineLockedRef.current = false;
|
|
2232
2411
|
replaceErrors({});
|
|
2233
2412
|
initialSnapshot.current = deepClone(fresh);
|
|
2234
2413
|
prevAutoSaveValues.current = deepClone(fresh);
|
|
@@ -2268,7 +2447,7 @@ var FormBuilder = (0, import_react2.forwardRef)(function FormBuilder2(props, ref
|
|
|
2268
2447
|
if (controlledLoading == null) setInternalLoading(false);
|
|
2269
2448
|
}
|
|
2270
2449
|
},
|
|
2271
|
-
[validateOnSubmit, allVisibleFields, validateVisibleFields, replaceErrors, onSubmit, values, controlledLoading, transformValues, onBeforeSubmit, onSubmitSuccess, onSubmitError, resetOnSuccess, formValues, fieldByName,
|
|
2450
|
+
[validateOnSubmit, allVisibleFields, validateVisibleFields, replaceErrors, onSubmit, values, controlledLoading, transformValues, onBeforeSubmit, onSubmitSuccess, onSubmitError, resetOnSuccess, formValues, fieldByName, getAsyncValidationTargets, runAsyncValidationTarget]
|
|
2272
2451
|
);
|
|
2273
2452
|
const handleNext = (0, import_react2.useCallback)(async () => {
|
|
2274
2453
|
if (!isMultiStep) return;
|
|
@@ -2280,7 +2459,7 @@ var FormBuilder = (0, import_react2.forwardRef)(function FormBuilder2(props, ref
|
|
|
2280
2459
|
replaceErrors({ ...formErrorsRef.current, ...errors });
|
|
2281
2460
|
return;
|
|
2282
2461
|
}
|
|
2283
|
-
const asyncStepValidations = stepFields.map((
|
|
2462
|
+
const asyncStepValidations = getAsyncValidationTargets(stepFields).map((target) => runAsyncValidationTarget(target)).filter(Boolean);
|
|
2284
2463
|
if (asyncStepValidations.length > 0 || asyncValidationRef.current.size > 0) {
|
|
2285
2464
|
const pendingValidations = [
|
|
2286
2465
|
.../* @__PURE__ */ new Set([
|
|
@@ -2305,7 +2484,7 @@ var FormBuilder = (0, import_react2.forwardRef)(function FormBuilder2(props, ref
|
|
|
2305
2484
|
} else {
|
|
2306
2485
|
setInternalStep(nextStep);
|
|
2307
2486
|
}
|
|
2308
|
-
}, [isMultiStep, validateStepOnNext, steps, currentStep, formValues, validateVisibleFields, controlledStep, onStepChange, replaceErrors, allVisibleFields,
|
|
2487
|
+
}, [isMultiStep, validateStepOnNext, steps, currentStep, formValues, validateVisibleFields, controlledStep, onStepChange, replaceErrors, allVisibleFields, getAsyncValidationTargets, runAsyncValidationTarget]);
|
|
2309
2488
|
const handleBack = (0, import_react2.useCallback)(() => {
|
|
2310
2489
|
if (!isMultiStep) return;
|
|
2311
2490
|
const prevStep = Math.max(currentStep - 1, 0);
|
|
@@ -2337,6 +2516,7 @@ var FormBuilder = (0, import_react2.forwardRef)(function FormBuilder2(props, ref
|
|
|
2337
2516
|
reset: () => {
|
|
2338
2517
|
const fresh = computeInitialValues();
|
|
2339
2518
|
if (values == null) setInternalValues(fresh);
|
|
2519
|
+
controlledBaselineLockedRef.current = false;
|
|
2340
2520
|
replaceErrors({});
|
|
2341
2521
|
initialSnapshot.current = deepClone(fresh);
|
|
2342
2522
|
prevAutoSaveValues.current = deepClone(fresh);
|
|
@@ -2349,30 +2529,6 @@ var FormBuilder = (0, import_react2.forwardRef)(function FormBuilder2(props, ref
|
|
|
2349
2529
|
replaceErrors(errors);
|
|
2350
2530
|
}
|
|
2351
2531
|
}));
|
|
2352
|
-
const setRepeaterSubFieldError = (0, import_react2.useCallback)(
|
|
2353
|
-
(fieldName, rowIdx, subFieldName, errorMessage) => {
|
|
2354
|
-
const key = getRepeaterErrorKey(fieldName, rowIdx, subFieldName);
|
|
2355
|
-
const merged = { ...formErrorsRef.current };
|
|
2356
|
-
if (errorMessage) {
|
|
2357
|
-
merged[key] = errorMessage;
|
|
2358
|
-
} else {
|
|
2359
|
-
delete merged[key];
|
|
2360
|
-
}
|
|
2361
|
-
const subErrors = Object.keys(merged).filter((k) => k.startsWith(`${fieldName}[`)).map((k) => {
|
|
2362
|
-
const match = k.match(/\[(\d+)\]\./);
|
|
2363
|
-
const row = match ? Number(match[1]) : Number.MAX_SAFE_INTEGER;
|
|
2364
|
-
return { key: k, row };
|
|
2365
|
-
}).sort((a, b) => a.row - b.row);
|
|
2366
|
-
if (subErrors.length > 0) {
|
|
2367
|
-
const first = subErrors[0];
|
|
2368
|
-
merged[fieldName] = `Row ${first.row + 1}: ${merged[first.key]}`;
|
|
2369
|
-
} else if (!merged[fieldName] || merged[fieldName].startsWith("Row ")) {
|
|
2370
|
-
delete merged[fieldName];
|
|
2371
|
-
}
|
|
2372
|
-
replaceErrors(merged);
|
|
2373
|
-
},
|
|
2374
|
-
[replaceErrors]
|
|
2375
|
-
);
|
|
2376
2532
|
const renderField = (field) => {
|
|
2377
2533
|
const fieldError = formErrors[field.name] || null;
|
|
2378
2534
|
const rendered = renderFieldInner(field);
|
|
@@ -2852,12 +3008,13 @@ var FormBuilder = (0, import_react2.forwardRef)(function FormBuilder2(props, ref
|
|
|
2852
3008
|
const rowValues = { ...formValues, [field.name]: nextRows };
|
|
2853
3009
|
const err = runValidators(subValue, subField, rowValues, fieldTypes, { messages: validationMessages });
|
|
2854
3010
|
setRepeaterSubFieldError(field.name, rowIdx, subField.name, err);
|
|
3011
|
+
return err;
|
|
2855
3012
|
};
|
|
2856
3013
|
const handleSubFieldChange = (rowIdx, subField, subValue) => {
|
|
2857
3014
|
const updated = rows.map(
|
|
2858
3015
|
(row, i) => i === rowIdx ? { ...row, [subField.name]: subValue } : row
|
|
2859
3016
|
);
|
|
2860
|
-
handleFieldChange(field.name, updated);
|
|
3017
|
+
handleFieldChange(field.name, updated, { clearNestedErrors: false });
|
|
2861
3018
|
if (validateOnChange) {
|
|
2862
3019
|
validateSubField(rowIdx, subField, subValue, updated);
|
|
2863
3020
|
}
|
|
@@ -2867,13 +3024,24 @@ var FormBuilder = (0, import_react2.forwardRef)(function FormBuilder2(props, ref
|
|
|
2867
3024
|
const nextRows = rows.map(
|
|
2868
3025
|
(row, i) => i === rowIdx ? { ...row, [subField.name]: subValue } : row
|
|
2869
3026
|
);
|
|
2870
|
-
validateSubField(rowIdx, subField, subValue, nextRows);
|
|
3027
|
+
const err = validateSubField(rowIdx, subField, subValue, nextRows);
|
|
3028
|
+
if (err) return;
|
|
3029
|
+
const validationKey = getRepeaterErrorKey(field.name, rowIdx, subField.name);
|
|
3030
|
+
const rowValues = { ...formValues, [field.name]: nextRows };
|
|
3031
|
+
triggerAsyncValidationTarget({
|
|
3032
|
+
validationKey,
|
|
3033
|
+
field: subField,
|
|
3034
|
+
value: subValue,
|
|
3035
|
+
allValues: rowValues,
|
|
3036
|
+
applyError: (errorMessage) => setRepeaterSubFieldError(field.name, rowIdx, subField.name, errorMessage)
|
|
3037
|
+
});
|
|
2871
3038
|
};
|
|
2872
3039
|
return /* @__PURE__ */ import_react2.default.createElement(import_ui_extensions2.Flex, { direction: "column", gap: "xs" }, field.label && /* @__PURE__ */ import_react2.default.createElement(import_ui_extensions2.Text, { format: { fontWeight: "demibold" } }, field.label, isRequired ? " *" : ""), field.description && /* @__PURE__ */ import_react2.default.createElement(import_ui_extensions2.Text, { variant: "microcopy" }, field.description), rows.map((row, rowIdx) => /* @__PURE__ */ import_react2.default.createElement(import_ui_extensions2.Flex, { key: getRowKey(field.name, row, rowIdx), direction: "row", gap: "xs", align: "end" }, subFields.map((sf) => {
|
|
2873
3040
|
const sfValue = row[sf.name];
|
|
2874
3041
|
const sfLabel = rowIdx === 0 ? sf.label : void 0;
|
|
2875
3042
|
const sfOptions = resolveOptions(sf, { ...formValues, [field.name]: rows });
|
|
2876
3043
|
const sfError = formErrors[getRepeaterErrorKey(field.name, rowIdx, sf.name)] || null;
|
|
3044
|
+
const validationKey = getRepeaterErrorKey(field.name, rowIdx, sf.name);
|
|
2877
3045
|
const sfProps = {
|
|
2878
3046
|
name: `${field.name}-${rowIdx}-${sf.name}`,
|
|
2879
3047
|
label: sfLabel,
|
|
@@ -2882,6 +3050,7 @@ var FormBuilder = (0, import_react2.forwardRef)(function FormBuilder2(props, ref
|
|
|
2882
3050
|
disabled: resolveDisabled(sf, formValues) || isDisabled,
|
|
2883
3051
|
error: !!sfError,
|
|
2884
3052
|
validationMessage: sfError || void 0,
|
|
3053
|
+
...validatingFields[validationKey] ? { loading: true } : {},
|
|
2885
3054
|
...sf.fieldProps || {}
|
|
2886
3055
|
};
|
|
2887
3056
|
let sfElement;
|
|
@@ -3310,9 +3479,212 @@ var FormBuilder = (0, import_react2.forwardRef)(function FormBuilder2(props, ref
|
|
|
3310
3479
|
formContent
|
|
3311
3480
|
);
|
|
3312
3481
|
});
|
|
3482
|
+
|
|
3483
|
+
// src/common-components/AutoTag.js
|
|
3484
|
+
var import_react3 = __toESM(require("react"));
|
|
3485
|
+
var import_ui_extensions3 = require("@hubspot/ui-extensions");
|
|
3486
|
+
|
|
3487
|
+
// src/utils/tagVariants.js
|
|
3488
|
+
var DEFAULT_VARIANT = "default";
|
|
3489
|
+
var DANGER_VARIANT = "danger";
|
|
3490
|
+
var ERROR_VARIANT = "error";
|
|
3491
|
+
var SUCCESS_MATCHERS = [
|
|
3492
|
+
"active",
|
|
3493
|
+
"success",
|
|
3494
|
+
"succeeded",
|
|
3495
|
+
"complete",
|
|
3496
|
+
"completed",
|
|
3497
|
+
"approved",
|
|
3498
|
+
"won",
|
|
3499
|
+
"healthy",
|
|
3500
|
+
"enabled",
|
|
3501
|
+
"connected",
|
|
3502
|
+
"paid",
|
|
3503
|
+
"live",
|
|
3504
|
+
"published",
|
|
3505
|
+
"available",
|
|
3506
|
+
"synced",
|
|
3507
|
+
"resolved"
|
|
3508
|
+
];
|
|
3509
|
+
var WARNING_MATCHERS = [
|
|
3510
|
+
"warning",
|
|
3511
|
+
"at risk",
|
|
3512
|
+
"risky",
|
|
3513
|
+
"pending",
|
|
3514
|
+
"paused",
|
|
3515
|
+
"pause",
|
|
3516
|
+
"on hold",
|
|
3517
|
+
"hold",
|
|
3518
|
+
"review",
|
|
3519
|
+
"expiring",
|
|
3520
|
+
"trial",
|
|
3521
|
+
"in progress",
|
|
3522
|
+
"awaiting",
|
|
3523
|
+
"scheduled"
|
|
3524
|
+
];
|
|
3525
|
+
var DANGER_MATCHERS = [
|
|
3526
|
+
"danger",
|
|
3527
|
+
"error",
|
|
3528
|
+
"failed",
|
|
3529
|
+
"failure",
|
|
3530
|
+
"inactive",
|
|
3531
|
+
"disabled",
|
|
3532
|
+
"blocked",
|
|
3533
|
+
"cancelled",
|
|
3534
|
+
"canceled",
|
|
3535
|
+
"rejected",
|
|
3536
|
+
"denied",
|
|
3537
|
+
"churned",
|
|
3538
|
+
"lost",
|
|
3539
|
+
"overdue",
|
|
3540
|
+
"expired",
|
|
3541
|
+
"offline",
|
|
3542
|
+
"deleted",
|
|
3543
|
+
"archived",
|
|
3544
|
+
"unpaid"
|
|
3545
|
+
];
|
|
3546
|
+
var INFO_MATCHERS = [
|
|
3547
|
+
"info",
|
|
3548
|
+
"new",
|
|
3549
|
+
"queued",
|
|
3550
|
+
"processing",
|
|
3551
|
+
"progress",
|
|
3552
|
+
"upcoming",
|
|
3553
|
+
"draft",
|
|
3554
|
+
"open"
|
|
3555
|
+
];
|
|
3556
|
+
var normalizeTagValue = (value) => {
|
|
3557
|
+
if (value == null) return "";
|
|
3558
|
+
if (typeof value === "boolean") return value ? "true" : "false";
|
|
3559
|
+
return String(value).trim().toLowerCase().replace(/[_-]+/g, " ").replace(/\s+/g, " ");
|
|
3560
|
+
};
|
|
3561
|
+
var matchesAny = (value, matchers) => matchers.some((matcher) => {
|
|
3562
|
+
if (value === matcher) return true;
|
|
3563
|
+
return ` ${value} `.includes(` ${matcher} `);
|
|
3564
|
+
});
|
|
3565
|
+
var getSemanticVariant = (value, options = {}) => {
|
|
3566
|
+
const normalized = normalizeTagValue(value);
|
|
3567
|
+
const fallback = options.fallback || DEFAULT_VARIANT;
|
|
3568
|
+
if (!normalized) return fallback;
|
|
3569
|
+
if (options.overrides) {
|
|
3570
|
+
const overrideKey = Object.keys(options.overrides).find(
|
|
3571
|
+
(key) => normalizeTagValue(key) === normalized
|
|
3572
|
+
);
|
|
3573
|
+
if (overrideKey) return options.overrides[overrideKey];
|
|
3574
|
+
}
|
|
3575
|
+
if (normalized === "true") return "success";
|
|
3576
|
+
if (normalized === "false") return fallback;
|
|
3577
|
+
if (matchesAny(normalized, SUCCESS_MATCHERS)) return "success";
|
|
3578
|
+
if (matchesAny(normalized, DANGER_MATCHERS)) return DANGER_VARIANT;
|
|
3579
|
+
if (matchesAny(normalized, WARNING_MATCHERS)) return "warning";
|
|
3580
|
+
if (matchesAny(normalized, INFO_MATCHERS)) return "info";
|
|
3581
|
+
return fallback;
|
|
3582
|
+
};
|
|
3583
|
+
var getAutoTagVariant = (value, options = {}) => {
|
|
3584
|
+
const semanticVariant = getSemanticVariant(value, options);
|
|
3585
|
+
return semanticVariant === DANGER_VARIANT ? ERROR_VARIANT : semanticVariant;
|
|
3586
|
+
};
|
|
3587
|
+
var getAutoStatusTagVariant = (value, options = {}) => getSemanticVariant(value, options);
|
|
3588
|
+
var getAutoTagDisplayValue = (value) => {
|
|
3589
|
+
if (typeof value === "boolean") return value ? "True" : "False";
|
|
3590
|
+
return value;
|
|
3591
|
+
};
|
|
3592
|
+
var DEFAULT_STATUS_TAG_COLOR_ORDER = [
|
|
3593
|
+
"success",
|
|
3594
|
+
"warning",
|
|
3595
|
+
"danger",
|
|
3596
|
+
"error",
|
|
3597
|
+
"info",
|
|
3598
|
+
"default"
|
|
3599
|
+
];
|
|
3600
|
+
var createStatusTagSortComparator = (options = {}) => {
|
|
3601
|
+
const {
|
|
3602
|
+
variantOrder = DEFAULT_STATUS_TAG_COLOR_ORDER,
|
|
3603
|
+
overrides,
|
|
3604
|
+
fallback,
|
|
3605
|
+
getLabel
|
|
3606
|
+
} = options;
|
|
3607
|
+
const variantIndex = (variant) => {
|
|
3608
|
+
const idx = variantOrder.indexOf(variant);
|
|
3609
|
+
return idx === -1 ? variantOrder.length : idx;
|
|
3610
|
+
};
|
|
3611
|
+
const labelOf = (value) => {
|
|
3612
|
+
if (getLabel) return String(getLabel(value) ?? "");
|
|
3613
|
+
if (value == null) return "";
|
|
3614
|
+
return String(getAutoTagDisplayValue(value) ?? "");
|
|
3615
|
+
};
|
|
3616
|
+
return (aVal, bVal) => {
|
|
3617
|
+
const aVariant = getSemanticVariant(aVal, { overrides, fallback });
|
|
3618
|
+
const bVariant = getSemanticVariant(bVal, { overrides, fallback });
|
|
3619
|
+
const diff = variantIndex(aVariant) - variantIndex(bVariant);
|
|
3620
|
+
if (diff !== 0) return diff;
|
|
3621
|
+
return labelOf(aVal).localeCompare(labelOf(bVal));
|
|
3622
|
+
};
|
|
3623
|
+
};
|
|
3624
|
+
|
|
3625
|
+
// src/common-components/AutoTag.js
|
|
3626
|
+
var AutoTag = ({
|
|
3627
|
+
value,
|
|
3628
|
+
tag,
|
|
3629
|
+
children,
|
|
3630
|
+
variant,
|
|
3631
|
+
overrides,
|
|
3632
|
+
fallback,
|
|
3633
|
+
...props
|
|
3634
|
+
}) => {
|
|
3635
|
+
const resolvedValue = value ?? tag ?? children;
|
|
3636
|
+
const displayValue = children ?? getAutoTagDisplayValue(resolvedValue);
|
|
3637
|
+
const resolvedVariant = variant || getAutoTagVariant(resolvedValue, {
|
|
3638
|
+
overrides,
|
|
3639
|
+
fallback
|
|
3640
|
+
});
|
|
3641
|
+
return import_react3.default.createElement(
|
|
3642
|
+
import_ui_extensions3.Tag,
|
|
3643
|
+
{ variant: resolvedVariant, ...props },
|
|
3644
|
+
displayValue
|
|
3645
|
+
);
|
|
3646
|
+
};
|
|
3647
|
+
|
|
3648
|
+
// src/common-components/AutoStatusTag.js
|
|
3649
|
+
var import_react4 = __toESM(require("react"));
|
|
3650
|
+
var import_ui_extensions4 = require("@hubspot/ui-extensions");
|
|
3651
|
+
var AutoStatusTag = ({
|
|
3652
|
+
value,
|
|
3653
|
+
status,
|
|
3654
|
+
children,
|
|
3655
|
+
variant,
|
|
3656
|
+
overrides,
|
|
3657
|
+
fallback,
|
|
3658
|
+
...props
|
|
3659
|
+
}) => {
|
|
3660
|
+
const resolvedValue = value ?? status ?? children;
|
|
3661
|
+
const displayValue = children ?? getAutoTagDisplayValue(resolvedValue);
|
|
3662
|
+
const resolvedVariant = variant || getAutoStatusTagVariant(resolvedValue, {
|
|
3663
|
+
overrides,
|
|
3664
|
+
fallback
|
|
3665
|
+
});
|
|
3666
|
+
return import_react4.default.createElement(
|
|
3667
|
+
import_ui_extensions4.StatusTag,
|
|
3668
|
+
{ variant: resolvedVariant, ...props },
|
|
3669
|
+
displayValue
|
|
3670
|
+
);
|
|
3671
|
+
};
|
|
3672
|
+
|
|
3673
|
+
// src/common-components/KeyValueList.js
|
|
3674
|
+
var import_react5 = __toESM(require("react"));
|
|
3675
|
+
var import_ui_extensions5 = require("@hubspot/ui-extensions");
|
|
3676
|
+
|
|
3677
|
+
// src/common-components/SectionHeader.js
|
|
3678
|
+
var import_react6 = __toESM(require("react"));
|
|
3679
|
+
var import_ui_extensions6 = require("@hubspot/ui-extensions");
|
|
3313
3680
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3314
3681
|
0 && (module.exports = {
|
|
3682
|
+
AutoStatusTag,
|
|
3683
|
+
AutoTag,
|
|
3315
3684
|
DataTable,
|
|
3316
3685
|
FormBuilder,
|
|
3686
|
+
createStatusTagSortComparator,
|
|
3687
|
+
getAutoStatusTagVariant,
|
|
3688
|
+
getAutoTagVariant,
|
|
3317
3689
|
useFormPrefill
|
|
3318
3690
|
});
|