[MAJOR] Added tab bar, fixed bugs

This commit is contained in:
2023-08-07 03:14:11 +05:30
parent 7add1edd40
commit 72d5402c01
60 changed files with 1440 additions and 261 deletions

515
package-lock.json generated
View File

@@ -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",

View File

@@ -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",

View File

@@ -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 <div className="ar-{{pascalCase name}}">In Component {{pascalCase name}}</div>

View File

@@ -0,0 +1,2 @@
/* PLOP_INJECT_INTERFACE */

View File

@@ -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", {

View File

@@ -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 (
<Suspense fallback={<div>Loading...</div>}>
<Header />
{useRoutes(ROUTES)}
<Alert {...alertInfo} />
</Suspense>

View File

@@ -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 (

View File

@@ -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<FrameContentDefinition | null>(null)
const [theme, setTheme] = useState<string>("th-light-1")
const [portal, setPortal] = useState<ReactNode>()
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(
<FrameContent
contentDefinition={selectedComponentDefinition}
notificationProps={notificationProps}
/>,
mountNode,
),
)
}, [selectedComponentDefinition, mountNode, notificationProps, theme])
return (
<div className="ar-Editor w-100 h-100 d-flex flex-column">
<div className="ar-Editor__tools px-3 py-2">
@@ -198,16 +203,9 @@ const Editor = (): JSX.Element | string => {
ref={setContentRef}
title="Armco form-componentComponent Viewer"
>
{mountNode &&
createPortal(
<FrameContent
contentDefinition={selectedComponentDefinition}
notificationProps={notificationProps}
/>,
mountNode,
)}
{/* <div className="ar-Editor__props-container d-inline-block h-100"></div> */}
{portal}
</iframe>
{/* <div className="ar-Editor__props-container d-inline-block h-100"></div> */}
</div>
)
}

View File

@@ -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%;
}
}
}

View File

@@ -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 <header className="ar-Header w-100"></header>
const Header = (): JSX.Element => {
const navigate = useNavigate()
const location = useLocation()
const [activeTabId, setActiveTabId] = useState<string>()
useEffect(() => {
const matchedTab =
tabs && tabs.find((tab) => location.pathname.startsWith(tab.route))
if (matchedTab) {
setActiveTabId(matchedTab.id)
}
}, [location])
return (
<header className="ar-Header w-100 flex-v-center px-2">
<div className="ar-Header__app-logo" onClick={() => navigate("/")}>
<img
src={AppLogo}
alt="App Logo"
className="ar-Header__brand mx-2"
width="32"
height="32"
/>
<AppName className="ar-Header__app-name" width="50" />
</div>
<TabBar
classes="ms-auto"
data={tabs.map((tab: TabProps) => {
tab.isActive = activeTabId === tab.id
return tab
})}
variant={ArTabType.MODERN}
onTabSelected={(id: string, data: TabProps) => {
data?.data?.route && navigate(data.data.route)
}}
/>
</header>
)
}
export default Header

View File

@@ -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 (
<div className="ar-IconsList h-100 w-100 overflow-auto p-3">
<div className="ar-IconsList h-100 w-100 overflow-auto position-relative">
{!icons && (
<Loader label="Loading Icons..." type={ArLoaderTypes.CUSTOM} />
)}
<div className="ar-IconsList__header-pagination-search py-2 px-3 mb-3 border">
<div className="row">
<div className="col-2 d-flex align-items-center">
@@ -88,14 +92,13 @@ const IconsList = (props: IconsListProps): JSX.Element => {
</div>
</div>
</div>
<div className="ar-IconsList__icon-tile-container py-2 px-3 border d-flex justify-content-between flex-wrap">
{icons &&
icons
.slice(0, 100)
.map((icon, index) => (
<IconTile key={index} icon={icon} onClick={onIconTileClick} />
))}
</div>
{icons && (
<div className="ar-IconsList__icon-tile-container py-2 px-3 border d-flex justify-content-between flex-wrap">
{icons.slice(0, 100).map((icon, index) => (
<IconTile key={index} icon={icon} onClick={onIconTileClick} />
))}
</div>
)}
</div>
)
}

View File

@@ -14,7 +14,9 @@ const Main = (props: MainProps): JSX.Element => {
<main className="ar-Main d-flex flex-grow-1 w-100">
<Drawer classes="d-flex h-100">{drawerContent}</Drawer>
<ErrorBoundary>
<Content classes="flex-center p-3">{mainContent}</Content>
<Content classes="flex-center p-3 position-relative">
{mainContent}
</Content>
</ErrorBoundary>
</main>
)

View File

@@ -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 {

View File

@@ -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])

View File

@@ -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 (
<div className="ar-BrowserIncompatibility p-3 flex-center flex-column">
<Icon
src={`${ICON_ROOT}/vsc/VscRunErrors/black/10rem${heroIconSize}`}
<LoadableIcon
icon="vsc.VscRunErrors"
size={heroIconSize}
containerClasses="mb-3"
color={theme && theme === "th-dark-1" ? "white" : "black"}
classes="mb-3"
theme={theme}
/>
<h5 className="mb-3">{app} can not run on this browser</h5>
<p className="mb-2">
Supported browsers are Google Chrome v51+ & Microsoft's Edge v32+
</p>
<p>For More details you can also check the below link</p>
<div
className="ar-BrowserIncompatibility__help-link px-3 py-2"
<Link
to={helpLink}
label={helpLink}
classes="ar-BrowserIncompatibility__help-link px-3 py-2"
onClick={() => {
Helper.copyToClipboard(helpLink)
window.top?.postMessage(
@@ -40,15 +40,15 @@ const BrowserIncompatibility = (
type: "success",
closeable: true,
message: "Link Copied!",
show: true,
},
},
"*",
)
}}
>
{helpLink}
<Alert message="Link Copied!" />
</div>
preemptNavigation
/>
<Alert message="Link Copied!" />
</div>
)
}

View File

@@ -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,

View File

@@ -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 <div className="ar-Link">In Component Link</div>
const Link = (props: LinkProps): JSX.Element => {
const {
classes,
label,
to,
children,
onClick,
openInNew,
preemptNavigation,
} = props
const navigate = useNavigate()
return (
<div
className={`ar-Link btn btn-link${classes ? " " + classes : ""}`}
onClick={(e) => {
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}
</div>
)
}
export default Link

View File

@@ -0,0 +1,3 @@
.ar-LoadableIcon {
transition: all 0.3s;
}

View File

@@ -0,0 +1,6 @@
import React from "react"
import LoadableIcon from "./LoadableIcon"
describe("LoadableIcon", () => {
it("renders without error", () => {})
})

View File

@@ -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<SVGSVGElement> = {}
const placeholder = parser
.parseFromString(
'<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 24 24" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><rect width="20" height="20" x="2" y="2" fill="none" stroke="#000" stroke-width="2"rx="2"></rect></svg>',
"image/svg+xml",
)
.querySelector("svg")
const LoadableIcon = (props: LoadableIconProps) => {
const { classes, color, height, isLocal, size, width } = props
let { icon } = props
const [b64, setB64] = useState<string>()
const [iconContent, setIconContent] = useState<SVGSVGElement | null>(
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 (
<img
className={`ar-LoadableIcon${classes ? " " + classes : ""}`}
src={icon}
style={{
width: width || size || "1rem",
height: height || size || "1rem",
}}
alt="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 ? (
<img
className={`ar-LoadableIcon${classes ? " " + classes : ""}`}
src={`data:image/svg+xml;base64,${b64}`}
style={{
width: width || size || "1rem",
height: height || size || "1rem",
}}
alt="Icon"
/>
) : null
}
export default LoadableIcon

View File

@@ -0,0 +1,3 @@
import LoadableIcon from "./LoadableIcon"
export default LoadableIcon

View File

@@ -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 */
}
}
}

View File

@@ -0,0 +1,8 @@
import React from "react"
import Loader from "./Loader"
describe("Loader", () => {
it("renders without error", () => {
})
})

View File

@@ -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 = <ProgressIndicator progress={progress} />
break
case ArLoaderTypes.CUSTOM:
loaderContent = (
<>
<span className="loader">
<LoadableIcon icon={icon || AppLogo} size="50px" isLocal />
</span>
{label ? <span className="mt-3">{label}</span> : ""}
</>
)
break
case ArLoaderTypes.CIRCLE:
default:
loaderContent = (
<>
<span className="loader" />
{label ? <span className="mt-3">{label}</span> : ""}
</>
)
}
return (
<div className="position-absolute ar-Loader h-100 w-100">
<div
className={`ar-Loader-content flex-column flex-center${
type ? " " + type : ""
}${size ? " " + size : ""}`}
>
{loaderContent}
</div>
</div>
)
}
export default Loader

View File

@@ -0,0 +1,3 @@
import Loader from "./Loader"
export default Loader

View File

@@ -1,14 +1,11 @@
import React from "react"
import "./ProgressIndicator.component.scss"
interface ProgressIndicatorProps {}
const ProgressIndicator = (props: any): JSX.Element => {
return (
<div className="ar-ProgressIndicator">
In Component ProgressIndicator
</div>
<div className="ar-ProgressIndicator">In Component ProgressIndicator</div>
)
}
export default ProgressIndicator
export default ProgressIndicator

View File

@@ -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 {

View File

@@ -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 (
<div
className={`ar-Tab position-relative${isActive ? " active" : ""}${
size ? " " + size : ""
}${variant ? " " + variant : ""}${deletable ? " pe-3" : ""}`}
id={id || useLabel}
onClick={() => onSelect && onSelect(id, data)}
>
{deletable && (
<Icon
containerClasses="ar-Tab__delete-icon position-absolute"
src="rx/RxCross2"
size="0.8rem"
/>
)}
{useLabel}
</div>
)
}
const Tab = memo(
(props: TabProps): JSX.Element => {
const {
bubbleDimensions,
data,
demo,
deletable,
icon,
id,
isActive,
label,
onSelect,
size,
variant,
} = props
const tabRef = useRef<HTMLDivElement>(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 (
<div
className={`ar-Tab position-relative h-100 flex-center px-2 fw-bold${
isActive ? " active" : ""
}${size ? " " + size : ""}${variant ? " " + variant : ""}${
deletable ? " pe-3" : ""
}`}
id={id || useLabel}
onClick={() => onSelect && onSelect(id, props)}
ref={tabRef}
>
{deletable && (
<Icon
containerClasses="ar-Tab__delete-icon position-absolute"
src="rx/RxCross2"
size="0.8rem"
/>
)}
{useLabel}
{icon && <LoadableIcon classes="ms-1" icon={icon} />}
</div>
)
},
(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

View File

@@ -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;
}
}
}

View File

@@ -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<string>()
const {
classes,
data,
demo,
onTabSelected,
size,
variant,
activeId,
...rest
} = props
const [activeTab, setActiveTab] = useState<ObjectType>()
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 (
<Tab
label={tab.label}
bubbleDimensions={receiveDimensionsOfSelectedTab}
data={tab}
icon={tab.icon}
id={tab.id}
isActive={activeTab === tab.id}
onSelect={onLocalTabChanged}
variant={variant}
size={size}
isActive={activeTab && activeTab.id === tab.id}
label={tab.label}
onSelect={onLocalTabSelected}
/>
)
})
return (
<div
className={`ar-TabBar d-flex${variant ? " " + variant : ""}${
size ? " " + size : ""
}`}
className={`ar-TabBar d-flex position-relative${
variant ? " " + variant : ""
}${size ? " " + size : ""}${classes ? " " + classes : ""}`}
{...rest}
>
{tabRenders}
{activeTab &&
activeTab.selectedLeft !== undefined &&
activeTab.selectedWidth !== undefined && (
<div
className="position-absolute slider"
role="presentation"
style={{
left:
typeof activeTab.selectedLeft === "number"
? activeTab.selectedLeft
: 0,
width:
typeof activeTab.selectedWidth === "number"
? activeTab.selectedWidth
: 0,
}}
/>
)}
</div>
)
}

View File

@@ -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,

View File

@@ -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);
}
}
}

View File

@@ -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 <div className="ar-Component_404">In Component Component_404</div>
const { iconSize } = props
return (
<div className="ar-Component_404 flex-center h-100">
<div className="ar-Component_404-content border flex-v-center flex-column p-3">
<Icon src="gi/GiDigHole" size={iconSize || "20rem"} />
<h5 className="mb-4">Could not dig what you asked for</h5>
<p className="mb-2">Please check the URL and try again.</p>
<p className="mb-1">
You may also use the tabs (right-top) to navigate if you're not sure
about the URL
</p>
</div>
</div>
)
}
export default Component_404

View File

@@ -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",
},
}

View File

@@ -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: [],

View File

@@ -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 (
<div className="ar-ComponentsViewerPage vh-100 d-flex flex-column">
<Header />
<div className="ar-ComponentsViewerPage d-flex flex-column">
<Main
drawerContent={<ComponentList />}
mainContent={

View File

@@ -0,0 +1,3 @@
.ar-FontsPage {
}

View File

@@ -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

View File

@@ -0,0 +1,8 @@
import React from "react"
import FontsPage from "./FontsPage"
describe("FontsPage", () => {
it("renders without error", () => {
})
})

View File

@@ -0,0 +1,9 @@
import "./FontsPage.page.scss"
interface FontsPageProps {}
const FontsPage = (props: FontsPageProps): JSX.Element => {
return <div className="ar-FontsPage">Be Here Soon</div>
}
export default FontsPage

View File

@@ -0,0 +1,3 @@
import FontsPage from "./FontsPage"
export default FontsPage

View File

@@ -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<BasicFilterConfig>).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<ObjectType>).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 (
<div className="ar-IconsPage vh-100 d-flex flex-column">
<Header />
<div className="ar-IconsPage d-flex flex-column">
<Main
drawerContent={
<Filters
@@ -97,7 +98,6 @@ const IconsPage = (props: IconsPageProps): JSX.Element => {
onFilterChange={setFilters}
/>
}
// mainContent={<IconsList icons={filteredIcons || icons} />}
mainContent={
<IconsList icons={filteredIcons} onSearchChanged={setSearchText} />
}

View File

@@ -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,

View File

@@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -1,3 +1,4 @@
import AppLogo from "./ARC_logo.jpeg"
import Balloon from "./balloon.jpg"
export { Balloon }
export { AppLogo, Balloon }

View File

@@ -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;

View File

@@ -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;

View File

@@ -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<LinkChildrenProps>)
| (Partial<LinkLabelProps> & LinkChildrenProps)
export interface Component_404Props extends BaseProps {
iconSize?: string
}
export interface FrameContentProps extends BaseProps {
contentDefinition: FrameContentDefinition | null
notificationProps?: any
}
// export interface LoaderProps extends BaseProps {
// }

View File

@@ -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
}

29
src/app/types/enums.ts Normal file
View File

@@ -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",
}

14
src/app/types/types.ts Normal file
View File

@@ -0,0 +1,14 @@
export type ObjectType = {
[key: string]:
| string
| number
| boolean
| null
| undefined
| ObjectType
| ArrayType
}
export type ArrayType = Array<string | number | boolean | ObjectType>
export type GenericObject<T> = { [key: string]: T }

View File

@@ -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

View File

@@ -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,
)
}

6
src/app/utils/index.ts Normal file
View File

@@ -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 }

View File

@@ -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(

View File

@@ -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,
},