@uniform-ts/core 0.0.7 → 0.0.9
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 +19 -16
- package/dist/{field-DPgaGkOL.d.mts → field-Cogi7eQc.d.mts} +62 -30
- package/dist/{field-DPgaGkOL.d.ts → field-Cogi7eQc.d.ts} +62 -30
- package/dist/index.d.mts +54 -8
- package/dist/index.d.ts +54 -8
- package/dist/index.js +418 -53
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +419 -55
- package/dist/index.mjs.map +1 -1
- package/dist/locales/en.d.mts +1 -1
- package/dist/locales/en.d.ts +1 -1
- package/dist/locales/es.d.mts +1 -1
- package/dist/locales/es.d.ts +1 -1
- package/dist/locales/he.d.mts +1 -1
- package/dist/locales/he.d.ts +1 -1
- package/package.json +3 -2
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as z from 'zod/v4/core';
|
|
2
2
|
import * as React3 from 'react';
|
|
3
3
|
import { useMemo, useRef, useEffect, useCallback, useState } from 'react';
|
|
4
|
-
import {
|
|
4
|
+
import { useWatch, useFormState, useForm, useFieldArray, Controller } from 'react-hook-form';
|
|
5
5
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
6
6
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
7
7
|
|
|
@@ -635,6 +635,24 @@ function SelectField({
|
|
|
635
635
|
}
|
|
636
636
|
);
|
|
637
637
|
}
|
|
638
|
+
function useConditionalFields(fields, control, scopeName) {
|
|
639
|
+
const allValues = useWatch({ control });
|
|
640
|
+
const scopedValues = useWatch({ control, name: scopeName });
|
|
641
|
+
const values = scopeName ? scopedValues : allValues;
|
|
642
|
+
return useMemo(() => {
|
|
643
|
+
return fields.filter((field) => {
|
|
644
|
+
if (field.meta.hidden) return false;
|
|
645
|
+
if (typeof field.meta.condition === "function") {
|
|
646
|
+
return field.meta.condition(values);
|
|
647
|
+
}
|
|
648
|
+
return true;
|
|
649
|
+
}).sort((a, b) => {
|
|
650
|
+
const orderA = typeof a.meta.order === "number" ? a.meta.order : Infinity;
|
|
651
|
+
const orderB = typeof b.meta.order === "number" ? b.meta.order : Infinity;
|
|
652
|
+
return orderA - orderB;
|
|
653
|
+
});
|
|
654
|
+
}, [fields, values]);
|
|
655
|
+
}
|
|
638
656
|
function ObjectField({
|
|
639
657
|
field,
|
|
640
658
|
control,
|
|
@@ -643,7 +661,7 @@ function ObjectField({
|
|
|
643
661
|
shouldUnregister
|
|
644
662
|
}) {
|
|
645
663
|
const { classNames, layout } = useAutoFormContext();
|
|
646
|
-
const children = field.children;
|
|
664
|
+
const children = useConditionalFields(field.children, control, namePrefix);
|
|
647
665
|
const content = children.map((child, idx) => /* @__PURE__ */ jsx(
|
|
648
666
|
FieldRenderer,
|
|
649
667
|
{
|
|
@@ -698,6 +716,124 @@ function getDefaultValue(field) {
|
|
|
698
716
|
return void 0;
|
|
699
717
|
}
|
|
700
718
|
}
|
|
719
|
+
|
|
720
|
+
// src/utils/reindexDynamicMeta.ts
|
|
721
|
+
function buildKeyPattern(arrayName) {
|
|
722
|
+
return new RegExp(`^${escapeRegExp(arrayName)}\\.(\\d+)\\.(.+)$`);
|
|
723
|
+
}
|
|
724
|
+
function escapeRegExp(str) {
|
|
725
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
726
|
+
}
|
|
727
|
+
function reindexDynamicMeta(dynamicMeta, arrayName, mutation) {
|
|
728
|
+
const pattern = buildKeyPattern(arrayName);
|
|
729
|
+
const matched = [];
|
|
730
|
+
const result = {};
|
|
731
|
+
for (const [key, value] of Object.entries(dynamicMeta)) {
|
|
732
|
+
const match = pattern.exec(key);
|
|
733
|
+
if (match) {
|
|
734
|
+
matched.push({
|
|
735
|
+
key,
|
|
736
|
+
index: parseInt(match[1], 10),
|
|
737
|
+
childField: match[2],
|
|
738
|
+
value
|
|
739
|
+
});
|
|
740
|
+
} else {
|
|
741
|
+
result[key] = value;
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
if (!isValidMutation(mutation)) {
|
|
745
|
+
return dynamicMeta;
|
|
746
|
+
}
|
|
747
|
+
switch (mutation.type) {
|
|
748
|
+
case "remove":
|
|
749
|
+
applyRemove(matched, mutation.index, arrayName, result);
|
|
750
|
+
break;
|
|
751
|
+
case "move":
|
|
752
|
+
applyMove(matched, mutation.from, mutation.to, arrayName, result);
|
|
753
|
+
break;
|
|
754
|
+
case "duplicate":
|
|
755
|
+
applyDuplicate(matched, mutation.index, arrayName, result);
|
|
756
|
+
break;
|
|
757
|
+
case "add":
|
|
758
|
+
applyAdd(matched, mutation.index, arrayName, result);
|
|
759
|
+
break;
|
|
760
|
+
}
|
|
761
|
+
return result;
|
|
762
|
+
}
|
|
763
|
+
function isValidMutation(mutation, _entries) {
|
|
764
|
+
switch (mutation.type) {
|
|
765
|
+
case "remove":
|
|
766
|
+
return mutation.index >= 0;
|
|
767
|
+
case "move":
|
|
768
|
+
return mutation.from >= 0 && mutation.to >= 0;
|
|
769
|
+
case "duplicate":
|
|
770
|
+
return mutation.index >= 0;
|
|
771
|
+
case "add":
|
|
772
|
+
return mutation.index >= 0;
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
function buildKey(arrayName, index, childField) {
|
|
776
|
+
return `${arrayName}.${index}.${childField}`;
|
|
777
|
+
}
|
|
778
|
+
function applyRemove(entries, removedIndex, arrayName, result) {
|
|
779
|
+
for (const entry of entries) {
|
|
780
|
+
if (entry.index === removedIndex) {
|
|
781
|
+
continue;
|
|
782
|
+
} else if (entry.index > removedIndex) {
|
|
783
|
+
result[buildKey(arrayName, entry.index - 1, entry.childField)] = entry.value;
|
|
784
|
+
} else {
|
|
785
|
+
result[buildKey(arrayName, entry.index, entry.childField)] = entry.value;
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
function applyMove(entries, from, to, arrayName, result) {
|
|
790
|
+
if (from === to) {
|
|
791
|
+
for (const entry of entries) {
|
|
792
|
+
result[buildKey(arrayName, entry.index, entry.childField)] = entry.value;
|
|
793
|
+
}
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
for (const entry of entries) {
|
|
797
|
+
let newIndex;
|
|
798
|
+
if (entry.index === from) {
|
|
799
|
+
newIndex = to;
|
|
800
|
+
} else if (from < to) {
|
|
801
|
+
if (entry.index > from && entry.index <= to) {
|
|
802
|
+
newIndex = entry.index - 1;
|
|
803
|
+
} else {
|
|
804
|
+
newIndex = entry.index;
|
|
805
|
+
}
|
|
806
|
+
} else {
|
|
807
|
+
if (entry.index >= to && entry.index < from) {
|
|
808
|
+
newIndex = entry.index + 1;
|
|
809
|
+
} else {
|
|
810
|
+
newIndex = entry.index;
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
result[buildKey(arrayName, newIndex, entry.childField)] = entry.value;
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
function applyDuplicate(entries, sourceIndex, arrayName, result) {
|
|
817
|
+
for (const entry of entries) {
|
|
818
|
+
if (entry.index === sourceIndex) {
|
|
819
|
+
result[buildKey(arrayName, entry.index, entry.childField)] = entry.value;
|
|
820
|
+
result[buildKey(arrayName, sourceIndex + 1, entry.childField)] = entry.value;
|
|
821
|
+
} else if (entry.index > sourceIndex) {
|
|
822
|
+
result[buildKey(arrayName, entry.index + 1, entry.childField)] = entry.value;
|
|
823
|
+
} else {
|
|
824
|
+
result[buildKey(arrayName, entry.index, entry.childField)] = entry.value;
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
function applyAdd(entries, newIndex, arrayName, result) {
|
|
829
|
+
for (const entry of entries) {
|
|
830
|
+
if (entry.index >= newIndex) {
|
|
831
|
+
result[buildKey(arrayName, entry.index + 1, entry.childField)] = entry.value;
|
|
832
|
+
} else {
|
|
833
|
+
result[buildKey(arrayName, entry.index, entry.childField)] = entry.value;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
}
|
|
701
837
|
function getRowSummary(row, itemConfig, index, itemSummary) {
|
|
702
838
|
if (itemConfig.type === "object") {
|
|
703
839
|
for (const child of itemConfig.children) {
|
|
@@ -710,8 +846,43 @@ function getRowSummary(row, itemConfig, index, itemSummary) {
|
|
|
710
846
|
}
|
|
711
847
|
return itemSummary?.(index) ?? `Item ${index + 1}`;
|
|
712
848
|
}
|
|
849
|
+
function bindRowIndexToItemConfig(itemConfig, rowIndex) {
|
|
850
|
+
if (itemConfig.type !== "object") return itemConfig;
|
|
851
|
+
const children = itemConfig.children.map((child) => {
|
|
852
|
+
if (!child.meta.onChange) return child;
|
|
853
|
+
const originalOnChange = child.meta.onChange;
|
|
854
|
+
return {
|
|
855
|
+
...child,
|
|
856
|
+
meta: {
|
|
857
|
+
...child.meta,
|
|
858
|
+
onChange: (value, formMethods) => {
|
|
859
|
+
void originalOnChange(value, formMethods, rowIndex);
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
};
|
|
863
|
+
});
|
|
864
|
+
return { ...itemConfig, children };
|
|
865
|
+
}
|
|
866
|
+
function applyRowDynamicMeta(itemConfig, rowOverrides) {
|
|
867
|
+
if (itemConfig.type !== "object") return itemConfig;
|
|
868
|
+
const children = itemConfig.children.map((child) => {
|
|
869
|
+
const override = rowOverrides[child.name];
|
|
870
|
+
if (!override) return child;
|
|
871
|
+
const { options, label, ...metaOverrides } = override;
|
|
872
|
+
let updated = {
|
|
873
|
+
...child,
|
|
874
|
+
...label !== void 0 ? { label } : {},
|
|
875
|
+
meta: { ...child.meta, ...metaOverrides }
|
|
876
|
+
};
|
|
877
|
+
if (options !== void 0 && updated.type === "select") {
|
|
878
|
+
updated = { ...updated, options };
|
|
879
|
+
}
|
|
880
|
+
return updated;
|
|
881
|
+
});
|
|
882
|
+
return { ...itemConfig, children };
|
|
883
|
+
}
|
|
713
884
|
function ArrayField({ field, control, effectiveName }) {
|
|
714
|
-
const { classNames, layout, labels } = useAutoFormContext();
|
|
885
|
+
const { classNames, layout, labels, setDynamicMeta } = useAutoFormContext();
|
|
715
886
|
const {
|
|
716
887
|
fields: rows,
|
|
717
888
|
append,
|
|
@@ -757,9 +928,10 @@ function ArrayField({ field, control, effectiveName }) {
|
|
|
757
928
|
} = layout.arrayButtons;
|
|
758
929
|
const ArrayFieldLayout = layout.arrayFieldLayout;
|
|
759
930
|
const RowLayout = layout.arrayRowLayout;
|
|
931
|
+
const rowDynamicMeta = field._rowDynamicMeta;
|
|
760
932
|
const renderedRows = rows.map((row, index) => {
|
|
761
933
|
const isCollapsed = showCollapse && collapsed.has(index);
|
|
762
|
-
const collapseButton = showCollapse ? /* @__PURE__ */ jsxs(
|
|
934
|
+
const collapseButton = showCollapse && CollapseBtn ? /* @__PURE__ */ jsxs(
|
|
763
935
|
CollapseBtn,
|
|
764
936
|
{
|
|
765
937
|
type: "button",
|
|
@@ -783,29 +955,47 @@ function ArrayField({ field, control, effectiveName }) {
|
|
|
783
955
|
]
|
|
784
956
|
}
|
|
785
957
|
) : null;
|
|
786
|
-
const moveUpButton = showMove && rows.length > 1 ? /* @__PURE__ */ jsx(
|
|
958
|
+
const moveUpButton = showMove && rows.length > 1 && MoveUpBtn ? /* @__PURE__ */ jsx(
|
|
787
959
|
MoveUpBtn,
|
|
788
960
|
{
|
|
789
961
|
type: "button",
|
|
790
962
|
className: classNames.arrayMove,
|
|
791
|
-
onClick: () =>
|
|
963
|
+
onClick: () => {
|
|
964
|
+
move(index, index - 1);
|
|
965
|
+
setDynamicMeta(
|
|
966
|
+
(prev) => reindexDynamicMeta(prev, effectiveName, {
|
|
967
|
+
type: "move",
|
|
968
|
+
from: index,
|
|
969
|
+
to: index - 1
|
|
970
|
+
})
|
|
971
|
+
);
|
|
972
|
+
},
|
|
792
973
|
disabled: index === 0,
|
|
793
974
|
"aria-label": labels.arrayAriaMoveUp?.(index) ?? `Move item ${index + 1} up`,
|
|
794
975
|
children: labels.arrayMoveUp ?? "\u2191"
|
|
795
976
|
}
|
|
796
977
|
) : null;
|
|
797
|
-
const moveDownButton = showMove && rows.length > 1 ? /* @__PURE__ */ jsx(
|
|
978
|
+
const moveDownButton = showMove && rows.length > 1 && MoveDownBtn ? /* @__PURE__ */ jsx(
|
|
798
979
|
MoveDownBtn,
|
|
799
980
|
{
|
|
800
981
|
type: "button",
|
|
801
982
|
className: classNames.arrayMove,
|
|
802
|
-
onClick: () =>
|
|
983
|
+
onClick: () => {
|
|
984
|
+
move(index, index + 1);
|
|
985
|
+
setDynamicMeta(
|
|
986
|
+
(prev) => reindexDynamicMeta(prev, effectiveName, {
|
|
987
|
+
type: "move",
|
|
988
|
+
from: index,
|
|
989
|
+
to: index + 1
|
|
990
|
+
})
|
|
991
|
+
);
|
|
992
|
+
},
|
|
803
993
|
disabled: index === rows.length - 1,
|
|
804
994
|
"aria-label": labels.arrayAriaMoveDown?.(index) ?? `Move item ${index + 1} down`,
|
|
805
995
|
children: labels.arrayMoveDown ?? "\u2193"
|
|
806
996
|
}
|
|
807
997
|
) : null;
|
|
808
|
-
const duplicateButton = showDuplicate && !atMax ? /* @__PURE__ */ jsx(
|
|
998
|
+
const duplicateButton = showDuplicate && !atMax && DuplicateBtn ? /* @__PURE__ */ jsx(
|
|
809
999
|
DuplicateBtn,
|
|
810
1000
|
{
|
|
811
1001
|
type: "button",
|
|
@@ -815,26 +1005,43 @@ function ArrayField({ field, control, effectiveName }) {
|
|
|
815
1005
|
Object.entries(row).filter(([k]) => k !== "id")
|
|
816
1006
|
);
|
|
817
1007
|
insert(index + 1, values);
|
|
1008
|
+
setDynamicMeta(
|
|
1009
|
+
(prev) => reindexDynamicMeta(prev, effectiveName, {
|
|
1010
|
+
type: "duplicate",
|
|
1011
|
+
index
|
|
1012
|
+
})
|
|
1013
|
+
);
|
|
818
1014
|
},
|
|
819
1015
|
"aria-label": labels.arrayAriaDuplicate?.(index) ?? `Duplicate item ${index + 1}`,
|
|
820
1016
|
children: labels.arrayDuplicate ?? "Duplicate"
|
|
821
1017
|
}
|
|
822
1018
|
) : null;
|
|
823
|
-
const removeButton = /* @__PURE__ */ jsx(
|
|
1019
|
+
const removeButton = RemoveBtn ? /* @__PURE__ */ jsx(
|
|
824
1020
|
RemoveBtn,
|
|
825
1021
|
{
|
|
826
1022
|
type: "button",
|
|
827
1023
|
className: classNames.arrayRemove,
|
|
828
|
-
onClick: () =>
|
|
1024
|
+
onClick: () => {
|
|
1025
|
+
remove(index);
|
|
1026
|
+
setDynamicMeta(
|
|
1027
|
+
(prev) => reindexDynamicMeta(prev, effectiveName, {
|
|
1028
|
+
type: "remove",
|
|
1029
|
+
index
|
|
1030
|
+
})
|
|
1031
|
+
);
|
|
1032
|
+
},
|
|
829
1033
|
disabled: atMin,
|
|
830
1034
|
"aria-label": labels.arrayAriaRemove?.(index) ?? `Remove item ${index + 1}`,
|
|
831
1035
|
children: labels.arrayRemove ?? "Remove"
|
|
832
1036
|
}
|
|
833
|
-
);
|
|
1037
|
+
) : null;
|
|
834
1038
|
const fieldContent = !isCollapsed ? /* @__PURE__ */ jsx(
|
|
835
1039
|
FieldRenderer,
|
|
836
1040
|
{
|
|
837
|
-
field:
|
|
1041
|
+
field: bindRowIndexToItemConfig(
|
|
1042
|
+
rowDynamicMeta?.[index] ? applyRowDynamicMeta(effectiveItemConfig, rowDynamicMeta[index]) : effectiveItemConfig,
|
|
1043
|
+
index
|
|
1044
|
+
),
|
|
838
1045
|
control,
|
|
839
1046
|
namePrefix: `${effectiveName}.${index}`
|
|
840
1047
|
}
|
|
@@ -856,16 +1063,25 @@ function ArrayField({ field, control, effectiveName }) {
|
|
|
856
1063
|
row.id
|
|
857
1064
|
);
|
|
858
1065
|
});
|
|
859
|
-
const addButton = /* @__PURE__ */ jsx(
|
|
1066
|
+
const addButton = AddBtn ? /* @__PURE__ */ jsx(
|
|
860
1067
|
AddBtn,
|
|
861
1068
|
{
|
|
862
1069
|
type: "button",
|
|
863
1070
|
className: classNames.arrayAdd,
|
|
864
1071
|
disabled: atMax,
|
|
865
|
-
onClick: () =>
|
|
1072
|
+
onClick: () => {
|
|
1073
|
+
const newIndex = rows.length;
|
|
1074
|
+
append(getDefaultValue(itemConfig));
|
|
1075
|
+
setDynamicMeta(
|
|
1076
|
+
(prev) => reindexDynamicMeta(prev, effectiveName, {
|
|
1077
|
+
type: "add",
|
|
1078
|
+
index: newIndex
|
|
1079
|
+
})
|
|
1080
|
+
);
|
|
1081
|
+
},
|
|
866
1082
|
children: labels.arrayAdd ?? "Add"
|
|
867
1083
|
}
|
|
868
|
-
);
|
|
1084
|
+
) : null;
|
|
869
1085
|
const content = /* @__PURE__ */ jsx(
|
|
870
1086
|
ArrayFieldLayout,
|
|
871
1087
|
{
|
|
@@ -1027,22 +1243,6 @@ function FieldRenderer({
|
|
|
1027
1243
|
}
|
|
1028
1244
|
);
|
|
1029
1245
|
}
|
|
1030
|
-
function useConditionalFields(fields, control) {
|
|
1031
|
-
const values = useWatch({ control });
|
|
1032
|
-
return useMemo(() => {
|
|
1033
|
-
return fields.filter((field) => {
|
|
1034
|
-
if (field.meta.hidden) return false;
|
|
1035
|
-
if (typeof field.meta.condition === "function") {
|
|
1036
|
-
return field.meta.condition(values);
|
|
1037
|
-
}
|
|
1038
|
-
return true;
|
|
1039
|
-
}).sort((a, b) => {
|
|
1040
|
-
const orderA = typeof a.meta.order === "number" ? a.meta.order : Infinity;
|
|
1041
|
-
const orderB = typeof b.meta.order === "number" ? b.meta.order : Infinity;
|
|
1042
|
-
return orderA - orderB;
|
|
1043
|
-
});
|
|
1044
|
-
}, [fields, values]);
|
|
1045
|
-
}
|
|
1046
1246
|
function useSectionGrouping(fields) {
|
|
1047
1247
|
return useMemo(() => {
|
|
1048
1248
|
const ungrouped = [];
|
|
@@ -1131,6 +1331,28 @@ function useLatestRef(value) {
|
|
|
1131
1331
|
return ref;
|
|
1132
1332
|
}
|
|
1133
1333
|
|
|
1334
|
+
// src/utils/createRowScopedContext.ts
|
|
1335
|
+
function createRowScopedContext(baseCtx, arrayName, rowIndex, itemFieldNames, getValues) {
|
|
1336
|
+
return {
|
|
1337
|
+
...baseCtx,
|
|
1338
|
+
getValues,
|
|
1339
|
+
setFieldMeta: (field, meta) => {
|
|
1340
|
+
const fieldStr = field;
|
|
1341
|
+
const prefix = arrayName + ".";
|
|
1342
|
+
const childName = fieldStr.startsWith(prefix) ? fieldStr.slice(prefix.length) : fieldStr;
|
|
1343
|
+
if (itemFieldNames.has(childName)) {
|
|
1344
|
+
const qualifiedKey = `${arrayName}.${rowIndex}.${childName}`;
|
|
1345
|
+
baseCtx.setFieldMeta(
|
|
1346
|
+
qualifiedKey,
|
|
1347
|
+
meta
|
|
1348
|
+
);
|
|
1349
|
+
} else {
|
|
1350
|
+
baseCtx.setFieldMeta(field, meta);
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
};
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1134
1356
|
// src/utils/fieldPipeline.ts
|
|
1135
1357
|
function applyFieldOverrides(fields, overrides) {
|
|
1136
1358
|
return fields.map((field) => {
|
|
@@ -1191,10 +1413,74 @@ function injectOnChangeHandlers(fields, uniForm, ctx, handlerKeys = new Set(uniF
|
|
|
1191
1413
|
} else if (updated.type === "array") {
|
|
1192
1414
|
const prefix = field.name + ".";
|
|
1193
1415
|
const itemKeys = /* @__PURE__ */ new Set();
|
|
1416
|
+
const indexedKeys = /* @__PURE__ */ new Set();
|
|
1194
1417
|
for (const key of handlerKeys) {
|
|
1195
|
-
if (key.startsWith(prefix))
|
|
1418
|
+
if (key.startsWith(prefix)) {
|
|
1419
|
+
const remainder = key.slice(prefix.length);
|
|
1420
|
+
const indexMatch = remainder.match(/^(\d+)\.(.+)$/);
|
|
1421
|
+
if (indexMatch) {
|
|
1422
|
+
indexedKeys.add(remainder);
|
|
1423
|
+
itemKeys.add(indexMatch[2]);
|
|
1424
|
+
} else {
|
|
1425
|
+
itemKeys.add(remainder);
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1196
1428
|
}
|
|
1197
|
-
if (itemKeys.size) {
|
|
1429
|
+
if (itemKeys.size && updated.itemConfig.type === "object") {
|
|
1430
|
+
const itemFieldNames = new Set(
|
|
1431
|
+
updated.itemConfig.children.map((c) => c.name)
|
|
1432
|
+
);
|
|
1433
|
+
const arrayName = field.name;
|
|
1434
|
+
const newChildren = updated.itemConfig.children.map((child) => {
|
|
1435
|
+
if (!itemKeys.has(child.name)) return child;
|
|
1436
|
+
const existingOnChange = child.meta.onChange;
|
|
1437
|
+
const rowAwareHandler = (value, formMethods, rowIndex) => {
|
|
1438
|
+
void existingOnChange?.(value, formMethods);
|
|
1439
|
+
const rowCtx = createRowScopedContext(
|
|
1440
|
+
ctx,
|
|
1441
|
+
arrayName,
|
|
1442
|
+
rowIndex,
|
|
1443
|
+
itemFieldNames,
|
|
1444
|
+
() => {
|
|
1445
|
+
const allValues = ctx.getValues();
|
|
1446
|
+
const arrayValues = allValues?.[arrayName];
|
|
1447
|
+
if (Array.isArray(arrayValues)) {
|
|
1448
|
+
return arrayValues[rowIndex] ?? {};
|
|
1449
|
+
}
|
|
1450
|
+
return {};
|
|
1451
|
+
}
|
|
1452
|
+
);
|
|
1453
|
+
void uniForm._fireHandler(
|
|
1454
|
+
`${arrayName}.${child.name}`,
|
|
1455
|
+
value,
|
|
1456
|
+
rowCtx
|
|
1457
|
+
);
|
|
1458
|
+
const indexedKey = `${rowIndex}.${child.name}`;
|
|
1459
|
+
if (indexedKeys.has(indexedKey)) {
|
|
1460
|
+
void uniForm._fireHandler(
|
|
1461
|
+
`${arrayName}.${indexedKey}`,
|
|
1462
|
+
value,
|
|
1463
|
+
rowCtx
|
|
1464
|
+
);
|
|
1465
|
+
}
|
|
1466
|
+
};
|
|
1467
|
+
return {
|
|
1468
|
+
...child,
|
|
1469
|
+
meta: {
|
|
1470
|
+
...child.meta,
|
|
1471
|
+
// Cast to FieldMeta onChange type — ArrayField's bindRowIndexToItemConfig
|
|
1472
|
+
// will call this with the rowIndex third argument at render time.
|
|
1473
|
+
onChange: rowAwareHandler
|
|
1474
|
+
}
|
|
1475
|
+
};
|
|
1476
|
+
});
|
|
1477
|
+
const newItemConfig = {
|
|
1478
|
+
...updated.itemConfig,
|
|
1479
|
+
children: newChildren
|
|
1480
|
+
};
|
|
1481
|
+
if (newItemConfig !== updated.itemConfig)
|
|
1482
|
+
updated = { ...updated, itemConfig: newItemConfig };
|
|
1483
|
+
} else if (itemKeys.size) {
|
|
1198
1484
|
const remappedUniForm = {
|
|
1199
1485
|
_getWatchedFields: () => Array.from(itemKeys),
|
|
1200
1486
|
_fireHandlers: (name, value, c) => uniForm._fireHandler(`${field.name}.${name}`, value, c)
|
|
@@ -1240,18 +1526,43 @@ function injectConditions(fields, conditions) {
|
|
|
1240
1526
|
return updated;
|
|
1241
1527
|
});
|
|
1242
1528
|
}
|
|
1529
|
+
var ROW_KEY_PATTERN = /^(.+?)\.(\d+)\.(.+)$/;
|
|
1243
1530
|
function applyDynamicMeta(fields, overrides) {
|
|
1244
1531
|
if (!Object.keys(overrides).length) return fields;
|
|
1245
1532
|
return fields.map((field) => {
|
|
1246
1533
|
const override = overrides[field.name];
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1534
|
+
let updated = field;
|
|
1535
|
+
if (override) {
|
|
1536
|
+
const { options, label, ...metaOverrides } = override;
|
|
1537
|
+
updated = {
|
|
1538
|
+
...field,
|
|
1539
|
+
...label !== void 0 ? { label } : {},
|
|
1540
|
+
...options !== void 0 ? { options } : {},
|
|
1541
|
+
meta: { ...field.meta, ...metaOverrides }
|
|
1542
|
+
};
|
|
1543
|
+
}
|
|
1544
|
+
if (updated.type === "array") {
|
|
1545
|
+
const prefix = `${updated.name}.`;
|
|
1546
|
+
let rowDynamicMeta;
|
|
1547
|
+
for (const [key, value] of Object.entries(overrides)) {
|
|
1548
|
+
if (!key.startsWith(prefix)) continue;
|
|
1549
|
+
const match = ROW_KEY_PATTERN.exec(key);
|
|
1550
|
+
if (!match) continue;
|
|
1551
|
+
const [, matchedArrayName, indexStr, childField] = match;
|
|
1552
|
+
if (matchedArrayName !== updated.name) continue;
|
|
1553
|
+
const rowIndex = Number(indexStr);
|
|
1554
|
+
if (!rowDynamicMeta) rowDynamicMeta = {};
|
|
1555
|
+
if (!rowDynamicMeta[rowIndex]) rowDynamicMeta[rowIndex] = {};
|
|
1556
|
+
rowDynamicMeta[rowIndex][childField] = value;
|
|
1557
|
+
}
|
|
1558
|
+
if (rowDynamicMeta) {
|
|
1559
|
+
updated = {
|
|
1560
|
+
...updated,
|
|
1561
|
+
_rowDynamicMeta: rowDynamicMeta
|
|
1562
|
+
};
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
return updated;
|
|
1255
1566
|
});
|
|
1256
1567
|
}
|
|
1257
1568
|
function buildDefaults(fields) {
|
|
@@ -1281,6 +1592,12 @@ function buildDefaults(fields) {
|
|
|
1281
1592
|
}
|
|
1282
1593
|
return result;
|
|
1283
1594
|
}
|
|
1595
|
+
|
|
1596
|
+
// src/utils/resolveNullableSlot.ts
|
|
1597
|
+
function resolveNullableSlot(slot, fallback) {
|
|
1598
|
+
if (slot === null) return null;
|
|
1599
|
+
return slot ?? fallback;
|
|
1600
|
+
}
|
|
1284
1601
|
function AutoForm(props) {
|
|
1285
1602
|
const {
|
|
1286
1603
|
form: uniForm,
|
|
@@ -1505,24 +1822,33 @@ function AutoForm(props) {
|
|
|
1505
1822
|
const visibleFields = useConditionalFields(fieldsWithDynamic, control);
|
|
1506
1823
|
const sections = useSectionGrouping(visibleFields);
|
|
1507
1824
|
const resolvedLayout = React3.useMemo(() => {
|
|
1508
|
-
const base =
|
|
1825
|
+
const base = resolveNullableSlot(
|
|
1826
|
+
layout?.arrayButtons?.base,
|
|
1827
|
+
DefaultArrayButton
|
|
1828
|
+
);
|
|
1509
1829
|
const slots = layout?.arrayButtons;
|
|
1510
1830
|
return {
|
|
1511
1831
|
formWrapper: layout?.formWrapper ?? DefaultFormWrapper,
|
|
1512
1832
|
sectionWrapper: layout?.sectionWrapper ?? DefaultSectionWrapper,
|
|
1513
|
-
submitButton:
|
|
1833
|
+
submitButton: resolveNullableSlot(
|
|
1834
|
+
layout?.submitButton,
|
|
1835
|
+
DefaultSubmitButton
|
|
1836
|
+
),
|
|
1514
1837
|
arrayRowLayout: layout?.arrayRowLayout ?? DefaultArrayRowLayout,
|
|
1515
1838
|
arrayFieldLayout: layout?.arrayFieldLayout ?? DefaultArrayFieldLayout,
|
|
1516
1839
|
objectWrapper: layout?.objectWrapper ?? DefaultObjectWrapper,
|
|
1517
1840
|
arrayWrapper: layout?.arrayWrapper ?? DefaultArrayWrapper,
|
|
1518
1841
|
arrayButtons: {
|
|
1519
1842
|
base,
|
|
1520
|
-
add: slots?.add
|
|
1521
|
-
remove: slots?.remove
|
|
1522
|
-
moveUp: slots?.moveUp
|
|
1523
|
-
moveDown: slots?.moveDown
|
|
1524
|
-
duplicate: slots?.duplicate
|
|
1525
|
-
collapse:
|
|
1843
|
+
add: resolveNullableSlot(slots?.add, base),
|
|
1844
|
+
remove: resolveNullableSlot(slots?.remove, base),
|
|
1845
|
+
moveUp: resolveNullableSlot(slots?.moveUp, base),
|
|
1846
|
+
moveDown: resolveNullableSlot(slots?.moveDown, base),
|
|
1847
|
+
duplicate: resolveNullableSlot(slots?.duplicate, base),
|
|
1848
|
+
collapse: resolveNullableSlot(
|
|
1849
|
+
slots?.collapse,
|
|
1850
|
+
DefaultArrayCollapseButton
|
|
1851
|
+
)
|
|
1526
1852
|
},
|
|
1527
1853
|
loadingFallback: layout?.loadingFallback ?? /* @__PURE__ */ jsx("p", { children: "Loading\u2026" })
|
|
1528
1854
|
};
|
|
@@ -1544,6 +1870,7 @@ function AutoForm(props) {
|
|
|
1544
1870
|
const contextValue = React3.useMemo(
|
|
1545
1871
|
() => ({
|
|
1546
1872
|
registry,
|
|
1873
|
+
fieldConfigs: mergedFields,
|
|
1547
1874
|
fieldOverrides: fieldOverridesProp,
|
|
1548
1875
|
fieldWrapper: resolvedFieldWrapper,
|
|
1549
1876
|
layout: resolvedLayout,
|
|
@@ -1552,10 +1879,13 @@ function AutoForm(props) {
|
|
|
1552
1879
|
coercions,
|
|
1553
1880
|
messages,
|
|
1554
1881
|
labels,
|
|
1555
|
-
formMethods
|
|
1882
|
+
formMethods,
|
|
1883
|
+
control,
|
|
1884
|
+
setDynamicMeta
|
|
1556
1885
|
}),
|
|
1557
1886
|
[
|
|
1558
1887
|
registry,
|
|
1888
|
+
mergedFields,
|
|
1559
1889
|
fieldOverridesProp,
|
|
1560
1890
|
resolvedFieldWrapper,
|
|
1561
1891
|
resolvedLayout,
|
|
@@ -1564,7 +1894,9 @@ function AutoForm(props) {
|
|
|
1564
1894
|
coercions,
|
|
1565
1895
|
messages,
|
|
1566
1896
|
labels,
|
|
1567
|
-
formMethods
|
|
1897
|
+
formMethods,
|
|
1898
|
+
control,
|
|
1899
|
+
setDynamicMeta
|
|
1568
1900
|
]
|
|
1569
1901
|
);
|
|
1570
1902
|
if (isLoadingDefaults) {
|
|
@@ -1608,13 +1940,13 @@ function AutoForm(props) {
|
|
|
1608
1940
|
section.title
|
|
1609
1941
|
);
|
|
1610
1942
|
}),
|
|
1611
|
-
/* @__PURE__ */ jsx(
|
|
1943
|
+
SubmitButton ? /* @__PURE__ */ jsx(
|
|
1612
1944
|
SubmitButton,
|
|
1613
1945
|
{
|
|
1614
1946
|
isSubmitting: formState.isSubmitting,
|
|
1615
1947
|
label: labels.submit ?? "Submit"
|
|
1616
1948
|
}
|
|
1617
|
-
)
|
|
1949
|
+
) : null
|
|
1618
1950
|
] })
|
|
1619
1951
|
}
|
|
1620
1952
|
) });
|
|
@@ -1681,6 +2013,10 @@ var UniForm = class {
|
|
|
1681
2013
|
* Replaces any previously registered handler for that field — only one
|
|
1682
2014
|
* handler per field is kept. This prevents accidental handler accumulation
|
|
1683
2015
|
* when called inside a React render cycle.
|
|
2016
|
+
*
|
|
2017
|
+
* Supports both generic array paths (`"tasks.priority"` — fires for all rows)
|
|
2018
|
+
* and indexed paths (`"tasks.0.priority"` — fires only for row 0).
|
|
2019
|
+
*
|
|
1684
2020
|
* Returns `this` for fluent chaining.
|
|
1685
2021
|
*/
|
|
1686
2022
|
setOnChange(field, handler) {
|
|
@@ -1713,7 +2049,35 @@ var UniForm = class {
|
|
|
1713
2049
|
function createForm(schema) {
|
|
1714
2050
|
return new UniForm(schema);
|
|
1715
2051
|
}
|
|
2052
|
+
function findArrayConfig(fields, name) {
|
|
2053
|
+
for (const field of fields) {
|
|
2054
|
+
if (field.name === name) {
|
|
2055
|
+
return field.type === "array" ? field : void 0;
|
|
2056
|
+
}
|
|
2057
|
+
if (field.type === "object") {
|
|
2058
|
+
const found = findArrayConfig(field.children, name);
|
|
2059
|
+
if (found) return found;
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
return void 0;
|
|
2063
|
+
}
|
|
2064
|
+
function useArrayField(fieldName) {
|
|
2065
|
+
const { control, fieldConfigs } = useAutoFormContext();
|
|
2066
|
+
const result = useFieldArray({ control, name: fieldName });
|
|
2067
|
+
const rowCount = result.fields.length;
|
|
2068
|
+
const config = findArrayConfig(fieldConfigs, fieldName);
|
|
2069
|
+
const minItems = config?.minItems;
|
|
2070
|
+
const maxItems = config?.maxItems;
|
|
2071
|
+
const canAdd = maxItems == null || rowCount < maxItems;
|
|
2072
|
+
const atMin = minItems != null && rowCount <= minItems;
|
|
2073
|
+
return {
|
|
2074
|
+
...result,
|
|
2075
|
+
rowCount,
|
|
2076
|
+
canAdd,
|
|
2077
|
+
atMin
|
|
2078
|
+
};
|
|
2079
|
+
}
|
|
1716
2080
|
|
|
1717
|
-
export { AutoForm, DefaultArrayButton, DefaultArrayCollapseButton, DefaultArrayFieldLayout, DefaultArrayRowLayout, DefaultArrayWrapper, DefaultCheckbox, DefaultFieldWrapper, DefaultInput, DefaultObjectWrapper, DefaultSelect, DefaultSubmitButton, FieldRenderer, UniForm, coerceValue, createAutoForm, createForm, defaultCoercionMap, defaultRegistry, introspectObjectSchema, introspectSchema, mergeRegistries, useAutoFormContext, useConditionalFields, useFormPersistence, useSectionGrouping };
|
|
2081
|
+
export { AutoForm, DefaultArrayButton, DefaultArrayCollapseButton, DefaultArrayFieldLayout, DefaultArrayRowLayout, DefaultArrayWrapper, DefaultCheckbox, DefaultFieldWrapper, DefaultInput, DefaultObjectWrapper, DefaultSelect, DefaultSubmitButton, FieldRenderer, UniForm, coerceValue, createAutoForm, createForm, defaultCoercionMap, defaultRegistry, introspectObjectSchema, introspectSchema, mergeRegistries, useArrayField, useAutoFormContext, useConditionalFields, useFormPersistence, useSectionGrouping };
|
|
1718
2082
|
//# sourceMappingURL=index.mjs.map
|
|
1719
2083
|
//# sourceMappingURL=index.mjs.map
|