diff --git a/packages/examples/packages/bip32/snap.manifest.json b/packages/examples/packages/bip32/snap.manifest.json
index 6f486d3b0a..472409d061 100644
--- a/packages/examples/packages/bip32/snap.manifest.json
+++ b/packages/examples/packages/bip32/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "EmIaWoL8nod1rTuXeLuMVRItSn4yygM0QwF0575u4pI=",
+ "shasum": "3cyrvn8TOcqu5AG1BfJ+bHNhlGzJNjD1WrvZnGzA9cM=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/bip44/snap.manifest.json b/packages/examples/packages/bip44/snap.manifest.json
index 2cc7973b11..b80df34711 100644
--- a/packages/examples/packages/bip44/snap.manifest.json
+++ b/packages/examples/packages/bip44/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "3MsLr8jtTbv2bEGnK4qfD6OhE16rtXctYYW8LDjbL1U=",
+ "shasum": "PvcD86EO/ZJWmK+OjX1S9Dx7JbLENispYZ0TlxqyBWg=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/browserify-plugin/snap.manifest.json b/packages/examples/packages/browserify-plugin/snap.manifest.json
index c8d56e5520..d23963ce1e 100644
--- a/packages/examples/packages/browserify-plugin/snap.manifest.json
+++ b/packages/examples/packages/browserify-plugin/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "93dNm72NPNodS7UnTsxbAbxEgr81msGHGlBnxasd4hA=",
+ "shasum": "Z7bFULEf26ABMGWFe56MUwxdFqqk7wSXpEqBnVOc0QI=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/browserify/snap.manifest.json b/packages/examples/packages/browserify/snap.manifest.json
index 3f42b544fa..cd71d2cbd6 100644
--- a/packages/examples/packages/browserify/snap.manifest.json
+++ b/packages/examples/packages/browserify/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "rSs7zVVuekYGpvFT7xMmVHUwuJVmrYtJ1TpZiLln4+M=",
+ "shasum": "gkiI/1xzz3QLou/HR+0p8nPGdrr6s3EoVKSIEhpHSEc=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/client-status/snap.manifest.json b/packages/examples/packages/client-status/snap.manifest.json
index 7884b976df..53ee5e927c 100644
--- a/packages/examples/packages/client-status/snap.manifest.json
+++ b/packages/examples/packages/client-status/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "Lw+o0xSBK3RLoxMPA3VV9pcJts7slKwlw/FLH2os7Rs=",
+ "shasum": "QR/NJxBMFk0XrPJyuVgcFuR/YiqLKdj2JZjxkY4lZj0=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/cronjobs/snap.manifest.json b/packages/examples/packages/cronjobs/snap.manifest.json
index d5afd08e6e..9e7121c0e9 100644
--- a/packages/examples/packages/cronjobs/snap.manifest.json
+++ b/packages/examples/packages/cronjobs/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "suKnTPMwveOjTGAh5LZhnEflYUfoEclrm7MEQMekFSc=",
+ "shasum": "+4Yl3+BXI3uaZfjSrQxuPMLQY2476cAO/FcR/a2jycU=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/dialogs/snap.manifest.json b/packages/examples/packages/dialogs/snap.manifest.json
index cb72e0f2ce..60a934cbd7 100644
--- a/packages/examples/packages/dialogs/snap.manifest.json
+++ b/packages/examples/packages/dialogs/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "sVbh3wlE3T2kxAgUvCwBk7aBxmJGwyMYojvVamglYyc=",
+ "shasum": "g2p8BK9pJXrC9/hJw+n3BkBKDfS0Dng/oR1cJGLrnuc=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/ethereum-provider/snap.manifest.json b/packages/examples/packages/ethereum-provider/snap.manifest.json
index 99c196d239..d6d24254af 100644
--- a/packages/examples/packages/ethereum-provider/snap.manifest.json
+++ b/packages/examples/packages/ethereum-provider/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "iha5MN97D891xWP1typXrc0OHZAyRZQRQgpbrYtrub0=",
+ "shasum": "8cRG0o0f7+IZWgMNYyAHRO3Nrht3779FDBiNclCYxYU=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/ethers-js/snap.manifest.json b/packages/examples/packages/ethers-js/snap.manifest.json
index 56b726c77f..43f7629016 100644
--- a/packages/examples/packages/ethers-js/snap.manifest.json
+++ b/packages/examples/packages/ethers-js/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "D7hWiwyKT0CVTINjQZvUDKk3kj8mhngADM1bSKpp/js=",
+ "shasum": "Zqdf6Sl/sfvJYl7A87/BB7e0nhdXqe+0KxIeGxnjr5g=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/file-upload/snap.manifest.json b/packages/examples/packages/file-upload/snap.manifest.json
index 9e32641e66..c03fd8e5c2 100644
--- a/packages/examples/packages/file-upload/snap.manifest.json
+++ b/packages/examples/packages/file-upload/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "LtCe3Khdid7ufThHQQEJb1OOrO72iD5uyK7B2DQRi4c=",
+ "shasum": "Ko0mJ92OTHqNdBu/CHrMImRa+Afyr8AsEyojCczLLsc=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/get-entropy/snap.manifest.json b/packages/examples/packages/get-entropy/snap.manifest.json
index 43d147d03d..d548afcbfe 100644
--- a/packages/examples/packages/get-entropy/snap.manifest.json
+++ b/packages/examples/packages/get-entropy/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "zuc2MclbVUnpaFuvx3H1HwYsJymvVsfJsBq1wrSEElQ=",
+ "shasum": "Ii9gvF7VRzccakiuibaWqR5fcGUmn3bADL6vSxr5Lc8=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/get-file/snap.manifest.json b/packages/examples/packages/get-file/snap.manifest.json
index bab5831c93..fab639f5e1 100644
--- a/packages/examples/packages/get-file/snap.manifest.json
+++ b/packages/examples/packages/get-file/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "eiyB374KOWchfjaUeqCmN5wpKhBNb1yNiTobgJMJG6I=",
+ "shasum": "d7GagnmYnwhrnLc+oQQV7IC9f4cPRM8BZUeQ50cuydA=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/home-page/snap.manifest.json b/packages/examples/packages/home-page/snap.manifest.json
index c75f7d5786..377a5a4071 100644
--- a/packages/examples/packages/home-page/snap.manifest.json
+++ b/packages/examples/packages/home-page/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "RZyBT/FIDK7GtFwshSGOYXczOrVteUn4H5DS+ZbgsbU=",
+ "shasum": "YMn4Z3+ddOce0OOYrk39M+kmlaIXfYaurjAOWpJhzp0=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/images/snap.manifest.json b/packages/examples/packages/images/snap.manifest.json
index b450de22f4..c10843f18f 100644
--- a/packages/examples/packages/images/snap.manifest.json
+++ b/packages/examples/packages/images/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "xcXlfc8BGEa4XLJ9uGTWNveYej9QikFZn4nQ9NdxlsM=",
+ "shasum": "roTBoTud+bVBTfv04q2wAIOzbV75XAIPTa+fbs+u4S0=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/interactive-ui/snap.manifest.json b/packages/examples/packages/interactive-ui/snap.manifest.json
index 931d7c069f..3c51e8e2c5 100644
--- a/packages/examples/packages/interactive-ui/snap.manifest.json
+++ b/packages/examples/packages/interactive-ui/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "Q5Uq4v0Mmevehh0PIJvusWEHFH+ITLysyyY+17JUsK0=",
+ "shasum": "6k3MXI/vf6lRt5uVk586yydm6LZaqS0NZ4TP2se6XBg=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/invoke-snap/packages/consumer-signer/snap.manifest.json b/packages/examples/packages/invoke-snap/packages/consumer-signer/snap.manifest.json
index 68088609f9..8cd98c0c8f 100644
--- a/packages/examples/packages/invoke-snap/packages/consumer-signer/snap.manifest.json
+++ b/packages/examples/packages/invoke-snap/packages/consumer-signer/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "Xr795QUI4U++cOYMm9FVpXVarO1mjIDSjKF+QQF2UZI=",
+ "shasum": "wWbKF414M1/e1r9bG0Y+Ntbcn1XX7DIml4pwl041Uug=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/invoke-snap/packages/core-signer/snap.manifest.json b/packages/examples/packages/invoke-snap/packages/core-signer/snap.manifest.json
index 95b3b01ce0..08e8ad7544 100644
--- a/packages/examples/packages/invoke-snap/packages/core-signer/snap.manifest.json
+++ b/packages/examples/packages/invoke-snap/packages/core-signer/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "1E0eIMXYC+twPeiAqcuRRPu5fxf5FD4f1dV08VUGwK0=",
+ "shasum": "xvwZwBbmoekH92t7tYei5dZ5uKxtdvz85kesxMab8mo=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/json-rpc/snap.manifest.json b/packages/examples/packages/json-rpc/snap.manifest.json
index 74aa5d5ddc..54dfbdaa7c 100644
--- a/packages/examples/packages/json-rpc/snap.manifest.json
+++ b/packages/examples/packages/json-rpc/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "yJziKY8cECUlDoxP8VFfsH2oEhPFn0ZWKFbYPkjujpM=",
+ "shasum": "WxAHmnlgdoRw7w0u8B9N3C8aB52epM3JUy2TpFRu46g=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/jsx/snap.manifest.json b/packages/examples/packages/jsx/snap.manifest.json
index 6ce7ca8f05..6aa4c5e92a 100644
--- a/packages/examples/packages/jsx/snap.manifest.json
+++ b/packages/examples/packages/jsx/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "VFtSPt9oGHKJZJT0+xPNssG/2ihl+rXg5gQGFTnHfrk=",
+ "shasum": "yP7SkzjBPN5/uvEnqGjTGGyq5GBHPm8py/VNJW0h//4=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/lifecycle-hooks/snap.manifest.json b/packages/examples/packages/lifecycle-hooks/snap.manifest.json
index 9b8f67d90c..222bf95150 100644
--- a/packages/examples/packages/lifecycle-hooks/snap.manifest.json
+++ b/packages/examples/packages/lifecycle-hooks/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "oLzmeZcE9qxgf+jQpA9OiqFpuf2dfBT3Y9nED5z6nWs=",
+ "shasum": "/WjyMJSHqfad0PNKZGei84ChfrZQiQpOCumQpDxSZ7A=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/localization/snap.manifest.json b/packages/examples/packages/localization/snap.manifest.json
index f828c0bdc5..ea759c8386 100644
--- a/packages/examples/packages/localization/snap.manifest.json
+++ b/packages/examples/packages/localization/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "Se1CTGg3ExDVv9SNZ6oaAE4ADWDYiET+Y4OW7N+P8xE=",
+ "shasum": "xnBCnKIYB1IJXLUx0iDC4U+QdGVDM72i4uQ9+vVupBo=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/manage-state/snap.manifest.json b/packages/examples/packages/manage-state/snap.manifest.json
index 928a360a86..8372d8c033 100644
--- a/packages/examples/packages/manage-state/snap.manifest.json
+++ b/packages/examples/packages/manage-state/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "wwwWEa/1xj0n+1uUmkCs7tUYvDcbfoDYQKOXfJfPJuY=",
+ "shasum": "SRpkwJ5zj0JuY112AOcufRVqqsAheKhEtv4D9WqVvZY=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/network-access/snap.manifest.json b/packages/examples/packages/network-access/snap.manifest.json
index a85dffa0de..75175e34f5 100644
--- a/packages/examples/packages/network-access/snap.manifest.json
+++ b/packages/examples/packages/network-access/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "6cLHi5YriTK9gqn9cOx6CJavruqrkhRLaX/Ckgy6s4s=",
+ "shasum": "JZ2kwUDXE7cu77OVONa8GdxwjUSqMqgv3JKUPSArElg=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/notifications/snap.manifest.json b/packages/examples/packages/notifications/snap.manifest.json
index 5740adff5e..92ac7fd2c3 100644
--- a/packages/examples/packages/notifications/snap.manifest.json
+++ b/packages/examples/packages/notifications/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "UPKvEsDiuFKi9GAm42/PaCXR9iy4yf7sHVF4dl4Sc84=",
+ "shasum": "JR9gpxBsEizgvJLKe7cjMHnEUks/dlmK/kTq+OcdcIo=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/rollup-plugin/snap.manifest.json b/packages/examples/packages/rollup-plugin/snap.manifest.json
index 14a77aa5f8..95a9e4846d 100644
--- a/packages/examples/packages/rollup-plugin/snap.manifest.json
+++ b/packages/examples/packages/rollup-plugin/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "Vx4Qu2N6v706JMplTl9yZjjY+E1SzH3E4kRvPS6aO9c=",
+ "shasum": "NVGTP6xdPKOSoReiGTr18o8r08qTsQqAE4JP+f9aisU=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/signature-insights/snap.manifest.json b/packages/examples/packages/signature-insights/snap.manifest.json
index 3273fe7fad..830aa27ef7 100644
--- a/packages/examples/packages/signature-insights/snap.manifest.json
+++ b/packages/examples/packages/signature-insights/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "tRru7Bgry6u3eoboCgkXy5pAYrEDVhVVZg0CcTI8K88=",
+ "shasum": "X8e8OA1+EUjGr0uVpwkvmKEFGdOE8Sif1ngaGEh5SmU=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/transaction-insights/snap.manifest.json b/packages/examples/packages/transaction-insights/snap.manifest.json
index ca67591732..6d472637e1 100644
--- a/packages/examples/packages/transaction-insights/snap.manifest.json
+++ b/packages/examples/packages/transaction-insights/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "+sNj2KKAA6mES8j1X544gahfD1EVxN7NUruGHug7PAw=",
+ "shasum": "w7qMjYQa/4n/DMD33zMRIW6YGtp4vOiAC1GIzebGF6M=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/wasm/snap.manifest.json b/packages/examples/packages/wasm/snap.manifest.json
index 1567ff020d..5413372445 100644
--- a/packages/examples/packages/wasm/snap.manifest.json
+++ b/packages/examples/packages/wasm/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "wrvKQQKLWFp3fD4gVxAUd/g89JCMk3dYCTh/jTvmrl0=",
+ "shasum": "afWjohN+iHMlPf+cooYW1l9bkvdxHNu5coHTSIVixlI=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/examples/packages/webpack-plugin/snap.manifest.json b/packages/examples/packages/webpack-plugin/snap.manifest.json
index 57fed9017a..b52da23ea2 100644
--- a/packages/examples/packages/webpack-plugin/snap.manifest.json
+++ b/packages/examples/packages/webpack-plugin/snap.manifest.json
@@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
- "shasum": "g2mArhUUuqRTQKapIisLg0ZcjmrOuDa+9K+LHyUBdJ8=",
+ "shasum": "Vqgei7k5/YlpTKwwRtQMltlGMZJF6AWR/2UY9UYjMAo=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
diff --git a/packages/snaps-controllers/coverage.json b/packages/snaps-controllers/coverage.json
index 8ecb65b9fd..263bcd6345 100644
--- a/packages/snaps-controllers/coverage.json
+++ b/packages/snaps-controllers/coverage.json
@@ -1,6 +1,6 @@
{
- "branches": 91.78,
- "functions": 96.77,
- "lines": 97.9,
- "statements": 97.57
+ "branches": 91.98,
+ "functions": 96.73,
+ "lines": 97.95,
+ "statements": 97.63
}
diff --git a/packages/snaps-controllers/src/interface/utils.test.tsx b/packages/snaps-controllers/src/interface/utils.test.tsx
index 7fad537297..59f41f9ae9 100644
--- a/packages/snaps-controllers/src/interface/utils.test.tsx
+++ b/packages/snaps-controllers/src/interface/utils.test.tsx
@@ -305,6 +305,61 @@ describe('constructState', () => {
});
});
+ it('supports nested fields', () => {
+ const element = (
+
+
+
+ );
+
+ const result = constructState({}, element);
+ expect(result).toStrictEqual({
+ form: { bar: 'option2' },
+ });
+ });
+
+ it('supports nested forms by tying fields to nearest form', () => {
+ const element = (
+
+
+
+ );
+
+ const result = constructState({}, element);
+ expect(result).toStrictEqual({
+ form: { baz: 'option4' },
+ form2: { bar: 'option2' },
+ });
+ });
+
it('deletes unused root level values', () => {
const element = (
diff --git a/packages/snaps-controllers/src/interface/utils.ts b/packages/snaps-controllers/src/interface/utils.ts
index 8ef7b6fa27..f1965bbd08 100644
--- a/packages/snaps-controllers/src/interface/utils.ts
+++ b/packages/snaps-controllers/src/interface/utils.ts
@@ -4,21 +4,21 @@ import type {
InterfaceState,
ComponentOrElement,
InterfaceContext,
+ State,
} from '@metamask/snaps-sdk';
import type {
- ButtonElement,
DropdownElement,
- FieldElement,
- FileInputElement,
InputElement,
JSXElement,
OptionElement,
+ FileInputElement,
} from '@metamask/snaps-sdk/jsx';
import { isJSXElementUnsafe } from '@metamask/snaps-sdk/jsx';
import {
getJsonSizeUnsafe,
getJsxChildren,
getJsxElementFromComponent,
+ walkJsx,
} from '@metamask/snaps-utils';
/**
@@ -75,143 +75,88 @@ function constructComponentSpecificDefaultState(
*
* @param oldState - The previous state.
* @param element - The input element.
+ * @param form - An optional form that the input is enclosed in.
* @returns The input state.
*/
function constructInputState(
oldState: InterfaceState,
element: InputElement | DropdownElement | FileInputElement,
+ form?: string,
) {
- if (element.type === 'FileInput') {
- return oldState[element.props.name] ?? null;
- }
-
- return (
- element.props.value ??
- oldState[element.props.name] ??
- constructComponentSpecificDefaultState(element) ??
- null
- );
-}
-
-/**
- * Construct the state for a form input.
- *
- * @param oldState - The previous state.
- * @param component - The input element.
- * @param form - The parent form name of the input.
- * @returns The input state.
- */
-function constructFormInputState(
- oldState: InterfaceState,
- component: InputElement | DropdownElement | FileInputElement,
- form: string,
-) {
- const oldFormState = oldState[form] as FormState;
- const oldInputState = oldFormState?.[component.props.name];
+ const oldStateUnwrapped = form ? (oldState[form] as FormState) : oldState;
+ const oldInputState = oldStateUnwrapped?.[element.props.name] as State;
- if (component.type === 'FileInput') {
+ if (element.type === 'FileInput') {
return oldInputState ?? null;
}
return (
- component.props.value ??
+ element.props.value ??
oldInputState ??
- constructComponentSpecificDefaultState(component) ??
+ constructComponentSpecificDefaultState(element) ??
null
);
}
-/**
- * Get the input field from a field element.
- *
- * @param element - The field element.
- * @returns The input element.
- */
-function getFieldInput(element: FieldElement) {
- if (Array.isArray(element.props.children)) {
- return element.props.children[0];
- }
-
- return element.props.children;
-}
-
-/**
- * Construct the state for a form input.
- *
- * @param oldState - The previous state.
- * @param component - The field element.
- * @param form - The parent form name of the input.
- * @param newState - The new state.
- * @returns The input state.
- */
-function constructFormState(
- oldState: InterfaceState,
- component: FieldElement | ButtonElement,
- form: string,
- newState: FormState,
-): FormState {
- if (component.type === 'Button') {
- return newState;
- }
-
- const input = getFieldInput(component);
- assertNameIsUnique(newState, input.props.name);
-
- newState[input.props.name] = constructFormInputState(oldState, input, form);
-
- return newState;
-}
-
/**
* Construct the interface state for a given component tree.
*
* @param oldState - The previous state.
- * @param component - The UI component to construct state from.
- * @param newState - The state that is being constructed.
+ * @param rootComponent - The UI component to construct state from.
* @returns The interface state of the passed component.
*/
export function constructState(
oldState: InterfaceState,
- component: JSXElement,
- newState: InterfaceState = {},
+ rootComponent: JSXElement,
): InterfaceState {
- if (component.type === 'Box') {
- const children = getJsxChildren(component);
- return children.reduce(
- (accumulator, node) =>
- constructState(oldState, node as JSXElement, accumulator),
- newState,
- );
- }
-
- if (component.type === 'Form') {
- assertNameIsUnique(newState, component.props.name);
-
- const children = getJsxChildren(component);
- newState[component.props.name] = children.reduce(
- (accumulator, node) => {
- return constructFormState(
- oldState,
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
- node as FieldElement | ButtonElement,
- component.props.name,
- accumulator,
- );
- },
- {},
- );
-
- return newState;
- }
-
- if (
- component.type === 'Input' ||
- component.type === 'Dropdown' ||
- component.type === 'FileInput'
- ) {
- assertNameIsUnique(newState, component.props.name);
- newState[component.props.name] = constructInputState(oldState, component);
- }
+ const newState: InterfaceState = {};
+
+ // Stack containing the forms we have visited and at which depth
+ const formStack: { name: string; depth: number }[] = [];
+
+ walkJsx(rootComponent, (component, depth) => {
+ let currentForm = formStack[formStack.length - 1];
+
+ // Pop the current form of the stack once we leave its depth.
+ if (currentForm && depth <= currentForm.depth) {
+ formStack.pop();
+ currentForm = formStack[formStack.length - 1];
+ }
+
+ if (component.type === 'Form') {
+ assertNameIsUnique(newState, component.props.name);
+ formStack.push({ name: component.props.name, depth });
+ newState[component.props.name] = {};
+ return;
+ }
+
+ // Stateful components inside a form
+ if (
+ currentForm &&
+ (component.type === 'Input' ||
+ component.type === 'Dropdown' ||
+ component.type === 'FileInput')
+ ) {
+ const formState = newState[currentForm.name] as FormState;
+ assertNameIsUnique(formState, component.props.name);
+ formState[component.props.name] = constructInputState(
+ oldState,
+ component,
+ currentForm.name,
+ );
+ return;
+ }
+
+ // Stateful components outside a form
+ if (
+ component.type === 'Input' ||
+ component.type === 'Dropdown' ||
+ component.type === 'FileInput'
+ ) {
+ assertNameIsUnique(newState, component.props.name);
+ newState[component.props.name] = constructInputState(oldState, component);
+ }
+ });
return newState;
}
diff --git a/packages/snaps-sdk/src/jsx/components/form/Form.ts b/packages/snaps-sdk/src/jsx/components/form/Form.ts
index 6c80870823..be1671c22f 100644
--- a/packages/snaps-sdk/src/jsx/components/form/Form.ts
+++ b/packages/snaps-sdk/src/jsx/components/form/Form.ts
@@ -1,19 +1,17 @@
-import type { MaybeArray } from '../../component';
+import type { GenericSnapElement, MaybeArray } from '../../component';
import { createSnapComponent } from '../../component';
-import type { ButtonElement } from './Button';
-import type { FieldElement } from './Field';
// TODO: Add `onSubmit` prop to the `FormProps` type.
/**
* The props of the {@link Form} component.
*
- * @property children - The form fields. See {@link Field}.
+ * @property children - The children of the form.
* @property name - The name of the form. This is used to identify the form in
* the event handler.
*/
export type FormProps = {
- children: MaybeArray;
+ children: MaybeArray;
name: string;
};
diff --git a/packages/snaps-sdk/src/jsx/validation.test.tsx b/packages/snaps-sdk/src/jsx/validation.test.tsx
index f99f85124b..eb6a2a0efa 100644
--- a/packages/snaps-sdk/src/jsx/validation.test.tsx
+++ b/packages/snaps-sdk/src/jsx/validation.test.tsx
@@ -285,9 +285,6 @@ describe('FormStruct', () => {
[],
// @ts-expect-error - Invalid props.
,
- ,