├── .babelrc ├── .env.sample ├── .eslintrc.json ├── .github └── workflows │ └── codeql-analysis.yml ├── .gitignore ├── .prettierrc.json ├── README.md ├── SECURITY.md ├── components ├── 404 │ ├── index.js │ └── index.module.css ├── docs │ ├── index.js │ └── index.module.css ├── hero │ ├── index.js │ └── index.module.css ├── info │ ├── index.js │ └── index.module.css ├── layout │ └── index.js ├── result │ ├── index.js │ └── index.module.css ├── seo │ └── index.js ├── svg │ ├── index.js │ └── postman.js └── video │ └── index.js ├── constants └── index.js ├── contexts └── MailContext.js ├── package-lock.json ├── package.json ├── pages ├── 404.js ├── _app.js ├── _document.js ├── api │ └── hello.js ├── docs.js ├── index.js └── result.js ├── postcss.config.js ├── public ├── docs.png ├── spacez.ico └── vercel.svg ├── styles └── globals.css ├── tailwind.config.js └── utils └── index.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["next/babel", {}]], 3 | "plugins": [ 4 | [ 5 | "module-resolver", 6 | { 7 | "root": ["./"], 8 | "alias": { 9 | "@c": "./components", 10 | "@const": "./constants", 11 | "@s": "./styles", 12 | "@svg": "./components/svg", 13 | "@cx": "./contexts/", 14 | "@utils": "./utils" 15 | } 16 | } 17 | ] 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /.env.sample: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fport/spacez-link/7613205110ecc9b29209f382913504de806da1a5/.env.sample -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:react/recommended" 9 | ], 10 | "parserOptions": { 11 | "ecmaFeatures": { 12 | "jsx": true 13 | }, 14 | "ecmaVersion": 13, 15 | "sourceType": "module" 16 | }, 17 | "plugins": [ 18 | "react" 19 | ], 20 | "rules": { 21 | "react/no-unescaped-entities": "off", 22 | "@next/next/no-page-custom-font": "off" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ main ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ main ] 20 | schedule: 21 | - cron: '25 19 * * 3' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'javascript' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://git.io/codeql-language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v2 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v1 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 52 | 53 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 54 | # If this step fails, then you should remove it and run the build manually (see below) 55 | - name: Autobuild 56 | uses: github/codeql-action/autobuild@v1 57 | 58 | # ℹ️ Command-line programs to run using the OS shell. 59 | # 📚 https://git.io/JvXDl 60 | 61 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 62 | # and modify them (or add more) to build your code if your project 63 | # uses a compiled language 64 | 65 | #- run: | 66 | # make bootstrap 67 | # make release 68 | 69 | - name: Perform CodeQL Analysis 70 | uses: github/codeql-action/analyze@v1 71 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "es5", 4 | "print-width": 120, 5 | "tab-width": 4 6 | } 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |

5 | This is a project that makes easy to integrate email service. 6 |

7 |
8 | 9 | ## Backend Repository 10 | [Click](https://github.com/BijanE/spacez-link-backend) for backend repository. 11 | 12 | ## Figma Design 13 | [Click](https://www.figma.com/file/5rJZnc5YOrMM9zI0zEcgup/spacez-link?node-id=2%3A1494) for design page. 14 | 15 | ## Example Usage 16 | [Click](https://github.com/fport/spacez-link-basic-example) for basic example usage. 17 | 18 |

Preview

19 | 20 |
21 | 22 | ![Preview](https://user-images.githubusercontent.com/56169582/150584640-20df2ffd-9785-41cc-8647-0f406b640eb9.png) 23 | 24 | ![Preview](https://user-images.githubusercontent.com/56169582/150585057-f7d826ca-7e5d-4c2d-917f-76aac6a1aa46.png) 25 | 26 | ![Preview](https://user-images.githubusercontent.com/56169582/150585060-6073754c-d3a0-451e-8310-66d4d739c629.png) 27 | 28 |
29 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Use this section to tell people about which versions of your project are 6 | currently being supported with security updates. 7 | 8 | | Version | Supported | 9 | | ------- | ------------------ | 10 | | 5.1.x | :white_check_mark: | 11 | | 5.0.x | :x: | 12 | | 4.0.x | :white_check_mark: | 13 | | < 4.0 | :x: | 14 | 15 | ## Reporting a Vulnerability 16 | 17 | Use this section to tell people how to report a vulnerability. 18 | 19 | Tell them where to go, how often they can expect to get an update on a 20 | reported vulnerability, what to expect if the vulnerability is accepted or 21 | declined, etc. 22 | -------------------------------------------------------------------------------- /components/404/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styles from './index.module.css'; 3 | import { useRouter } from 'next/router'; 4 | 5 | function ErrorComponent() { 6 | const router = useRouter(); 7 | 8 | return ( 9 |
10 |

11 | {router.pathname} Aradığınız {router.asPath} bulunamadı 12 |

13 |
14 | ); 15 | } 16 | 17 | export default ErrorComponent; 18 | -------------------------------------------------------------------------------- /components/404/index.module.css: -------------------------------------------------------------------------------- 1 | .error { 2 | @apply full:container text-secondary mx-auto text-center text-36 xs:p-32 md:p-95; 3 | } 4 | 5 | .errorText { 6 | @apply text-36 text-primary; 7 | } 8 | -------------------------------------------------------------------------------- /components/docs/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styles from './index.module.css'; 3 | 4 | export default function DocsComponent() { 5 | return ( 6 |
7 |
8 | docs 9 |
10 |
11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /components/docs/index.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | @apply flex flex-col items-center justify-center mt-64 w-full; 3 | } 4 | 5 | .content { 6 | @apply flex items-center justify-start flex-col w-full text-gray bg-shadow max-w-600 p-large rounded-2xl; 7 | } 8 | -------------------------------------------------------------------------------- /components/hero/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styles from './index.module.css'; 3 | import { Postman } from '@svg'; 4 | import Link from 'next/link'; 5 | 6 | export default function Hero() { 7 | return ( 8 |
9 | 10 | E-Mail Sender for Website 11 | 12 | 13 |
14 |

15 | This is a application that makes easy to integrate email service. The 16 | application provides an easy method when you want to integrate Email 17 | service. 18 |

19 | 20 |
21 |
22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /components/hero/index.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | @apply flex flex-col items-center justify-center mt-64; 3 | } 4 | 5 | .heroTitle { 6 | @apply text-h2 text-secondary ; 7 | } 8 | 9 | .content { 10 | @apply flex max-w-3/4; 11 | } 12 | 13 | .contentText { 14 | @apply flex items-center max-w-400 mr-32 text-white; 15 | } 16 | -------------------------------------------------------------------------------- /components/info/index.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect, useContext } from 'react'; 2 | import styles from './index.module.css'; 3 | import { MailContext } from '@cx/MailContext'; 4 | 5 | export default function Info(props) { 6 | const p = props; 7 | const [email, setEmail] = useState(''); 8 | const [pass, setPass] = useState(''); 9 | const [err, setErr] = useState(false); 10 | 11 | const { sendMail } = useContext(MailContext); 12 | 13 | useEffect(() => { 14 | if (email && pass) setErr(false); 15 | }, [email, pass]); 16 | 17 | useEffect(() => { 18 | if (p.error) { 19 | setTimeout(() => { 20 | p.removeError(); 21 | }, [3000]); 22 | } 23 | }, [p.error]); 24 | 25 | /* eslint-disable */ 26 | const validateEmail = (email) => { 27 | return email.match( 28 | /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ 29 | ); 30 | }; 31 | 32 | const handleSubmit = (e) => { 33 | e.preventDefault(); 34 | if (email && pass && validateEmail(email)) { 35 | sendMail({ 36 | email, 37 | pass, 38 | }); 39 | } else { 40 | setErr(true); 41 | } 42 | setEmail(''); 43 | setPass(''); 44 | }; 45 | 46 | const isLoading = () => { 47 | return Loading; 48 | }; 49 | 50 | const errorHandler = () => { 51 | return {p.error}; 52 | }; 53 | 54 | return ( 55 |
56 |
57 | {err && ( 58 | You must fill in the blanks 59 | )} 60 | {p.error && !p.isLoading && errorHandler()} 61 | {!p.error && p.isLoading && isLoading()} 62 |
63 | 64 | setEmail(e.target.value)} 70 | /> 71 | 74 | setPass(e.target.value)} 80 | /> 81 | 84 |
85 |
86 |
87 | ); 88 | } 89 | -------------------------------------------------------------------------------- /components/info/index.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | @apply flex flex-col items-center justify-center mt-64 w-full; 3 | } 4 | 5 | .content { 6 | @apply flex items-center justify-start flex-col w-full text-gray bg-shadow max-w-600 p-large rounded-2xl; 7 | } 8 | 9 | .contentInput { 10 | @apply w-full bg-gray h-64 flex my-10 max-w-500 border-0 rounded-2xl placeholder-white px-40 text-secondary; 11 | } 12 | 13 | .btn { 14 | @apply text-secondary bg-gray p-8 w-100 mt-8 rounded-2xl; 15 | 16 | } 17 | 18 | .emailLabel { 19 | @apply text-secondary; 20 | } 21 | 22 | .errText { 23 | @apply text-warning flex mb-10; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /components/layout/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Seo from '../seo'; 3 | 4 | /* eslint-disable react/prop-types */ 5 | function Layout({ children }) { 6 | return ( 7 | <> 8 | 9 |
{children}
10 | 11 | ); 12 | } 13 | 14 | export default Layout; 15 | -------------------------------------------------------------------------------- /components/result/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styles from './index.module.css'; 3 | import { useCopyToClipboard } from '@utils'; 4 | import Link from 'next/link'; 5 | 6 | /* eslint-disable react/prop-types */ 7 | export default function Info({ data }) { 8 | const [isCopied, copyToClipboard] = useCopyToClipboard({ 9 | debug: true, 10 | message: 'Press #{x} to copy', 11 | interval: 3000, 12 | }); 13 | 14 | return ( 15 |
16 |
17 | 20 |
copyToClipboard(data)}> 21 | {data} 22 |
23 | {isCopied && 'kopyalandi'} 24 | 25 | Get Document 26 | 27 |
28 |
29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /components/result/index.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | @apply flex flex-col items-center justify-center mt-64 w-full; 3 | } 4 | 5 | .content { 6 | @apply flex items-center justify-center flex-col w-full text-gray bg-shadow max-w-600 p-large rounded-2xl; 7 | } 8 | 9 | .contentInput { 10 | @apply w-full h-32 flex my-10 max-w-400 border-0; 11 | } 12 | 13 | .btn { 14 | @apply w-200 mt-8 text-secondary bg-gray p-8 rounded-2xl flex items-center justify-center mt-24; 15 | 16 | } 17 | 18 | .link { 19 | @apply text-white cursor-pointer text-center bg-gray rounded-2xl p-8; 20 | } 21 | 22 | .copy { 23 | @apply text-white; 24 | } 25 | 26 | .title { 27 | @apply text-secondary mb-10; 28 | } 29 | -------------------------------------------------------------------------------- /components/seo/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Head from 'next/head'; 3 | 4 | /* eslint-disable react/prop-types */ 5 | export default function Seo({ title }) { 6 | return ( 7 | 8 | 9 | 13 | 14 | Spacez - {title} 15 | 16 | 17 | 18 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 38 | 39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /components/svg/index.js: -------------------------------------------------------------------------------- 1 | import Postman from './postman'; 2 | 3 | export { Postman }; 4 | -------------------------------------------------------------------------------- /components/svg/postman.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | export default function Postman() { 3 | return ( 4 | 11 | 15 | 19 | 23 | 27 | 31 | 32 | 37 | 38 | 42 | 46 | 50 | 54 | 58 | 62 | 66 | 70 | 74 | 78 | 82 | 86 | 90 | 94 | 98 | 102 | 106 | 110 | 114 | 118 | 122 | 127 | 132 | 137 | 141 | 145 | 149 | 153 | 157 | 161 | 165 | 169 | 173 | 177 | 181 | 185 | 189 | 193 | 197 | 201 | 206 | 210 | 214 | 218 | 222 | 226 | 230 | 234 | 238 | 242 | 246 | 250 | 254 | 258 | 262 | 266 | 270 | 275 | 279 | 283 | 287 | 291 | 296 | 300 | 304 | 308 | 312 | 317 | 321 | 326 | 330 | 334 | 338 | 339 | ); 340 | } 341 | -------------------------------------------------------------------------------- /components/video/index.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | 3 | export default function Video() { 4 | const [playVideo, setPlayVideo] = useState(false); 5 | return ( 6 |
7 |
setPlayVideo(!playVideo)} 9 | className="relative bg-indigo-300 cursor-pointer aspect-w-16 aspect-h-9 bg-gradient-to-tr from-purple-400 to-indigo-700" 10 | > 11 | {!playVideo && ( 12 | 27 | )} 28 | {playVideo && ( 29 | 36 | )} 37 |
38 |
39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /constants/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fport/spacez-link/7613205110ecc9b29209f382913504de806da1a5/constants/index.js -------------------------------------------------------------------------------- /contexts/MailContext.js: -------------------------------------------------------------------------------- 1 | import React, { createContext, useState } from 'react'; 2 | import axios from 'axios'; 3 | 4 | const MailContext = createContext(); 5 | 6 | /* eslint-disable react/prop-types */ 7 | const MailProvider = ({ children }) => { 8 | const [todos, setTodos] = useState(''); 9 | const [isLoading, setIsLoading] = useState(false); 10 | const [err, setErr] = useState(); 11 | 12 | const sendMail = async (data) => { 13 | const osman = { 14 | email_username: data.email, 15 | email_password: data.pass, 16 | }; 17 | try { 18 | setIsLoading(true); 19 | const res = await axios 20 | .post( 21 | 'https://spacez-link.herokuapp.com/api/submit/email-config', 22 | osman 23 | ) 24 | .then((res) => { 25 | const data = res; 26 | setTodos((prevTodos) => { 27 | const updatedTodos = data.data.link; 28 | setIsLoading(false); 29 | return updatedTodos; 30 | }); 31 | }) 32 | .catch((err) => { 33 | console.log('asdasd', err.response.data.massage); 34 | const handle = err.response.data.massage; 35 | setErr(handle); 36 | setIsLoading(false); 37 | }); 38 | } catch (err) { 39 | console.error('asdsd', err); 40 | } 41 | }; 42 | 43 | const removeError = () => { 44 | setErr(); 45 | }; 46 | 47 | return ( 48 | 57 | {children} 58 | 59 | ); 60 | }; 61 | 62 | export { MailProvider, MailContext }; 63 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-project", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "axios": "^0.24.0", 13 | "babel-plugin-module-resolver": "^4.1.0", 14 | "copy-to-clipboard": "^3.3.1", 15 | "next": "12.0.7", 16 | "react": "17.0.2", 17 | "react-dom": "17.0.2" 18 | }, 19 | "devDependencies": { 20 | "autoprefixer": "^10.4.2", 21 | "babel-loader": "^8.2.3", 22 | "eslint": "^8.6.0", 23 | "eslint-plugin-react": "^7.28.0", 24 | "postcss": "^8.4.5", 25 | "postcss-import": "^14.0.2", 26 | "prettier": "2.5.1", 27 | "tailwindcss": "^3.0.12" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /pages/404.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | // import Layout from '@c/layout'; 3 | // import Seo from '@c/layout/seo'; 4 | import ErrorComponent from '@c/404'; 5 | 6 | function ErrorPage() { 7 | return ( 8 | <> 9 | 10 | 11 | ); 12 | } 13 | export default ErrorPage; 14 | 15 | // 16 | // 17 | // 18 | // 19 | -------------------------------------------------------------------------------- /pages/_app.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import '@s/globals.css'; 3 | import { MailProvider } from '@cx/MailContext'; 4 | 5 | /* eslint-disable react/prop-types */ 6 | function MyApp({ Component, pageProps }) { 7 | return ( 8 | 9 | 10 | 11 | ); 12 | } 13 | 14 | export default MyApp; 15 | -------------------------------------------------------------------------------- /pages/_document.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Document, { Html, Head, Main, NextScript } from 'next/document'; 3 | 4 | /* ADD GA */ /* ~/lib folder */ 5 | class Site extends Document { 6 | render() { 7 | return ( 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | ); 16 | } 17 | } 18 | 19 | export default Site; 20 | -------------------------------------------------------------------------------- /pages/api/hello.js: -------------------------------------------------------------------------------- 1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction 2 | 3 | export default (req, res) => { 4 | res.status(200).json({ name: 'John Doe' }) 5 | } 6 | -------------------------------------------------------------------------------- /pages/docs.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DocsComponent from '@c/docs'; 3 | import Hero from '@c/hero'; 4 | import Layout from '@c/layout'; 5 | import Seo from '@c/seo'; 6 | 7 | export default function Docs() { 8 | return ( 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /pages/index.js: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import Layout from '@c/layout'; 3 | import Seo from '@c/seo'; 4 | import Hero from '@c/hero'; 5 | import Info from '@c/info'; 6 | import Result from '@c/result'; 7 | import { MailContext } from '@cx/MailContext'; 8 | 9 | function LandingPage() { 10 | // eslint-disable-next-line no-unused-vars 11 | const { todos, setTodos, removeError } = useContext(MailContext); 12 | const { isLoading, err } = useContext(MailContext); 13 | 14 | return ( 15 | <> 16 | 17 | 18 | 19 | {!todos ? ( 20 | 21 | ) : ( 22 | 23 | )} 24 | 25 | 26 | ); 27 | } 28 | export default LandingPage; 29 | -------------------------------------------------------------------------------- /pages/result.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Video from '@c/video'; 3 | export default function Result() { 4 | return ( 5 |
6 |
8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /public/docs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fport/spacez-link/7613205110ecc9b29209f382913504de806da1a5/public/docs.png -------------------------------------------------------------------------------- /public/spacez.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fport/spacez-link/7613205110ecc9b29209f382913504de806da1a5/public/spacez.ico -------------------------------------------------------------------------------- /public/vercel.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /styles/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --primary-color: #282C34; 7 | --secondary-color: #5FF59B; 8 | --shadow-color: #636363; 9 | --danger-color: #e53549; 10 | --warning-color: #ffcf5c; 11 | --success-color: #00c48c; 12 | --info-color: #f4f6f9; 13 | --light-color: #f4f6f9; 14 | --gray-color: #272727; 15 | --background-color: #272727; 16 | --white: #fff; 17 | } 18 | 19 | @layer base { 20 | html { 21 | @apply select-none; 22 | } 23 | body { 24 | @apply bg-primary m-0 antialiased font-primary text-16 font-bold; 25 | } 26 | a { 27 | @apply no-underline hover:text-secondary visited:text-secondary; 28 | } 29 | li { 30 | @apply list-none p-0; 31 | } 32 | ol, 33 | ul { 34 | @apply list-none m-0 p-0; 35 | } 36 | } 37 | 38 | a:link { 39 | color: #5affc9; 40 | } 41 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | purge: [], 3 | darkMode: false, // or 'media' or 'class' 4 | important: true, 5 | theme: { 6 | screens: { 7 | full: { max: '320px' }, 8 | xs: '0px', 9 | sm: '640px', 10 | md: '768px', 11 | lg: '1024px', 12 | xl: '1280px', 13 | xxl: '1536px', 14 | }, 15 | width: { 16 | 100: '100px', 17 | 200: '200px', 18 | 400: '400px', 19 | full: '100%', 20 | }, 21 | maxWidth: { 22 | '1/4': '25%', 23 | '1/2': '50%', 24 | '3/4': '75%', 25 | 600: '600px', 26 | 500: '500px', 27 | 400: '400px', 28 | 200: '200px', 29 | 100: '100px', 30 | full: '100%', 31 | max: 'max-content', 32 | }, 33 | colors: { 34 | primary: 'var(--primary-color)', 35 | secondary: 'var(--secondary-color)', 36 | shadow: 'var(--shadow-color)', 37 | danger: 'var(--danger-color)', 38 | warning: 'var(--warning-color)', 39 | success: 'var(--success-color)', 40 | info: 'var(--info-color)', 41 | light: 'var(--light-color)', 42 | gray: 'var(--gray-color)', 43 | background: 'var(--background-color)', 44 | white: 'var(--white)', 45 | }, 46 | borderRadius: { 47 | none: '0px', 48 | sm: '0.125rem', 49 | DEFAULT: '0.25rem', 50 | md: '0.375rem', 51 | lg: '0.5rem', 52 | xl: '0.75rem', 53 | '2xl': '8px', 54 | '3xl': '50px', 55 | full: '9999px', 56 | }, 57 | spacing: { 58 | default: '0.375rem 0.75rem', 59 | small: '0.19rem 0.375rem', 60 | large: '0.75rem 1.5rem', 61 | 0: '0px', 62 | 1: '1px', 63 | 2: '2px', 64 | 3: '3px', 65 | 4: '4px', 66 | 6: '6px', 67 | 8: '8px', 68 | 10: '10px', 69 | 12: '12px', 70 | 16: '16px', 71 | 24: '24px', 72 | 32: '32px', 73 | 36: '36px', 74 | 40: '40px', 75 | 48: '48px', 76 | 54: '54px', 77 | 64: '64px', 78 | 76: '76px', 79 | 90: '90px', 80 | 95: '95px', 81 | 200: '200px', 82 | 338: '338px', 83 | 360: '360px', 84 | }, 85 | zIndex: {}, 86 | fontFamily: { 87 | primary: ['IBM Plex Sans', 'ui-sans-serif', 'system-ui'], 88 | secondary: ['Roboto'], 89 | }, 90 | boxShadow: { 91 | sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)', 92 | DEFAULT: 93 | '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)', 94 | md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)', 95 | lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)', 96 | xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)', 97 | '2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)', 98 | '3xl': '0 35px 60px -15px rgba(0, 0, 0, 0.3)', 99 | none: 'none', 100 | }, 101 | fontSize: { 102 | 14: '14px', 103 | 16: '16px', 104 | 18: '18px', 105 | 24: '24px', 106 | 32: '32px', 107 | 36: '36px', 108 | h1: '72px', 109 | h2: '50px', 110 | h3: '46px', 111 | h4: '30px', 112 | h5: '12px', 113 | h6: '20px', 114 | ind: '35px', 115 | }, 116 | inset: { 117 | 3: '3px', 118 | 20: '20px', 119 | }, 120 | letterSpacing: {}, 121 | }, 122 | 123 | variants: { 124 | extend: { 125 | textColor: ['visited'], 126 | }, 127 | }, 128 | plugins: [], 129 | }; 130 | -------------------------------------------------------------------------------- /utils/index.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect, useCallback } from 'react'; 2 | import copy from 'copy-to-clipboard'; 3 | 4 | const useCopyToClipboard = ({ 5 | debug = false, 6 | message = '', 7 | interval = null, 8 | }) => { 9 | const [isCopied, setCopied] = useState(false); 10 | 11 | useEffect(() => { 12 | let timeout; 13 | if (isCopied && interval) { 14 | timeout = setTimeout(() => { 15 | setCopied(false); 16 | }, interval); 17 | } 18 | 19 | return () => { 20 | clearTimeout(timeout); 21 | }; 22 | }, [isCopied, interval]); 23 | 24 | const copyToClipboard = useCallback((text) => { 25 | if (typeof text === 'string' || typeof text === 'number') { 26 | copy(text.toString(), { 27 | debug, 28 | message, 29 | }); 30 | 31 | setCopied(true); 32 | } 33 | }, []); 34 | 35 | return [isCopied, copyToClipboard]; 36 | }; 37 | 38 | export {useCopyToClipboard} 39 | --------------------------------------------------------------------------------