diff --git a/.changeset/mighty-apes-drive.md b/.changeset/mighty-apes-drive.md new file mode 100644 index 0000000..c95c3da --- /dev/null +++ b/.changeset/mighty-apes-drive.md @@ -0,0 +1,5 @@ +--- +"penpot-exporter": minor +--- + +Rethink the UI to be more usable diff --git a/package-lock.json b/package-lock.json index ea62737..78fab06 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,9 @@ "version": "0.2.2", "license": "MPL2.0", "dependencies": { - "react": "^18.3", - "react-dom": "^18.3", + "@create-figma-plugin/ui": "^3.2", + "classnames": "^2.5", + "preact": "^10.21", "react-hook-form": "^7.51", "romans": "^2.0", "slugify": "^1.6", @@ -21,9 +22,8 @@ "@changesets/cli": "^2.27", "@figma/eslint-plugin-figma-plugins": "^0.15", "@figma/plugin-typings": "^1.92", + "@preact/preset-vite": "^2.8", "@trivago/prettier-plugin-sort-imports": "^4.3", - "@types/react": "^18.3", - "@types/react-dom": "^18.3", "@types/svg-path-parser": "^1.1", "@typescript-eslint/eslint-plugin": "^7.8", "@typescript-eslint/parser": "^7.8", @@ -191,6 +191,32 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure/node_modules/@babel/types": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz", + "integrity": "sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.24.1", + "@babel/helper-validator-identifier": "^7.24.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-compilation-targets": { "version": "7.23.6", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", @@ -338,6 +364,15 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz", + "integrity": "sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-simple-access": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", @@ -400,9 +435,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz", + "integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==", "dev": true, "engines": { "node": ">=6.9.0" @@ -508,6 +543,69 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", + "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.23.4.tgz", + "integrity": "sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.23.3", + "@babel/types": "^7.23.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz", + "integrity": "sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==", + "dev": true, + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx/node_modules/@babel/types": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz", + "integrity": "sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.24.1", + "@babel/helper-validator-identifier": "^7.24.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/runtime": { "version": "7.24.4", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.4.tgz", @@ -1003,6 +1101,33 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/@create-figma-plugin/ui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@create-figma-plugin/ui/-/ui-3.2.0.tgz", + "integrity": "sha512-E0is67aaoVECDgSMAlkp584wI24yglENH6M4OIJwDMbHBXidIbtAk9RIbUDr0gC+2NWNRLpIyFQH6LnZcqO+0A==", + "dependencies": { + "@create-figma-plugin/utilities": "^3.2.0" + }, + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "preact": ">=10" + } + }, + "node_modules/@create-figma-plugin/utilities": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@create-figma-plugin/utilities/-/utilities-3.2.0.tgz", + "integrity": "sha512-+5JddDqI6XjVJs0EqgLd+6B9ukjhHFEBesqPI/e0okqS+Ay7Gt3xsD0vMrZjVYfJcmRAprgJhdGBGJZjOZiQIA==", + "dependencies": { + "hex-rgb": "^5.0.0", + "natural-compare-lite": "1.4.0", + "rgb-hex": "^4.1.0" + }, + "engines": { + "node": ">=20" + } + }, "node_modules/@csstools/css-parser-algorithms": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.6.1.tgz", @@ -1493,6 +1618,120 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/@preact/preset-vite": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/@preact/preset-vite/-/preset-vite-2.8.2.tgz", + "integrity": "sha512-m3tl+M8IO8jgiHnk+7LSTFl8axdPXloewi7iGVLdmCwf34XOzEUur0bZVewW4DUbUipFjTS2CXu27+5f/oexBA==", + "dev": true, + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.22.15", + "@babel/plugin-transform-react-jsx-development": "^7.22.5", + "@prefresh/vite": "^2.4.1", + "@rollup/pluginutils": "^4.1.1", + "babel-plugin-transform-hook-names": "^1.0.2", + "debug": "^4.3.4", + "kolorist": "^1.8.0", + "magic-string": "0.30.5", + "node-html-parser": "^6.1.10", + "resolve": "^1.22.8", + "source-map": "^0.7.4", + "stack-trace": "^1.0.0-pre2" + }, + "peerDependencies": { + "@babel/core": "7.x", + "vite": "2.x || 3.x || 4.x || 5.x" + } + }, + "node_modules/@preact/preset-vite/node_modules/@rollup/pluginutils": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", + "dev": true, + "dependencies": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/@preact/preset-vite/node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/@preact/preset-vite/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@prefresh/babel-plugin": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@prefresh/babel-plugin/-/babel-plugin-0.5.1.tgz", + "integrity": "sha512-uG3jGEAysxWoyG3XkYfjYHgaySFrSsaEb4GagLzYaxlydbuREtaX+FTxuIidp241RaLl85XoHg9Ej6E4+V1pcg==", + "dev": true + }, + "node_modules/@prefresh/core": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@prefresh/core/-/core-1.5.2.tgz", + "integrity": "sha512-A/08vkaM1FogrCII5PZKCrygxSsc11obExBScm3JF1CryK2uDS3ZXeni7FeKCx1nYdUkj4UcJxzPzc1WliMzZA==", + "dev": true, + "peerDependencies": { + "preact": "^10.0.0" + } + }, + "node_modules/@prefresh/utils": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@prefresh/utils/-/utils-1.2.0.tgz", + "integrity": "sha512-KtC/fZw+oqtwOLUFM9UtiitB0JsVX0zLKNyRTA332sqREqSALIIQQxdUCS1P3xR/jT1e2e8/5rwH6gdcMLEmsQ==", + "dev": true + }, + "node_modules/@prefresh/vite": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/@prefresh/vite/-/vite-2.4.5.tgz", + "integrity": "sha512-iForDVJ2M8gQYnm5pHumvTEJjGGc7YNYC0GVKnHFL+GvFfKHfH9Rpq67nUAzNbjuLEpqEOUuQVQajMazWu2ZNQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.22.1", + "@prefresh/babel-plugin": "0.5.1", + "@prefresh/core": "^1.5.1", + "@prefresh/utils": "^1.2.0", + "@rollup/pluginutils": "^4.2.1" + }, + "peerDependencies": { + "preact": "^10.4.0", + "vite": ">=2.0.0" + } + }, + "node_modules/@prefresh/vite/node_modules/@rollup/pluginutils": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", + "dev": true, + "dependencies": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/@rollup/pluginutils": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", @@ -1937,31 +2176,6 @@ "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", "dev": true }, - "node_modules/@types/prop-types": { - "version": "15.7.12", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", - "dev": true - }, - "node_modules/@types/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.1.tgz", - "integrity": "sha512-V0kuGBX3+prX+DQ/7r2qsv1NsdfnCLnTgnRJ1pYnxykBhGMz+qj+box5lq7XsO5mtZsBqpjwwTu/7wszPfMBcw==", - "dev": true, - "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-dom": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", - "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", - "dev": true, - "dependencies": { - "@types/react": "*" - } - }, "node_modules/@types/semver": { "version": "7.5.8", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", @@ -2692,6 +2906,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/babel-plugin-transform-hook-names": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-hook-names/-/babel-plugin-transform-hook-names-1.0.2.tgz", + "integrity": "sha512-5gafyjyyBTTdX/tQQ0hRgu4AhNHG/hqWi0ZZmg2xvs2FgRkJXzDNKBZCyoYqgFkovfDrgM8OoKg8karoUvWeCw==", + "dev": true, + "peerDependencies": { + "@babel/core": "^7.12.10" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2710,6 +2933,12 @@ "node": ">=4" } }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -2893,6 +3122,11 @@ "node": ">=8" } }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==" + }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -3110,6 +3344,22 @@ "node": ">=12 || >=16" } }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/css-tree": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", @@ -3123,6 +3373,18 @@ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" } }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -3135,12 +3397,6 @@ "node": ">=4" } }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true - }, "node_modules/csv": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/csv/-/csv-5.5.3.tgz", @@ -3383,6 +3639,61 @@ "node": ">=6.0.0" } }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dev": true, + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, "node_modules/dot-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", @@ -4615,6 +4926,26 @@ "node": ">= 0.4" } }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/hex-rgb": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/hex-rgb/-/hex-rgb-5.0.0.tgz", + "integrity": "sha512-NQO+lgVUCtHxZ792FodgW0zflK+ozS9X9dwGp9XvvmPlH7pyxd588cn24TD3rmPm/N0AIRXF10Otah8yKqGw4w==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", @@ -5164,7 +5495,8 @@ "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true }, "node_modules/js-yaml": { "version": "4.1.0", @@ -5283,6 +5615,12 @@ "integrity": "sha512-VSWXYUnsPu9+WYKkfmJyLKtIvaRJi1kXUqVmBACORXZQxT5oZDsoZ2vQP+bQFDnWtpI/4eq3MLoRMjI2fnLzTQ==", "dev": true }, + "node_modules/kolorist": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", + "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", + "dev": true + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -5382,6 +5720,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, @@ -5410,6 +5749,18 @@ "node": ">=10" } }, + "node_modules/magic-string": { + "version": "0.30.5", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", + "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/map-obj": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", @@ -5549,6 +5900,11 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==" + }, "node_modules/no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", @@ -5579,6 +5935,16 @@ } } }, + "node_modules/node-html-parser": { + "version": "6.1.13", + "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.13.tgz", + "integrity": "sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==", + "dev": true, + "dependencies": { + "css-select": "^5.1.0", + "he": "1.2.0" + } + }, "node_modules/node-releases": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", @@ -5632,6 +5998,18 @@ "node": ">=0.10.0" } }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -6095,6 +6473,15 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true }, + "node_modules/preact": { + "version": "10.21.0", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.21.0.tgz", + "integrity": "sha512-aQAIxtzWEwH8ou+OovWVSVNlFImL7xUCwJX3YMqA3U8iKCNC34999fFOnWjYNsylgfPgMexpbk7WYOLtKr/mxg==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, "node_modules/preferred-pm": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/preferred-pm/-/preferred-pm-3.1.3.tgz", @@ -6202,26 +6589,13 @@ } }, "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - }, + "name": "@preact/compat", + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/@preact/compat/-/compat-17.1.2.tgz", + "integrity": "sha512-7pOZN9lMDDRQ+6aWvjwTp483KR8/zOpfS83wmOo3zfuLKdngS8/5RLbsFWzFZMGdYlotAhX980hJ75bjOHTwWg==", + "peer": true, "peerDependencies": { - "react": "^18.3.1" + "preact": "*" } }, "node_modules/react-hook-form": { @@ -6502,6 +6876,17 @@ "node": ">=0.10.0" } }, + "node_modules/rgb-hex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/rgb-hex/-/rgb-hex-4.1.0.tgz", + "integrity": "sha512-UZLM57BW09Yi9J1R3OP8B1yCbbDK3NT8BDtihGZkGkGEs2b6EaV85rsfJ6yK4F+8UbxFFmfA+9xHT5ZWhN1gDQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -6629,14 +7014,6 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, - "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, "node_modules/semver": { "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", @@ -7145,6 +7522,15 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, + "node_modules/stack-trace": { + "version": "1.0.0-pre2", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-1.0.0-pre2.tgz", + "integrity": "sha512-2ztBJRek8IVofG9DBJqdy2N5kulaacX30Nz7xmkYF6ale9WBVmIy6mFBchvGX7Vx/MyjBhx+Rcxqrj+dbOnQ6A==", + "dev": true, + "engines": { + "node": ">=16" + } + }, "node_modules/stream-transform": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/stream-transform/-/stream-transform-2.1.3.tgz", diff --git a/package.json b/package.json index 8236031..7a0272b 100644 --- a/package.json +++ b/package.json @@ -23,8 +23,9 @@ "author": "Kaleidos", "license": "MPL2.0", "dependencies": { - "react": "^18.3", - "react-dom": "^18.3", + "@create-figma-plugin/ui": "^3.2", + "classnames": "^2.5", + "preact": "^10.21", "react-hook-form": "^7.51", "romans": "^2.0", "slugify": "^1.6", @@ -35,9 +36,8 @@ "@changesets/cli": "^2.27", "@figma/eslint-plugin-figma-plugins": "^0.15", "@figma/plugin-typings": "^1.92", + "@preact/preset-vite": "^2.8", "@trivago/prettier-plugin-sort-imports": "^4.3", - "@types/react": "^18.3", - "@types/react-dom": "^18.3", "@types/svg-path-parser": "^1.1", "@typescript-eslint/eslint-plugin": "^7.8", "@typescript-eslint/parser": "^7.8", diff --git a/plugin-src/code.ts b/plugin-src/code.ts index 6198282..df7bc25 100644 --- a/plugin-src/code.ts +++ b/plugin-src/code.ts @@ -1,9 +1,9 @@ -import { transformDocumentNode } from '@plugin/transformers'; - import { findAllTextNodes } from './findAllTextnodes'; -import { setCustomFontId } from './translators/text/font/custom'; +import { handleExportMessage } from './handleExportMessage'; +import { BASE_WIDTH, LOADING_HEIGHT } from './pluginSizes'; +import { registerChange } from './registerChange'; -figma.showUI(__html__, { themeColors: true, height: 300, width: 400 }); +figma.showUI(__html__, { themeColors: true, width: BASE_WIDTH, height: LOADING_HEIGHT }); figma.ui.onmessage = message => { if (message.type === 'ready') { @@ -17,17 +17,12 @@ figma.ui.onmessage = message => { if (message.type === 'cancel') { figma.closePlugin(); } + + if (message.type === 'reload') { + findAllTextNodes(); + } }; -const handleExportMessage = async (missingFontIds: Record) => { - await figma.loadAllPagesAsync(); - - Object.entries(missingFontIds).forEach(([fontFamily, fontId]) => { - setCustomFontId(fontFamily, fontId); - }); - - figma.ui.postMessage({ - type: 'PENPOT_DOCUMENT', - data: await transformDocumentNode(figma.root) - }); -}; +figma.on('currentpagechange', () => { + figma.currentPage.once('nodechange', registerChange); +}); diff --git a/plugin-src/findAllTextnodes.ts b/plugin-src/findAllTextnodes.ts index 7a8113d..b6fa894 100644 --- a/plugin-src/findAllTextnodes.ts +++ b/plugin-src/findAllTextnodes.ts @@ -1,3 +1,10 @@ +import { + BASE_WIDTH, + MISSING_FONTS_TEXT_HEIGHT, + MISSING_SINGLE_FONT_HEIGHT, + NORMAL_HEIGHT +} from './pluginSizes'; +import { registerChange } from './registerChange'; import { isGoogleFont } from './translators/text/font/gfonts'; import { isLocalFont } from './translators/text/font/local'; @@ -27,14 +34,10 @@ export const findAllTextNodes = async () => { data: Array.from(fonts) }); - const maxHeight = 300; + const newHeight = + NORMAL_HEIGHT + + (fonts.size > 0 ? MISSING_FONTS_TEXT_HEIGHT + fonts.size * MISSING_SINGLE_FONT_HEIGHT : 0); - if (fonts.size === 0) return; - - if (fonts.size * 40 > maxHeight) { - figma.ui.resize(400, 300 + maxHeight); - return; - } - - figma.ui.resize(400, 300 + fonts.size * 40); + figma.ui.resize(BASE_WIDTH, newHeight); + figma.currentPage.once('nodechange', registerChange); }; diff --git a/plugin-src/handleExportMessage.ts b/plugin-src/handleExportMessage.ts new file mode 100644 index 0000000..93dbdd5 --- /dev/null +++ b/plugin-src/handleExportMessage.ts @@ -0,0 +1,15 @@ +import { transformDocumentNode } from '@plugin/transformers'; +import { setCustomFontId } from '@plugin/translators/text/font/custom'; + +export const handleExportMessage = async (missingFontIds: Record) => { + await figma.loadAllPagesAsync(); + + Object.entries(missingFontIds).forEach(([fontFamily, fontId]) => { + setCustomFontId(fontFamily, fontId); + }); + + figma.ui.postMessage({ + type: 'PENPOT_DOCUMENT', + data: await transformDocumentNode(figma.root) + }); +}; diff --git a/plugin-src/pluginSizes.ts b/plugin-src/pluginSizes.ts new file mode 100644 index 0000000..e67d4e2 --- /dev/null +++ b/plugin-src/pluginSizes.ts @@ -0,0 +1,8 @@ +export const LOADING_HEIGHT = 130; +export const NORMAL_HEIGHT = LOADING_HEIGHT + 5; +export const BASE_WIDTH = 290; + +export const MISSING_FONTS_TEXT_HEIGHT = 195; +export const MISSING_SINGLE_FONT_HEIGHT = 65; + +export const NEEDS_RELOAD_TEXT_HEIGHT = 90; diff --git a/plugin-src/registerChange.ts b/plugin-src/registerChange.ts new file mode 100644 index 0000000..ce2f87f --- /dev/null +++ b/plugin-src/registerChange.ts @@ -0,0 +1,6 @@ +import { BASE_WIDTH, NEEDS_RELOAD_TEXT_HEIGHT, NORMAL_HEIGHT } from './pluginSizes'; + +export const registerChange = () => { + figma.ui.postMessage({ type: 'CHANGES_DETECTED' }); + figma.ui.resize(BASE_WIDTH, NORMAL_HEIGHT + NEEDS_RELOAD_TEXT_HEIGHT); +}; diff --git a/ui-src/App.tsx b/ui-src/App.tsx index be898c6..276112a 100644 --- a/ui-src/App.tsx +++ b/ui-src/App.tsx @@ -1,12 +1,21 @@ -import Logo from '@ui/assets/logo.svg?react'; +import Penpot from '@ui/assets/penpot.svg?react'; import { PenpotExporter } from '@ui/components/PenpotExporter'; +import { Stack } from '@ui/components/Stack'; + +import { Wrapper } from './components/Wrapper/Wrapper'; export const App = () => ( -
-
- -

Penpot Exporter

-
- -
+ + + + + + ); diff --git a/ui-src/assets/logo.svg b/ui-src/assets/logo.svg deleted file mode 100644 index 06adb5d..0000000 --- a/ui-src/assets/logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/ui-src/assets/penpot.svg b/ui-src/assets/penpot.svg new file mode 100644 index 0000000..bb3e0d8 --- /dev/null +++ b/ui-src/assets/penpot.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ui-src/components/Loader.tsx b/ui-src/components/Loader.tsx deleted file mode 100644 index 7ec728f..0000000 --- a/ui-src/components/Loader.tsx +++ /dev/null @@ -1,9 +0,0 @@ -type LoaderProps = { - loading: boolean; -}; - -export const Loader = ({ loading }: LoaderProps) => { - if (!loading) return; - - return
Checking for missing fonts...
; -}; diff --git a/ui-src/components/MissingFontsSection.tsx b/ui-src/components/MissingFontsSection.tsx index a7156bd..a9bc7a6 100644 --- a/ui-src/components/MissingFontsSection.tsx +++ b/ui-src/components/MissingFontsSection.tsx @@ -1,34 +1,61 @@ -import { useFormContext } from 'react-hook-form'; +import { Banner, IconInfo32, Link, Textbox } from '@create-figma-plugin/ui'; +import { Controller, useFormContext } from 'react-hook-form'; + +import { Stack } from './Stack'; type MissingFontsSectionProps = { fonts?: string[]; }; export const MissingFontsSection = ({ fonts }: MissingFontsSectionProps) => { - const { register } = useFormContext(); - - if (fonts === undefined || !fonts.length) return; + if (!fonts || !fonts.length) return null; return ( -
-
- {fonts.length} missing font{fonts.length > 1 ? 's' : ''}:{' '} -
- - Ensure fonts are installed in Penpot before exporting. - -
- {fonts.map(font => ( -
- {font} - -
- ))} -
-
+ + + }> + {fonts.length} custom font{fonts.length > 1 ? 's' : ''} detected + + To export your file with custom fonts, please follow these steps: + +
  • + Upload your local fonts in Penpot. +
    + + Learn how to do it. + +
  • +
  • Copy and paste the font IDs from Penpot below.
  • +
    +
    + {fonts.map(font => ( + + + {font} + + ))} +
    + ); +}; + +type ControlledTextboxProps = { name: string; placeholder: string }; + +const ControlledTextbox = ({ name, placeholder }: ControlledTextboxProps) => { + const { control } = useFormContext(); + + return ( + ( + + )} + /> ); }; diff --git a/ui-src/components/PenpotExporter.tsx b/ui-src/components/PenpotExporter.tsx index 4a9b313..e3dc7f2 100644 --- a/ui-src/components/PenpotExporter.tsx +++ b/ui-src/components/PenpotExporter.tsx @@ -1,16 +1,19 @@ +import { Banner, Button, IconInfo32, LoadingIndicator } from '@create-figma-plugin/ui'; import { useEffect, useState } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; +import { Stack } from '@ui/components/Stack'; import { createPenpotFile } from '@ui/converters'; import { PenpotDocument } from '@ui/lib/types/penpotDocument'; -import { Loader } from './Loader'; import { MissingFontsSection } from './MissingFontsSection'; type FormValues = Record; export const PenpotExporter = () => { const [missingFonts, setMissingFonts] = useState(); + const [needsReload, setNeedsReload] = useState(false); + const [loading, setLoading] = useState(true); const [exporting, setExporting] = useState(false); const methods = useForm(); @@ -26,6 +29,10 @@ export const PenpotExporter = () => { setExporting(false); } else if (event.data.pluginMessage?.type == 'CUSTOM_FONTS') { setMissingFonts(event.data.pluginMessage.data as string[]); + setLoading(false); + setNeedsReload(false); + } else if (event.data.pluginMessage?.type == 'CHANGES_DETECTED') { + setNeedsReload(true); } }; @@ -47,6 +54,11 @@ export const PenpotExporter = () => { parent.postMessage({ pluginMessage: { type: 'cancel' } }, '*'); }; + const reload = () => { + setLoading(true); + parent.postMessage({ pluginMessage: { type: 'reload' } }, '*'); + }; + useEffect(() => { window.addEventListener('message', onMessage); @@ -57,21 +69,43 @@ export const PenpotExporter = () => { }; }, []); - const pluginReady = missingFonts !== undefined; + if (loading) { + return ; + } + + if (needsReload) { + return ( + + }> + Changes detected. Please reload the plug-in to ensure all modifications are included in + the exported file. + + + + + + + ); + } return ( -
    - -
    + + -
    -
    - - -
    + + + + +
    ); diff --git a/ui-src/components/Stack/Stack.module.css b/ui-src/components/Stack/Stack.module.css new file mode 100644 index 0000000..8c0a99c --- /dev/null +++ b/ui-src/components/Stack/Stack.module.css @@ -0,0 +1,32 @@ +.stack { + --direction: column; + --spacing: 1.5rem; + + display: flex; + flex-direction: var(--direction); + gap: var(--spacing); + + & > * { + flex: 1; + } + + .stack-row { + --direction: row; + } + + .stack-small { + --spacing: 1rem; + } + + .stack-xsmall { + --spacing: 0.5rem; + } + + .stack-2xsmall { + --spacing: 0.25rem; + } + + .stack-center { + align-items: center; + } +} diff --git a/ui-src/components/Stack/Stack.tsx b/ui-src/components/Stack/Stack.tsx new file mode 100644 index 0000000..ad18430 --- /dev/null +++ b/ui-src/components/Stack/Stack.tsx @@ -0,0 +1,37 @@ +import classNames from 'classnames'; +import { CSSProperties, PropsWithChildren } from 'react'; + +import styles from './Stack.module.css'; + +type StackProps = PropsWithChildren & { + space?: 'medium' | 'small' | 'xsmall' | '2xsmall'; + direction?: 'column' | 'row'; + horizontalAlign?: 'start' | 'center'; + style?: CSSProperties; + as?: 'div' | 'ol'; +}; + +export const Stack = ({ + space = 'medium', + direction = 'column', + horizontalAlign = 'start', + style, + as = 'div', + children +}: StackProps) => { + const Tag = as; + + return ( + + {children} + + ); +}; diff --git a/ui-src/components/Stack/index.ts b/ui-src/components/Stack/index.ts new file mode 100644 index 0000000..453d31c --- /dev/null +++ b/ui-src/components/Stack/index.ts @@ -0,0 +1 @@ +export * from './Stack'; diff --git a/ui-src/components/Wrapper/Wrapper.module.css b/ui-src/components/Wrapper/Wrapper.module.css new file mode 100644 index 0000000..af6b489 --- /dev/null +++ b/ui-src/components/Wrapper/Wrapper.module.css @@ -0,0 +1,3 @@ +.wrapper { + margin: 1.5rem 1rem 0; +} diff --git a/ui-src/components/Wrapper/Wrapper.tsx b/ui-src/components/Wrapper/Wrapper.tsx new file mode 100644 index 0000000..7a8105c --- /dev/null +++ b/ui-src/components/Wrapper/Wrapper.tsx @@ -0,0 +1,15 @@ +import { CSSProperties, PropsWithChildren } from 'react'; + +import styles from './Wrapper.module.css'; + +type WrapperProps = PropsWithChildren & { + style?: CSSProperties; +}; + +export const Wrapper = ({ style, children }: WrapperProps) => { + return ( +
    + {children} +
    + ); +}; diff --git a/ui-src/main.css b/ui-src/main.css index f565ef0..9b19ebf 100644 --- a/ui-src/main.css +++ b/ui-src/main.css @@ -1,176 +1,40 @@ -:root { - --color-bg: var(--figma-color-bg); - --color-bg-hover: var(--figma-color-bg-hover); - --color-bg-active: var(--figma-color-bg-pressed); - --color-border: var(--figma-color-border); - --color-border-focus: var(--figma-color-border-selected); - --color-icon: var(--figma-color-icon); - --color-text: var(--figma-color-text); - --color-bg-brand: var(--figma-color-bg-brand); - --color-bg-brand-hover: var(--figma-color-bg-brand-hover); - --color-bg-brand-active: var(--figma-color-bg-brand-pressed); - --color-border-brand: var(--figma-color-border-brand); - --color-border-brand-focus: var(--figma-color-border-selected-strong); - --color-text-brand: var(--figma-color-text-onbrand); +*, +*::before, +*::after { + box-sizing: border-box; } -html, -body, -main { - height: 100%; -} - -body, -input, -button { - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, - 'Open Sans', 'Helvetica Neue', sans-serif; - font-size: 1rem; - text-align: center; -} - -body { - background: var(--color-bg); - color: var(--color-text); +* { margin: 0; } -button { - border-radius: 0.25rem; - background: var(--color-bg); - color: var(--color-text); - cursor: pointer; - border: 1px solid var(--color-border); - padding: 0.5rem 1rem; -} - -button:hover { - background-color: var(--color-bg-hover); -} - -button:active { - background-color: var(--color-bg-active); -} - -button:focus-visible { - border: none; - outline-color: var(--color-border-focus); -} - -button:disabled { - background-color: black; - color: var(--color-text); - cursor: not-allowed; -} - -button.brand { - --color-bg: var(--color-bg-brand); - --color-text: var(--color-text-brand); - --color-bg-hover: var(--color-bg-brand-hover); - --color-bg-active: var(--color-bg-brand-active); - --color-border: transparent; - --color-border-focus: var(--color-border-brand-focus); -} - -input { - background: 1px solid var(--color-bg); - border: 1px solid var(--color-border); - color: 1px solid var(--color-text); - padding: 0.5rem; -} - -input:focus-visible { - border-color: var(--color-border-focus); - outline-color: var(--color-border-focus); +body { + line-height: 1.5; + -webkit-font-smoothing: antialiased; } +img, +picture, +video, +canvas, svg { - stroke: var(--color-icon, rgb(0 0 0 / 90%)); - height: auto; - width: 2rem; + display: block; + max-width: 100%; } -main { - align-items: center; - display: flex; - flex-direction: column; - justify-content: center; +input, +button, +textarea, +select { + font: inherit; } -section { - align-items: center; - display: flex; - flex-direction: column; - justify-content: center; - margin-bottom: 1rem; -} - -section > * + * { - margin-top: 0.5rem; -} - -footer > * + * { - margin-left: 0.5rem; -} - -.missing-fonts small { - font-size: 0.5rem; - padding-top: 5px; - padding-bottom: 5px; -} - -ul { - padding: 0; - list-style-type: none; -} - -.centered-form { - display: flex; - flex-direction: column; - align-items: center; - width: 100%; -} - -.missing-fonts-form-container { - width: 100%; - margin: 0 auto 10px; - max-height: 300px; - overflow: auto; -} - -.missing-fonts-section { - width: 100%; - max-width: 500px; - margin: 0 auto; -} - -.missing-fonts-list { - display: flex; - flex-direction: column; - align-items: stretch; - width: 90%; -} - -.font-input-row { - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: 15px; -} - -.font-name { - flex: 0 0 auto; - width: 100%; - max-width: 30%; - text-align: center; - white-space: normal; -} - -.font-id-input { - flex: 1; - width: 70%; - max-width: 70%; - margin-left: 10px; - padding: 5px; - box-sizing: border-box; +p, +h1, +h2, +h3, +h4, +h5, +h6 { + overflow-wrap: break-word; } diff --git a/ui-src/main.tsx b/ui-src/main.tsx index 2c09097..523af78 100644 --- a/ui-src/main.tsx +++ b/ui-src/main.tsx @@ -1,3 +1,4 @@ +import 'node_modules/@create-figma-plugin/ui/lib/css/base.css'; import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; diff --git a/ui-src/tsconfig.json b/ui-src/tsconfig.json index bcec7bf..b71e408 100644 --- a/ui-src/tsconfig.json +++ b/ui-src/tsconfig.json @@ -4,8 +4,15 @@ "target": "ESNext", "useDefineForClassFields": true, "lib": ["DOM", "DOM.Iterable", "ESNext"], + "paths": { + "@plugin/*": ["./plugin-src/*"], + "@ui/*": ["./ui-src/*"], + "react": ["./node_modules/preact/compat/"], + "react-dom": ["./node_modules/preact/compat/"], + "react-dom/client": ["./node_modules/preact/compat/client"] + }, "allowJs": false, - "skipLibCheck": false, + "skipLibCheck": true, "esModuleInterop": false, "strict": true, "forceConsistentCasingInFileNames": true, @@ -14,6 +21,7 @@ "isolatedModules": true, "noEmit": true, "jsx": "react-jsx", + "jsxImportSource": "preact", "allowSyntheticDefaultImports": true } } diff --git a/vite.config.ts b/vite.config.ts index 12ab218..bcd9e6d 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,4 +1,4 @@ -import react from '@vitejs/plugin-react-swc'; +import preact from '@preact/preset-vite'; import { defineConfig } from 'vite'; import { viteSingleFile } from 'vite-plugin-singlefile'; import svgr from 'vite-plugin-svgr'; @@ -6,7 +6,7 @@ import tsconfigPaths from 'vite-tsconfig-paths'; export default defineConfig({ root: './ui-src', - plugins: [svgr(), react(), viteSingleFile(), tsconfigPaths()], + plugins: [svgr(), preact(), viteSingleFile(), tsconfigPaths()], build: { target: 'esnext', assetsInlineLimit: 100000000, @@ -16,7 +16,8 @@ export default defineConfig({ rollupOptions: { output: { inlineDynamicImports: true - } + }, + external: ['!../css/base.css'] } } });