diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..fbe0e55 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,6 @@ +{ + "trailingComma": "es5", + "tabWidth": 2, + "semi": false, + "singleQuote": true +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 26f9883..ac39cdb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,12 +8,23 @@ "name": "react-portfolio", "version": "0.1.0", "dependencies": { + "@emailjs/browser": "^3.10.0", + "@fortawesome/free-brands-svg-icons": "^6.4.0", + "@fortawesome/free-solid-svg-icons": "^6.4.0", + "@fortawesome/react-fontawesome": "^0.2.0", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "animate.css": "^4.1.1", + "gsap-trial": "^3.11.5", + "loaders.css": "^0.1.2", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-leaflet": "^4.2.1", + "react-loaders": "^3.0.1", + "react-router-dom": "^6.10.0", "react-scripts": "5.0.1", + "sass": "^1.60.0", "web-vitals": "^2.1.4" } }, @@ -2132,6 +2143,14 @@ "postcss-selector-parser": "^6.0.10" } }, + "node_modules/@emailjs/browser": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/@emailjs/browser/-/browser-3.10.0.tgz", + "integrity": "sha512-pregUOBkSjjctQoAgn8DcSaeY4ypHjXAJEzWlJysM3RkQXw1ulavfHva3YYeAkxfJ7qbIhpyvRmhyQlgNG4GVg==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -2225,6 +2244,64 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@fortawesome/fontawesome-common-types": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz", + "integrity": "sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ==", + "hasInstallScript": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/fontawesome-svg-core": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.0.tgz", + "integrity": "sha512-Bertv8xOiVELz5raB2FlXDPKt+m94MQ3JgDfsVbrqNpLU9+UE2E18GKjLKw+d3XbeYPqg1pzyQKGsrzbw+pPaw==", + "hasInstallScript": true, + "peer": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.4.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-brands-svg-icons": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.4.0.tgz", + "integrity": "sha512-qvxTCo0FQ5k2N+VCXb/PZQ+QMhqRVM4OORiO6MXdG6bKolIojGU/srQ1ptvKk0JTbRgaJOfL2qMqGvBEZG7Z6g==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.4.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-solid-svg-icons": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.0.tgz", + "integrity": "sha512-kutPeRGWm8V5dltFP1zGjQOEAzaLZj4StdQhWVZnfGFCvAPVvHh8qk5bRrU4KXnRRRNni5tKQI9PBAdI6MP8nQ==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.4.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/react-fontawesome": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz", + "integrity": "sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==", + "dependencies": { + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "@fortawesome/fontawesome-svg-core": "~1 || ~6", + "react": ">=16.3" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.8", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", @@ -3115,6 +3192,24 @@ } } }, + "node_modules/@react-leaflet/core": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-2.1.0.tgz", + "integrity": "sha512-Qk7Pfu8BSarKGqILj4x7bCSZ1pjuAPZ+qmRwH5S7mDS91VSbVVsJSrW4qA+GPrro8t69gFYVMWb1Zc4yFmPiVg==", + "peerDependencies": { + "leaflet": "^1.9.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@remix-run/router": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.5.0.tgz", + "integrity": "sha512-bkUDCp8o1MvFO+qxkODcbhSqRa6P2GXgrGZVpt0dCXNW2HCSCqYI0ZoAqEOSAjRWmmlKcYgFvN4B4S+zo/f8kg==", + "engines": { + "node": ">=14" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -4808,6 +4903,11 @@ "ajv": "^6.9.1" } }, + "node_modules/animate.css": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/animate.css/-/animate.css-4.1.1.tgz", + "integrity": "sha512-+mRmCTv6SbCmtYJCN4faJMNFVNN5EuCTTprDTAo7YzIGji2KADmakjVA3+8mVDkZ2Bf09vayB35lSQIex2+QaQ==" + }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -5740,6 +5840,11 @@ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==" }, + "node_modules/classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, "node_modules/clean-css": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz", @@ -8572,6 +8677,11 @@ "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==" }, + "node_modules/gsap-trial": { + "version": "3.11.5", + "resolved": "https://registry.npmjs.org/gsap-trial/-/gsap-trial-3.11.5.tgz", + "integrity": "sha512-yh6+QR+OuzIlaJkMCS0PiVpQ0arNuV8FHjFaFJZ47qjSaYEo6vl3FOvtqDy7A9+D9tTPlxVfD6vk5f5lgFcbKw==" + }, "node_modules/gzip-size": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", @@ -8959,6 +9069,11 @@ "url": "https://opencollective.com/immer" } }, + "node_modules/immutable": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz", + "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==" + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -11705,6 +11820,12 @@ "shell-quote": "^1.7.3" } }, + "node_modules/leaflet": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.3.tgz", + "integrity": "sha512-iB2cR9vAkDOu5l3HAay2obcUHZ7xwUBBjph8+PGtmW/2lYhbLizWtG7nTeYht36WfOslixQF9D/uSIzhZgGMfQ==", + "peer": true + }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -11759,6 +11880,11 @@ "node": ">=8.9.0" } }, + "node_modules/loaders.css": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/loaders.css/-/loaders.css-0.1.2.tgz", + "integrity": "sha512-Rhowlq24ey1VOeor+3wYOt9+MjaxBOJm1u4KlQgNC3+0xJ0LS4wq4iG57D/BPzvuD/7HHDGQOWJ+81oR2EI9bQ==" + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -14335,6 +14461,31 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "node_modules/react-leaflet": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/react-leaflet/-/react-leaflet-4.2.1.tgz", + "integrity": "sha512-p9chkvhcKrWn/H/1FFeVSqLdReGwn2qmiobOQGO3BifX+/vV/39qhY8dGqbdcPh1e6jxh/QHriLXr7a4eLFK4Q==", + "dependencies": { + "@react-leaflet/core": "^2.1.0" + }, + "peerDependencies": { + "leaflet": "^1.9.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/react-loaders": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/react-loaders/-/react-loaders-3.0.1.tgz", + "integrity": "sha512-4igMNqs9Fb3d4Z+0UHIGQNJsw/37gX0nUO8QxupnEKRn1dtyYC1LGwk5GuaoDciMQCQc/MmPwb4Fn6ZfdoX1FQ==", + "dependencies": { + "classnames": "^2.2.3" + }, + "peerDependencies": { + "prop-types": ">=15.6.0", + "react": ">=15" + } + }, "node_modules/react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -14343,6 +14494,36 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.10.0.tgz", + "integrity": "sha512-Nrg0BWpQqrC3ZFFkyewrflCud9dio9ME3ojHCF/WLsprJVzkq3q3UeEhMCAW1dobjeGbWgjNn/PVF6m46ANxXQ==", + "dependencies": { + "@remix-run/router": "1.5.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.10.0.tgz", + "integrity": "sha512-E5dfxRPuXKJqzwSe/qGcqdwa18QiWC6f3H3cWXM24qj4N0/beCIf/CWTipop2xm7mR0RCS99NnaqPNjHtrAzCg==", + "dependencies": { + "@remix-run/router": "1.5.0", + "react-router": "6.10.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", @@ -14859,6 +15040,22 @@ "resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-13.0.0.tgz", "integrity": "sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA==" }, + "node_modules/sass": { + "version": "1.60.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.60.0.tgz", + "integrity": "sha512-updbwW6fNb5gGm8qMXzVO7V4sWf7LMXnMly/JEyfbfERbVH46Fn6q02BX7/eHTdKpE7d+oTkMMQpFWNUMfFbgQ==", + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/sass-loader": { "version": "12.6.0", "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz", @@ -18656,6 +18853,11 @@ "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==", "requires": {} }, + "@emailjs/browser": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/@emailjs/browser/-/browser-3.10.0.tgz", + "integrity": "sha512-pregUOBkSjjctQoAgn8DcSaeY4ypHjXAJEzWlJysM3RkQXw1ulavfHva3YYeAkxfJ7qbIhpyvRmhyQlgNG4GVg==" + }, "@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -18718,6 +18920,44 @@ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.37.0.tgz", "integrity": "sha512-x5vzdtOOGgFVDCUs81QRB2+liax8rFg3+7hqM+QhBG0/G3F1ZsoYl97UrqgHgQ9KKT7G6c4V+aTUCgu/n22v1A==" }, + "@fortawesome/fontawesome-common-types": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz", + "integrity": "sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ==" + }, + "@fortawesome/fontawesome-svg-core": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.0.tgz", + "integrity": "sha512-Bertv8xOiVELz5raB2FlXDPKt+m94MQ3JgDfsVbrqNpLU9+UE2E18GKjLKw+d3XbeYPqg1pzyQKGsrzbw+pPaw==", + "peer": true, + "requires": { + "@fortawesome/fontawesome-common-types": "6.4.0" + } + }, + "@fortawesome/free-brands-svg-icons": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.4.0.tgz", + "integrity": "sha512-qvxTCo0FQ5k2N+VCXb/PZQ+QMhqRVM4OORiO6MXdG6bKolIojGU/srQ1ptvKk0JTbRgaJOfL2qMqGvBEZG7Z6g==", + "requires": { + "@fortawesome/fontawesome-common-types": "6.4.0" + } + }, + "@fortawesome/free-solid-svg-icons": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.0.tgz", + "integrity": "sha512-kutPeRGWm8V5dltFP1zGjQOEAzaLZj4StdQhWVZnfGFCvAPVvHh8qk5bRrU4KXnRRRNni5tKQI9PBAdI6MP8nQ==", + "requires": { + "@fortawesome/fontawesome-common-types": "6.4.0" + } + }, + "@fortawesome/react-fontawesome": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz", + "integrity": "sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==", + "requires": { + "prop-types": "^15.8.1" + } + }, "@humanwhocodes/config-array": { "version": "0.11.8", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", @@ -19362,6 +19602,17 @@ "source-map": "^0.7.3" } }, + "@react-leaflet/core": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-2.1.0.tgz", + "integrity": "sha512-Qk7Pfu8BSarKGqILj4x7bCSZ1pjuAPZ+qmRwH5S7mDS91VSbVVsJSrW4qA+GPrro8t69gFYVMWb1Zc4yFmPiVg==", + "requires": {} + }, + "@remix-run/router": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.5.0.tgz", + "integrity": "sha512-bkUDCp8o1MvFO+qxkODcbhSqRa6P2GXgrGZVpt0dCXNW2HCSCqYI0ZoAqEOSAjRWmmlKcYgFvN4B4S+zo/f8kg==" + }, "@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -20645,6 +20896,11 @@ "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "requires": {} }, + "animate.css": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/animate.css/-/animate.css-4.1.1.tgz", + "integrity": "sha512-+mRmCTv6SbCmtYJCN4faJMNFVNN5EuCTTprDTAo7YzIGji2KADmakjVA3+8mVDkZ2Bf09vayB35lSQIex2+QaQ==" + }, "ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -21320,6 +21576,11 @@ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==" }, + "classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, "clean-css": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz", @@ -23389,6 +23650,11 @@ "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==" }, + "gsap-trial": { + "version": "3.11.5", + "resolved": "https://registry.npmjs.org/gsap-trial/-/gsap-trial-3.11.5.tgz", + "integrity": "sha512-yh6+QR+OuzIlaJkMCS0PiVpQ0arNuV8FHjFaFJZ47qjSaYEo6vl3FOvtqDy7A9+D9tTPlxVfD6vk5f5lgFcbKw==" + }, "gzip-size": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", @@ -23666,6 +23932,11 @@ "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==" }, + "immutable": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz", + "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==" + }, "import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -25641,6 +25912,12 @@ "shell-quote": "^1.7.3" } }, + "leaflet": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.3.tgz", + "integrity": "sha512-iB2cR9vAkDOu5l3HAay2obcUHZ7xwUBBjph8+PGtmW/2lYhbLizWtG7nTeYht36WfOslixQF9D/uSIzhZgGMfQ==", + "peer": true + }, "leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -25680,6 +25957,11 @@ "json5": "^2.1.2" } }, + "loaders.css": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/loaders.css/-/loaders.css-0.1.2.tgz", + "integrity": "sha512-Rhowlq24ey1VOeor+3wYOt9+MjaxBOJm1u4KlQgNC3+0xJ0LS4wq4iG57D/BPzvuD/7HHDGQOWJ+81oR2EI9bQ==" + }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -27359,11 +27641,44 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "react-leaflet": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/react-leaflet/-/react-leaflet-4.2.1.tgz", + "integrity": "sha512-p9chkvhcKrWn/H/1FFeVSqLdReGwn2qmiobOQGO3BifX+/vV/39qhY8dGqbdcPh1e6jxh/QHriLXr7a4eLFK4Q==", + "requires": { + "@react-leaflet/core": "^2.1.0" + } + }, + "react-loaders": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/react-loaders/-/react-loaders-3.0.1.tgz", + "integrity": "sha512-4igMNqs9Fb3d4Z+0UHIGQNJsw/37gX0nUO8QxupnEKRn1dtyYC1LGwk5GuaoDciMQCQc/MmPwb4Fn6ZfdoX1FQ==", + "requires": { + "classnames": "^2.2.3" + } + }, "react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==" }, + "react-router": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.10.0.tgz", + "integrity": "sha512-Nrg0BWpQqrC3ZFFkyewrflCud9dio9ME3ojHCF/WLsprJVzkq3q3UeEhMCAW1dobjeGbWgjNn/PVF6m46ANxXQ==", + "requires": { + "@remix-run/router": "1.5.0" + } + }, + "react-router-dom": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.10.0.tgz", + "integrity": "sha512-E5dfxRPuXKJqzwSe/qGcqdwa18QiWC6f3H3cWXM24qj4N0/beCIf/CWTipop2xm7mR0RCS99NnaqPNjHtrAzCg==", + "requires": { + "@remix-run/router": "1.5.0", + "react-router": "6.10.0" + } + }, "react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", @@ -27727,6 +28042,16 @@ "resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-13.0.0.tgz", "integrity": "sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA==" }, + "sass": { + "version": "1.60.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.60.0.tgz", + "integrity": "sha512-updbwW6fNb5gGm8qMXzVO7V4sWf7LMXnMly/JEyfbfERbVH46Fn6q02BX7/eHTdKpE7d+oTkMMQpFWNUMfFbgQ==", + "requires": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + } + }, "sass-loader": { "version": "12.6.0", "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz", diff --git a/package.json b/package.json index b445b2c..160e938 100644 --- a/package.json +++ b/package.json @@ -3,12 +3,23 @@ "version": "0.1.0", "private": true, "dependencies": { + "@emailjs/browser": "^3.10.0", + "@fortawesome/free-brands-svg-icons": "^6.4.0", + "@fortawesome/free-solid-svg-icons": "^6.4.0", + "@fortawesome/react-fontawesome": "^0.2.0", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "animate.css": "^4.1.1", + "gsap-trial": "^3.11.5", + "loaders.css": "^0.1.2", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-leaflet": "^4.2.1", + "react-loaders": "^3.0.1", + "react-router-dom": "^6.10.0", "react-scripts": "5.0.1", + "sass": "^1.60.0", "web-vitals": "^2.1.4" }, "scripts": { diff --git a/src/App.css b/src/App.css deleted file mode 100644 index 74b5e05..0000000 --- a/src/App.css +++ /dev/null @@ -1,38 +0,0 @@ -.App { - text-align: center; -} - -.App-logo { - height: 40vmin; - pointer-events: none; -} - -@media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } -} - -.App-header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; -} - -.App-link { - color: #61dafb; -} - -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} diff --git a/src/App.js b/src/App.js index 3784575..846aaef 100644 --- a/src/App.js +++ b/src/App.js @@ -1,25 +1,18 @@ -import logo from './logo.svg'; -import './App.css'; +import './App.scss'; +import { Routes, Route } from 'react-router-dom' +import Layout from './components/Layout' +import Home from './components/Home' function App() { return ( -
-
- logo -

- Edit src/App.js and save to reload. -

- - Learn React - -
-
- ); + <> + + }> + } /> + + + + ) } -export default App; +export default App diff --git a/src/App.scss b/src/App.scss new file mode 100644 index 0000000..98bd543 --- /dev/null +++ b/src/App.scss @@ -0,0 +1,23 @@ +$primary-color: #ffd700; + +@import 'animate.css'; + +@font-face { + font-family: 'Helvetica Neue'; + src: url('./assets/fonts/helvetica-neu.ttf') format('ttf') ; +} + +@font-face { + font-family: 'La Belle Aurore'; + src: url('./assets/fonts/LaBelleAurore.woff2') format('woff2') ; +} + +@font-face { + font-family: 'Coolvetica'; + src: url('./assets/fonts/CoolveticaRg-Regular.woff2') format('woff2') ; +} + +input, +textarea { + font-family: 'Helvetica Neue'; +} \ No newline at end of file diff --git a/src/assets/fonts/CoolveticaRg-Regular.woff b/src/assets/fonts/CoolveticaRg-Regular.woff new file mode 100644 index 0000000..7758083 Binary files /dev/null and b/src/assets/fonts/CoolveticaRg-Regular.woff differ diff --git a/src/assets/fonts/CoolveticaRg-Regular.woff2 b/src/assets/fonts/CoolveticaRg-Regular.woff2 new file mode 100644 index 0000000..2fcabd9 Binary files /dev/null and b/src/assets/fonts/CoolveticaRg-Regular.woff2 differ diff --git a/src/assets/fonts/LaBelleAurore.woff b/src/assets/fonts/LaBelleAurore.woff new file mode 100644 index 0000000..d04aec5 Binary files /dev/null and b/src/assets/fonts/LaBelleAurore.woff differ diff --git a/src/assets/fonts/LaBelleAurore.woff2 b/src/assets/fonts/LaBelleAurore.woff2 new file mode 100644 index 0000000..fab4296 Binary files /dev/null and b/src/assets/fonts/LaBelleAurore.woff2 differ diff --git a/src/assets/fonts/helvetica-neu.ttf b/src/assets/fonts/helvetica-neu.ttf new file mode 100644 index 0000000..22023f0 Binary files /dev/null and b/src/assets/fonts/helvetica-neu.ttf differ diff --git a/src/assets/images/logo.png b/src/assets/images/logo.png new file mode 100644 index 0000000..a11cbc2 Binary files /dev/null and b/src/assets/images/logo.png differ diff --git a/src/assets/images/logo_sub.png b/src/assets/images/logo_sub.png new file mode 100644 index 0000000..0e5dc5b Binary files /dev/null and b/src/assets/images/logo_sub.png differ diff --git a/src/components/AnimatedLetters/index.js b/src/components/AnimatedLetters/index.js new file mode 100644 index 0000000..b5ae726 --- /dev/null +++ b/src/components/AnimatedLetters/index.js @@ -0,0 +1,17 @@ +import './index.scss'; + +const AnimatedLetters = ({ letterClass, strArray, idx }) => { + return ( + + { + strArray.map((char, i) => ( + + {char} + + )) + } + + ) +}; + +export default AnimatedLetters \ No newline at end of file diff --git a/src/components/AnimatedLetters/index.scss b/src/components/AnimatedLetters/index.scss new file mode 100644 index 0000000..d97d716 --- /dev/null +++ b/src/components/AnimatedLetters/index.scss @@ -0,0 +1,25 @@ +.text-animate { + display: inline-block; + opacity: 0; + animation: bounceIn 1s 1s; + animation-fill-mode: forwards; + min-width: 10px; + +} + +.text-animate-hover { + min-width: 10px; + display: inline-block; + animation-fill-mode: both; + + &:hover { + animation: rubberBand 1s; + color: #ffd700; + } +} + +@for $i from 1 through 35 { + .text-animate._#{$i} { + animation-delay: #{$i / 10}s; + } +} \ No newline at end of file diff --git a/src/components/Home/index.js b/src/components/Home/index.js new file mode 100644 index 0000000..341d916 --- /dev/null +++ b/src/components/Home/index.js @@ -0,0 +1,45 @@ +import { Link } from 'react-router-dom'; +import LogoTitle from '../../assets/images/logo.png'; +import './index.scss' +import AnimatedLetters from '../AnimatedLetters'; +import { useEffect, useState } from 'react' + + +const Home = () => { + const [letterClass, setLetterClass] = useState('text-animate') + const nameArray = ['l', 'y', 's', 'o', 'n'] + const jobArray = ['C', 'o', 'm', 'p', 'u', 't', 'e', 'r', ' ', 'S', 'c', 'i', 'e', 'n', 'c', 'e', ' ', 'S', 't', 'u', 'd', 'e', 'n', 't'] + + // useEffect(() => { + // return setTimeout(() => { + // setLetterClass('text-animate-hover') + // }, 4000) + // }, []) + + return ( +
+
+

+ H + i, +
+ I + 'm + developer + +
+ +

+

Frontend Developer / JavaScript

+ CONTACT ME +
+ +
+ ) +} + +export default Home \ No newline at end of file diff --git a/src/components/Home/index.scss b/src/components/Home/index.scss new file mode 100644 index 0000000..14af13c --- /dev/null +++ b/src/components/Home/index.scss @@ -0,0 +1,79 @@ +.home-page { + + .text-zone { + position: absolute; + left: 10%; + top: 50%; + transform: translateY(-50%); + width: 40%; + max-height: 90%; + } + h1 { + color: #fff; + font-size: 53px; + margin: 0; + font-family: 'Coolvetica'; + font-weight: 400; + + &::before { + content: '

'; + font-family: 'La Belle Aurore'; + color: #ffd700; + font-size: 18px; + position: absolute; + margin-top: -40px; + left: 15px; + opacity: 0.6; + } + + &::after { + content: '

'; + font-family: 'La Belle Aurore'; + color: #ffd700; + font-size: 18px; + position: absolute; + margin-top: 18px; + margin-left: 20px; + animation: fadeIn 1s 1.7s backwards; + opacity: 0.6; + } + img { + width: 32px; + margin-left: 20px; + opacity: 0; + height: auto; + animation: rotateIn 1s linear both; + animation-delay: 1.4s; + } + } + + h2 { + color: #8d8d8d; + margin-top: 20px; + font-weight: 400; + font-size: 11px; + font-family: sans-serif; + letter-spacing: 3px; + animation: fadeIn 1s 1.8s backwards; + } + + .flat-button { + color: #ffd700; + font-size: 13px; + font-weight: 400; + letter-spacing: 4px; + font-family: sans-serif; + text-decoration: none; + padding: 10px 18px; + border: 1px solid #ffd700; + margin-top: 25px; + float: left; + animation: fadeIn 1s 1.8s backwards; + white-space: nowrap; + + &:hover { + background: #ffd700; + color: #333; + } + } +} \ No newline at end of file diff --git a/src/components/Layout/index.js b/src/components/Layout/index.js new file mode 100644 index 0000000..ce5d870 --- /dev/null +++ b/src/components/Layout/index.js @@ -0,0 +1,23 @@ +import { Outlet } from 'react-router-dom'; +import Sidebar from '../Sidebar' +import './index.scss'; + +const Layout = () => { + return ( +
+ +
+ <body> + + + + + </body> +
+ </html> +
+
+
+ ) +} +export default Layout \ No newline at end of file diff --git a/src/components/Layout/index.scss b/src/components/Layout/index.scss new file mode 100644 index 0000000..0666367 --- /dev/null +++ b/src/components/Layout/index.scss @@ -0,0 +1,39 @@ +.page { + width: 100%; + height: 100%; + position: absolute; +} + +.top-tags { + bottom: auto; + top: 35px; +} + +.tags { + color: #ffd700; + opacity: 0.6; + position: absolute; + bottom: 0; + left: 120px; + font-size: 18px; + font-family: 'La Belle Aurore'; +} + +.bottom-tag-html { + margin-left: -20px; +} + +.container { + width: 100%; + will-change: contents; + height: 90%; + min-height: 566px; + position: absolute; + opacity: 0; + top: 5; + margin: 0 auto; + z-index: 1; + transform-style: preserve-3d; + animation: fadeIn 1s forwards; + animation-delay: 1s; +} \ No newline at end of file diff --git a/src/components/Sidebar/index.js b/src/components/Sidebar/index.js new file mode 100644 index 0000000..cff314c --- /dev/null +++ b/src/components/Sidebar/index.js @@ -0,0 +1,49 @@ +import { Link, NavLink } from 'react-router-dom' +import './index.scss' +import LogoS from '../../assets/images/logo.png' +import LogoSubtitle from '../../assets/images/logo_sub.png' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faEnvelope, faHome, faUser } from '@fortawesome/free-solid-svg-icons' +import { faGithub, faLinkedin } from '@fortawesome/free-brands-svg-icons' + +const Sidebar = () => ( +
+ + logo + slobodan + + + +
+) + +export default Sidebar \ No newline at end of file diff --git a/src/components/Sidebar/index.scss b/src/components/Sidebar/index.scss new file mode 100644 index 0000000..59b7fce --- /dev/null +++ b/src/components/Sidebar/index.scss @@ -0,0 +1,119 @@ +.nav-bar { + background: #181818; + width: 60px; + height: 100%; + position: absolute; + top: 0; + z-index: 3; + min-height: 500px; + + .logo { + display: block; + padding: 8px 0; + + img { + display: block; + margin: 8px auto; + width: 24px; + height: auto; + + &.sub-logo { + width: 50px; + } + } + } + + nav { + display: block; + text-align: center; + position: absolute; + height: 210px; + top: 50%; + margin-top: -120px; + width: 100%; + + a { + font-size: 22px; + color: #4d4d4e; + display: block; + line-height: 51px; + height: 51px; + position: relative; + text-decoration: none; + + i { + transition: all 0.3s ease-out; + } + + &:hover { + color: #ffd700; + + svg { + opacity: 0; + } + + &:after { + opacity: 1; + } + } + + &:after { + content: ''; + font-size: 9px; + letter-spacing: 2px; + position: absolute; + bottom: 0; + display: block; + width: 100%; + text-align: center; + opacity: 0; + transition: all 0.3s ease-out; + } + + &:first-child { + &::after { + content: 'HOME'; + } + } + } + a.about-link { + &:after { + content: 'ABOUT'; + } + } + + a.contact-link { + &:after { + content: 'CONTACT'; + } + } + a.active { + svg { + color: #ffd700; + } + } + } + ul { + position: absolute; + bottom: 20px; + width: 100%; + display: block; + padding: 0; + list-style: none; + text-align: center; + margin: 0; + + li { + a { + padding: 7px 0; + display: block; + font-size: 15px; + line-height: 16px; + + &:hover svg{ + color:#ffd700; + } + } + } + } +} \ No newline at end of file diff --git a/src/index.css b/src/index.css index ec2585e..070ba93 100644 --- a/src/index.css +++ b/src/index.css @@ -1,13 +1,15 @@ +html { + font-size: 62.5%; + +} body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; + font: 300 11px/1.4 'Helvetica Neue', 'sans-serif'; + color: #444; + background: #022c43; + overflow: hidden; + display: block; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; -} diff --git a/src/index.js b/src/index.js index d563c0f..7a6abde 100644 --- a/src/index.js +++ b/src/index.js @@ -3,11 +3,14 @@ import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; +import { BrowserRouter } from 'react-router-dom'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( - + + + );