Skip to content

Commit 313efc6

Browse files
Addressing PR feedback
1 parent 48ee93f commit 313efc6

File tree

2 files changed

+120
-17
lines changed

2 files changed

+120
-17
lines changed

packages/connect-react/src/components/ControlArray.tsx

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import { useState, useEffect, type CSSProperties } from "react";
1+
import {
2+
useState, useEffect, type CSSProperties,
3+
} from "react";
24
import { useFormFieldContext } from "../hooks/form-field-context";
35
import { useCustomize } from "../hooks/customization-context";
46

@@ -14,24 +16,37 @@ export function ControlArray() {
1416
// Initialize values from the current value
1517
const initializeValues = (): string[] => {
1618
if (!value || !Array.isArray(value)) {
17-
return [""];
19+
return [
20+
"",
21+
];
1822
}
19-
20-
const stringValues = value.map(v => typeof v === "string" ? v : JSON.stringify(v));
21-
return stringValues.length > 0 ? stringValues : [""];
23+
24+
const stringValues = value.map((v) => typeof v === "string"
25+
? v
26+
: JSON.stringify(v));
27+
return stringValues.length > 0
28+
? stringValues
29+
: [
30+
"",
31+
];
2232
};
2333

24-
const [values, setValues] = useState<string[]>(initializeValues);
34+
const [
35+
values,
36+
setValues,
37+
] = useState<string[]>(initializeValues);
2538

2639
// Update values when value changes externally
2740
useEffect(() => {
2841
setValues(initializeValues());
29-
}, [value]);
42+
}, [
43+
value,
44+
]);
3045

3146
const updateArray = (newValues: string[]) => {
3247
// Filter out empty values
33-
const validValues = newValues.filter(v => v.trim() !== "");
34-
48+
const validValues = newValues.filter((v) => v.trim() !== "");
49+
3550
if (validValues.length === 0) {
3651
onChange(undefined);
3752
return;
@@ -41,20 +56,29 @@ export function ControlArray() {
4156
};
4257

4358
const handleValueChange = (index: number, newValue: string) => {
44-
const newValues = [...values];
59+
const newValues = [
60+
...values,
61+
];
4562
newValues[index] = newValue;
4663
setValues(newValues);
4764
updateArray(newValues);
4865
};
4966

5067
const addValue = () => {
51-
const newValues = [...values, ""];
68+
const newValues = [
69+
...values,
70+
"",
71+
];
5272
setValues(newValues);
5373
};
5474

5575
const removeValue = (index: number) => {
5676
const newValues = values.filter((_, i) => i !== index);
57-
setValues(newValues.length > 0 ? newValues : [""]);
77+
setValues(newValues.length > 0
78+
? newValues
79+
: [
80+
"",
81+
]);
5882
updateArray(newValues);
5983
};
6084

@@ -104,6 +128,9 @@ export function ControlArray() {
104128
padding: "6px 8px",
105129
};
106130

131+
// Show "Add more" button if the last input has content or if there are multiple inputs
132+
const shouldShowAddMoreButton = values[values.length - 1]?.trim() || values.length > 1;
133+
107134
return (
108135
<div {...getProps("controlArray", containerStyles, formFieldContextProps)}>
109136
{values.map((value, index) => (
@@ -112,7 +139,7 @@ export function ControlArray() {
112139
type="text"
113140
value={value}
114141
onChange={(e) => handleValueChange(index, e.target.value)}
115-
placeholder=""
142+
placeholder=""
116143
style={inputStyles}
117144
required={!prop.optional && index === 0}
118145
/>
@@ -128,7 +155,7 @@ placeholder=""
128155
)}
129156
</div>
130157
))}
131-
{(values[values.length - 1]?.trim() || values.length > 1) && (
158+
{shouldShowAddMoreButton && (
132159
<button
133160
type="button"
134161
onClick={addValue}
@@ -144,4 +171,4 @@ placeholder=""
144171
)}
145172
</div>
146173
);
147-
}
174+
}

packages/connect-react/src/components/ControlObject.tsx

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,22 @@ export function ControlObject() {
1818
getProps, theme,
1919
} = useCustomize();
2020

21+
// Check if the value is a plain object (not Date, Function, etc.)
22+
const isPlainObject = (obj: any): boolean => {
23+
if (obj === null || typeof obj !== "object") {
24+
return false;
25+
}
26+
27+
// Check for Date, Function, RegExp, and other built-in objects
28+
if (obj instanceof Date || obj instanceof Function || obj instanceof RegExp) {
29+
return false;
30+
}
31+
32+
// Check if it's a plain object with Object.prototype or null prototype
33+
const proto = Object.getPrototypeOf(obj);
34+
return proto === Object.prototype || proto === null;
35+
};
36+
2137
// Initialize pairs from the current value
2238
const initializePairs = (): KeyValuePair[] => {
2339
if (!value || typeof value !== "object" || Array.isArray(value)) {
@@ -29,14 +45,30 @@ export function ControlObject() {
2945
];
3046
}
3147

48+
if (!isPlainObject(value)) {
49+
return [
50+
{
51+
key: "",
52+
value: "",
53+
},
54+
];
55+
}
56+
3257
const pairs = Object.entries(value).map(([
3358
k,
3459
v,
3560
]) => ({
3661
key: k,
3762
value: typeof v === "string"
3863
? v
39-
: JSON.stringify(v),
64+
: (() => {
65+
try {
66+
return JSON.stringify(v);
67+
} catch (error) {
68+
// Handle circular references or non-serializable values
69+
return String(v);
70+
}
71+
})(),
4072
}));
4173

4274
return pairs.length > 0
@@ -56,7 +88,51 @@ export function ControlObject() {
5688

5789
// Update pairs when value changes externally
5890
useEffect(() => {
59-
setPairs(initializePairs());
91+
if (!value || typeof value !== "object" || Array.isArray(value)) {
92+
setPairs([
93+
{
94+
key: "",
95+
value: "",
96+
},
97+
]);
98+
return;
99+
}
100+
101+
if (!isPlainObject(value)) {
102+
setPairs([
103+
{
104+
key: "",
105+
value: "",
106+
},
107+
]);
108+
return;
109+
}
110+
111+
const newPairs = Object.entries(value).map(([
112+
k,
113+
v,
114+
]) => ({
115+
key: k,
116+
value: typeof v === "string"
117+
? v
118+
: (() => {
119+
try {
120+
return JSON.stringify(v);
121+
} catch (error) {
122+
// Handle circular references or non-serializable values
123+
return String(v);
124+
}
125+
})(),
126+
}));
127+
128+
setPairs(newPairs.length > 0
129+
? newPairs
130+
: [
131+
{
132+
key: "",
133+
value: "",
134+
},
135+
]);
60136
}, [
61137
value,
62138
]);

0 commit comments

Comments
 (0)