diff --git a/.gitignore b/.gitignore
index 3e3705bce0..a03ceceab0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,3 +41,5 @@
*storybook.log
storybook-static
+
+.claude
\ No newline at end of file
diff --git a/eslint.config.mjs b/eslint.config.mjs
index 8f438a7c21..71b218056a 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -149,6 +149,7 @@ export default [
files: [
'**/*.stories.*',
'**/*.test.*',
+ '**/*.figma.*',
'**/examples/**',
'**/packages/**/__testfixtures__/**',
],
diff --git a/figma.config.json b/figma.config.json
new file mode 100644
index 0000000000..6ad577edc1
--- /dev/null
+++ b/figma.config.json
@@ -0,0 +1,25 @@
+{
+ "codeConnect": {
+ "parser": "react",
+ "include": [
+ "packages/components/**/*.figma.tsx",
+ "packages/components/**/src/**/*.tsx",
+ "packages/core/**/*.figma.tsx",
+ "packages/core/**/src/**/*.tsx"
+ ],
+ "exclude": [
+ "**/*.test.*",
+ "**/*.stories.*",
+ "**/index.ts",
+ "**/index.tsx",
+ "**/examples/**"
+ ],
+ "label": "React",
+ "language": "typescript",
+ "importPaths": {
+ "packages/components/navbar/src/*": "@contentful/f36-navbar",
+ "packages/components/icons/src/*": "@contentful/f36-icons",
+ "src/*": "@contentful/f36-components"
+ }
+ }
+}
diff --git a/package-lock.json b/package-lock.json
index 254b2251c9..0f9537bbf8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -30,6 +30,7 @@
"@eslint/compat": "^2.0.1",
"@eslint/eslintrc": "^3",
"@eslint/js": "^9.35.0",
+ "@figma/code-connect": "^1.4.4",
"@manypkg/get-packages": "1.1.3",
"@size-limit/preset-big-lib": "^12.0.0",
"@storybook/addon-a11y": "^9.1.19",
@@ -5632,6 +5633,564 @@
"js-compute-runtime": "js-compute-runtime-cli.js"
}
},
+ "node_modules/@figma/code-connect": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/@figma/code-connect/-/code-connect-1.4.4.tgz",
+ "integrity": "sha512-XgEel2frygcDxU6KhJKG1+qVGOKC9Ifz0iiWclfMkFU8aLvHN2VtewoeqKqchtwW4MNPcNcxYJl2FHQ4quYvQQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "boxen": "5.1.1",
+ "chalk": "^4.1.2",
+ "commander": "^11.1.0",
+ "compare-versions": "^6.1.0",
+ "cross-spawn": "^7.0.3",
+ "dotenv": "^16.3.1",
+ "fast-fuzzy": "^1.12.0",
+ "find-up": "^5.0.0",
+ "glob": "^11.0.4",
+ "jsdom": "^24.1.1",
+ "lodash": "4.18.1",
+ "minimatch": "^9.0.3",
+ "ora": "^5.4.1",
+ "parse5": "^7.1.2",
+ "prettier": "^2.8.8",
+ "prompts": "^2.4.2",
+ "strip-ansi": "^6.0.0",
+ "ts-morph": "^27.0.0",
+ "typescript": "5.9.3",
+ "undici": "^7.19.1",
+ "zod": "3.25.58",
+ "zod-validation-error": "^3.2.0"
+ },
+ "bin": {
+ "figma": "bin/figma"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/@isaacs/cliui": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-9.0.0.tgz",
+ "integrity": "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/bl": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/brace-expansion": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz",
+ "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "restore-cursor": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/commander": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
+ "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/glob": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz",
+ "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==",
+ "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "foreground-child": "^3.3.1",
+ "jackspeak": "^4.1.1",
+ "minimatch": "^10.1.1",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^2.0.0"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/glob/node_modules/balanced-match": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
+ "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/glob/node_modules/brace-expansion": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
+ "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^4.0.2"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/glob/node_modules/minimatch": {
+ "version": "10.2.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
+ "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "brace-expansion": "^5.0.5"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/is-interactive": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
+ "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/jackspeak": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.2.3.tgz",
+ "integrity": "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^9.0.0"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/jsdom": {
+ "version": "24.1.3",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.3.tgz",
+ "integrity": "sha512-MyL55p3Ut3cXbeBEG7Hcv0mVM8pp8PBNWxRqchZnSfAiES1v1mRnMeFfaHWIPULpwsYfvO+ZmMZz5tGCnjzDUQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cssstyle": "^4.0.1",
+ "data-urls": "^5.0.0",
+ "decimal.js": "^10.4.3",
+ "form-data": "^4.0.0",
+ "html-encoding-sniffer": "^4.0.0",
+ "http-proxy-agent": "^7.0.2",
+ "https-proxy-agent": "^7.0.5",
+ "is-potential-custom-element-name": "^1.0.1",
+ "nwsapi": "^2.2.12",
+ "parse5": "^7.1.2",
+ "rrweb-cssom": "^0.7.1",
+ "saxes": "^6.0.0",
+ "symbol-tree": "^3.2.4",
+ "tough-cookie": "^4.1.4",
+ "w3c-xmlserializer": "^5.0.0",
+ "webidl-conversions": "^7.0.0",
+ "whatwg-encoding": "^3.1.1",
+ "whatwg-mimetype": "^4.0.0",
+ "whatwg-url": "^14.0.0",
+ "ws": "^8.18.0",
+ "xml-name-validator": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "canvas": "^2.11.2"
+ },
+ "peerDependenciesMeta": {
+ "canvas": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/lru-cache": {
+ "version": "11.3.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz",
+ "integrity": "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/minimatch": {
+ "version": "9.0.9",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
+ "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/ora": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
+ "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "bl": "^4.1.0",
+ "chalk": "^4.1.0",
+ "cli-cursor": "^3.1.0",
+ "cli-spinners": "^2.5.0",
+ "is-interactive": "^1.0.0",
+ "is-unicode-supported": "^0.1.0",
+ "log-symbols": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "wcwidth": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/path-scurry": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz",
+ "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^11.0.0",
+ "minipass": "^7.1.2"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/prettier": {
+ "version": "2.8.8",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
+ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "prettier": "bin-prettier.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/restore-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/rrweb-cssom": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz",
+ "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@figma/code-connect/node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/@figma/code-connect/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/tough-cookie": {
+ "version": "4.1.4",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz",
+ "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "psl": "^1.1.33",
+ "punycode": "^2.1.1",
+ "universalify": "^0.2.0",
+ "url-parse": "^1.5.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/universalify": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
+ "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/zod": {
+ "version": "3.25.58",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.58.tgz",
+ "integrity": "sha512-DVLmMQzSZwNYzQoMaM3MQWnxr2eq+AtM9Hx3w1/Yl0pH8sLTSjN4jGP7w6f7uand6Hw44tsnSu1hz1AOA6qI2Q==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
+ "node_modules/@figma/code-connect/node_modules/zod-validation-error": {
+ "version": "3.5.4",
+ "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-3.5.4.tgz",
+ "integrity": "sha512-+hEiRIiPobgyuFlEojnqjJnhFvg4r/i3cqgcm67eehZf/WBaK3g6cD02YU9mtdVxZjv8CzCA9n/Rhrs3yAAvAw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "zod": "^3.24.4"
+ }
+ },
"node_modules/@floating-ui/core": {
"version": "1.7.4",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.4.tgz",
@@ -11610,6 +12169,57 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@ts-morph/common": {
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.28.1.tgz",
+ "integrity": "sha512-W74iWf7ILp1ZKNYXY5qbddNaml7e9Sedv5lvU1V8lftlitkc9Pq1A+jlH23ltDgWYeZFFEqGCD1Ies9hqu3O+g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "minimatch": "^10.0.1",
+ "path-browserify": "^1.0.1",
+ "tinyglobby": "^0.2.14"
+ }
+ },
+ "node_modules/@ts-morph/common/node_modules/balanced-match": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
+ "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/@ts-morph/common/node_modules/brace-expansion": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
+ "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^4.0.2"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/@ts-morph/common/node_modules/minimatch": {
+ "version": "10.2.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
+ "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "brace-expansion": "^5.0.5"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/@tsconfig/node10": {
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz",
@@ -13619,6 +14229,51 @@
"integrity": "sha512-vcZjxvvVoxTeR5XBNJB38oTu/7eDCZlwdz32N1eNgpyPF7j/Z7Idf+CUwQOkKKpJ7RJyjxgLHCM7vdIK0iCNMQ==",
"license": "MIT"
},
+ "node_modules/ansi-align": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz",
+ "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.1.0"
+ }
+ },
+ "node_modules/ansi-align/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/ansi-align/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-align/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/ansi-colors": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
@@ -14045,6 +14700,13 @@
"node": ">= 0.4"
}
},
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/asyncro": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/asyncro/-/asyncro-3.0.0.tgz",
@@ -14713,6 +15375,141 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/boxen": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.1.tgz",
+ "integrity": "sha512-JtIQYts08AFAYGF4eSh3pUt3NQkYV/e75pRtQmAVTLNWR/1L7Bsswxlgzgk8nmLEM+gFszsIlA9BgD3XnSqp3g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-align": "^3.0.0",
+ "camelcase": "^6.2.0",
+ "chalk": "^4.1.0",
+ "cli-boxes": "^2.2.1",
+ "string-width": "^4.2.2",
+ "type-fest": "^0.20.2",
+ "widest-line": "^3.1.0",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/boxen/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/boxen/node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/boxen/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/boxen/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/boxen/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/boxen/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/boxen/node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/boxen/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
"node_modules/brace-expansion": {
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz",
@@ -15425,6 +16222,19 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/cli-boxes": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz",
+ "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/cli-cursor": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz",
@@ -15805,6 +16615,13 @@
"node": ">= 0.12.0"
}
},
+ "node_modules/code-block-writer": {
+ "version": "13.0.3",
+ "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.3.tgz",
+ "integrity": "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/collapse-white-space": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz",
@@ -15857,6 +16674,19 @@
"node": ">=0.1.90"
}
},
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/combined-stream2": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/combined-stream2/-/combined-stream2-1.1.2.tgz",
@@ -15938,6 +16768,13 @@
"dot-prop": "^5.1.0"
}
},
+ "node_modules/compare-versions": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz",
+ "integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -18041,6 +18878,16 @@
"node": ">=4"
}
},
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
"node_modules/deprecation": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
@@ -20424,6 +21271,16 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/fast-fuzzy": {
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/fast-fuzzy/-/fast-fuzzy-1.12.0.tgz",
+ "integrity": "sha512-sXxGgHS+ubYpsdLnvOvJ9w5GYYZrtL9mkosG3nfuD446ahvoWEsSKBP7ieGmWIKVLnaxRDgUJkZMdxRgA2Ni+Q==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "graphemesplit": "^2.4.1"
+ }
+ },
"node_modules/fast-glob": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
@@ -20979,6 +21836,23 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/form-data": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
+ "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.2",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/form-data2": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/form-data2/-/form-data2-1.0.4.tgz",
@@ -21676,6 +22550,17 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/graphemesplit": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/graphemesplit/-/graphemesplit-2.6.0.tgz",
+ "integrity": "sha512-rG9w2wAfkpg0DILa1pjnjNfucng3usON360shisqIMUBw/87pojcBSrHmeE4UwryAuBih7g8m1oilf5/u8EWdQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "js-base64": "^3.6.0",
+ "unicode-trie": "^2.0.0"
+ }
+ },
"node_modules/gray-matter": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz",
@@ -25002,6 +25887,13 @@
"node": ">=10"
}
},
+ "node_modules/js-base64": {
+ "version": "3.7.8",
+ "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.8.tgz",
+ "integrity": "sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
"node_modules/js-sha256": {
"version": "0.10.1",
"resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.10.1.tgz",
@@ -31041,6 +31933,13 @@
"quansync": "^0.2.7"
}
},
+ "node_modules/pako": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
+ "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -31168,6 +32067,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/path-browserify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
+ "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/path-exists": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz",
@@ -32604,6 +33510,13 @@
],
"license": "MIT"
},
+ "node_modules/querystringify": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
+ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@@ -34532,6 +35445,13 @@
"node": ">=0.10.0"
}
},
+ "node_modules/requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/resolve": {
"version": "1.22.11",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
@@ -37746,6 +38666,13 @@
"globrex": "^0.1.2"
}
},
+ "node_modules/tiny-inflate": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
+ "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/tiny-invariant": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
@@ -38183,6 +39110,17 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/ts-morph": {
+ "version": "27.0.2",
+ "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-27.0.2.tgz",
+ "integrity": "sha512-fhUhgeljcrdZ+9DZND1De1029PrE+cMkIP7ooqkLRTrRLTqcki2AstsyJm0vRNbTbVCNJ0idGlbBrfqc7/nA8w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@ts-morph/common": "~0.28.1",
+ "code-block-writer": "^13.0.3"
+ }
+ },
"node_modules/tsconfig-paths": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz",
@@ -39919,6 +40857,17 @@
"node": ">=4"
}
},
+ "node_modules/unicode-trie": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz",
+ "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "pako": "^0.2.5",
+ "tiny-inflate": "^1.0.0"
+ }
+ },
"node_modules/unicorn-magic": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz",
@@ -40219,6 +41168,17 @@
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
}
},
+ "node_modules/url-parse": {
+ "version": "1.5.10",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
+ "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "querystringify": "^2.1.1",
+ "requires-port": "^1.0.0"
+ }
+ },
"node_modules/urlcache": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/urlcache/-/urlcache-0.7.0.tgz",
@@ -41466,6 +42426,54 @@
"node": ">=8"
}
},
+ "node_modules/widest-line": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz",
+ "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "string-width": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/widest-line/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/widest-line/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/widest-line/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/win-release": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/win-release/-/win-release-1.1.1.tgz",
diff --git a/package.json b/package.json
index db17b0c363..6c1fe005c7 100644
--- a/package.json
+++ b/package.json
@@ -43,7 +43,10 @@
"changelog:write": "node scripts/changesets/changelog-write.js",
"changeset:publish": "node scripts/changesets/generate-releases.js",
"postversion": "npx prettier",
- "prerelease": "node scripts/prerelease.mjs"
+ "prerelease": "node scripts/prerelease.mjs",
+ "figma:publish": "figma connect publish --token $FIGMA_ACCESS_TOKEN",
+ "figma:publish:dry": "figma connect publish --token $FIGMA_ACCESS_TOKEN --dry-run",
+ "figma:unpublish": "figma connect unpublish --token $FIGMA_ACCESS_TOKEN"
},
"packageManager": "npm@8.5.0",
"browserslist": "extends @contentful/browserslist-config",
@@ -67,6 +70,7 @@
"@eslint/compat": "^2.0.1",
"@eslint/eslintrc": "^3",
"@eslint/js": "^9.35.0",
+ "@figma/code-connect": "^1.4.4",
"@manypkg/get-packages": "1.1.3",
"@size-limit/preset-big-lib": "^12.0.0",
"@storybook/addon-a11y": "^9.1.19",
@@ -140,4 +144,4 @@
"react": ">=19.1.0"
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/components/accordion/src/Accordion.figma.tsx b/packages/components/accordion/src/Accordion.figma.tsx
new file mode 100644
index 0000000000..1f5c7733cd
--- /dev/null
+++ b/packages/components/accordion/src/Accordion.figma.tsx
@@ -0,0 +1,60 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Accordion } from './CompoundAccordion';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=4744:57213';
+
+figma.connect(Accordion, FIGMA_URL, {
+ variant: { Open: 'False', State: 'Default' },
+ props: {
+ align: figma.enum('Align chevron', {
+ End: 'end',
+ Start: 'start',
+ }),
+ title: figma.string('Title'),
+ bodyText: figma.boolean('Show body copy', {
+ true: figma.string('Text'),
+ false: undefined,
+ }),
+ contentSlot: figma.boolean('Content slot', {
+ true: figma.instance('Replace with'),
+ false: undefined,
+ }),
+ },
+ example: ({ align, title, bodyText, contentSlot }) => (
+
+
+ {bodyText}
+ {contentSlot}
+
+
+ ),
+});
+
+figma.connect(Accordion, FIGMA_URL, {
+ variant: { Open: 'True', State: 'Default' },
+ props: {
+ align: figma.enum('Align chevron', {
+ End: 'end',
+ Start: 'start',
+ }),
+ title: figma.string('Title'),
+ bodyText: figma.boolean('Show body copy', {
+ true: figma.string('Text'),
+ false: undefined,
+ }),
+ contentSlot: figma.boolean('Content slot', {
+ true: figma.instance('Replace with'),
+ false: undefined,
+ }),
+ },
+ example: ({ align, title, bodyText, contentSlot }) => (
+
+
+ {bodyText}
+ {contentSlot}
+
+
+ ),
+});
diff --git a/packages/components/asset/src/Asset.figma.tsx b/packages/components/asset/src/Asset.figma.tsx
new file mode 100644
index 0000000000..2d76e80319
--- /dev/null
+++ b/packages/components/asset/src/Asset.figma.tsx
@@ -0,0 +1,23 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Asset } from './Asset';
+
+/**
+ * Note: The Figma "Size" variant has no corresponding code prop.
+ * The Asset component fills 100% of its container width; sizing is
+ * controlled by the parent layout, not by the component itself.
+ */
+figma.connect(
+ Asset,
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=447:13241',
+ {
+ props: {},
+ example: () => (
+
+ ),
+ },
+);
diff --git a/packages/components/autocomplete/src/Autocomplete.figma.tsx b/packages/components/autocomplete/src/Autocomplete.figma.tsx
new file mode 100644
index 0000000000..fde660eae9
--- /dev/null
+++ b/packages/components/autocomplete/src/Autocomplete.figma.tsx
@@ -0,0 +1,31 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Autocomplete } from './Autocomplete';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=13825:4394';
+
+figma.connect(Autocomplete, FIGMA_URL, {
+ props: {
+ isDisabled: figma.enum('States', {
+ Disabled: true,
+ Default: undefined,
+ Active: undefined,
+ 'Active typing': undefined,
+ 'Item selected': undefined,
+ }),
+ isRequired: figma.boolean('is Required', {
+ true: true,
+ false: undefined,
+ }),
+ },
+ example: ({ isDisabled, isRequired }) => (
+ {}}
+ isDisabled={isDisabled}
+ isRequired={isRequired}
+ placeholder="Search"
+ />
+ ),
+});
diff --git a/packages/components/avatar/src/Avatar/Avatar.figma.tsx b/packages/components/avatar/src/Avatar/Avatar.figma.tsx
new file mode 100644
index 0000000000..c442e5d75a
--- /dev/null
+++ b/packages/components/avatar/src/Avatar/Avatar.figma.tsx
@@ -0,0 +1,34 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Avatar } from './Avatar';
+
+figma.connect(
+ Avatar,
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=11225:120217',
+ {
+ props: {
+ variant: figma.enum('Type', {
+ User: 'user',
+ App: 'app',
+ }),
+ size: figma.enum('Size', {
+ Tiny: 'tiny',
+ Small: 'small',
+ Medium: 'medium',
+ Large: 'large',
+ }),
+ colorVariant: figma.enum('Muted', {
+ True: 'muted',
+ False: 'gray',
+ }),
+ },
+ example: ({ variant, size, colorVariant }) => (
+
+ ),
+ },
+);
diff --git a/packages/components/badge/src/Badge/Badge.figma.tsx b/packages/components/badge/src/Badge/Badge.figma.tsx
new file mode 100644
index 0000000000..db2773606c
--- /dev/null
+++ b/packages/components/badge/src/Badge/Badge.figma.tsx
@@ -0,0 +1,43 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Badge } from './Badge';
+figma.connect(
+ Badge,
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=10438:127259',
+ {
+ props: {
+ variant: figma.enum('Type', {
+ Primary: 'primary',
+ 'Primary filled': 'primary-filled',
+ Positive: 'positive',
+ Negative: 'negative',
+ Warning: 'warning',
+ Secondary: 'secondary',
+ Featured: 'featured',
+ }),
+ size: figma.enum('Size', {
+ Medium: 'default',
+ Small: 'small',
+ }),
+ children: figma.textContent('Label'),
+ startIcon: figma.boolean('Show start icon', {
+ true: figma.instance('Start icon'),
+ false: undefined,
+ }),
+ endIcon: figma.boolean('Show end icon', {
+ true: figma.instance('End icon'),
+ false: undefined,
+ }),
+ },
+ example: ({ variant, size, children, startIcon, endIcon }) => (
+
+ {children}
+
+ ),
+ },
+);
diff --git a/packages/components/button/src/Button/Button.figma.tsx b/packages/components/button/src/Button/Button.figma.tsx
new file mode 100644
index 0000000000..874ee947e5
--- /dev/null
+++ b/packages/components/button/src/Button/Button.figma.tsx
@@ -0,0 +1,83 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Button } from './Button';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=16755:33991';
+
+figma.connect(Button, FIGMA_URL, {
+ variant: { State: 'Default' },
+ props: {
+ variant: figma.enum('Type', {
+ Primary: 'primary',
+ Secondary: 'secondary',
+ Positive: 'positive',
+ Negative: 'negative',
+ Transparent: 'transparent',
+ }),
+ size: figma.enum('Size', {
+ 'Small (default)': 'small',
+ Medium: 'medium',
+ }),
+ children: figma.string('Label'),
+ isLoading: figma.boolean('Loading'),
+ startIcon: figma.boolean('Show start icon', {
+ true: figma.instance('Start icon'),
+ false: undefined,
+ }),
+ endIcon: figma.boolean('Show end icon', {
+ true: figma.instance('End icon'),
+ false: undefined,
+ }),
+ },
+ example: ({ variant, size, children, isLoading, startIcon, endIcon }) => (
+
+ ),
+});
+
+figma.connect(Button, FIGMA_URL, {
+ variant: { State: 'Disabled' },
+ props: {
+ variant: figma.enum('Type', {
+ Primary: 'primary',
+ Secondary: 'secondary',
+ Positive: 'positive',
+ Negative: 'negative',
+ Transparent: 'transparent',
+ }),
+ size: figma.enum('Size', {
+ 'Small (default)': 'small',
+ Medium: 'medium',
+ }),
+ children: figma.string('Label'),
+ isLoading: figma.boolean('Loading'),
+ startIcon: figma.boolean('Show start icon', {
+ true: figma.instance('Start icon'),
+ false: undefined,
+ }),
+ endIcon: figma.boolean('Show end icon', {
+ true: figma.instance('End icon'),
+ false: undefined,
+ }),
+ },
+ example: ({ variant, size, children, isLoading, startIcon, endIcon }) => (
+
+ ),
+});
diff --git a/packages/components/button/src/ButtonGroup/ButtonGroup.figma.tsx b/packages/components/button/src/ButtonGroup/ButtonGroup.figma.tsx
new file mode 100644
index 0000000000..6d33a2e66b
--- /dev/null
+++ b/packages/components/button/src/ButtonGroup/ButtonGroup.figma.tsx
@@ -0,0 +1,23 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { ButtonGroup } from './ButtonGroup';
+import { Button } from '../Button/Button';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=9060:153860';
+
+figma.connect(ButtonGroup, FIGMA_URL, {
+ props: {
+ variant: figma.enum('Spaced', {
+ True: 'spaced',
+ False: 'merged',
+ }),
+ },
+ example: ({ variant }) => (
+
+
+
+
+
+ ),
+});
diff --git a/packages/components/button/src/IconButton/IconButton.figma.tsx b/packages/components/button/src/IconButton/IconButton.figma.tsx
new file mode 100644
index 0000000000..389dbd05e1
--- /dev/null
+++ b/packages/components/button/src/IconButton/IconButton.figma.tsx
@@ -0,0 +1,58 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { IconButton } from './IconButton';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=9060:150415';
+
+figma.connect(IconButton, FIGMA_URL, {
+ variant: { State: 'Default' },
+ props: {
+ variant: figma.enum('Type', {
+ Primary: 'primary',
+ Secondary: 'secondary',
+ Positive: 'positive',
+ Negative: 'negative',
+ Transparent: 'transparent',
+ }),
+ size: figma.enum('Size', {
+ 'Small (default)': 'small',
+ Medium: 'medium',
+ }),
+ icon: figma.instance('Icon'),
+ },
+ example: ({ variant, size, icon }) => (
+
+ ),
+});
+
+figma.connect(IconButton, FIGMA_URL, {
+ variant: { State: 'Disabled' },
+ props: {
+ variant: figma.enum('Type', {
+ Primary: 'primary',
+ Secondary: 'secondary',
+ Positive: 'positive',
+ Negative: 'negative',
+ Transparent: 'transparent',
+ }),
+ size: figma.enum('Size', {
+ 'Small (default)': 'small',
+ Medium: 'medium',
+ }),
+ },
+ example: ({ variant, size }) => (
+ }
+ aria-label="Icon button"
+ />
+ ),
+});
diff --git a/packages/components/button/src/ToggleButton/ToggleButton.figma.tsx b/packages/components/button/src/ToggleButton/ToggleButton.figma.tsx
new file mode 100644
index 0000000000..fe886969a3
--- /dev/null
+++ b/packages/components/button/src/ToggleButton/ToggleButton.figma.tsx
@@ -0,0 +1,66 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { ToggleButton } from './ToggleButton';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=9318:148375';
+
+figma.connect(ToggleButton, FIGMA_URL, {
+ variant: { State: 'Default' },
+ props: {
+ size: figma.enum('Size', {
+ 'Small (default)': 'small',
+ Medium: 'medium',
+ }),
+ children: figma.string('Label'),
+ icon: figma.boolean('Show start icon', {
+ true: figma.instance('Start icon'),
+ false: undefined,
+ }),
+ },
+ example: ({ size, children, icon }) => (
+ {}}>
+ {children}
+
+ ),
+});
+
+figma.connect(ToggleButton, FIGMA_URL, {
+ variant: { State: 'Active' },
+ props: {
+ size: figma.enum('Size', {
+ 'Small (default)': 'small',
+ Medium: 'medium',
+ }),
+ children: figma.string('Label'),
+ icon: figma.boolean('Show start icon', {
+ true: figma.instance('Start icon'),
+ false: undefined,
+ }),
+ },
+ example: ({ size, children, icon }) => (
+ {}}>
+ {children}
+
+ ),
+});
+
+figma.connect(ToggleButton, FIGMA_URL, {
+ variant: { State: 'Disabled' },
+ props: {
+ size: figma.enum('Size', {
+ 'Small (default)': 'small',
+ Medium: 'medium',
+ }),
+ children: figma.string('Label'),
+ icon: figma.boolean('Show start icon', {
+ true: figma.instance('Start icon'),
+ false: undefined,
+ }),
+ },
+ example: ({ size, children, icon }) => (
+ {}}>
+ {children}
+
+ ),
+});
diff --git a/packages/components/card/src/Card/Card.figma.tsx b/packages/components/card/src/Card/Card.figma.tsx
new file mode 100644
index 0000000000..d15165dd1a
--- /dev/null
+++ b/packages/components/card/src/Card/Card.figma.tsx
@@ -0,0 +1,97 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Card } from './Card';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=9658:125200';
+
+figma.connect(Card, FIGMA_URL, {
+ variant: { State: 'Default' },
+ props: {
+ padding: figma.enum('Margins', {
+ Medium: 'default',
+ Large: 'large',
+ }),
+ title: figma.boolean('Show title', {
+ true: figma.string('Title'),
+ false: undefined,
+ }),
+ bodyText: figma.boolean('Show body copy', {
+ true: figma.string('Text'),
+ false: undefined,
+ }),
+ contentSlot: figma.boolean('Content slot', {
+ true: figma.instance('Replace with'),
+ false: undefined,
+ }),
+ withDragHandle: figma.boolean('Dragable'),
+ icon: figma.boolean('Show icon', {
+ true: figma.instance('Icon'),
+ false: undefined,
+ }),
+ },
+ example: ({
+ padding,
+ title,
+ bodyText,
+ contentSlot,
+ withDragHandle,
+ icon,
+ }) => (
+
+ {bodyText}
+ {contentSlot}
+
+ ),
+});
+
+figma.connect(Card, FIGMA_URL, {
+ variant: { State: 'Selected' },
+ props: {
+ padding: figma.enum('Margins', {
+ Medium: 'default',
+ Large: 'large',
+ }),
+ title: figma.boolean('Show title', {
+ true: figma.string('Title'),
+ false: undefined,
+ }),
+ bodyText: figma.boolean('Show body copy', {
+ true: figma.string('Text'),
+ false: undefined,
+ }),
+ contentSlot: figma.boolean('Content slot', {
+ true: figma.instance('Replace with'),
+ false: undefined,
+ }),
+ withDragHandle: figma.boolean('Dragable'),
+ icon: figma.boolean('Show icon', {
+ true: figma.instance('Icon'),
+ false: undefined,
+ }),
+ },
+ example: ({
+ padding,
+ title,
+ bodyText,
+ contentSlot,
+ withDragHandle,
+ icon,
+ }) => (
+
+ {bodyText}
+ {contentSlot}
+
+ ),
+});
diff --git a/packages/components/copybutton/src/CopyButton.figma.tsx b/packages/components/copybutton/src/CopyButton.figma.tsx
new file mode 100644
index 0000000000..ad7bc38a16
--- /dev/null
+++ b/packages/components/copybutton/src/CopyButton.figma.tsx
@@ -0,0 +1,30 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { CopyButton } from './CopyButton';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=4943:99660';
+
+figma.connect(CopyButton, FIGMA_URL, {
+ variant: { State: 'Default' },
+ props: {
+ size: figma.enum('Size', {
+ 'Small (default)': 'small',
+ Medium: 'medium',
+ }),
+ },
+ example: ({ size }) => ,
+});
+
+figma.connect(CopyButton, FIGMA_URL, {
+ variant: { State: 'Disabled' },
+ props: {
+ size: figma.enum('Size', {
+ 'Small (default)': 'small',
+ Medium: 'medium',
+ }),
+ },
+ example: ({ size }) => (
+
+ ),
+});
diff --git a/packages/components/datepicker/src/Datepicker.figma.tsx b/packages/components/datepicker/src/Datepicker.figma.tsx
new file mode 100644
index 0000000000..85209ce0c1
--- /dev/null
+++ b/packages/components/datepicker/src/Datepicker.figma.tsx
@@ -0,0 +1,18 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Datepicker } from './Datepicker';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=11753:92754';
+
+figma.connect(Datepicker, FIGMA_URL, {
+ variant: { Invalid: 'False' },
+ example: () => {}} />,
+});
+
+figma.connect(Datepicker, FIGMA_URL, {
+ variant: { Invalid: 'True' },
+ example: () => (
+ {}} inputProps={{ isInvalid: true }} />
+ ),
+});
diff --git a/packages/components/drag-handle/src/DragHandle.figma.tsx b/packages/components/drag-handle/src/DragHandle.figma.tsx
new file mode 100644
index 0000000000..42e8cfe243
--- /dev/null
+++ b/packages/components/drag-handle/src/DragHandle.figma.tsx
@@ -0,0 +1,21 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { DragHandle } from './DragHandle';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=902:7955';
+
+figma.connect(DragHandle, FIGMA_URL, {
+ variant: { State: 'Default' },
+ example: () => ,
+});
+
+figma.connect(DragHandle, FIGMA_URL, {
+ variant: { State: 'Active' },
+ example: () => ,
+});
+
+figma.connect(DragHandle, FIGMA_URL, {
+ variant: { State: 'Hover' },
+ example: () => ,
+});
diff --git a/packages/components/entity-list/src/EntityListItem/EntityListItem.figma.tsx b/packages/components/entity-list/src/EntityListItem/EntityListItem.figma.tsx
new file mode 100644
index 0000000000..a1a1a59d16
--- /dev/null
+++ b/packages/components/entity-list/src/EntityListItem/EntityListItem.figma.tsx
@@ -0,0 +1,35 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { EntityListItem } from './EntityListItem';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=1128:62288';
+
+figma.connect(EntityListItem, FIGMA_URL, {
+ variant: { State: 'Default' },
+ props: {
+ withDragHandle: figma.enum('Dragable', {
+ true: true,
+ false: undefined,
+ }),
+ thumbnailUrl: figma.enum('Thumbnail', {
+ true: 'https://via.placeholder.com/46',
+ false: undefined,
+ }),
+ status: figma.enum('Tag', {
+ true: 'published',
+ false: undefined,
+ }),
+ },
+ example: ({ withDragHandle, thumbnailUrl, status }) => (
+
+ ),
+});
diff --git a/packages/components/forms/src/Checkbox/Checkbox.figma.tsx b/packages/components/forms/src/Checkbox/Checkbox.figma.tsx
new file mode 100644
index 0000000000..5483632b98
--- /dev/null
+++ b/packages/components/forms/src/Checkbox/Checkbox.figma.tsx
@@ -0,0 +1,85 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Checkbox } from './Checkbox';
+
+const figmaNodeUrl =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=10943:4306';
+
+/**
+ * Checked: False
+ */
+figma.connect(Checkbox, figmaNodeUrl, {
+ variant: { Checked: 'False' },
+ props: {
+ isDisabled: figma.enum('Disabled', {
+ True: true,
+ False: undefined,
+ }),
+ isInvalid: figma.boolean('Invalid'),
+ helpText: figma.boolean('Help text', {
+ true: 'Help text',
+ false: undefined,
+ }),
+ },
+ example: ({ isDisabled, isInvalid, helpText }) => (
+
+ Label
+
+ ),
+});
+
+/**
+ * Checked: True
+ */
+figma.connect(Checkbox, figmaNodeUrl, {
+ variant: { Checked: 'True' },
+ props: {
+ isDisabled: figma.enum('Disabled', {
+ True: true,
+ False: undefined,
+ }),
+ isInvalid: figma.boolean('Invalid'),
+ helpText: figma.boolean('Help text', {
+ true: 'Help text',
+ false: undefined,
+ }),
+ },
+ example: ({ isDisabled, isInvalid, helpText }) => (
+
+ Label
+
+ ),
+});
+
+/**
+ * Checked: Indeterminate
+ */
+figma.connect(Checkbox, figmaNodeUrl, {
+ variant: { Checked: 'Indeterminate' },
+ props: {
+ isDisabled: figma.enum('Disabled', {
+ True: true,
+ False: undefined,
+ }),
+ isInvalid: figma.boolean('Invalid'),
+ helpText: figma.boolean('Help text', {
+ true: 'Help text',
+ false: undefined,
+ }),
+ },
+ example: ({ isDisabled, isInvalid, helpText }) => (
+
+ Label
+
+ ),
+});
diff --git a/packages/components/forms/src/Radio/Radio.figma.tsx b/packages/components/forms/src/Radio/Radio.figma.tsx
new file mode 100644
index 0000000000..340d4f6654
--- /dev/null
+++ b/packages/components/forms/src/Radio/Radio.figma.tsx
@@ -0,0 +1,36 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+
+import { Radio } from './Radio';
+
+figma.connect(
+ Radio,
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=11289:94882',
+ {
+ props: {
+ isChecked: figma.enum('Checked', {
+ True: true,
+ False: false,
+ }),
+ isDisabled: figma.enum('Disabled', {
+ True: true,
+ False: false,
+ }),
+ isInvalid: figma.boolean('Invalid'),
+ helpText: figma.boolean('Help text', {
+ true: 'Help text content',
+ false: undefined,
+ }),
+ },
+ example: (props) => (
+
+ Label
+
+ ),
+ },
+);
diff --git a/packages/components/forms/src/Select/Select.figma.tsx b/packages/components/forms/src/Select/Select.figma.tsx
new file mode 100644
index 0000000000..ff79dc0ae2
--- /dev/null
+++ b/packages/components/forms/src/Select/Select.figma.tsx
@@ -0,0 +1,61 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Select } from './CompoundSelect';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=11367:96616';
+
+/**
+ * Default state (not disabled)
+ */
+figma.connect(Select, FIGMA_URL, {
+ variant: { State: 'Default' },
+ props: {
+ size: figma.enum('Size', {
+ Medium: 'medium',
+ Small: 'small',
+ }),
+ isInvalid: figma.enum('Invalid', {
+ True: true,
+ False: false,
+ }),
+ defaultValue: figma.string('Value'),
+ },
+ example: ({ size, isInvalid, defaultValue }) => (
+
+ ),
+});
+
+/**
+ * Disabled state
+ */
+figma.connect(Select, FIGMA_URL, {
+ variant: { State: 'Disabled' },
+ props: {
+ size: figma.enum('Size', {
+ Medium: 'medium',
+ Small: 'small',
+ }),
+ isInvalid: figma.enum('Invalid', {
+ True: true,
+ False: false,
+ }),
+ defaultValue: figma.string('Value'),
+ },
+ example: ({ size, isInvalid, defaultValue }) => (
+
+ ),
+});
diff --git a/packages/components/forms/src/Switch/Switch.figma.tsx b/packages/components/forms/src/Switch/Switch.figma.tsx
new file mode 100644
index 0000000000..c9573aadab
--- /dev/null
+++ b/packages/components/forms/src/Switch/Switch.figma.tsx
@@ -0,0 +1,41 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+
+import { Switch } from './Switch';
+
+figma.connect(
+ Switch,
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=11289:95266',
+ {
+ props: {
+ size: figma.enum('Size', {
+ Medium: 'medium',
+ Small: 'small',
+ }),
+ isChecked: figma.enum('Checked', {
+ True: true,
+ False: false,
+ }),
+ isDisabled: figma.enum('Disabled', {
+ True: true,
+ False: false,
+ }),
+ isInvalid: figma.boolean('Invalid'),
+ helpText: figma.boolean('Help text', {
+ true: 'Help text content',
+ false: undefined,
+ }),
+ },
+ example: (props) => (
+
+ Label
+
+ ),
+ },
+);
diff --git a/packages/components/forms/src/TextInput/TextInput.figma.tsx b/packages/components/forms/src/TextInput/TextInput.figma.tsx
new file mode 100644
index 0000000000..e15a50dcc0
--- /dev/null
+++ b/packages/components/forms/src/TextInput/TextInput.figma.tsx
@@ -0,0 +1,106 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { TextInput } from './CompoundTextInput';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=11213:118061';
+
+figma.connect(TextInput, FIGMA_URL, {
+ variant: { 'Field type': 'Default' },
+ props: {
+ size: figma.enum('Size', {
+ Medium: 'medium',
+ Small: 'small',
+ }),
+ isDisabled: figma.enum('Disabled', {
+ True: true,
+ False: false,
+ }),
+ isInvalid: figma.enum('Invalid', {
+ True: true,
+ False: false,
+ }),
+ defaultValue: figma.string('Value'),
+ icon: figma.boolean('Show start icon', {
+ true: figma.instance('Start icon'),
+ false: undefined,
+ }),
+ },
+ example: ({ size, isDisabled, isInvalid, defaultValue, icon }) => (
+
+ ),
+});
+
+figma.connect(TextInput, FIGMA_URL, {
+ variant: { 'Field type': 'Group merged' },
+ props: {
+ size: figma.enum('Size', {
+ Medium: 'medium',
+ Small: 'small',
+ }),
+ isDisabled: figma.enum('Disabled', {
+ True: true,
+ False: false,
+ }),
+ isInvalid: figma.enum('Invalid', {
+ True: true,
+ False: false,
+ }),
+ defaultValue: figma.string('Value'),
+ icon: figma.boolean('Show start icon', {
+ true: figma.instance('Start icon'),
+ false: undefined,
+ }),
+ },
+ example: ({ size, isDisabled, isInvalid, defaultValue, icon }) => (
+
+
+
+ ),
+});
+
+figma.connect(TextInput, FIGMA_URL, {
+ variant: { 'Field type': 'Group spaced' },
+ props: {
+ size: figma.enum('Size', {
+ Medium: 'medium',
+ Small: 'small',
+ }),
+ isDisabled: figma.enum('Disabled', {
+ True: true,
+ False: false,
+ }),
+ isInvalid: figma.enum('Invalid', {
+ True: true,
+ False: false,
+ }),
+ defaultValue: figma.string('Value'),
+ icon: figma.boolean('Show start icon', {
+ true: figma.instance('Start icon'),
+ false: undefined,
+ }),
+ },
+ example: ({ size, isDisabled, isInvalid, defaultValue, icon }) => (
+
+
+
+ ),
+});
diff --git a/packages/components/forms/src/Textarea/Textarea.figma.tsx b/packages/components/forms/src/Textarea/Textarea.figma.tsx
new file mode 100644
index 0000000000..871fc6ac9e
--- /dev/null
+++ b/packages/components/forms/src/Textarea/Textarea.figma.tsx
@@ -0,0 +1,37 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Textarea } from './Textarea';
+import { FormControl } from '../FormControl/CompoundFormControl';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=16509:101241';
+
+figma.connect(Textarea, FIGMA_URL, {
+ props: {
+ label: figma.boolean('Show label', {
+ true: Label,
+ false: undefined,
+ }),
+ helpText: figma.boolean('Help text', {
+ true: Help text,
+ false: undefined,
+ }),
+ counter: figma.boolean('Counter', {
+ true: ,
+ false: undefined,
+ }),
+ isRequired: figma.boolean('Required'),
+ isInvalid: figma.enum('Invalid', {
+ True: true,
+ False: false,
+ }),
+ },
+ example: ({ label, helpText, counter, isRequired, isInvalid }) => (
+
+ {label}
+
+ {helpText}
+ {counter}
+
+ ),
+});
diff --git a/packages/components/header/src/Header.figma.tsx b/packages/components/header/src/Header.figma.tsx
new file mode 100644
index 0000000000..71d35d2cca
--- /dev/null
+++ b/packages/components/header/src/Header.figma.tsx
@@ -0,0 +1,33 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Header } from './Header';
+import { Button } from '@contentful/f36-button';
+import { TextInput } from '@contentful/f36-forms';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=13601:122226';
+
+figma.connect(Header, FIGMA_URL, {
+ props: {
+ breadcrumbs: figma.enum('Title variant', {
+ Breadcrumb: [{ content: 'Parent', url: '/parent' }],
+ Title: undefined,
+ }),
+ actions: figma.boolean('Actions', {
+ true: ,
+ false: undefined,
+ }),
+ filters: figma.boolean('With filters', {
+ true: ,
+ false: undefined,
+ }),
+ },
+ example: ({ breadcrumbs, actions, filters }) => (
+
+ ),
+});
diff --git a/packages/components/menu/src/MenuItem/MenuItem.figma.tsx b/packages/components/menu/src/MenuItem/MenuItem.figma.tsx
new file mode 100644
index 0000000000..2111f772f9
--- /dev/null
+++ b/packages/components/menu/src/MenuItem/MenuItem.figma.tsx
@@ -0,0 +1,86 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Menu } from '../CompoundMenu';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=10619:13878';
+
+figma.connect(Menu.Item, FIGMA_URL, {
+ variant: { State: 'Default', Destructive: 'False' },
+ props: {
+ children: figma.string('Title'),
+ icon: figma.boolean('Show start icon', {
+ true: figma.instance('Start icon'),
+ false: undefined,
+ }),
+ shortcut: figma.boolean('Show hint', {
+ true: figma.string('Hint label'),
+ false: undefined,
+ }),
+ },
+ example: ({ children, icon, shortcut }) => (
+
+ {children}
+
+ ),
+});
+
+figma.connect(Menu.Item, FIGMA_URL, {
+ variant: { State: 'Disabled', Destructive: 'False' },
+ props: {
+ children: figma.string('Title'),
+ icon: figma.boolean('Show start icon', {
+ true: figma.instance('Start icon'),
+ false: undefined,
+ }),
+ shortcut: figma.boolean('Show hint', {
+ true: figma.string('Hint label'),
+ false: undefined,
+ }),
+ },
+ example: ({ children, icon, shortcut }) => (
+
+ {children}
+
+ ),
+});
+
+figma.connect(Menu.Item, FIGMA_URL, {
+ variant: { State: 'Default', Destructive: 'True' },
+ props: {
+ children: figma.string('Title'),
+ icon: figma.boolean('Show start icon', {
+ true: figma.instance('Start icon'),
+ false: undefined,
+ }),
+ shortcut: figma.boolean('Show hint', {
+ true: figma.string('Hint label'),
+ false: undefined,
+ }),
+ },
+ example: ({ children, icon, shortcut }) => (
+
+ {children}
+
+ ),
+});
+
+figma.connect(Menu.Item, FIGMA_URL, {
+ variant: { State: 'Disabled', Destructive: 'True' },
+ props: {
+ children: figma.string('Title'),
+ icon: figma.boolean('Show start icon', {
+ true: figma.instance('Start icon'),
+ false: undefined,
+ }),
+ shortcut: figma.boolean('Show hint', {
+ true: figma.string('Hint label'),
+ false: undefined,
+ }),
+ },
+ example: ({ children, icon, shortcut }) => (
+
+ {children}
+
+ ),
+});
diff --git a/packages/components/modal/src/Modal.figma.tsx b/packages/components/modal/src/Modal.figma.tsx
new file mode 100644
index 0000000000..444455846e
--- /dev/null
+++ b/packages/components/modal/src/Modal.figma.tsx
@@ -0,0 +1,33 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Modal } from './CompoundModal';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=9565:124579';
+
+figma.connect(Modal, FIGMA_URL, {
+ props: {
+ size: figma.enum('Size', {
+ 'Small (400px)': 'small',
+ 'Medium (520px)': 'medium',
+ 'Large (700px)': 'large',
+ 'Full width': 'fullWidth',
+ 'Full screen': 'fullscreen',
+ }),
+ title: figma.string('Title'),
+ bodyText: figma.string('Text'),
+ contentSlot: figma.boolean('Content slot', {
+ true: figma.instance('Replace with'),
+ false: undefined,
+ }),
+ },
+ example: ({ size, title, bodyText, contentSlot }) => (
+ {}} size={size}>
+ {}} />
+
+ {bodyText}
+ {contentSlot}
+
+
+ ),
+});
diff --git a/packages/components/multiselect/src/Multiselect.figma.tsx b/packages/components/multiselect/src/Multiselect.figma.tsx
new file mode 100644
index 0000000000..61ee76f29b
--- /dev/null
+++ b/packages/components/multiselect/src/Multiselect.figma.tsx
@@ -0,0 +1,31 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Multiselect } from './CompoundMultiselect';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=12925:124903';
+
+figma.connect(Multiselect, FIGMA_URL, {
+ example: () => (
+
+ {}}
+ />
+ {}}
+ />
+ {}}
+ />
+
+ ),
+});
diff --git a/packages/components/navlist/src/NavListItem/NavListItem.figma.tsx b/packages/components/navlist/src/NavListItem/NavListItem.figma.tsx
new file mode 100644
index 0000000000..caf3b18585
--- /dev/null
+++ b/packages/components/navlist/src/NavListItem/NavListItem.figma.tsx
@@ -0,0 +1,38 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { NavListItem } from './NavListItem';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=10671:5210';
+
+figma.connect(NavListItem, FIGMA_URL, {
+ variant: { State: 'Default' },
+ props: {
+ children: figma.string('Label'),
+ },
+ example: ({ children }) => {children},
+});
+
+figma.connect(NavListItem, FIGMA_URL, {
+ variant: { State: 'Active' },
+ props: {
+ children: figma.string('Label'),
+ },
+ example: ({ children }) => (
+
+ {children}
+
+ ),
+});
+
+figma.connect(NavListItem, FIGMA_URL, {
+ variant: { State: 'Disabled' },
+ props: {
+ children: figma.string('Label'),
+ },
+ example: ({ children }) => (
+
+ {children}
+
+ ),
+});
diff --git a/packages/components/note/src/Note.figma.tsx b/packages/components/note/src/Note.figma.tsx
new file mode 100644
index 0000000000..0193c7cfd1
--- /dev/null
+++ b/packages/components/note/src/Note.figma.tsx
@@ -0,0 +1,40 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Note } from './Note';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=11733:9310';
+
+figma.connect(Note, FIGMA_URL, {
+ props: {
+ variant: figma.enum('Type', {
+ Neutral: 'neutral',
+ Primary: 'primary',
+ Positive: 'positive',
+ Warning: 'warning',
+ Negative: 'negative',
+ Highlight: 'premium',
+ }),
+ title: figma.boolean('Show title', {
+ true: figma.string('Title'),
+ false: undefined,
+ }),
+ children: figma.string('Body copy'),
+ withCloseButton: figma.boolean('Close button'),
+ icon: figma.boolean('Content slot', {
+ true: figma.instance('Replace with'),
+ false: undefined,
+ }),
+ },
+ example: ({ variant, title, children, withCloseButton, icon }) => (
+ {}}
+ icon={icon}
+ >
+ {children}
+
+ ),
+});
diff --git a/packages/components/notification/src/Notification.figma.tsx b/packages/components/notification/src/Notification.figma.tsx
new file mode 100644
index 0000000000..7ba8d27030
--- /dev/null
+++ b/packages/components/notification/src/Notification.figma.tsx
@@ -0,0 +1,38 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { NotificationItem } from './NotificationItem';
+
+/**
+ * The primary Notification API is imperative:
+ * Notification.success('body', { title: '...' })
+ * Notification.error('body')
+ * Notification.warning('body')
+ * Notification.info('body')
+ *
+ * NotificationItem is the declarative component that renders the
+ * notification UI and maps directly to what appears on the Figma canvas.
+ */
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=10594:6198';
+
+figma.connect(NotificationItem, FIGMA_URL, {
+ props: {
+ variant: figma.enum('Type', {
+ Positive: 'positive',
+ Negative: 'negative',
+ Warning: 'warning',
+ Info: 'primary',
+ }),
+ title: figma.boolean('Show title', {
+ true: figma.string('Title'),
+ false: undefined,
+ }),
+ body: figma.string('Body copy'),
+ },
+ example: ({ variant, body, title }) => (
+ {}}>
+ {body}
+
+ ),
+});
diff --git a/packages/components/pagination/src/Pagination.figma.tsx b/packages/components/pagination/src/Pagination.figma.tsx
new file mode 100644
index 0000000000..b95ed07eda
--- /dev/null
+++ b/packages/components/pagination/src/Pagination.figma.tsx
@@ -0,0 +1,28 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Pagination } from './Pagination';
+
+figma.connect(
+ Pagination,
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=10438:126777',
+ {
+ props: {
+ activePage: figma.boolean('Previous button', {
+ true: 2,
+ false: 0,
+ }),
+ totalItems: figma.boolean('Show total', {
+ true: 113,
+ false: undefined,
+ }),
+ },
+ example: ({ activePage, totalItems }) => (
+ {}}
+ />
+ ),
+ },
+);
diff --git a/packages/components/pill/src/Pill.figma.tsx b/packages/components/pill/src/Pill.figma.tsx
new file mode 100644
index 0000000000..5a6d1ce33d
--- /dev/null
+++ b/packages/components/pill/src/Pill.figma.tsx
@@ -0,0 +1,67 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Pill } from './Pill';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=1114:529';
+
+figma.connect(Pill, FIGMA_URL, {
+ variant: { State: 'Default' },
+ props: {
+ onClose: figma.enum('Close', {
+ true: () => {},
+ false: undefined,
+ }),
+ isDraggable: figma.enum('Draggable', {
+ true: true,
+ false: undefined,
+ }),
+ },
+ example: ({ onClose, isDraggable }) => (
+
+ ),
+});
+
+figma.connect(Pill, FIGMA_URL, {
+ variant: { State: 'Active' },
+ props: {
+ onClose: figma.enum('Close', {
+ true: () => {},
+ false: undefined,
+ }),
+ isDraggable: figma.enum('Draggable', {
+ true: true,
+ false: undefined,
+ }),
+ },
+ example: ({ onClose, isDraggable }) => (
+
+ ),
+});
+
+figma.connect(Pill, FIGMA_URL, {
+ variant: { State: 'Deleted' },
+ props: {
+ onClose: figma.enum('Close', {
+ true: () => {},
+ false: undefined,
+ }),
+ isDraggable: figma.enum('Draggable', {
+ true: true,
+ false: undefined,
+ }),
+ },
+ example: ({ onClose, isDraggable }) => (
+
+ ),
+});
diff --git a/packages/components/popover/src/Popover.figma.tsx b/packages/components/popover/src/Popover.figma.tsx
new file mode 100644
index 0000000000..5fe7d707bd
--- /dev/null
+++ b/packages/components/popover/src/Popover.figma.tsx
@@ -0,0 +1,21 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Popover } from './CompoundPopover';
+import { Button } from '@contentful/f36-button';
+
+figma.connect(
+ Popover,
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=11517:111133',
+ {
+ example: () => (
+
+
+
+
+
+ Popover content
+
+
+ ),
+ },
+);
diff --git a/packages/components/progress-stepper/src/ProgressStepper.figma.tsx b/packages/components/progress-stepper/src/ProgressStepper.figma.tsx
new file mode 100644
index 0000000000..88336a2361
--- /dev/null
+++ b/packages/components/progress-stepper/src/ProgressStepper.figma.tsx
@@ -0,0 +1,30 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { ProgressStepper } from './CompoundProgressStepper';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=13450:393';
+
+figma.connect(ProgressStepper, FIGMA_URL, {
+ props: {
+ orientation: figma.enum('Orientation', {
+ Horizontal: undefined,
+ Vertical: 'vertical',
+ }),
+ stepStyle: figma.enum('Step style', {
+ Numbers: 'number',
+ Icons: undefined,
+ }),
+ },
+ example: ({ orientation, stepStyle }) => (
+
+
+
+
+
+ ),
+});
diff --git a/packages/components/skeleton/src/SkeletonContainer/SkeletonContainer.figma.tsx b/packages/components/skeleton/src/SkeletonContainer/SkeletonContainer.figma.tsx
new file mode 100644
index 0000000000..6a8043f908
--- /dev/null
+++ b/packages/components/skeleton/src/SkeletonContainer/SkeletonContainer.figma.tsx
@@ -0,0 +1,45 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { SkeletonContainer } from './SkeletonContainer';
+import { SkeletonImage } from '../SkeletonImage/SkeletonImage';
+import { SkeletonBodyText } from '../SkeletonBodyText/SkeletonBodyText';
+import { SkeletonDisplayText } from '../SkeletonDisplayText/SkeletonDisplayText';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=11349:96138';
+
+figma.connect(SkeletonContainer, FIGMA_URL, {
+ variant: { Type: 'Image' },
+ example: () => (
+
+
+
+ ),
+});
+
+figma.connect(SkeletonContainer, FIGMA_URL, {
+ variant: { Type: 'Image round' },
+ example: () => (
+
+
+
+ ),
+});
+
+figma.connect(SkeletonContainer, FIGMA_URL, {
+ variant: { Type: 'Body text / Basic' },
+ example: () => (
+
+
+
+ ),
+});
+
+figma.connect(SkeletonContainer, FIGMA_URL, {
+ variant: { Type: 'Display text' },
+ example: () => (
+
+
+
+ ),
+});
diff --git a/packages/components/spinner/src/Spinner.figma.tsx b/packages/components/spinner/src/Spinner.figma.tsx
new file mode 100644
index 0000000000..3806c3eae7
--- /dev/null
+++ b/packages/components/spinner/src/Spinner.figma.tsx
@@ -0,0 +1,12 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Spinner } from './Spinner';
+
+figma.connect(
+ Spinner,
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=9014:128775',
+ {
+ props: {},
+ example: () => ,
+ },
+);
diff --git a/packages/components/tabs/src/Tabs.figma.tsx b/packages/components/tabs/src/Tabs.figma.tsx
new file mode 100644
index 0000000000..2dba9042a4
--- /dev/null
+++ b/packages/components/tabs/src/Tabs.figma.tsx
@@ -0,0 +1,28 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Tabs } from './CompoundTabs';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=1207:837';
+
+figma.connect(Tabs, FIGMA_URL, {
+ props: {
+ variant: figma.enum('Divider', {
+ None: 'default',
+ Horizontal: 'horizontal-divider',
+ Vertical: 'vertical-divider',
+ }),
+ },
+ example: ({ variant }) => (
+
+
+ First
+ Second
+ Third
+
+ Content for the first tab
+ Content for the second tab
+ Content for the third tab
+
+ ),
+});
diff --git a/packages/components/text-link/src/TextLink.figma.tsx b/packages/components/text-link/src/TextLink.figma.tsx
new file mode 100644
index 0000000000..c2325720ec
--- /dev/null
+++ b/packages/components/text-link/src/TextLink.figma.tsx
@@ -0,0 +1,70 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { TextLink } from './TextLink';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=9505:122034';
+
+figma.connect(TextLink, FIGMA_URL, {
+ variant: { State: 'Default' },
+ props: {
+ variant: figma.enum('Type', {
+ Primary: 'primary',
+ Secondary: 'secondary',
+ Positive: 'positive',
+ Negative: 'negative',
+ White: 'white',
+ Muted: 'muted',
+ Highlight: 'premium',
+ }),
+ children: figma.string('Label'),
+ icon: figma.boolean('Show start icon', {
+ true: figma.instance('Start icon'),
+ false: figma.boolean('Show end icon', {
+ true: figma.instance('End icon'),
+ false: undefined,
+ }),
+ }),
+ alignIcon: figma.boolean('Show end icon', {
+ true: 'end',
+ false: undefined,
+ }),
+ },
+ example: ({ variant, children, icon, alignIcon }) => (
+
+ {children}
+
+ ),
+});
+
+figma.connect(TextLink, FIGMA_URL, {
+ variant: { State: 'Disabled' },
+ props: {
+ variant: figma.enum('Type', {
+ Primary: 'primary',
+ Secondary: 'secondary',
+ Positive: 'positive',
+ Negative: 'negative',
+ White: 'white',
+ Muted: 'muted',
+ Highlight: 'premium',
+ }),
+ children: figma.string('Label'),
+ icon: figma.boolean('Show start icon', {
+ true: figma.instance('Start icon'),
+ false: figma.boolean('Show end icon', {
+ true: figma.instance('End icon'),
+ false: undefined,
+ }),
+ }),
+ alignIcon: figma.boolean('Show end icon', {
+ true: 'end',
+ false: undefined,
+ }),
+ },
+ example: ({ variant, children, icon, alignIcon }) => (
+
+ {children}
+
+ ),
+});
diff --git a/packages/components/tooltip/src/Tooltip.figma.tsx b/packages/components/tooltip/src/Tooltip.figma.tsx
new file mode 100644
index 0000000000..3e22b4e41e
--- /dev/null
+++ b/packages/components/tooltip/src/Tooltip.figma.tsx
@@ -0,0 +1,24 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Tooltip } from './Tooltip';
+
+figma.connect(
+ Tooltip,
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=902:9261',
+ {
+ props: {
+ content: figma.string('Text'),
+ placement: figma.enum('Placement', {
+ Top: 'top',
+ Bottom: 'bottom',
+ Left: 'left',
+ Right: 'right',
+ }),
+ },
+ example: ({ content, placement }) => (
+
+
+
+ ),
+ },
+);
diff --git a/packages/components/typography/src/Caption/Caption.figma.tsx b/packages/components/typography/src/Caption/Caption.figma.tsx
new file mode 100644
index 0000000000..962d857047
--- /dev/null
+++ b/packages/components/typography/src/Caption/Caption.figma.tsx
@@ -0,0 +1,25 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Caption } from './Caption';
+
+figma.connect(
+ Caption,
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=16786:124472',
+ {
+ props: {
+ fontWeight: figma.enum('Font weight', {
+ Regular: undefined,
+ Medium: 'fontWeightMedium',
+ }),
+ isTruncated: figma.enum('Truncated', {
+ True: true,
+ False: undefined,
+ }),
+ },
+ example: ({ fontWeight, isTruncated }) => (
+
+ Caption text
+
+ ),
+ },
+);
diff --git a/packages/components/typography/src/DisplayText/DisplayText.figma.tsx b/packages/components/typography/src/DisplayText/DisplayText.figma.tsx
new file mode 100644
index 0000000000..9a07451820
--- /dev/null
+++ b/packages/components/typography/src/DisplayText/DisplayText.figma.tsx
@@ -0,0 +1,26 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { DisplayText } from './DisplayText';
+
+figma.connect(
+ DisplayText,
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=16387:969',
+ {
+ props: {
+ size: figma.enum('Font size', {
+ Default: undefined,
+ Large: 'large',
+ Huge: 'large',
+ }),
+ isTruncated: figma.enum('Truncated', {
+ True: true,
+ False: undefined,
+ }),
+ },
+ example: ({ size, isTruncated }) => (
+
+ Display text
+
+ ),
+ },
+);
diff --git a/packages/components/typography/src/Heading/Heading.figma.tsx b/packages/components/typography/src/Heading/Heading.figma.tsx
new file mode 100644
index 0000000000..47b0e6b1a5
--- /dev/null
+++ b/packages/components/typography/src/Heading/Heading.figma.tsx
@@ -0,0 +1,25 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Heading } from './Heading';
+
+figma.connect(
+ Heading,
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=16387:978',
+ {
+ props: {
+ isTruncated: figma.enum('Truncated', {
+ True: true,
+ False: undefined,
+ }),
+ marginBottom: figma.enum('Bottom margin', {
+ True: undefined,
+ False: 'none',
+ }),
+ },
+ example: ({ isTruncated, marginBottom }) => (
+
+ Heading text
+
+ ),
+ },
+);
diff --git a/packages/components/typography/src/Paragraph/Paragraph.figma.tsx b/packages/components/typography/src/Paragraph/Paragraph.figma.tsx
new file mode 100644
index 0000000000..4d5ba7ad2c
--- /dev/null
+++ b/packages/components/typography/src/Paragraph/Paragraph.figma.tsx
@@ -0,0 +1,34 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Paragraph } from './Paragraph';
+
+figma.connect(
+ Paragraph,
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=16387:964',
+ {
+ props: {
+ fontWeight: figma.enum('Font weight', {
+ Regular: undefined,
+ Medium: 'fontWeightMedium',
+ 'Demi bold': 'fontWeightDemiBold',
+ }),
+ isTruncated: figma.enum('Truncated', {
+ True: true,
+ False: undefined,
+ }),
+ marginBottom: figma.enum('Bottom margin', {
+ True: undefined,
+ False: 'none',
+ }),
+ },
+ example: ({ fontWeight, isTruncated, marginBottom }) => (
+
+ Paragraph text
+
+ ),
+ },
+);
diff --git a/packages/components/typography/src/SectionHeading/SectionHeading.figma.tsx b/packages/components/typography/src/SectionHeading/SectionHeading.figma.tsx
new file mode 100644
index 0000000000..c4ce4459f9
--- /dev/null
+++ b/packages/components/typography/src/SectionHeading/SectionHeading.figma.tsx
@@ -0,0 +1,25 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { SectionHeading } from './SectionHeading';
+
+figma.connect(
+ SectionHeading,
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=16387:3324',
+ {
+ props: {
+ isTruncated: figma.enum('Truncated', {
+ True: true,
+ False: undefined,
+ }),
+ marginBottom: figma.enum('Bottom margin', {
+ True: undefined,
+ False: 'none',
+ }),
+ },
+ example: ({ isTruncated, marginBottom }) => (
+
+ Section heading text
+
+ ),
+ },
+);
diff --git a/packages/components/typography/src/Subheading/Subheading.figma.tsx b/packages/components/typography/src/Subheading/Subheading.figma.tsx
new file mode 100644
index 0000000000..b1eddd3b20
--- /dev/null
+++ b/packages/components/typography/src/Subheading/Subheading.figma.tsx
@@ -0,0 +1,25 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { Subheading } from './Subheading';
+
+figma.connect(
+ Subheading,
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=16387:985',
+ {
+ props: {
+ isTruncated: figma.enum('Truncated', {
+ True: true,
+ False: undefined,
+ }),
+ marginBottom: figma.enum('Bottom margin', {
+ True: undefined,
+ False: 'none',
+ }),
+ },
+ example: ({ isTruncated, marginBottom }) => (
+
+ Subheading text
+
+ ),
+ },
+);
diff --git a/packages/components/usage-card/src/UsageCard.figma.tsx b/packages/components/usage-card/src/UsageCard.figma.tsx
new file mode 100644
index 0000000000..755f9ce46c
--- /dev/null
+++ b/packages/components/usage-card/src/UsageCard.figma.tsx
@@ -0,0 +1,27 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { UsageCard } from './CompoundUsageCard';
+import { UsageCount } from '@contentful/f36-usage-count';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=16663:2166';
+
+figma.connect(UsageCard, FIGMA_URL, {
+ variant: { Type: 'Usage' },
+ example: () => (
+
+
+
+
+ ),
+});
+
+figma.connect(UsageCard, FIGMA_URL, {
+ variant: { Type: 'Info' },
+ example: () => (
+
+
+ Description text
+
+ ),
+});
diff --git a/packages/components/usage-count/src/UsageCount.figma.tsx b/packages/components/usage-count/src/UsageCount.figma.tsx
new file mode 100644
index 0000000000..ec342e8261
--- /dev/null
+++ b/packages/components/usage-count/src/UsageCount.figma.tsx
@@ -0,0 +1,23 @@
+import React from 'react';
+import figma from '@figma/code-connect';
+import { UsageCount } from './UsageCount';
+
+const FIGMA_URL =
+ 'https://www.figma.com/design/BDteZSphg3YPJTMlABQozc/Forma-36-Components?node-id=16668:6256';
+
+figma.connect(UsageCount, FIGMA_URL, {
+ variant: { Type: 'Periodic' },
+ example: () => ,
+});
+
+figma.connect(UsageCount, FIGMA_URL, {
+ variant: { Type: 'Consumption' },
+ example: () => (
+
+ ),
+});
+
+figma.connect(UsageCount, FIGMA_URL, {
+ variant: { Type: 'Entitlement' },
+ example: () => ,
+});