diff --git a/package-lock.json b/package-lock.json index 46548f8a..0f4f07b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,9 +15,8 @@ "lodash.camelcase": "^4.3.0", "lodash.clonedeep": "^4.5.0", "lodash.debounce": "^4.0.8", - "lodash.get": "^4.4.2", "lodash.isequal": "^4.5.0", - "lodash.set": "^4.3.2", + "lodash.merge": "^4.6.2", "lodash.uniqueid": "^4.0.1", "react-intl": "^6.3.2", "react-select": "^5.7.2", @@ -36,7 +35,7 @@ "@formatjs/cli": "^6.1.1", "@formatjs/ts-transformer": "^3.12.0", "@fortawesome/fontawesome-free": "^6.4.0", - "@open-formulieren/types": "^0.9.0", + "@open-formulieren/types": "^0.10.0", "@storybook/addon-actions": "^7.3.2", "@storybook/addon-essentials": "^7.3.2", "@storybook/addon-interactions": "^7.3.2", @@ -51,9 +50,8 @@ "@types/lodash.camelcase": "^4.3.7", "@types/lodash.clonedeep": "^4.5.7", "@types/lodash.debounce": "^4.0.7", - "@types/lodash.get": "^4.4.7", "@types/lodash.isequal": "^4.5.6", - "@types/lodash.set": "^4.3.7", + "@types/lodash.merge": "^4.6.7", "@types/lodash.uniqueid": "^4.0.7", "@types/react": "^18.0.33", "@types/sanitize-html": "^2.9.0", @@ -80,9 +78,9 @@ } }, "node_modules/@adobe/css-tools": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.2.0.tgz", - "integrity": "sha512-E09FiIft46CmH5Qnjb0wsW54/YQd69LsxeKUOWawmws1XWvyFGURnAChH0mlr7YPFR1ofwvUQfcL0J3lMxXqPA==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.1.tgz", + "integrity": "sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg==", "dev": true }, "node_modules/@ampproject/remapping": { @@ -5870,9 +5868,9 @@ } }, "node_modules/@open-formulieren/types": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@open-formulieren/types/-/types-0.9.0.tgz", - "integrity": "sha512-zYsktHug8lLJNBa+JBlGKhLLif1d+R0D67kl1ZZg4dh/Ma4qYwppVjYCZZopre+ox5i53MeZwj2aUdCWrVE0kQ==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@open-formulieren/types/-/types-0.10.0.tgz", + "integrity": "sha512-OIrMhT1UHvQk2rYFmzts4LUhq8t8JqkOitjRcA52I6Nfgf5VymFZfZDEcIFzns7mjFjeGKaxdlviHy+KEj91GA==", "dev": true }, "node_modules/@pkgjs/parseargs": { @@ -14860,15 +14858,6 @@ "@types/lodash": "*" } }, - "node_modules/@types/lodash.get": { - "version": "4.4.7", - "resolved": "https://registry.npmjs.org/@types/lodash.get/-/lodash.get-4.4.7.tgz", - "integrity": "sha512-af34Mj+KdDeuzsJBxc/XeTtOx0SZHZNLd+hdrn+PcKGQs0EG2TJTzQAOTCZTgDJCArahlCzLWSy8c2w59JRz7Q==", - "dev": true, - "dependencies": { - "@types/lodash": "*" - } - }, "node_modules/@types/lodash.isequal": { "version": "4.5.6", "resolved": "https://registry.npmjs.org/@types/lodash.isequal/-/lodash.isequal-4.5.6.tgz", @@ -14878,10 +14867,10 @@ "@types/lodash": "*" } }, - "node_modules/@types/lodash.set": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/@types/lodash.set/-/lodash.set-4.3.7.tgz", - "integrity": "sha512-bS5Wkg/nrT82YUfkNYPSccFrNZRL+irl7Yt4iM6OTSQ0VZJED2oUIVm15NkNtUAQ8SRhCe+axqERUV6MJgkeEg==", + "node_modules/@types/lodash.merge": { + "version": "4.6.7", + "resolved": "https://registry.npmjs.org/@types/lodash.merge/-/lodash.merge-4.6.7.tgz", + "integrity": "sha512-OwxUJ9E50gw3LnAefSHJPHaBLGEKmQBQ7CZe/xflHkyy/wH2zVyEIAKReHvVrrn7zKdF58p16We9kMfh7v0RRQ==", "dev": true, "dependencies": { "@types/lodash": "*" @@ -20827,9 +20816,9 @@ } }, "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -24196,9 +24185,9 @@ "dev": true }, "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.4.0.tgz", - "integrity": "sha512-RgOxM8Mw+7Zus0+zcLEUn8+JfoLpj/huFTItQy2hsM4khuC1HYRDp0cU482Ewn/Fcy6bCjufD8vAj7voC66KQw==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -25560,20 +25549,15 @@ "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", "dev": true }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" - }, "node_modules/lodash.isequal": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" }, - "node_modules/lodash.set": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==" + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, "node_modules/lodash.uniqueid": { "version": "4.0.1", @@ -25720,9 +25704,9 @@ } }, "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -26434,9 +26418,9 @@ } }, "node_modules/nyc/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -27105,9 +27089,9 @@ } }, "node_modules/postcss": { - "version": "8.4.21", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", - "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "funding": [ { "type": "opencollective", @@ -27116,10 +27100,14 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -28632,9 +28620,9 @@ } }, "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, "bin": { "semver": "bin/semver" @@ -30776,9 +30764,9 @@ } }, "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "engines": { "node": ">=0.10.0" @@ -31018,9 +31006,9 @@ } }, "node_modules/zod": { - "version": "3.21.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz", - "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==", + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", "funding": { "url": "https://github.com/sponsors/colinhacks" } @@ -31037,9 +31025,9 @@ }, "dependencies": { "@adobe/css-tools": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.2.0.tgz", - "integrity": "sha512-E09FiIft46CmH5Qnjb0wsW54/YQd69LsxeKUOWawmws1XWvyFGURnAChH0mlr7YPFR1ofwvUQfcL0J3lMxXqPA==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.1.tgz", + "integrity": "sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg==", "dev": true }, "@ampproject/remapping": { @@ -35284,9 +35272,9 @@ } }, "@open-formulieren/types": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@open-formulieren/types/-/types-0.9.0.tgz", - "integrity": "sha512-zYsktHug8lLJNBa+JBlGKhLLif1d+R0D67kl1ZZg4dh/Ma4qYwppVjYCZZopre+ox5i53MeZwj2aUdCWrVE0kQ==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@open-formulieren/types/-/types-0.10.0.tgz", + "integrity": "sha512-OIrMhT1UHvQk2rYFmzts4LUhq8t8JqkOitjRcA52I6Nfgf5VymFZfZDEcIFzns7mjFjeGKaxdlviHy+KEj91GA==", "dev": true }, "@pkgjs/parseargs": { @@ -41635,15 +41623,6 @@ "@types/lodash": "*" } }, - "@types/lodash.get": { - "version": "4.4.7", - "resolved": "https://registry.npmjs.org/@types/lodash.get/-/lodash.get-4.4.7.tgz", - "integrity": "sha512-af34Mj+KdDeuzsJBxc/XeTtOx0SZHZNLd+hdrn+PcKGQs0EG2TJTzQAOTCZTgDJCArahlCzLWSy8c2w59JRz7Q==", - "dev": true, - "requires": { - "@types/lodash": "*" - } - }, "@types/lodash.isequal": { "version": "4.5.6", "resolved": "https://registry.npmjs.org/@types/lodash.isequal/-/lodash.isequal-4.5.6.tgz", @@ -41653,10 +41632,10 @@ "@types/lodash": "*" } }, - "@types/lodash.set": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/@types/lodash.set/-/lodash.set-4.3.7.tgz", - "integrity": "sha512-bS5Wkg/nrT82YUfkNYPSccFrNZRL+irl7Yt4iM6OTSQ0VZJED2oUIVm15NkNtUAQ8SRhCe+axqERUV6MJgkeEg==", + "@types/lodash.merge": { + "version": "4.6.7", + "resolved": "https://registry.npmjs.org/@types/lodash.merge/-/lodash.merge-4.6.7.tgz", + "integrity": "sha512-OwxUJ9E50gw3LnAefSHJPHaBLGEKmQBQ7CZe/xflHkyy/wH2zVyEIAKReHvVrrn7zKdF58p16We9kMfh7v0RRQ==", "dev": true, "requires": { "@types/lodash": "*" @@ -46274,9 +46253,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true } } @@ -48941,9 +48920,9 @@ "dev": true }, "semver": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.4.0.tgz", - "integrity": "sha512-RgOxM8Mw+7Zus0+zcLEUn8+JfoLpj/huFTItQy2hsM4khuC1HYRDp0cU482Ewn/Fcy6bCjufD8vAj7voC66KQw==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -49890,20 +49869,15 @@ "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", "dev": true }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" - }, "lodash.isequal": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" }, - "lodash.set": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==" + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, "lodash.uniqueid": { "version": "4.0.1", @@ -50013,9 +49987,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true } } @@ -50554,9 +50528,9 @@ } }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true }, "wrap-ansi": { @@ -51055,11 +51029,11 @@ } }, "postcss": { - "version": "8.4.21", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", - "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "requires": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } @@ -52183,9 +52157,9 @@ "integrity": "sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==" }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true }, "send": { @@ -53808,9 +53782,9 @@ } }, "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true }, "wordwrap": { @@ -53984,9 +53958,9 @@ "dev": true }, "zod": { - "version": "3.21.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz", - "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==" + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==" }, "zod-formik-adapter": { "version": "1.2.0", diff --git a/package.json b/package.json index 46980148..25ad1653 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "@formatjs/cli": "^6.1.1", "@formatjs/ts-transformer": "^3.12.0", "@fortawesome/fontawesome-free": "^6.4.0", - "@open-formulieren/types": "^0.9.0", + "@open-formulieren/types": "^0.10.0", "@storybook/addon-actions": "^7.3.2", "@storybook/addon-essentials": "^7.3.2", "@storybook/addon-interactions": "^7.3.2", @@ -76,9 +76,8 @@ "@types/lodash.camelcase": "^4.3.7", "@types/lodash.clonedeep": "^4.5.7", "@types/lodash.debounce": "^4.0.7", - "@types/lodash.get": "^4.4.7", "@types/lodash.isequal": "^4.5.6", - "@types/lodash.set": "^4.3.7", + "@types/lodash.merge": "^4.6.7", "@types/lodash.uniqueid": "^4.0.7", "@types/react": "^18.0.33", "@types/sanitize-html": "^2.9.0", @@ -106,9 +105,8 @@ "lodash.camelcase": "^4.3.0", "lodash.clonedeep": "^4.5.0", "lodash.debounce": "^4.0.8", - "lodash.get": "^4.4.2", "lodash.isequal": "^4.5.0", - "lodash.set": "^4.3.2", + "lodash.merge": "^4.6.2", "lodash.uniqueid": "^4.0.1", "react-intl": "^6.3.2", "react-select": "^5.7.2", diff --git a/src/components/ComponentEditForm.tsx b/src/components/ComponentEditForm.tsx index b1c7125c..89399c5c 100644 --- a/src/components/ComponentEditForm.tsx +++ b/src/components/ComponentEditForm.tsx @@ -1,7 +1,7 @@ import {Form, Formik} from 'formik'; import {ExtendedComponentSchema} from 'formiojs/types/components/schema'; import cloneDeep from 'lodash.clonedeep'; -import set from 'lodash.set'; +import merge from 'lodash.merge'; import {FormattedMessage, useIntl} from 'react-intl'; import {toFormikValidationSchema} from 'zod-formik-adapter'; @@ -19,8 +19,6 @@ export interface BuilderInfo { weight: number; } -type ObjecEntry = [K, T[K]]; - export interface ComponentEditFormProps { isNew: boolean; // it is (currently) possible someone drags a component type into the canvas that we @@ -45,16 +43,9 @@ const ComponentEditForm: React.FC = ({ const registryEntry = getRegistryEntry(component); const {edit: EditForm, editSchema: zodSchema} = registryEntry; - // FIXME: recipes may have non-default values that would be overwritten here with default - // values - we need a deep merge & some logic to detect this. - const initialValues = cloneDeep(component); + let initialValues = cloneDeep(component); if (isNew && isKnownComponentType(component)) { - Object.entries(EditForm.defaultValues).forEach( - ([key, value]: ObjecEntry) => { - const val = component?.[key] || value; - set(initialValues, key, val); - } - ); + initialValues = merge(EditForm.defaultValues, initialValues); } // we infer the specific schema from the EditForm component obtained from the registry. diff --git a/src/components/builder/description.tsx b/src/components/builder/description.tsx index 7fa7967b..c78b6e30 100644 --- a/src/components/builder/description.tsx +++ b/src/components/builder/description.tsx @@ -1,21 +1,14 @@ import {FormattedMessage} from 'react-intl'; import {TextField} from '../formio'; +import {LABELS} from './messages'; /* * The description contains additional useful information/hints for a given field to * clarify what's expected by the end-user filling out the form. */ const Description: React.FC = () => ( - - } - /> + } /> ); export default Description; diff --git a/src/components/builder/i18n.stories.tsx b/src/components/builder/i18n.stories.tsx index e2450c57..f27e0db1 100644 --- a/src/components/builder/i18n.stories.tsx +++ b/src/components/builder/i18n.stories.tsx @@ -1,11 +1,11 @@ import {expect} from '@storybook/jest'; -import {Meta, StoryFn} from '@storybook/react'; +import {Meta, StoryFn, StoryObj} from '@storybook/react'; import {userEvent, waitFor, within} from '@storybook/testing-library'; import {Formik} from 'formik'; import {TextField} from '@/components/formio'; -import {ComponentTranslations, useManageTranslations} from './i18n'; +import {ComponentTranslations} from './i18n'; export default { title: 'Formio/Builder/i18n/ComponentTranslations', @@ -21,83 +21,91 @@ export default { modal: {noModal: true}, builder: { enableContext: true, + // 'de' is not part of the languages type, but this is fine at runtime supportedLanguageCodes: ['nl', 'en', 'de'], - translationsStore: { - nl: { - 'Literal 1': 'Vertaling 1', - }, - en: {}, - de: {}, - }, }, }, args: { - translatableFields: ['translatableField', 'nested.translatableField'], + fieldLabels: { + label: 'Label', + description: 'Description', + }, + initialValues: { - translatableField: 'Literal 1', + label: 'Hi there {{ firstName }}', nonTranslatableField: '', - nested: {translatableField: ''}, - openForms: {translations: {}}, + openForms: { + translations: { + nl: { + label: 'Hallo daar, {{ firstName }}', + }, + }, + }, }, }, } as Meta; interface BodyProps { - translatableFields: string[]; + fieldLabels: { + label: string; + description: string; + }; +} + +interface DummyComponent { + type: 'textfield'; + key: string; + id: string; + label: string; + description: string; } -const Body: React.FC = ({translatableFields}) => { - // FIXME: proper typing with nested keys - useManageTranslations(translatableFields as any); +const Body: React.FC = ({fieldLabels}) => { return ( <> - + + - - + propertyLabels={fieldLabels} /> ); }; -interface StoryArgs { - translatableFields: string[]; +interface StoryArgs extends BodyProps { initialValues: { [key: string]: any; }; } -const Template: StoryFn> = ({translatableFields, initialValues}) => ( +type Story = StoryObj; + +const render: StoryFn> = ({fieldLabels, initialValues}) => ( - + ); -export const Default = { - render: Template, +export const Default: Story = { + render: render, play: async ({canvasElement}) => { const canvas = within(canvasElement); - // Translations component should initialize/synchronize with available literals and - // translations from the store. + // Translations component must display the registered/existing translations. + const translationField1 = canvas.getByLabelText('Translation for "label"'); + expect(translationField1).toBeVisible(); + + const translationField2 = canvas.queryByLabelText('Translation for "nonTranslatableField"'); + expect(translationField2).toBeNull(); + await waitFor(async () => { - const literal1Inputs = canvas.queryAllByDisplayValue('Literal 1'); - expect(literal1Inputs).toHaveLength(2); - await canvas.findByDisplayValue('Vertaling 1'); + const literal1Reference = canvas.getByText('Hi there {{ firstName }}'); + expect(literal1Reference).toBeVisible(); + await canvas.findByDisplayValue('Hallo daar, {{ firstName }}'); }); // Enter a value in the non-translatable field await userEvent.type(canvas.getByLabelText('Non-translatable field'), 'Literal 2'); - await waitFor(async () => { - const literal2Inputs = canvas.queryAllByDisplayValue('Literal 2'); - expect(literal2Inputs).toHaveLength(1); - }); - - // Enter a value for the nested translatable field - await userEvent.type(canvas.getByLabelText('Nested translatable field'), 'Literal 3'); - await waitFor(async () => { - const literal3Inputs = canvas.queryAllByDisplayValue('Literal 3'); - expect(literal3Inputs).toHaveLength(2); - }); + expect(translationField2).toBeNull(); }, }; diff --git a/src/components/builder/i18n.tsx b/src/components/builder/i18n.tsx index 233adb88..36aa2b36 100644 --- a/src/components/builder/i18n.tsx +++ b/src/components/builder/i18n.tsx @@ -1,173 +1,159 @@ -import {SupportedLocales, TranslationsContainer} from '@open-formulieren/types'; -import {Translation} from '@open-formulieren/types/lib/formio/i18n'; +import {css} from '@emotion/css'; +import {OFExtensions} from '@open-formulieren/types'; +import clsx from 'clsx'; import {useFormikContext} from 'formik'; -import get from 'lodash.get'; -import {useContext, useEffect, useRef} from 'react'; -import {FormattedMessage} from 'react-intl'; +import {useContext, useState} from 'react'; +import {FormattedMessage, useIntl} from 'react-intl'; import {BuilderContext} from '@/context'; +import {FilterByValueType} from '@/types'; import {AnyComponentSchema} from '@/types/schemas'; -import {DataGrid, DataGridRow, Tab, TabList, TabPanel, Tabs, TextField} from '..//formio'; +import {Component, TextField} from '../formio'; +import ComponentLabel from '../formio/component-label'; -export type SchemaKey = keyof S & string; +type ExtractTranslatableProperties = T extends OFExtensions ? TK : never; +type StringValueProperties = S extends AnyComponentSchema + ? keyof FilterByValueType + : never; -// Typing this to get rid of the `undefined`'s is surprisingly hard. This basically -// says that an object will be returned having each `languageCodes` element as key, -// with the value set to an (empty) Translation array. - -type EmptyTranslationsContainer = { - [K in T[number]]: Translation[]; -}; - -function getEmptyTranslationsObject( - languageCodes: T -): EmptyTranslationsContainer { - const result: Partial> = {}; - for (const code of languageCodes) { - result[code as keyof EmptyTranslationsContainer] = []; - } - return result as EmptyTranslationsContainer; +export interface ComponentTranslationsProps { + propertyLabels: { + [key in ExtractTranslatableProperties]: string; + }; } -/** - * Hook to observe literals and ensure the translations are correctly synchronized. - * - * Example usage: - * - * useManageTranslations(['label', 'description', 'defaultValue']); - * - * @todo: only consider field names where the value is a string -> translating defaultValue - * number makes no sense - * - * @param forProperties Array of form field names to monitor for translation. - */ -export function useManageTranslations( - forProperties: SchemaKey[] = [] -): void { - const FIELD = 'openForms.translations'; - - const {componentTranslationsRef, supportedLanguageCodes} = useContext(BuilderContext); - const {values, setFieldValue} = useFormikContext(); - - const translationsStore = componentTranslationsRef.current; - - const prevLiteralsRef = useRef>( - Object.fromEntries( - forProperties.map(property => { - const literal: string | undefined = get(values, property); - return [property, literal || '']; - }) - ) - ); - - // set initial translations as literal:translation key-value pairs - useEffect(() => { - const translations = getEmptyTranslationsObject(supportedLanguageCodes); - supportedLanguageCodes.forEach(code => { - forProperties.forEach(property => { - const literal: string = get(values, property); - if (!literal) return; - translations[code].push({ - literal, - translation: translationsStore?.[code]?.[literal] || '', - }); - }); - }); - setFieldValue(FIELD, translations); - }, []); - - // track changed literals and update the translations accordingly - const changed = forProperties.filter(property => { - const prevValue = prevLiteralsRef.current[property]; - const currentValue: string = get(values, property); - return currentValue != prevValue; - }); - - useEffect(() => { - if (!changed.length) return; - const currentTranslations = get(values, FIELD) as null | TranslationsContainer< - Translation[] - >; - if (currentTranslations == null) return; - - const updatedTranslations = getEmptyTranslationsObject(supportedLanguageCodes); - - for (const code of supportedLanguageCodes) { - const currentLanguageTranslations = currentTranslations[code] || []; - for (const property of forProperties) { - const currentLiteral: string | undefined = get(values, property); - if (!currentLiteral) continue; // drop the translation - - const previouslyAdded = updatedTranslations[code].find(t => t.literal === currentLiteral); - if (previouslyAdded) continue; - if (!changed.includes(property)) { - const translation = currentLanguageTranslations.find(t => t.literal === currentLiteral); - translation && updatedTranslations[code].push(translation); - continue; - } - - const prevLiteral = prevLiteralsRef.current[property]; - // find the old translation and update the literal - const oldTranslation = currentLanguageTranslations.find(t => t.literal === prevLiteral) || { - translation: '', - }; - updatedTranslations[code].push({ - translation: translationsStore?.[code]?.[currentLiteral] || oldTranslation.translation, - literal: currentLiteral, - }); - } - } - - for (const property of changed) { - prevLiteralsRef.current[property] = get(values, property); - } - setFieldValue(FIELD, updatedTranslations); - }); -} +// XXX: once we've moved away from bootstrap/formio 'component library', this fix and +// @emotion/css can be removed again. +const LABEL_CELL = css` + padding: 0 !important; + border-left-color: transparent !important; + border-top-color: transparent !important; + border-right-color: transparent !important; + border-bottom-width: 1px !important; +`; + +const TABS_CELL = css` + padding: 0 !important; + border-left-color: transparent !important; + border-top-color: transparent !important; + border-right-color: transparent !important; + border-bottom: none !important; +`; + +const TABS_OFFSET = css` + margin-left: -1px; + margin-bottom: -1px; + margin-right: -1px; +`; + +export function ComponentTranslations({ + propertyLabels, +}: ComponentTranslationsProps) { + const intl = useIntl(); + const {supportedLanguageCodes} = useContext(BuilderContext); + const {values} = useFormikContext(); + const [activeLanguage, setActiveLanguage] = useState(supportedLanguageCodes[0]); -interface SingleLanguageTranslationsProps { - languageCode: SupportedLocales; -} + // Object.keys has string[] type, by design. See https://stackoverflow.com/a/52856805 + // We can narrow this down - because of the propertyLabels type, we know that each key + // is a translatable property, and each key must also be a property of the particular + // component schema. + const properties = Object.keys(propertyLabels) as (ExtractTranslatableProperties & + StringValueProperties)[]; + const nameBase = `openForms.translations.${activeLanguage}`; -const SingleLanguageTranslations: React.FC = ({languageCode}) => { - const {values} = useFormikContext(); - const translations = values?.openForms?.translations?.[languageCode] || []; - const nonEmptyTranslations = translations.filter(t => t.literal); return ( - - } - tooltip="Translations for literals used in this component." - columns={['Literal', 'Translation']} - > - {nonEmptyTranslations.map(({literal}, index) => ( - - - - - ))} - + + + + + + + + + + + + + + + + + {properties.map(property => ( + + + + + + ))} + +
+ + } + tooltip={intl.formatMessage({ + description: 'Tooltip for component translations.', + defaultMessage: 'Translations for literals used in this component.', + })} + /> + + +
+ + + + + +
+ + {propertyLabels[property] || property} + + +
+ {(values?.[property] || '-') as string} +
+
+ +
+
); -}; - -export const ComponentTranslations = () => { - const {supportedLanguageCodes} = useContext(BuilderContext); - return ( - - - {supportedLanguageCodes.map(code => ( - {code.toUpperCase()} - ))} - - - {supportedLanguageCodes.map(code => ( - - - - ))} - - ); -}; +} diff --git a/src/components/builder/label.tsx b/src/components/builder/label.tsx index a609cc27..140199b8 100644 --- a/src/components/builder/label.tsx +++ b/src/components/builder/label.tsx @@ -1,6 +1,7 @@ import {FormattedMessage} from 'react-intl'; import {TextField} from '../formio'; +import {LABELS} from './messages'; /* * The label specifies the label for a form field visible for end users filling out the @@ -10,13 +11,7 @@ import {TextField} from '../formio'; * and can typically be translated by the form designers. */ const Label: React.FC = () => ( - - } - required - /> + } required /> ); export default Label; diff --git a/src/components/builder/messages.ts b/src/components/builder/messages.ts new file mode 100644 index 00000000..653bfe9c --- /dev/null +++ b/src/components/builder/messages.ts @@ -0,0 +1,25 @@ +import {defineMessages} from 'react-intl'; + +// Builder form field labels +export const LABELS = defineMessages({ + label: { + description: "Component property 'Label' label", + defaultMessage: 'Label', + }, + description: { + description: "Component property 'Description' label", + defaultMessage: 'Description', + }, + tooltip: { + description: "Component property 'Tooltip' label", + defaultMessage: 'Tooltip', + }, + placeholder: { + description: "Component property 'Placeholder' label", + defaultMessage: 'Placeholder', + }, + defaultValue: { + description: "Label for 'defaultValue' builder field", + defaultMessage: 'Default Value', + }, +}); diff --git a/src/components/builder/placeholder.tsx b/src/components/builder/placeholder.tsx index bbea87f8..859916ac 100644 --- a/src/components/builder/placeholder.tsx +++ b/src/components/builder/placeholder.tsx @@ -1,6 +1,7 @@ import {FormattedMessage, useIntl} from 'react-intl'; import {TextField} from '../formio'; +import {LABELS} from './messages'; const Placeholder = () => { const intl = useIntl(); @@ -15,12 +16,7 @@ const Placeholder = () => { return ( - } + label={} tooltip={tooltip} placeholder={placeholder} /> diff --git a/src/components/builder/tooltip.tsx b/src/components/builder/tooltip.tsx index 664b5f7c..7179265a 100644 --- a/src/components/builder/tooltip.tsx +++ b/src/components/builder/tooltip.tsx @@ -1,18 +1,14 @@ import {FormattedMessage} from 'react-intl'; import {TextField} from '../formio'; +import {LABELS} from './messages'; /* * The description contains additional useful information/hints for a given field to * clarify what's expected by the end-user filling out the form. */ const Tooltip: React.FC = () => ( - - } - /> + } /> ); export default Tooltip; diff --git a/src/registry/date/edit.tsx b/src/registry/date/edit.tsx index f7266cda..9811d822 100644 --- a/src/registry/date/edit.tsx +++ b/src/registry/date/edit.tsx @@ -21,6 +21,7 @@ import { Validate, useDeriveComponentKey, } from '@/components/builder'; +import {LABELS} from '@/components/builder/messages'; import {DateField, TabList, TabPanel, Tabs} from '@/components/formio'; import {EditFormDefinition} from '@/registry/types'; import {getErrorNames} from '@/utils/errors'; @@ -31,6 +32,7 @@ import DateConstraintValidation from './validation'; * Form to configure a Formio 'date' type component. */ const EditForm: EditFormDefinition = () => { + const intl = useIntl(); const [isKeyManuallySetRef, generatedKey] = useDeriveComponentKey(); const { values: {multiple = false}, @@ -46,7 +48,6 @@ const EditForm: EditFormDefinition = () => { return fieldNames.some(name => erroredFields.includes(name)); }; - Translations.useManageTranslations(['label', 'description', 'tooltip']); Validate.useManageValidatorsTranslations(['required']); return ( @@ -112,7 +113,13 @@ const EditForm: EditFormDefinition = () => { {/* Translations */} - + + propertyLabels={{ + label: intl.formatMessage(LABELS.label), + description: intl.formatMessage(LABELS.description), + tooltip: intl.formatMessage(LABELS.tooltip), + }} + /> ); @@ -188,12 +195,7 @@ const DefaultValue: React.FC = ({multiple}) => { return ( - } + label={} tooltip={tooltip} multiple={multiple} /> diff --git a/src/registry/email/edit-validation.ts b/src/registry/email/edit-validation.ts index 0b109ab2..f295de72 100644 --- a/src/registry/email/edit-validation.ts +++ b/src/registry/email/edit-validation.ts @@ -1,10 +1,9 @@ import {IntlShape, defineMessages} from 'react-intl'; import {z} from 'zod'; +import {LABELS} from '@/components/builder/messages'; import {buildCommonSchema, getErrorMap, isInvalidStringIssue} from '@/registry/validation'; -import {DEFAULT_VALUE_LABEL} from './edit'; - const VALIDATION_MESSAGES = defineMessages({ email: { description: 'Invalid email address format validation error', @@ -17,7 +16,7 @@ const buildDefaultValueSchema = (intl: IntlShape) => { .string({ errorMap: getErrorMap(issue => { if (isInvalidStringIssue(issue) && issue.validation === 'email') { - const fieldLabel = intl.formatMessage(DEFAULT_VALUE_LABEL); + const fieldLabel = intl.formatMessage(LABELS.defaultValue); return intl.formatMessage(VALIDATION_MESSAGES.email, {field: fieldLabel}); } return; diff --git a/src/registry/email/edit.tsx b/src/registry/email/edit.tsx index 3f1e068f..20fed8fc 100644 --- a/src/registry/email/edit.tsx +++ b/src/registry/email/edit.tsx @@ -1,6 +1,6 @@ import {EmailComponentSchema} from '@open-formulieren/types'; import {useFormikContext} from 'formik'; -import {FormattedMessage, defineMessage, useIntl} from 'react-intl'; +import {FormattedMessage, useIntl} from 'react-intl'; import { AutoComplete, @@ -20,6 +20,7 @@ import { Validate, useDeriveComponentKey, } from '@/components/builder'; +import {LABELS} from '@/components/builder/messages'; import {Checkbox, TabList, TabPanel, Tabs, TextField} from '@/components/formio'; import {getErrorNames} from '@/utils/errors'; @@ -29,6 +30,7 @@ import {EditFormDefinition} from '../types'; * Form to configure a Formio 'email' type component. */ const EditForm: EditFormDefinition = () => { + const intl = useIntl(); const [isKeyManuallySetRef, generatedKey] = useDeriveComponentKey(); const {values, errors} = useFormikContext(); @@ -43,12 +45,6 @@ const EditForm: EditFormDefinition = () => { return fieldNames.some(name => erroredFields.includes(name)); }; - Translations.useManageTranslations([ - 'label', - 'description', - 'tooltip', - 'defaultValue', - ]); Validate.useManageValidatorsTranslations(['required']); return ( @@ -111,7 +107,13 @@ const EditForm: EditFormDefinition = () => { {/* Translations */} - + + propertyLabels={{ + label: intl.formatMessage(LABELS.label), + description: intl.formatMessage(LABELS.description), + tooltip: intl.formatMessage(LABELS.tooltip), + }} + /> ); @@ -156,11 +158,6 @@ interface DefaultValueProps { multiple: boolean; } -export const DEFAULT_VALUE_LABEL = defineMessage({ - description: "Label for 'defaultValue' builder field", - defaultMessage: 'Default Value', -}); - const DefaultValue: React.FC = ({multiple}) => { const intl = useIntl(); const tooltip = intl.formatMessage({ @@ -171,7 +168,7 @@ const DefaultValue: React.FC = ({multiple}) => { diff --git a/src/registry/number/edit.tsx b/src/registry/number/edit.tsx index f71d6267..27f24ac1 100644 --- a/src/registry/number/edit.tsx +++ b/src/registry/number/edit.tsx @@ -19,6 +19,7 @@ import { Validate, useDeriveComponentKey, } from '@/components/builder'; +import {LABELS} from '@/components/builder/messages'; import {Checkbox, NumberField, TabList, TabPanel, Tabs} from '@/components/formio'; import {getErrorNames} from '@/utils/errors'; @@ -28,6 +29,7 @@ import {EditFormDefinition} from '../types'; * Form to configure a Formio 'number' type component. */ const EditForm: EditFormDefinition = () => { + const intl = useIntl(); const [isKeyManuallySetRef, generatedKey] = useDeriveComponentKey(); const {errors} = useFormikContext(); @@ -42,14 +44,6 @@ const EditForm: EditFormDefinition = () => { return fieldNames.some(name => erroredFields.includes(name)); }; - Translations.useManageTranslations([ - 'label', - 'description', - 'tooltip', - // XXX: enable translation in backend? Need to be careful though, HTML escaping - // will mess up any / tags that *are* supported. - // 'suffix', - ]); Validate.useManageValidatorsTranslations(['required', 'min', 'max']); return ( @@ -116,7 +110,17 @@ const EditForm: EditFormDefinition = () => { {/* Translations */} - + + propertyLabels={{ + label: intl.formatMessage(LABELS.label), + description: intl.formatMessage(LABELS.description), + tooltip: intl.formatMessage(LABELS.tooltip), + suffix: intl.formatMessage({ + description: "Component translations 'suffix' property label", + defaultMessage: 'Suffix (e.g. m²)', + }), + }} + /> ); @@ -167,12 +171,7 @@ const DefaultValue: React.FC = () => { return ( - } + label={} tooltip={tooltip} /> ); diff --git a/src/registry/textfield/edit.tsx b/src/registry/textfield/edit.tsx index b6e63ab4..bf777dfb 100644 --- a/src/registry/textfield/edit.tsx +++ b/src/registry/textfield/edit.tsx @@ -25,6 +25,7 @@ import { Validate, useDeriveComponentKey, } from '@/components/builder'; +import {LABELS} from '@/components/builder/messages'; import {Checkbox, Tab, TabList, TabPanel, Tabs, TextField} from '@/components/formio'; import {getErrorNames} from '@/utils/errors'; @@ -34,6 +35,7 @@ import {EditFormDefinition} from '../types'; * Form to configure a Formio 'textfield' type component. */ const EditForm: EditFormDefinition = () => { + const intl = useIntl(); const [isKeyManuallySetRef, generatedKey] = useDeriveComponentKey(); const {values, errors} = useFormikContext(); @@ -48,13 +50,6 @@ const EditForm: EditFormDefinition = () => { return fieldNames.some(name => erroredFields.includes(name)); }; - Translations.useManageTranslations([ - 'label', - 'description', - 'tooltip', - 'defaultValue', - 'placeholder', - ]); Validate.useManageValidatorsTranslations([ 'required', 'maxLength', @@ -155,7 +150,15 @@ const EditForm: EditFormDefinition = () => { {/* Translations */} - + + propertyLabels={{ + label: intl.formatMessage(LABELS.label), + description: intl.formatMessage(LABELS.description), + tooltip: intl.formatMessage(LABELS.tooltip), + defaultValue: intl.formatMessage(LABELS.defaultValue), + placeholder: intl.formatMessage(LABELS.placeholder), + }} + /> ); @@ -229,12 +232,7 @@ const DefaultValue: React.FC = ({multiple}) => { return ( - } + label={} tooltip={tooltip} multiple={multiple} /> diff --git a/tsconfig.json b/tsconfig.json index ac56c2c8..c4505a34 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,6 +17,7 @@ "strictBindCallApply": true, "strictNullChecks": true, "allowSyntheticDefaultImports": true, + "noErrorTruncation": true, "paths": { "@/*": ["./*"], "@/sb-decorators": ["../.storybook/decorators.tsx"],