diff --git a/package-lock.json b/package-lock.json index 1b837ad..c90e097 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,9 @@ "react-bootstrap": "^2.7.4", "react-dev-utils": "^12.0.1", "react-redux": "^8.0.1", - "react-router-dom": "^6.13.0" + "react-router-dom": "^6.13.0", + "uuid": "^9.0.0", + "vite-plugin-svgr": "^3.2.0" }, "devDependencies": { "@storybook/addon-essentials": "^7.0.23", @@ -37,6 +39,7 @@ "@types/react": "^18.0.15", "@types/react-dom": "^18.0.6", "@types/testing-library__jest-dom": "^5.14.5", + "@types/uuid": "^9.0.2", "@vitejs/plugin-react": "^4.0.0", "eslint": "^8.0.0", "eslint-config-react-app": "^7.0.1", @@ -9478,6 +9481,247 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-7.0.0.tgz", + "integrity": "sha512-khWbXesWIP9v8HuKCl2NU2HNAyqpSQ/vkIl36Nbn4HIwEYSRWL0H7Gs6idJdha2DkpFDWlsqMELvoCE8lfFY6Q==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-7.0.0.tgz", + "integrity": "sha512-iiZaIvb3H/c7d3TH2HBeK91uI2rMhZNwnsIrvd7ZwGLkFw6mmunOCoVnjdYua662MqGFxlN9xTq4fv9hgR4VXQ==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-7.0.0.tgz", + "integrity": "sha512-sQQmyo+qegBx8DfFc04PFmIO1FP1MHI1/QEpzcIcclo5OAISsOJPW76ZIs0bDyO/DBSJEa/tDa1W26pVtt0FRw==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-7.0.0.tgz", + "integrity": "sha512-i6MaAqIZXDOJeikJuzocByBf8zO+meLwfQ/qMHIjCcvpnfvWf82PFvredEZElErB5glQFJa2KVKk8N2xV6tRRA==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-7.0.0.tgz", + "integrity": "sha512-BoVSh6ge3SLLpKC0pmmN9DFlqgFy4NxNgdZNLPNJWBUU7TQpDWeBuyVuDW88iXydb5Cv0ReC+ffa5h3VrKfk1w==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-7.0.0.tgz", + "integrity": "sha512-tNDcBa+hYn0gO+GkP/AuNKdVtMufVhU9fdzu+vUQsR18RIJ9RWe7h/pSBY338RO08wArntwbDk5WhQBmhf2PaA==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-7.0.0.tgz", + "integrity": "sha512-qw54u8ljCJYL2KtBOjI5z7Nzg8LnSvQOP5hPKj77H4VQL4+HdKbAT5pnkkZLmHKYwzsIHSYKXxHouD8zZamCFQ==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-7.0.0.tgz", + "integrity": "sha512-CcFECkDj98daOg9jE3Bh3uyD9kzevCAnZ+UtzG6+BQG/jOQ2OA3jHnX6iG4G1MCJkUQFnUvEv33NvQfqrb/F3A==", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-7.0.0.tgz", + "integrity": "sha512-EX/NHeFa30j5UjldQGVQikuuQNHUdGmbh9kEpBKofGUtF0GUPJ4T4rhoYiqDAOmBOxojyot36JIFiDUHUK1ilQ==", + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "^7.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "^7.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "^7.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^7.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "^7.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "^7.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "^7.0.0", + "@svgr/babel-plugin-transform-svg-component": "^7.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-7.0.0.tgz", + "integrity": "sha512-ztAoxkaKhRVloa3XydohgQQCb0/8x9T63yXovpmHzKMkHO6pkjdsIAWKOS4bE95P/2quVh1NtjSKlMRNzSBffw==", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "^7.0.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/core/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/@svgr/core/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@svgr/core/node_modules/cosmiconfig": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.2.0.tgz", + "integrity": "sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==", + "dependencies": { + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/@svgr/core/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-7.0.0.tgz", + "integrity": "sha512-42Ej9sDDEmsJKjrfQ1PHmiDiHagh/u9AHO9QWbeNx4KmD9yS5d1XHmXUNINfUcykAU+4431Cn+k6Vn5mWBYimQ==", + "dependencies": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-7.0.0.tgz", + "integrity": "sha512-SWlTpPQmBUtLKxXWgpv8syzqIU8XgFRvyhfkam2So8b3BE0OS0HPe5UfmlJ2KIC+a7dpuuYovPR2WAQuSyMoPw==", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "^7.0.0", + "@svgr/hast-util-to-babel-ast": "^7.0.0", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, "node_modules/@swc/helpers": { "version": "0.4.14", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", @@ -9833,8 +10077,7 @@ "node_modules/@types/estree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", - "peer": true + "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==" }, "node_modules/@types/express": { "version": "4.17.17", @@ -10140,6 +10383,12 @@ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" }, + "node_modules/@types/uuid": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.2.tgz", + "integrity": "sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==", + "dev": true + }, "node_modules/@types/warning": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz", @@ -12644,6 +12893,17 @@ "node": ">=6" } }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/envinfo": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.9.0.tgz", @@ -13573,8 +13833,7 @@ "node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, "node_modules/esutils": { "version": "2.0.3", @@ -15031,7 +15290,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz", "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==", - "dev": true + "devOptional": true }, "node_modules/import-fresh": { "version": "3.3.0", @@ -18047,18 +18306,6 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/parse5/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -18355,7 +18602,6 @@ "version": "8.4.24", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.24.tgz", "integrity": "sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==", - "dev": true, "funding": [ { "type": "opencollective", @@ -19587,7 +19833,6 @@ "version": "3.25.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.25.1.tgz", "integrity": "sha512-tywOR+rwIt5m2ZAWSe5AIJcTat8vGlnPFAv15ycCrw33t6iFsXZ6mzHVFh2psSjxQPmI+xgzMZZizUAukBI4aQ==", - "dev": true, "bin": { "rollup": "dist/bin/rollup" }, @@ -19763,7 +20008,7 @@ "version": "1.63.4", "resolved": "https://registry.npmjs.org/sass/-/sass-1.63.4.tgz", "integrity": "sha512-Sx/+weUmK+oiIlI+9sdD0wZHsqpbgQg8wSwSnGBjwb5GwqFhYNwwnI+UWZtLjKvKyFlKkatRK235qQ3mokyPoQ==", - "dev": true, + "devOptional": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -20115,7 +20360,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -20420,6 +20664,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" + }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -21345,7 +21594,6 @@ "version": "4.3.9", "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.9.tgz", "integrity": "sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==", - "dev": true, "dependencies": { "esbuild": "^0.17.5", "postcss": "^8.4.23", @@ -21412,6 +21660,40 @@ "url": "https://github.com/sponsors/antfu" } }, + "node_modules/vite-plugin-svgr": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-3.2.0.tgz", + "integrity": "sha512-Uvq6niTvhqJU6ga78qLKBFJSDvxWhOnyfQSoKpDPMAGxJPo5S3+9hyjExE5YDj6Lpa4uaLkGc1cBgxXov+LjSw==", + "dependencies": { + "@rollup/pluginutils": "^5.0.2", + "@svgr/core": "^7.0.0", + "@svgr/plugin-jsx": "^7.0.0" + }, + "peerDependencies": { + "vite": "^2.6.0 || 3 || 4" + } + }, + "node_modules/vite-plugin-svgr/node_modules/@rollup/pluginutils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", + "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, "node_modules/vitest": { "version": "0.30.1", "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.30.1.tgz", @@ -28605,6 +28887,131 @@ "file-system-cache": "^2.0.0" } }, + "@svgr/babel-plugin-add-jsx-attribute": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-7.0.0.tgz", + "integrity": "sha512-khWbXesWIP9v8HuKCl2NU2HNAyqpSQ/vkIl36Nbn4HIwEYSRWL0H7Gs6idJdha2DkpFDWlsqMELvoCE8lfFY6Q==", + "requires": {} + }, + "@svgr/babel-plugin-remove-jsx-attribute": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-7.0.0.tgz", + "integrity": "sha512-iiZaIvb3H/c7d3TH2HBeK91uI2rMhZNwnsIrvd7ZwGLkFw6mmunOCoVnjdYua662MqGFxlN9xTq4fv9hgR4VXQ==", + "requires": {} + }, + "@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-7.0.0.tgz", + "integrity": "sha512-sQQmyo+qegBx8DfFc04PFmIO1FP1MHI1/QEpzcIcclo5OAISsOJPW76ZIs0bDyO/DBSJEa/tDa1W26pVtt0FRw==", + "requires": {} + }, + "@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-7.0.0.tgz", + "integrity": "sha512-i6MaAqIZXDOJeikJuzocByBf8zO+meLwfQ/qMHIjCcvpnfvWf82PFvredEZElErB5glQFJa2KVKk8N2xV6tRRA==", + "requires": {} + }, + "@svgr/babel-plugin-svg-dynamic-title": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-7.0.0.tgz", + "integrity": "sha512-BoVSh6ge3SLLpKC0pmmN9DFlqgFy4NxNgdZNLPNJWBUU7TQpDWeBuyVuDW88iXydb5Cv0ReC+ffa5h3VrKfk1w==", + "requires": {} + }, + "@svgr/babel-plugin-svg-em-dimensions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-7.0.0.tgz", + "integrity": "sha512-tNDcBa+hYn0gO+GkP/AuNKdVtMufVhU9fdzu+vUQsR18RIJ9RWe7h/pSBY338RO08wArntwbDk5WhQBmhf2PaA==", + "requires": {} + }, + "@svgr/babel-plugin-transform-react-native-svg": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-7.0.0.tgz", + "integrity": "sha512-qw54u8ljCJYL2KtBOjI5z7Nzg8LnSvQOP5hPKj77H4VQL4+HdKbAT5pnkkZLmHKYwzsIHSYKXxHouD8zZamCFQ==", + "requires": {} + }, + "@svgr/babel-plugin-transform-svg-component": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-7.0.0.tgz", + "integrity": "sha512-CcFECkDj98daOg9jE3Bh3uyD9kzevCAnZ+UtzG6+BQG/jOQ2OA3jHnX6iG4G1MCJkUQFnUvEv33NvQfqrb/F3A==", + "requires": {} + }, + "@svgr/babel-preset": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-7.0.0.tgz", + "integrity": "sha512-EX/NHeFa30j5UjldQGVQikuuQNHUdGmbh9kEpBKofGUtF0GUPJ4T4rhoYiqDAOmBOxojyot36JIFiDUHUK1ilQ==", + "requires": { + "@svgr/babel-plugin-add-jsx-attribute": "^7.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "^7.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "^7.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^7.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "^7.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "^7.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "^7.0.0", + "@svgr/babel-plugin-transform-svg-component": "^7.0.0" + } + }, + "@svgr/core": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-7.0.0.tgz", + "integrity": "sha512-ztAoxkaKhRVloa3XydohgQQCb0/8x9T63yXovpmHzKMkHO6pkjdsIAWKOS4bE95P/2quVh1NtjSKlMRNzSBffw==", + "requires": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "^7.0.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" + }, + "cosmiconfig": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.2.0.tgz", + "integrity": "sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==", + "requires": { + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0" + } + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "requires": { + "argparse": "^2.0.1" + } + } + } + }, + "@svgr/hast-util-to-babel-ast": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-7.0.0.tgz", + "integrity": "sha512-42Ej9sDDEmsJKjrfQ1PHmiDiHagh/u9AHO9QWbeNx4KmD9yS5d1XHmXUNINfUcykAU+4431Cn+k6Vn5mWBYimQ==", + "requires": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + } + }, + "@svgr/plugin-jsx": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-7.0.0.tgz", + "integrity": "sha512-SWlTpPQmBUtLKxXWgpv8syzqIU8XgFRvyhfkam2So8b3BE0OS0HPe5UfmlJ2KIC+a7dpuuYovPR2WAQuSyMoPw==", + "requires": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "^7.0.0", + "@svgr/hast-util-to-babel-ast": "^7.0.0", + "svg-parser": "^2.0.4" + } + }, "@swc/helpers": { "version": "0.4.14", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", @@ -28901,8 +29308,7 @@ "@types/estree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", - "peer": true + "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==" }, "@types/express": { "version": "4.17.17", @@ -29207,6 +29613,12 @@ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" }, + "@types/uuid": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.2.tgz", + "integrity": "sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==", + "dev": true + }, "@types/warning": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz", @@ -31116,6 +31528,11 @@ } } }, + "entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" + }, "envinfo": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.9.0.tgz", @@ -31806,8 +32223,7 @@ "estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, "esutils": { "version": "2.0.3", @@ -32908,7 +33324,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz", "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==", - "dev": true + "devOptional": true }, "import-fresh": { "version": "3.3.0", @@ -35094,14 +35510,6 @@ "dev": true, "requires": { "entities": "^4.4.0" - }, - "dependencies": { - "entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true - } } }, "parseurl": { @@ -35329,7 +35737,6 @@ "version": "8.4.24", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.24.tgz", "integrity": "sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==", - "dev": true, "requires": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", @@ -36240,7 +36647,6 @@ "version": "3.25.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.25.1.tgz", "integrity": "sha512-tywOR+rwIt5m2ZAWSe5AIJcTat8vGlnPFAv15ycCrw33t6iFsXZ6mzHVFh2psSjxQPmI+xgzMZZizUAukBI4aQ==", - "dev": true, "requires": { "fsevents": "~2.3.2" } @@ -36351,7 +36757,7 @@ "version": "1.63.4", "resolved": "https://registry.npmjs.org/sass/-/sass-1.63.4.tgz", "integrity": "sha512-Sx/+weUmK+oiIlI+9sdD0wZHsqpbgQg8wSwSnGBjwb5GwqFhYNwwnI+UWZtLjKvKyFlKkatRK235qQ3mokyPoQ==", - "dev": true, + "devOptional": true, "requires": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -36635,8 +37041,7 @@ "source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" }, "source-map-support": { "version": "0.5.21", @@ -36871,6 +37276,11 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" }, + "svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" + }, "symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -37575,7 +37985,6 @@ "version": "4.3.9", "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.9.tgz", "integrity": "sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==", - "dev": true, "requires": { "esbuild": "^0.17.5", "fsevents": "~2.3.2", @@ -37597,6 +38006,28 @@ "vite": "^3.0.0 || ^4.0.0" } }, + "vite-plugin-svgr": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-3.2.0.tgz", + "integrity": "sha512-Uvq6niTvhqJU6ga78qLKBFJSDvxWhOnyfQSoKpDPMAGxJPo5S3+9hyjExE5YDj6Lpa4uaLkGc1cBgxXov+LjSw==", + "requires": { + "@rollup/pluginutils": "^5.0.2", + "@svgr/core": "^7.0.0", + "@svgr/plugin-jsx": "^7.0.0" + }, + "dependencies": { + "@rollup/pluginutils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", + "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", + "requires": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + } + } + } + }, "vitest": { "version": "0.30.1", "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.30.1.tgz", diff --git a/package.json b/package.json index 846b72a..2729cc3 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,9 @@ "react-bootstrap": "^2.7.4", "react-dev-utils": "^12.0.1", "react-redux": "^8.0.1", - "react-router-dom": "^6.13.0" + "react-router-dom": "^6.13.0", + "uuid": "^9.0.0", + "vite-plugin-svgr": "^3.2.0" }, "devDependencies": { "@storybook/addon-essentials": "^7.0.23", @@ -56,6 +58,7 @@ "@types/react": "^18.0.15", "@types/react-dom": "^18.0.6", "@types/testing-library__jest-dom": "^5.14.5", + "@types/uuid": "^9.0.2", "@vitejs/plugin-react": "^4.0.0", "eslint": "^8.0.0", "eslint-config-react-app": "^7.0.1", diff --git a/plop-templates/Component/Component.tsx.hbs b/plop-templates/Component/Component.tsx.hbs index 14cbffe..2db4781 100755 --- a/plop-templates/Component/Component.tsx.hbs +++ b/plop-templates/Component/Component.tsx.hbs @@ -1,6 +1,5 @@ import "./{{pascalCase name}}.component.scss" - -interface {{pascalCase name}}Props {} +import { {{pascalCase name}}Props } from "../../../types/components.interface" const {{pascalCase name}} = (props: {{pascalCase name}}Props): JSX.Element => { return
In Component {{pascalCase name}}
diff --git a/plop-templates/components.interface.ts.hbs b/plop-templates/components.interface.ts.hbs new file mode 100644 index 0000000..1eb7881 --- /dev/null +++ b/plop-templates/components.interface.ts.hbs @@ -0,0 +1,2 @@ +/* PLOP_INJECT_INTERFACE */ + diff --git a/plopfile.cjs b/plopfile.cjs index c926a43..24913e3 100644 --- a/plopfile.cjs +++ b/plopfile.cjs @@ -47,6 +47,12 @@ module.exports = (plop) => { pattern: `/* PLOP_INJECT_EXPORT */`, template: `\t{{pascalCase name}},`, }, + { + type: "append", + path: "src/app/types/components.interface.ts", + pattern: `/* PLOP_INJECT_INTERFACE */`, + template: `export interface {{pascalCase name}}Props extends BaseProps {\n}\n`, + }, ], }) plop.setGenerator("atom", { @@ -97,6 +103,12 @@ module.exports = (plop) => { pattern: `/* PLOP_INJECT_EXPORT */`, template: `\t{{pascalCase name}},`, }, + { + type: "append", + path: "src/app/types/components.interface.ts", + pattern: `/* PLOP_INJECT_INTERFACE */`, + template: `export interface {{pascalCase name}}Props extends BaseProps {\n}\n`, + }, ], }) plop.setGenerator("molecule", { @@ -147,6 +159,12 @@ module.exports = (plop) => { pattern: `/* PLOP_INJECT_EXPORT */`, template: `\t{{pascalCase name}},`, }, + { + type: "append", + path: "src/app/types/components.interface.ts", + pattern: `/* PLOP_INJECT_INTERFACE */`, + template: `export interface {{pascalCase name}}Props extends BaseProps {\n}\n`, + }, ], }) plop.setGenerator("page", { diff --git a/src/app/Router.tsx b/src/app/Router.tsx index 330fabc..72e4a0a 100644 --- a/src/app/Router.tsx +++ b/src/app/Router.tsx @@ -1,6 +1,7 @@ import { Suspense, useEffect } from "react" import { useRoutes } from "react-router-dom" -import { AlertProps } from "./components/atoms/Alert/Alert" +import { AlertProps } from "./types/components.interface" +import Header from "./components/Header" import { useAppSelector } from "./hooks" import { notification } from "./store" import { Alert } from "./components" @@ -22,6 +23,7 @@ const Router = (props: RouterProps) => { return ( Loading...}> +
{useRoutes(ROUTES)} diff --git a/src/app/components/ComponentList/ComponentList.tsx b/src/app/components/ComponentList/ComponentList.tsx index 83b116d..830ea38 100755 --- a/src/app/components/ComponentList/ComponentList.tsx +++ b/src/app/components/ComponentList/ComponentList.tsx @@ -14,7 +14,7 @@ const ComponentList = (props: ComponentListProps): JSX.Element => { const params = treeNode.data?.props treeNode.data?.component && navigate( - Network.stringifyUrl(`/component/${treeNode.data?.component}`, params), + Network.stringifyUrl(`/components/${treeNode.data?.component}`, params), ) } return ( diff --git a/src/app/components/Editor/Editor.tsx b/src/app/components/Editor/Editor.tsx index 55d0cc5..cbf77a7 100755 --- a/src/app/components/Editor/Editor.tsx +++ b/src/app/components/Editor/Editor.tsx @@ -1,31 +1,14 @@ -import { useEffect, useState } from "react" +import { ReactNode, useEffect, useState } from "react" import { useLocation } from "react-router-dom" import { createPortal } from "react-dom" import { Alert, Toggle } from ".." +import { FrameContentDefinition } from "../../types/entity.interface" +import { FrameContentProps } from "../../types/components.interface" import Helper from "../../utils/helper" import COMPONENTS from "../../config/components" import * as images from "../../static/images" import "./Editor.component.scss" -interface FrameContentDefinition { - componentName: string - component: JSX.ElementType - props?: { - [key: string]: - | string - | number - | boolean - | { [key: string]: any } - | undefined - } - data: { [key: string]: any } - hierarchy: string -} -interface FrameContentProps { - contentDefinition: FrameContentDefinition | null - notificationProps?: any -} - const FrameContent = ( props: FrameContentProps, ): JSX.Element | string | null => { @@ -66,6 +49,7 @@ const Editor = (): JSX.Element | string => { const [selectedComponentDefinition, setSelectedComponentDefinition] = useState(null) const [theme, setTheme] = useState("th-light-1") + const [portal, setPortal] = useState() const location = useLocation() useEffect(() => { @@ -79,12 +63,20 @@ const Editor = (): JSX.Element | string => { const iframeHtml = contentRef?.contentWindow?.document?.getElementsByTagName("html")[0] iframeHtml && iframeHtml.setAttribute("ar-theme", theme) + const iframeBody = iframeHtml?.getElementsByTagName("body")[0] + iframeBody && (iframeBody.style.backgroundColor = "var(--ar-bg)") + if (selectedComponentDefinition && selectedComponentDefinition.props) { + selectedComponentDefinition.props.theme = theme + } } }, [contentRef, theme]) useEffect(() => { - const locationPathArr = location.pathname.split("/") - const componentName = locationPathArr[locationPathArr.length - 1] + const locationPathArr = location.pathname + .split("/") + .filter((p: string) => p) + const componentName = + locationPathArr.length > 1 && locationPathArr[locationPathArr.length - 1] if (componentName) { const { selectedItem, hierarchy } = Helper.findComponentDescription( componentName, @@ -180,6 +172,19 @@ const Editor = (): JSX.Element | string => { const mountNode = contentRef?.contentWindow?.document?.body + useEffect(() => { + mountNode && + setPortal( + createPortal( + , + mountNode, + ), + ) + }, [selectedComponentDefinition, mountNode, notificationProps, theme]) + return (
@@ -198,16 +203,9 @@ const Editor = (): JSX.Element | string => { ref={setContentRef} title="Armco form-componentComponent Viewer" > - {mountNode && - createPortal( - , - mountNode, - )} - {/*
*/} + {portal} + {/*
*/}
) } diff --git a/src/app/components/Header/Header.component.scss b/src/app/components/Header/Header.component.scss index 3790c81..77e1afe 100755 --- a/src/app/components/Header/Header.component.scss +++ b/src/app/components/Header/Header.component.scss @@ -1,4 +1,11 @@ .ar-Header { background-color: var(--ar-bg-base); border-bottom: 1px solid var(--ar-color-layout-border); + + .ar-Header__app-logo { + cursor: pointer; + .ar-Header__brand { + border-radius: 50%; + } + } } diff --git a/src/app/components/Header/Header.tsx b/src/app/components/Header/Header.tsx index 2cc0764..af52746 100755 --- a/src/app/components/Header/Header.tsx +++ b/src/app/components/Header/Header.tsx @@ -1,9 +1,74 @@ +import { useEffect, useState } from "react" +import { useLocation, useNavigate } from "react-router-dom" +import { v4 as uuid } from "uuid" +import { TabBar } from ".." +import { ArTabType } from "../../types/enums" +import { TabProps } from "../../types/entity.interface" +import { AppLogo } from "../../static/images" +import { ReactComponent as AppName } from "../../static/images/Omnia Alkatra.svg" import "./Header.component.scss" -interface HeaderProps {} +const tabs = [ + { + label: "Components", + id: uuid(), + isActive: true, + route: "/components", + icon: "cg.CgComponents", + }, + { + label: "Icons", + id: uuid(), + isActive: false, + route: "/icons", + icon: "md.MdOutlineInsertEmoticon", + }, + { + label: "Fonts", + id: uuid(), + isActive: false, + route: "/fonts", + icon: "bi.BiFontFamily", + }, +] -const Header = (props: HeaderProps): JSX.Element => { - return
+const Header = (): JSX.Element => { + const navigate = useNavigate() + const location = useLocation() + const [activeTabId, setActiveTabId] = useState() + + useEffect(() => { + const matchedTab = + tabs && tabs.find((tab) => location.pathname.startsWith(tab.route)) + if (matchedTab) { + setActiveTabId(matchedTab.id) + } + }, [location]) + return ( +
+
navigate("/")}> + App Logo + +
+ { + tab.isActive = activeTabId === tab.id + return tab + })} + variant={ArTabType.MODERN} + onTabSelected={(id: string, data: TabProps) => { + data?.data?.route && navigate(data.data.route) + }} + /> +
+ ) } export default Header diff --git a/src/app/components/IconsList/IconsList.tsx b/src/app/components/IconsList/IconsList.tsx index 3d10df7..8ecc65a 100755 --- a/src/app/components/IconsList/IconsList.tsx +++ b/src/app/components/IconsList/IconsList.tsx @@ -1,7 +1,8 @@ import { ChangeEvent } from "react" import { useAppDispatch } from "../../hooks" import { notify } from "../../store" -import { Pagination, Search } from ".." +import { Loader, Pagination, Search } from ".." +import { ArLoaderTypes } from "../../types/enums" import Helper from "../../utils/helper" import { ICON_ROOT } from "../../config/constants" import "./IconsList.component.scss" @@ -58,7 +59,10 @@ const IconsList = (props: IconsListProps): JSX.Element => { } return ( -
+
+ {!icons && ( + + )}
@@ -88,14 +92,13 @@ const IconsList = (props: IconsListProps): JSX.Element => {
-
- {icons && - icons - .slice(0, 100) - .map((icon, index) => ( - - ))} -
+ {icons && ( +
+ {icons.slice(0, 100).map((icon, index) => ( + + ))} +
+ )}
) } diff --git a/src/app/components/Main/Main.tsx b/src/app/components/Main/Main.tsx index 5e59f6e..bd301a1 100755 --- a/src/app/components/Main/Main.tsx +++ b/src/app/components/Main/Main.tsx @@ -14,7 +14,9 @@ const Main = (props: MainProps): JSX.Element => {
{drawerContent} - {mainContent} + + {mainContent} +
) diff --git a/src/app/components/atoms/Alert/Alert.component.scss b/src/app/components/atoms/Alert/Alert.component.scss index b601a2f..30aab15 100755 --- a/src/app/components/atoms/Alert/Alert.component.scss +++ b/src/app/components/atoms/Alert/Alert.component.scss @@ -3,6 +3,7 @@ transition: all 0.3s; border-radius: 0.2rem; opacity: 0; + color: white; &.show { opacity: 1; @@ -67,7 +68,7 @@ } &.success { background-color: var(--ar-color-success); - color: var(--ar-bg); + color: var(--ar-white); } .ar-Alert__icon { diff --git a/src/app/components/atoms/Alert/Alert.tsx b/src/app/components/atoms/Alert/Alert.tsx index e386e40..3908120 100755 --- a/src/app/components/atoms/Alert/Alert.tsx +++ b/src/app/components/atoms/Alert/Alert.tsx @@ -1,20 +1,8 @@ import { useEffect, useState } from "react" import Icon from "../Icon" -import API_CONFIG from "../../../config/api-config" -import "./Alert.component.scss" +import { AlertProps } from "../../../types/components.interface" import { ICON_ROOT } from "../../../config/constants" - -type AlertType = "success" | "warning" | "error" | "information" -export interface AlertProps { - classes?: string - closeable?: boolean - demo?: boolean - position?: string - show?: boolean - type?: AlertType - message: string - timeout?: number -} +import "./Alert.component.scss" let timeoutRef: any const Alert = (props: AlertProps): JSX.Element => { @@ -35,7 +23,10 @@ const Alert = (props: AlertProps): JSX.Element => { setTimeout(() => show("show"), 0) if (!demo || timeout) { clearTimeout(timeoutRef) - timeoutRef = setTimeout(() => show(""), timeout || 5000) + timeoutRef = setTimeout(() => { + show("") + window.top?.postMessage({ ar: null }, "*") + }, timeout || 5000) } } }, [position, type, timeout, externalShow, message, demo]) diff --git a/src/app/components/atoms/BrowserIncompatibility/BrowserIncompatibility.tsx b/src/app/components/atoms/BrowserIncompatibility/BrowserIncompatibility.tsx index 49df3ad..8231339 100755 --- a/src/app/components/atoms/BrowserIncompatibility/BrowserIncompatibility.tsx +++ b/src/app/components/atoms/BrowserIncompatibility/BrowserIncompatibility.tsx @@ -1,36 +1,36 @@ -import { Alert, Icon } from "../.." +import { Alert, Link, LoadableIcon } from "../.." +import { BrowserIncompatibilityProps } from "../../../types/components.interface" import Helper from "../../../utils/helper" -import { ICON_ROOT } from "../../../config/constants" import "./BrowserIncompatibility.component.scss" -interface BrowserIncompatibilityProps { - applicationName?: string - moreLink?: string -} - const BrowserIncompatibility = ( props: BrowserIncompatibilityProps, ): JSX.Element => { - const { applicationName, moreLink } = props - const demoDummyLink = "http://notabuck.com/armco-design-system/docs/devices" + const { applicationName, moreLink, theme } = props + const demoDummyLink = "https://notabuck.com/armco-design-system/docs/devices" const demoAppName = '"My Awesome App"' const helpLink = moreLink || demoDummyLink const app = applicationName || demoAppName const heroIconSize = "8rem" + return (
-
{app} can not run on this browser

Supported browsers are Google Chrome v51+ & Microsoft's Edge v32+

For More details you can also check the below link

-
{ Helper.copyToClipboard(helpLink) window.top?.postMessage( @@ -40,15 +40,15 @@ const BrowserIncompatibility = ( type: "success", closeable: true, message: "Link Copied!", + show: true, }, }, "*", ) }} - > - {helpLink} - -
+ preemptNavigation + /> +
) } diff --git a/src/app/components/atoms/Icon/Icon.tsx b/src/app/components/atoms/Icon/Icon.tsx index 304bc1f..62fd7c8 100755 --- a/src/app/components/atoms/Icon/Icon.tsx +++ b/src/app/components/atoms/Icon/Icon.tsx @@ -1,22 +1,7 @@ -import { MouseEventHandler } from "react" import { ICON_ROOT } from "../../../config/constants" +import { IconProps } from "../../../types/components.interface" import "./Icon.component.scss" -interface IconProps { - alt?: string - classes?: string - color?: string - containerClasses?: string - demo?: boolean - height?: string - onClick?: MouseEventHandler - onMouseEnter?: MouseEventHandler - onMouseLeave?: MouseEventHandler - size?: string - src: string - width?: string -} - const Icon = (props: IconProps): JSX.Element | null => { const { alt, diff --git a/src/app/components/atoms/Link/Link.tsx b/src/app/components/atoms/Link/Link.tsx index 6c31465..385cc12 100755 --- a/src/app/components/atoms/Link/Link.tsx +++ b/src/app/components/atoms/Link/Link.tsx @@ -1,10 +1,41 @@ -import React from "react" +import { useNavigate } from "react-router-dom" +import { LinkProps } from "../../../types/components.interface" import "./Link.component.scss" -interface LinkProps {} - -const Link = (props: any): JSX.Element => { - return
In Component Link
+const Link = (props: LinkProps): JSX.Element => { + const { + classes, + label, + to, + children, + onClick, + openInNew, + preemptNavigation, + } = props + const navigate = useNavigate() + return ( +
{ + if (!preemptNavigation) { + if (to) { + if ( + to.startsWith("http://") || + to.startsWith("https://") || + openInNew + ) { + !openInNew ? window.open(to) : window.open(to, "_blank") + } else { + navigate(to) + } + } + } + onClick && onClick(e) + }} + > + {label || children} +
+ ) } export default Link diff --git a/src/app/components/atoms/LoadableIcon/LoadableIcon.component.scss b/src/app/components/atoms/LoadableIcon/LoadableIcon.component.scss new file mode 100755 index 0000000..d03237c --- /dev/null +++ b/src/app/components/atoms/LoadableIcon/LoadableIcon.component.scss @@ -0,0 +1,3 @@ +.ar-LoadableIcon { + transition: all 0.3s; +} diff --git a/src/app/components/atoms/LoadableIcon/LoadableIcon.test.ts b/src/app/components/atoms/LoadableIcon/LoadableIcon.test.ts new file mode 100755 index 0000000..5526fc3 --- /dev/null +++ b/src/app/components/atoms/LoadableIcon/LoadableIcon.test.ts @@ -0,0 +1,6 @@ +import React from "react" +import LoadableIcon from "./LoadableIcon" + +describe("LoadableIcon", () => { + it("renders without error", () => {}) +}) diff --git a/src/app/components/atoms/LoadableIcon/LoadableIcon.tsx b/src/app/components/atoms/LoadableIcon/LoadableIcon.tsx new file mode 100755 index 0000000..106a366 --- /dev/null +++ b/src/app/components/atoms/LoadableIcon/LoadableIcon.tsx @@ -0,0 +1,113 @@ +import { useEffect, useState } from "react" +import { Network, DomHelper } from "../../../utils" +import { LoadableIconProps } from "../../../types/components.interface" +import { GenericObject, ObjectType } from "../../../types/types" +import "./LoadableIcon.component.scss" + +const parser = new DOMParser() + +// Add below string to prevent API calls for same iconKey, +// This value is overriden in promise resolution below +const ongoingApiCalls: ObjectType = {} + +const iconsFactory: GenericObject = {} + +const placeholder = parser + .parseFromString( + '', + "image/svg+xml", + ) + .querySelector("svg") + +const LoadableIcon = (props: LoadableIconProps) => { + const { classes, color, height, isLocal, size, width } = props + let { icon } = props + const [b64, setB64] = useState() + const [iconContent, setIconContent] = useState( + placeholder, + ) + + icon = !icon || icon.indexOf(".") < 0 ? "gr.GrStatusPlaceholder" : icon + const iconParts = icon.split(".") + const iconCategory = iconParts[0] ? iconParts[0].toLowerCase() : "" + const iconName = iconParts[1] + const iconKey = `${iconCategory}_${iconName}` + + const iData = iconsFactory[iconKey] + + const getIcon = () => { + if (!ongoingApiCalls[iconKey]) { + // console.log("Requesting Icon from Server for the icon: ", iconKey) + ongoingApiCalls[iconKey] = true + Network.getStatic(`/icon/${iconCategory}/${iconName}`) + .then((res) => { + const parsedSvg = parser + .parseFromString(res.body, "image/svg+xml") + .querySelector("svg") + if (parsedSvg) { + iconsFactory[iconKey] = parsedSvg + setIconContent(parsedSvg) + } + }) + .catch((e) => { + console.log(e) + ongoingApiCalls[iconKey] = false + }) + .finally(() => (ongoingApiCalls[iconKey] = false)) + } + } + + /* eslint-disable react-hooks/exhaustive-deps */ + useEffect(() => { + if (!isLocal) { + if (iconName && iconCategory) { + !iData && getIcon() + } else { + console.log("Icon name and category is required, received: ", icon) + } + } + }, []) + + useEffect(() => { + iconContent && !isLocal && setB64(DomHelper.svgToBase64(iconContent)) + }, [iconContent]) + + useEffect(() => { + iData && + !isLocal && + setB64(DomHelper.svgToBase64(iData, { size, classes, color })) + }, [size, classes, color]) + + if (isLocal) { + return ( + Icon + ) + } + + // Below is only for property changes after first render like on hover, click etc + if (iData && !b64) { + setB64(DomHelper.svgToBase64(iData, { size, classes, color })) + } + + return b64 ? ( + Icon + ) : null +} + +export default LoadableIcon diff --git a/src/app/components/atoms/LoadableIcon/index.ts b/src/app/components/atoms/LoadableIcon/index.ts new file mode 100755 index 0000000..210ab4b --- /dev/null +++ b/src/app/components/atoms/LoadableIcon/index.ts @@ -0,0 +1,3 @@ +import LoadableIcon from "./LoadableIcon" + +export default LoadableIcon diff --git a/src/app/components/atoms/Loader/Loader.component.scss b/src/app/components/atoms/Loader/Loader.component.scss new file mode 100755 index 0000000..9543cbf --- /dev/null +++ b/src/app/components/atoms/Loader/Loader.component.scss @@ -0,0 +1,74 @@ +.ar-Loader { + background: rgba(0, 0, 0, 0.2); + z-index: 1001; + .ar-Loader-content { + position: absolute; + + &.custom { + top: calc(50% - 25px); + left: calc(50% - 25px); + .loader { + width: 50px; + height: 50px; + animation: rotating 5s infinite; + border-radius: 50%; + overflow: hidden; + } + } + + &.circle { + top: calc(50% - 25px); + left: calc(50% - 25px); + .loader { + width: 50px; + height: 50px; + animation: effect 1s linear infinite; + border-radius: 50%; + border: 6px solid #a3bdda; + border-top-color: #3B77BC; + } + } + + &.small .loader { + top: calc(50% - 12.5px); + left: calc(50% - 12.5px); + width: 25px; + height: 25px; + } + + &.large .loader { + top: calc(50% - 50px); + left: calc(50% - 50px); + width: 100px; + height: 100px; + } + + } + @keyframes effect { + 0% {transform: rotate(0deg);} + 100% {transform: rotate(360deg);} + } + + @keyframes rotating { + 0% { + transform: rotate(0deg); + animation-timing-function: linear; /* Constant speed for the first 4s */ + } + 25% { + transform: rotate(1800deg); /* 10 rotations (10 x 360 degrees) */ + animation-timing-function: linear; /* Constant speed for the next 1s */ + } + 50% { + transform: rotate(3600deg); /* 6 rotations (6 x 360 degrees) */ + animation-timing-function: cubic-bezier(0, -200, 1, -200); /* Slow down for the next 4s */ + } + 75% { + transform: rotate(4320deg); /* 10 rotations (10 x 360 degrees) */ + animation-timing-function: cubic-bezier(0, -200, 1, -200); /* Constant speed for the next 1s */ + } + 100% { + transform: rotate(5040deg); /* 12 rotations (12 x 360 degrees) */ + animation-timing-function: linear; /* Constant speed for the last 4s */ + } + } +} diff --git a/src/app/components/atoms/Loader/Loader.test.ts b/src/app/components/atoms/Loader/Loader.test.ts new file mode 100755 index 0000000..ec79fa2 --- /dev/null +++ b/src/app/components/atoms/Loader/Loader.test.ts @@ -0,0 +1,8 @@ +import React from "react" +import Loader from "./Loader" + +describe("Loader", () => { + it("renders without error", () => { + + }) +}) diff --git a/src/app/components/atoms/Loader/Loader.tsx b/src/app/components/atoms/Loader/Loader.tsx new file mode 100755 index 0000000..036bd4b --- /dev/null +++ b/src/app/components/atoms/Loader/Loader.tsx @@ -0,0 +1,48 @@ +import { LoaderProps } from "../../../types/components.interface" +import { ArLoaderTypes } from "../../../types/enums" +import { LoadableIcon, ProgressIndicator } from "../.." +import { AppLogo } from "../../../static/images" +import "./Loader.component.scss" + +// Add ability to provide custom loader: an icon or image that rotates +const Loader = (props: LoaderProps): JSX.Element => { + const { type = ArLoaderTypes.CIRCLE, size, label, icon, progress } = props + let loaderContent + switch (type) { + case ArLoaderTypes.BAR: + loaderContent = + break + case ArLoaderTypes.CUSTOM: + loaderContent = ( + <> + + + + {label ? {label} : ""} + + ) + break + case ArLoaderTypes.CIRCLE: + default: + loaderContent = ( + <> + + {label ? {label} : ""} + + ) + } + + return ( +
+
+ {loaderContent} +
+
+ ) +} + +export default Loader diff --git a/src/app/components/atoms/Loader/index.ts b/src/app/components/atoms/Loader/index.ts new file mode 100755 index 0000000..2198ded --- /dev/null +++ b/src/app/components/atoms/Loader/index.ts @@ -0,0 +1,3 @@ +import Loader from "./Loader" + +export default Loader diff --git a/src/app/components/atoms/ProgressIndicator/ProgressIndicator.tsx b/src/app/components/atoms/ProgressIndicator/ProgressIndicator.tsx index 6b505c8..9041648 100755 --- a/src/app/components/atoms/ProgressIndicator/ProgressIndicator.tsx +++ b/src/app/components/atoms/ProgressIndicator/ProgressIndicator.tsx @@ -1,14 +1,11 @@ -import React from "react" import "./ProgressIndicator.component.scss" interface ProgressIndicatorProps {} const ProgressIndicator = (props: any): JSX.Element => { return ( -
- In Component ProgressIndicator -
+
In Component ProgressIndicator
) } -export default ProgressIndicator \ No newline at end of file +export default ProgressIndicator diff --git a/src/app/components/atoms/Tab/Tab.component.scss b/src/app/components/atoms/Tab/Tab.component.scss index 33eb855..4d66b47 100755 --- a/src/app/components/atoms/Tab/Tab.component.scss +++ b/src/app/components/atoms/Tab/Tab.component.scss @@ -1,37 +1,37 @@ .ar-Tab { - width: 5rem; - height: 2rem; + max-width: 10rem; + max-height: 3rem; line-height: 1; - border: var(--ar-border); - border-radius: 6px 6px 0 0; padding: 0.4rem 1rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer; + z-index: 1; - &:hover { + &:hover:not(.active) { background-color: var(--ar-bg-hover); } - .active { - + &.active { + // background-color: var(--ar-bg-selected); } - .compact { + &.compact { } - .comfortable { + &.comfortable { } - .modern { + &.modern { } - .classic { - + &.classic { + border: var(--ar-border); + border-radius: 6px 6px 0 0; } .ar-Tab__delete-icon { diff --git a/src/app/components/atoms/Tab/Tab.tsx b/src/app/components/atoms/Tab/Tab.tsx index 39cae67..eccd20e 100755 --- a/src/app/components/atoms/Tab/Tab.tsx +++ b/src/app/components/atoms/Tab/Tab.tsx @@ -1,55 +1,78 @@ -import Icon from "../Icon" +import { memo, useEffect, useRef } from "react" +import { TabProps } from "../../../types/components.interface" +import { LoadableIcon, Icon } from "../.." import "./Tab.component.scss" -export interface TabProps { - label: string - data?: any - demo?: boolean - deletable?: boolean - id?: string - isActive?: boolean - onSelect?: Function - size?: string - variant?: string -} - const dummyData = { label: "Tab 1", id: "23jhrfl2l3lkj2lk3jlkjlsd", isActive: false, } -const Tab = (props: TabProps): JSX.Element => { - const { - label, - data, - demo, - deletable, - id, - isActive, - onSelect, - size, - variant, - } = props - const useLabel = label ? label : demo ? dummyData.label : label - return ( -
onSelect && onSelect(id, data)} - > - {deletable && ( - - )} - {useLabel} -
- ) -} +const Tab = memo( + (props: TabProps): JSX.Element => { + const { + bubbleDimensions, + data, + demo, + deletable, + icon, + id, + isActive, + label, + onSelect, + size, + variant, + } = props + const tabRef = useRef(null) + let useLabel = label ? label : demo ? dummyData.label : label + + useEffect(() => { + if (isActive && bubbleDimensions) { + const selectedTabDimensions = + tabRef.current && tabRef.current.getBoundingClientRect() + let selectedWidth, selectedLeft + if (selectedTabDimensions) { + selectedWidth = selectedTabDimensions.width + selectedLeft = tabRef.current.offsetLeft + } + bubbleDimensions(selectedWidth, selectedLeft) + } + }, [isActive, bubbleDimensions]) + + return ( +
onSelect && onSelect(id, props)} + ref={tabRef} + > + {deletable && ( + + )} + {useLabel} + {icon && } +
+ ) + }, + (prevProps, props) => { + return ( + prevProps.isActive === props.isActive && + JSON.stringify(prevProps.data) === JSON.stringify(props.data) && + prevProps.icon === props.icon && + prevProps.label === props.label && + prevProps.size === props.size && + prevProps.variant === props.variant + ) + }, +) export default Tab diff --git a/src/app/components/atoms/TabBar/TabBar.component.scss b/src/app/components/atoms/TabBar/TabBar.component.scss index 57faee5..6163866 100755 --- a/src/app/components/atoms/TabBar/TabBar.component.scss +++ b/src/app/components/atoms/TabBar/TabBar.component.scss @@ -1,3 +1,17 @@ .ar-TabBar { height: 3.1rem; + font-size: 0.8rem; + + .slider { + height: 100%; + border-bottom: 3px solid blue; /* Change to your desired border color */ + bottom: 0; + background-color: var(--ar-bg-selected); + } + + &.modern { + .slider { + transition: left 0.3s, width 0.3s; + } + } } diff --git a/src/app/components/atoms/TabBar/TabBar.tsx b/src/app/components/atoms/TabBar/TabBar.tsx index bb0724e..e6909c7 100755 --- a/src/app/components/atoms/TabBar/TabBar.tsx +++ b/src/app/components/atoms/TabBar/TabBar.tsx @@ -1,17 +1,9 @@ import { useEffect, useState } from "react" -import { TabProps } from "../Tab/Tab" import { Tab } from "../.." +import { TabBarProps, TabProps } from "../../../types/components.interface" +import { ObjectType } from "../../../types/types" import "./TabBar.component.scss" -interface TabBarProps { - activeId?: string - data: TabProps[] - demo?: boolean - onTabChanged?: (id: string, data: any) => void - size?: string - variant?: string -} - const dummyData = [ { label: "Tab 1", @@ -31,39 +23,93 @@ const dummyData = [ ] const TabBar = (props: TabBarProps): JSX.Element => { - const { data, demo, onTabChanged, size, variant, activeId } = props - const [activeTab, setActiveTab] = useState() + const { + classes, + data, + demo, + onTabSelected, + size, + variant, + activeId, + ...rest + } = props + const [activeTab, setActiveTab] = useState() const useData = data || (demo && dummyData) + useEffect(() => { + demo && !activeId && setActiveTab({ id: "23jhrfl2l3lkj2lk3jlkjlsd" }) if (activeId !== undefined) { - setActiveTab(activeId) + setActiveTab({ id: activeId }) + } else { + const activeTab = data && data.find((t) => t.isActive) + if (activeTab && activeTab.id) { + setActiveTab({ id: activeTab.id }) + } } - }, [activeId]) - const onLocalTabChanged = (id: string, data: any) => { - if (activeId === undefined) { - setActiveTab(id) - } - onTabChanged && onTabChanged(id, data) + }, [activeId, data, demo]) + + const receiveDimensionsOfSelectedTab = ( + selectedWidth?: number, + selectedLeft?: number, + ) => { + setActiveTab({ ...activeTab, selectedWidth, selectedLeft }) } + + const onLocalTabSelected = (id: string, data: any) => { + if (activeTab) { + if (id !== activeTab.id) { + setActiveTab({ ...activeTab, id }) + onTabSelected && onTabSelected(id, data) + } + } else { + setActiveTab({ id }) + onTabSelected && onTabSelected(id, data) + } + } + const tabRenders = useData ?.filter((t) => t) .map((tab: TabProps) => { return ( ) }) return (
{tabRenders} + {activeTab && + activeTab.selectedLeft !== undefined && + activeTab.selectedWidth !== undefined && ( +
+ )}
) } diff --git a/src/app/components/index.ts b/src/app/components/index.ts index 598b0e4..0cf7967 100755 --- a/src/app/components/index.ts +++ b/src/app/components/index.ts @@ -1,4 +1,6 @@ /* PLOP_INJECT_IMPORT */ +import Loader from "./atoms/Loader" +import LoadableIcon from "./atoms/LoadableIcon" import ErrorBoundary from "./molecules/ErrorBoundary" import Component_404 from "./molecules/Component_404" import AlertStackManager from "./molecules/AlertStackManager" @@ -114,6 +116,8 @@ import Alert from "./atoms/Alert" export { /* PLOP_INJECT_EXPORT */ + Loader, + LoadableIcon, ErrorBoundary, Component_404, AlertStackManager, diff --git a/src/app/components/molecules/Component_404/Component_404.component.scss b/src/app/components/molecules/Component_404/Component_404.component.scss index 537ab7f..8997e16 100755 --- a/src/app/components/molecules/Component_404/Component_404.component.scss +++ b/src/app/components/molecules/Component_404/Component_404.component.scss @@ -1,3 +1,13 @@ .ar-Component_404 { - + .ar-Component_404-content { + height: 30rem; + min-width: 30rem; + font-size: 0.8rem; + border: var(--ar-border); + background-color: var(--ar-bg-base); + transition: box-shadow 0.3s; + &:hover { + box-shadow: 0px 4px 8px var(--ar-shadow); + } + } } diff --git a/src/app/components/molecules/Component_404/Component_404.tsx b/src/app/components/molecules/Component_404/Component_404.tsx index 95cbbc6..178773b 100755 --- a/src/app/components/molecules/Component_404/Component_404.tsx +++ b/src/app/components/molecules/Component_404/Component_404.tsx @@ -1,9 +1,22 @@ +import { Component_404Props } from "../../../types/components.interface" +import { Icon } from "../.." import "./Component_404.component.scss" -interface Component_404Props {} - const Component_404 = (props: Component_404Props): JSX.Element => { - return
In Component Component_404
+ const { iconSize } = props + return ( +
+
+ +
Could not dig what you asked for
+

Please check the URL and try again.

+

+ You may also use the tabs (right-top) to navigate if you're not sure + about the URL +

+
+
+ ) } export default Component_404 diff --git a/src/app/config/api-config.ts b/src/app/config/api-config.ts index c9777c6..b7f71f5 100644 --- a/src/app/config/api-config.ts +++ b/src/app/config/api-config.ts @@ -4,7 +4,7 @@ const API_CONFIG: ApiConfig = { production: "https://armco.tech/api", }, STATIC_HOST: { - development: "http://localhost:8080", + development: "https://static.armco.tech", production: "https://static.armco.tech", }, } diff --git a/src/app/config/components.ts b/src/app/config/components.ts index 5162581..54ee33e 100644 --- a/src/app/config/components.ts +++ b/src/app/config/components.ts @@ -209,6 +209,15 @@ const COMPONENTS: ComponentList = { props: [], variants: {}, }, + { + name: "Loader", + props: ["type", "label", "size"], + variants: { + size: ["small", "regular", "large"], + label: ["Loading Users...", "Submitting Report..."], + type: ["bar", "circle", "custom"], + }, + }, { name: "ProgressIndicator", props: [], diff --git a/src/app/pages/ComponentsViewerPage/ComponentsViewerPage.tsx b/src/app/pages/ComponentsViewerPage/ComponentsViewerPage.tsx index 0710f36..dc53993 100755 --- a/src/app/pages/ComponentsViewerPage/ComponentsViewerPage.tsx +++ b/src/app/pages/ComponentsViewerPage/ComponentsViewerPage.tsx @@ -1,5 +1,4 @@ import Main from "../../components/Main" -import Header from "../../components/Header" import Footer from "../../components/Footer" import ComponentList from "../../components/ComponentList" import Editor from "../../components/Editor" @@ -12,8 +11,7 @@ const ComponentsViewerPage = ( props: ComponentsViewerPageProps, ): JSX.Element => { return ( -
-
+
} mainContent={ diff --git a/src/app/pages/FontsPage/FontsPage.page.scss b/src/app/pages/FontsPage/FontsPage.page.scss new file mode 100755 index 0000000..f717786 --- /dev/null +++ b/src/app/pages/FontsPage/FontsPage.page.scss @@ -0,0 +1,3 @@ +.ar-FontsPage { + +} diff --git a/src/app/pages/FontsPage/FontsPage.slice.ts b/src/app/pages/FontsPage/FontsPage.slice.ts new file mode 100644 index 0000000..1cece56 --- /dev/null +++ b/src/app/pages/FontsPage/FontsPage.slice.ts @@ -0,0 +1,18 @@ +import { createSlice } from "@reduxjs/toolkit" + +export interface FontsPageState {} + +const initialState: FontsPageState = {} + +export const fontsPageSlice = createSlice({ + name: "fontsPage", + initialState, + reducers: { + increment: (state) => {}, + }, + extraReducers: (builder) => {}, +}) + +export const { increment } = fontsPageSlice.actions + +export default fontsPageSlice.reducer diff --git a/src/app/pages/FontsPage/FontsPage.test.ts b/src/app/pages/FontsPage/FontsPage.test.ts new file mode 100755 index 0000000..172187c --- /dev/null +++ b/src/app/pages/FontsPage/FontsPage.test.ts @@ -0,0 +1,8 @@ +import React from "react" +import FontsPage from "./FontsPage" + +describe("FontsPage", () => { + it("renders without error", () => { + + }) +}) diff --git a/src/app/pages/FontsPage/FontsPage.tsx b/src/app/pages/FontsPage/FontsPage.tsx new file mode 100755 index 0000000..cfdaeda --- /dev/null +++ b/src/app/pages/FontsPage/FontsPage.tsx @@ -0,0 +1,9 @@ +import "./FontsPage.page.scss" + +interface FontsPageProps {} + +const FontsPage = (props: FontsPageProps): JSX.Element => { + return
Be Here Soon
+} + +export default FontsPage diff --git a/src/app/pages/FontsPage/index.ts b/src/app/pages/FontsPage/index.ts new file mode 100755 index 0000000..6db5429 --- /dev/null +++ b/src/app/pages/FontsPage/index.ts @@ -0,0 +1,3 @@ +import FontsPage from "./FontsPage" + +export default FontsPage diff --git a/src/app/pages/IconsPage/IconsPage.tsx b/src/app/pages/IconsPage/IconsPage.tsx index cb1fada..c500f54 100755 --- a/src/app/pages/IconsPage/IconsPage.tsx +++ b/src/app/pages/IconsPage/IconsPage.tsx @@ -2,8 +2,8 @@ import { useEffect, useState } from "react" import { Filters } from "../../components" import Footer from "../../components/Footer" import Main from "../../components/Main" -import Header from "../../components/Header" import IconsList from "../../components/IconsList" +import { ObjectType } from "../../types/types" import Network from "../../utils/network" import Helper from "../../utils/helper" import "./IconsPage.page.scss" @@ -51,7 +51,7 @@ const IconsPage = (props: IconsPageProps): JSX.Element => { (filters.alphabet as Array).map( (al: BasicFilterConfig) => al.value, ) - Helper.matchArrayFilters( + finalFilteredIconList = Helper.matchArrayFilters( finalFilteredIconList, alphabet, "name", @@ -63,18 +63,20 @@ const IconsPage = (props: IconsPageProps): JSX.Element => { if (categories) { Object.keys(categories).forEach((category) => { const categoryValue = categories[category as keyof BasicFilterType] - Helper.matchArrayFilters( - finalFilteredIconList, - categoryValue, - "group", - ) + if ((categoryValue as Array).length > 0) { + finalFilteredIconList = Helper.matchArrayFilters( + finalFilteredIconList, + categoryValue, + "group", + ) + } }) } const countFilter = filters.count && "data" in filters.count && filters.count.data if (countFilter) { - finalFilteredIconList = finalFilteredIconList.slice( + finalFilteredIconList = finalFilteredIconList?.slice( "startIndex" in countFilter ? +countFilter.startIndex : 0, "endIndex" in countFilter ? +countFilter.endIndex : 0, ) @@ -85,8 +87,7 @@ const IconsPage = (props: IconsPageProps): JSX.Element => { }, [filters, icons, searchText]) return ( -
-
+
{ onFilterChange={setFilters} /> } - // mainContent={} mainContent={ } diff --git a/src/app/pages/index.ts b/src/app/pages/index.ts index 878d185..23f2a1b 100755 --- a/src/app/pages/index.ts +++ b/src/app/pages/index.ts @@ -1,4 +1,5 @@ /* PLOP_INJECT_IMPORT */ +import FontsPage from "./FontsPage" import DocsPage from "./DocsPage" import IconsPage from "./IconsPage" import ComponentsViewerPage from "./ComponentsViewerPage" @@ -6,6 +7,7 @@ import PlaygroundPage from "./PlaygroundPage" export { /* PLOP_INJECT_EXPORT */ + FontsPage, DocsPage, IconsPage, ComponentsViewerPage, diff --git a/src/app/routes.ts b/src/app/routes.ts index 7a45a7f..6941e89 100644 --- a/src/app/routes.ts +++ b/src/app/routes.ts @@ -15,7 +15,17 @@ const ROUTES = [ element: "IconsPage", }, { - path: "/component/:name", + path: "/fonts", + class: "fonts", + element: "FontsPage", + }, + { + path: "/components", + class: "component-viewer", + element: "ComponentsViewerPage", + }, + { + path: "/components/:name", class: "component-viewer", element: "ComponentsViewerPage", }, @@ -24,6 +34,11 @@ const ROUTES = [ class: "docs", element: "DocsPage", }, + { + path: "*", + class: "not-a-route", + element: "Component_404", + }, ] export default ROUTES diff --git a/src/app/static/images/ARC_logo.jpeg b/src/app/static/images/ARC_logo.jpeg new file mode 100644 index 0000000..45a1dab Binary files /dev/null and b/src/app/static/images/ARC_logo.jpeg differ diff --git a/src/app/static/images/ARC_logo1.jpeg b/src/app/static/images/ARC_logo1.jpeg new file mode 100644 index 0000000..0802040 Binary files /dev/null and b/src/app/static/images/ARC_logo1.jpeg differ diff --git a/src/app/static/images/Omnia Alkatra.svg b/src/app/static/images/Omnia Alkatra.svg new file mode 100644 index 0000000..0a0de93 --- /dev/null +++ b/src/app/static/images/Omnia Alkatra.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/app/static/images/Omnia.svg b/src/app/static/images/Omnia.svg new file mode 100644 index 0000000..e3dca15 --- /dev/null +++ b/src/app/static/images/Omnia.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/app/static/images/index.ts b/src/app/static/images/index.ts index f671d69..28502c5 100644 --- a/src/app/static/images/index.ts +++ b/src/app/static/images/index.ts @@ -1,3 +1,4 @@ +import AppLogo from "./ARC_logo.jpeg" import Balloon from "./balloon.jpg" -export { Balloon } +export { AppLogo, Balloon } diff --git a/src/app/static/styles/_global.scss b/src/app/static/styles/_global.scss index a8425f8..edbfd1e 100644 --- a/src/app/static/styles/_global.scss +++ b/src/app/static/styles/_global.scss @@ -1,5 +1,6 @@ @use "./variables"; @use "bootstrap/scss/bootstrap.scss"; +@import "../../static/styles/mixins"; html { font-size: 16px; @@ -12,12 +13,14 @@ html, body, #root { } body { + @include drawer-header-footer-layout; margin: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen' 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + color: var(--ar-color-font); } code { @@ -60,6 +63,11 @@ code { align-items: center; } +.flex-h-center { + display: flex; + justify-content: center; +} + .h-0 { height: 0 !important; min-height: 0 !important; diff --git a/src/app/static/styles/_variables.scss b/src/app/static/styles/_variables.scss index e8a44ac..8b6d187 100644 --- a/src/app/static/styles/_variables.scss +++ b/src/app/static/styles/_variables.scss @@ -2,6 +2,7 @@ // heights and layout --ar-height-header: 3rem; --ar-height-footer: 1.5rem; + --ar-white: rgba(250, 250, 240); --ar-color-font-danger-faded: rgba(243, 32, 19, 0.7); --ar-color-font-success-faded: rgba(92, 184, 92, 0.7); --ar-color-font-info-faded: rgba(13, 202, 240, 0.7); @@ -52,7 +53,7 @@ --ar-color-primary: #3232d8; --ar-color-primary-faded: rgba(50, 50, 216, 0.7); --ar-color-secondary: #525252; - --ar-bg-base: #030307; + --ar-bg-base: #101010; --ar-bg: black; --ar-bg-hover: #0a0700; --ar-bg-hover-2: #1f1c15; diff --git a/src/app/types/components.interface.ts b/src/app/types/components.interface.ts new file mode 100644 index 0000000..7ee7317 --- /dev/null +++ b/src/app/types/components.interface.ts @@ -0,0 +1,110 @@ +import { MouseEventHandler, ReactNode } from "react" +import { ArAlertType, ArLoaderTypes, ArSizes } from "./enums" +import { FrameContentDefinition } from "./entity.interface" + +export interface BaseProps { + classes?: string + containerClasses?: string + childClasses?: string + theme?: string +} + +/* PLOP_INJECT_INTERFACE */ +export interface LoaderProps extends BaseProps { + type?: ArLoaderTypes + size?: ArSizes + label?: string + icon?: string + progress?: number +} + +export interface LoadableIconProps extends BaseProps { + color?: string + icon?: string + height?: string + isLocal?: boolean + size?: string + width?: string +} + +export interface IconProps extends BaseProps { + alt?: string + color?: string + demo?: boolean + height?: string + onClick?: MouseEventHandler + onMouseEnter?: MouseEventHandler + onMouseLeave?: MouseEventHandler + size?: string + src: string + width?: string +} + +export interface TabProps extends BaseProps { + bubbleDimensions?: Function + data?: any + demo?: boolean + deletable?: boolean + icon?: string + id?: string + isActive?: boolean + label: string + onSelect?: Function + size?: string + variant?: string +} + +export interface TabBarProps extends BaseProps { + activeId?: string + data: TabProps[] + demo?: boolean + onTabSelected?: (id: string, data: any) => void + size?: string + variant?: string + [key: string]: any +} + +export interface AlertProps extends BaseProps { + closeable?: boolean + demo?: boolean + position?: string + show?: boolean + type?: ArAlertType + message: string + timeout?: number +} + +export interface BrowserIncompatibilityProps extends BaseProps { + applicationName?: string + moreLink?: string +} + +interface LinkBaseProps extends BaseProps { + to: string + onClick?: MouseEventHandler + openInNew?: boolean + preemptNavigation?: boolean +} +interface LinkLabelProps extends LinkBaseProps { + label: string +} + +interface LinkChildrenProps extends LinkBaseProps { + children: ReactNode +} +export type LinkProps = + | (LinkLabelProps & Partial) + | (Partial & LinkChildrenProps) + +export interface Component_404Props extends BaseProps { + iconSize?: string +} + +export interface FrameContentProps extends BaseProps { + contentDefinition: FrameContentDefinition | null + notificationProps?: any +} + +// export interface LoaderProps extends BaseProps { + +// } diff --git a/src/app/types/entity.interface.ts b/src/app/types/entity.interface.ts new file mode 100644 index 0000000..e734237 --- /dev/null +++ b/src/app/types/entity.interface.ts @@ -0,0 +1,15 @@ +export interface FrameContentDefinition { + componentName: string + component: JSX.ElementType + props?: { + theme?: string + [key: string]: + | string + | number + | boolean + | { [key: string]: any } + | undefined + } + data: { [key: string]: any } + hierarchy: string +} diff --git a/src/app/types/enums.ts b/src/app/types/enums.ts new file mode 100644 index 0000000..c7b1183 --- /dev/null +++ b/src/app/types/enums.ts @@ -0,0 +1,29 @@ +export enum ArTabType { + CLASSIC = "classic", + MODERN = "modern", +} + +export enum ArAriaRoles { + TAB = "tab", +} + +export enum ArAlertType { + SUCCESS = "success", + WARNING = "warning", + ERROR = "error", + INFORMATION = "information", +} + +export enum ArSizes { + XSMALL = "xsmall", + SMALL = "small", + REGULAR = "regular", + LARGE = "large", + XLARGE = "xlarge", +} + +export enum ArLoaderTypes { + BAR = "bar", + CIRCLE = "circle", + CUSTOM = "custom", +} diff --git a/src/app/types/types.ts b/src/app/types/types.ts new file mode 100644 index 0000000..939339e --- /dev/null +++ b/src/app/types/types.ts @@ -0,0 +1,14 @@ +export type ObjectType = { + [key: string]: + | string + | number + | boolean + | null + | undefined + | ObjectType + | ArrayType +} + +export type ArrayType = Array + +export type GenericObject = { [key: string]: T } diff --git a/src/app/utils/domHelper.ts b/src/app/utils/domHelper.ts new file mode 100644 index 0000000..7cf2cce --- /dev/null +++ b/src/app/utils/domHelper.ts @@ -0,0 +1,23 @@ +import { LoadableIconProps } from "../types/entity.interface" + +class DOMHelper { + static svgToBase64(svg: SVGSVGElement, svgProps?: LoadableIconProps) { + const { size, classes, color } = svgProps || {} + svg.setAttribute("height", size || "1rem") + svg.setAttribute("width", size || "1rem") + svg.setAttribute("class", classes || "") + svg.setAttribute("stroke", color || "black") + const path = svg.querySelector("path") + // Override stroke and color of "path" node inside SVG at below line. + path && + color && + !!path.getAttribute("stroke") && + path.setAttribute("stroke", color) + // path && color && !!path.getAttribute("fill") && path.setAttribute("fill", color); + svg.style.color = color || "black" + const serializedSvg = new XMLSerializer().serializeToString(svg) + return btoa(serializedSvg) + } +} + +export default DOMHelper diff --git a/src/app/utils/helper.tsx b/src/app/utils/helper.tsx index 67d5146..c878104 100644 --- a/src/app/utils/helper.tsx +++ b/src/app/utils/helper.tsx @@ -202,7 +202,7 @@ class Helper { : searchList.filter( (item) => filters.findIndex( - (al) => item[match].toLowerCase() === al.toLowerCase(), + (al) => item[match].toLowerCase() === al.value.toLowerCase(), ) > -1, ) } diff --git a/src/app/utils/index.ts b/src/app/utils/index.ts new file mode 100644 index 0000000..96f2795 --- /dev/null +++ b/src/app/utils/index.ts @@ -0,0 +1,6 @@ +import DomHelper from "./domHelper" +import Adapter from "./adapters" +import Helper from "./helper" +import Network from "./network" + +export { DomHelper, Adapter, Helper, Network } diff --git a/src/app/utils/network.ts b/src/app/utils/network.ts index f0b11ea..3a3de4f 100644 --- a/src/app/utils/network.ts +++ b/src/app/utils/network.ts @@ -27,8 +27,8 @@ export default class Network { static async getStatic( url: string, - queryParams: object | null, - options: Options | null, + queryParams?: object | null, + options?: Options | null, ) { let urlString = Network.stringifyUrl(url, queryParams) const environment = process.env.NODE_ENV || "development" @@ -119,7 +119,7 @@ export default class Network { throw new Error(err.message, err.error) } - static stringifyUrl(url: string, queryParams: any) { + static stringifyUrl(url: string, queryParams?: any) { return url ? queryParams ? Object.keys(queryParams).reduce( diff --git a/vite.config.ts b/vite.config.ts index b522027..9ebd33a 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,11 +1,13 @@ import { defineConfig } from "vitest/config" import react from "@vitejs/plugin-react" import path from "path" +import svgr from "vite-plugin-svgr" import { visualizer } from "rollup-plugin-visualizer" // https://vitejs.dev/config/ export default defineConfig({ plugins: [ + svgr(), react(), // visualizer({ // template: "treemap", // or sunburst @@ -26,7 +28,7 @@ export default defineConfig({ }, build: { outDir: "build", - // sourcemap: true, + sourcemap: true, rollupOptions: { treeshake: true, },