├── .gitignore ├── public ├── _redirects ├── favicon.ico ├── logo192.png ├── logo512.png ├── robots.txt ├── manifest.json └── index.html ├── src ├── index.js ├── components │ ├── pages │ │ ├── Editor │ │ │ ├── Editor.css │ │ │ └── Editor.js │ │ ├── Translate.js │ │ ├── Accordion.js │ │ ├── Dropdown.js │ │ ├── TextUtils.js │ │ └── Search.js │ └── base │ │ ├── Link.js │ │ ├── Header.js │ │ └── Convert.js ├── commons │ └── utils.js ├── routes │ └── index.js ├── index.css ├── data │ ├── accordionOptions.js │ ├── translateOptions.js │ └── colorOptions.js └── App.js ├── package.json ├── CONTRIBUTING.md ├── README.md └── CODE_OF_CONDUCT.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /public/_redirects: -------------------------------------------------------------------------------- 1 | /* /index.html 200 -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishal-codes/react-widgets/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishal-codes/react-widgets/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishal-codes/react-widgets/HEAD/public/logo512.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './index.css'; 3 | import ReactDOM from 'react-dom'; 4 | import App from './App'; 5 | 6 | ReactDOM.render(,document.getElementById('root')); 7 | 8 | -------------------------------------------------------------------------------- /src/components/pages/Editor/Editor.css: -------------------------------------------------------------------------------- 1 | .editor-container{ 2 | display: flex; 3 | flex-direction: column; 4 | gap: 1rem; 5 | } 6 | .editor-title{ 7 | color: white; 8 | } 9 | .editor-title-text{ 10 | height: 3rem; 11 | border-radius: 0.5rem; 12 | } 13 | .editor-content{ 14 | color: white; 15 | } 16 | .editor-content-text{ 17 | color: black; 18 | } -------------------------------------------------------------------------------- /src/commons/utils.js: -------------------------------------------------------------------------------- 1 | export const debounce = (func, delay) => { 2 | let debounceTimer; 3 | return function () { 4 | const context = this; 5 | const args = arguments; 6 | clearTimeout(debounceTimer); 7 | debounceTimer = setTimeout(() => func.apply(context, args), delay); 8 | }; 9 | }; 10 | 11 | export const createMarkup = (htmlString) => { 12 | return { __html: htmlString }; 13 | } 14 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /src/routes/index.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | 3 | const Routes = ( {path, children} ) => { 4 | const [currentPath, setCurrentPath] = useState(window.location.pathname); 5 | 6 | useEffect(() => { 7 | const onLocationChange = () =>{ 8 | setCurrentPath(window.location.pathname); 9 | }; 10 | 11 | window.addEventListener('popstate', onLocationChange); 12 | 13 | return () => { 14 | window.removeEventListener('popstate', onLocationChange); 15 | }; 16 | }, []); 17 | 18 | return currentPath === path ? children : null; 19 | }; 20 | 21 | export default Routes; -------------------------------------------------------------------------------- /src/components/base/Link.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const Link= ( {href, className, children} ) => { 4 | const onClickDo = (event) => { 5 | if(event.metaKey || event.ctrlKey){ 6 | return; 7 | } 8 | 9 | event.preventDefault(); 10 | window.history.pushState({}, '', href); 11 | 12 | const navEvent = new PopStateEvent('popstate'); 13 | window.dispatchEvent(navEvent); 14 | }; 15 | return( 16 | 21 | {children} 22 | 23 | ); 24 | } 25 | 26 | export default Link; -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: rgb(0, 0, 0); 3 | color: white; 4 | margin: 15px; 5 | } 6 | 7 | .ui.menu:not(.vertical) .item { 8 | display: -webkit-box; 9 | display: -ms-flexbox; 10 | display: flex; 11 | -webkit-box-align: center; 12 | -ms-flex-align: center; 13 | align-items: center; 14 | padding: 13px 12px 13px 12px; 15 | } 16 | 17 | .ui.header { 18 | color: white; 19 | } 20 | 21 | /* Search */ 22 | .ui.form .field > label { 23 | font-size: 19px; 24 | color: white; 25 | } 26 | .ui.list .list > .item .header, 27 | .ui.list > .item .header { 28 | color: white; 29 | } 30 | 31 | /* Accordion */ 32 | p { 33 | color: black; 34 | } 35 | 36 | .container-error-search { 37 | margin-top: 10px; 38 | } 39 | -------------------------------------------------------------------------------- /src/components/base/Header.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Link from './Link'; 3 | 4 | const Header = () => { 5 | return ( 6 |
7 | 8 | Accordion 9 | 10 | 11 | Search 12 | 13 | 14 | Dropdown 15 | 16 | 17 | Translator 18 | 19 | 20 | TextUtils 21 | 22 | 23 | Editor 24 | 25 |
26 | ); 27 | }; 28 | 29 | export default Header; 30 | -------------------------------------------------------------------------------- /src/components/pages/Translate.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import Dropdown from "./Dropdown"; 3 | import Convert from "../base/Convert"; 4 | import { translateOptions } from "../../data/translateOptions" 5 | 6 | const Translate = () => { 7 | const [language, setLanguage] = useState(translateOptions[0]); 8 | const [text, setText] = useState(""); 9 | 10 | return ( 11 |
12 |
13 |
14 |

15 | 16 |

17 | setText(e.target.value)} /> 18 |
19 |
20 | 27 | 28 |

Output

29 | 30 |
31 | ); 32 | }; 33 | 34 | export default Translate; 35 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "widgets", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@ckeditor/ckeditor5-build-classic": "^30.0.0", 7 | "@ckeditor/ckeditor5-heading": "^30.0.0", 8 | "@ckeditor/ckeditor5-react": "^3.0.3", 9 | "@testing-library/jest-dom": "^5.14.1", 10 | "@testing-library/react": "^11.2.7", 11 | "@testing-library/user-event": "^12.8.3", 12 | "axios": "^0.21.4", 13 | "react": "^17.0.2", 14 | "react-dom": "^17.0.2", 15 | "react-scripts": "4.0.3", 16 | "web-vitals": "^1.1.2" 17 | }, 18 | "scripts": { 19 | "start": "react-scripts start", 20 | "build": "react-scripts build", 21 | "test": "react-scripts test", 22 | "eject": "react-scripts eject" 23 | }, 24 | "eslintConfig": { 25 | "extends": [ 26 | "react-app", 27 | "react-app/jest" 28 | ] 29 | }, 30 | "browserslist": { 31 | "production": [ 32 | ">0.2%", 33 | "not dead", 34 | "not op_mini all" 35 | ], 36 | "development": [ 37 | "last 1 chrome version", 38 | "last 1 firefox version", 39 | "last 1 safari version" 40 | ] 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/components/pages/Accordion.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | 3 | const Accordion = ({ items }) => { 4 | const [activeIndex, setActiveIndex] = useState(null); 5 | 6 | const onTitleClick = (index) => { 7 | index === activeIndex ? setActiveIndex(null) : setActiveIndex(index) 8 | }; 9 | 10 | const renderedItems = items.map((item, index) => { 11 | 12 | const active = index === activeIndex ? 'active' : ''; 13 | 14 | return ( 15 | 16 |
onTitleClick(index)} 19 | > 20 | 21 | {item.title} 22 |
23 |
24 |

{item.content}

25 |
26 |
27 | ) 28 | }); 29 | 30 | return ( 31 |
32 | {renderedItems} 33 |
34 | ); 35 | 36 | }; 37 | 38 | export default Accordion; -------------------------------------------------------------------------------- /src/components/pages/Editor/Editor.js: -------------------------------------------------------------------------------- 1 | import "./Editor.css"; 2 | import { CKEditor } from "@ckeditor/ckeditor5-react"; 3 | import ClassicEditor from "@ckeditor/ckeditor5-build-classic"; 4 | import { useState } from "react"; 5 | 6 | const Editor = () => { 7 | const [title, setTitle] = useState(""); 8 | const [content, setContent] = useState(""); 9 | const handleChange = ({ target }) => { 10 | const { value } = target; 11 | setTitle(value); 12 | }; 13 | 14 | return ( 15 |
16 |

Title

17 | 24 |

Content

25 | { 31 | const data = editor.getData(); 32 | setContent(data); 33 | }} 34 | /> 35 |
36 | ); 37 | }; 38 | const editorConfiguration = { 39 | toolbar: [ 'bold', 'italic' ] 40 | }; 41 | export default Editor; 42 | -------------------------------------------------------------------------------- /src/data/accordionOptions.js: -------------------------------------------------------------------------------- 1 | export const accordionOptions = [ 2 | { 3 | title: 'What is React?', 4 | content: 'React is a JavaScript library for building user interfaces' 5 | }, 6 | { 7 | title: 'Component Based', 8 | content: 'Build encapsulated components that manage their own state, then compose them to make complex UIs.' 9 | }, 10 | { 11 | title: 'Declarative ?', 12 | content: 'React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes.' 13 | },{ 14 | title: 'what is bundling ?', 15 | content:'Most React apps will have their files “bundled” using tools like Webpack, Rollup or Browserify. Bundling is the process of following imported files and merging them into a single file: a “bundle”. This bundle can then be included on a webpage to load an entire app at once.' 16 | },{ 17 | title:'client side rendering', 18 | content:'Client-side rendering allows developers to make their websites entirely rendered in the browser with JavaScript. Instead of having a different HTML page per route, a client-side rendered website creates each route dynamically directly in the browser.' 19 | } 20 | ]; -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import Accordion from './components/pages/Accordion'; 3 | import Search from './components/pages/Search'; 4 | import Dropdown from './components/pages/Dropdown'; 5 | import Translate from './components/pages/Translate'; 6 | import TextUtils from './components/pages/TextUtils' 7 | import Editor from "./components/pages/Editor/Editor" 8 | import Header from './components/base/Header'; 9 | 10 | import Routes from './routes'; 11 | import { colorOptions } from './data/colorOptions'; 12 | import { accordionOptions } from './data/accordionOptions'; 13 | 14 | const App = ()=> { 15 | const [selected, setSelected] = useState(colorOptions[0]); 16 | 17 | return ( 18 |
19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 |
45 | ); 46 | }; 47 | 48 | export default App -------------------------------------------------------------------------------- /src/components/base/Convert.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import axios from "axios"; 3 | 4 | const Convert = ( {language, text} ) => { 5 | 6 | const [translated, setTranslated] = useState(''); 7 | const [debouncedText, setDebouncedText] = useState(text); 8 | const [isTranslated, setIsTranslated] = useState(false); 9 | 10 | useEffect(() => { 11 | const timerId = setTimeout(() => { 12 | setDebouncedText(text); 13 | },500); 14 | 15 | return () => { 16 | clearTimeout(timerId); 17 | }; 18 | },[text]); 19 | 20 | useEffect(() => { 21 | const doTranslation = async () => { 22 | setIsTranslated(true); 23 | const {data} = await axios.post('https://translation.googleapis.com/language/translate/v2', 24 | {}, 25 | { 26 | params: { 27 | q: debouncedText, 28 | target: language.value, 29 | key: 'AIzaSyDElOAEazlhJckWxrhwWt37KsJxXWBVlDA'//this api key is restricted :) 30 | } 31 | }); 32 | setIsTranslated(false); 33 | setTranslated(data.data.translations[0].translatedText); 34 | }; 35 | if (debouncedText !== "") { 36 | doTranslation(); 37 | } else { 38 | setTranslated(""); 39 | } 40 | }, [language,debouncedText]); 41 | 42 | return ( 43 |
44 | {isTranslated ? ( 45 | Translating... 46 | ) : ( 47 |

{translated}

48 | )} 49 |
50 | ); 51 | 52 | }; 53 | 54 | export default Convert; -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 18 | 19 | 28 | React App 29 | 30 | 31 | 32 |
33 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Before moving ahead with making contributions please make sure that you have read the code of conduct mentioned in the [CODE_OF_CONDUCT.md](https://github.com/vishal-codes/react-widgets/blob/main/CODE_OF_CONDUCT.md) file. 4 |
5 | 6 | ### Prerequisites 7 | Make sure you have node.js and git installed on your machine.
8 | If you haven't then [this article](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) will help you in installation of git and [this article](https://nodejs.dev/learn/how-to-install-nodejs) will help in istallation of node.js 9 | 10 | ### Setting up project locally 11 | 1. Fork this repository by clicking on the fork button on the top of this page, this will create a copy of this repository in your account. 12 | 2. Clone your forked version by entering ``` git clone "https://github.com/YOUR_GITHUB_UserName/react-widgets.git"``` 13 | 3. Change the directory from present to the project directory by entering ``` cd react-widgets/``` 14 | 4. Install all dependencies by entering ```npm i``` 15 | 5. Run the project locally by entering ```npm start```
This will run the project locally on port `localhost:3000` in your default browser. 16 | 17 | ### Branching 18 | 1. Open a new window of your terminal and change the directory into the project folder 19 | 2. Now create a new branch using `git checkout -b `
For example `git checkout-b vishal-codes` 20 | 3. Now make the required changes in the project which will resolve or add a feature as per mentioned in the respective issue. 21 | 22 | ### Commiting changes 23 | 1. Add the changes to the branch you just created using the `git add .` command 24 | 2. Now commit those changes using `git commit -m <"a short description about changes u made">`
For example `git commit -m "Added new language in translator"` 25 | 3. Push the changes using `git push origin `
For example `git push origin vishal-codes` 26 | 4. Submit your changes for review by creating a pull request, if you go to your repository on GitHub, you'll see a `Compare & pull request` button. Click on that button. 27 | 5. Soon I'll be merging all your changes into the master branch of this project. You will get a notification email once the changes have been merged. 28 | 29 | ### Where to go from here? 30 | Congrats! You just completed the standard _fork -> clone -> branch -> edit -> PR_ workflow that you'll encounter often as a contributor! 31 | 32 | 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Widgets 2 | 3 | ## Update 4 | This is a read-only project, so there will not be any further changes in the project and also I have used up my google cloud free credits so google translate api won't work. 5 | 6 | ## Description 7 | 8 | This is a project which I made while learning React.js from a [course on Udemy.](https://www.udemy.com/course/react-redux/) Along with Accordion, Dropdown it has a Search page where in you can search for anything on wikipedia, it uses Wikipedia api for fetching results of the entered search term and displays results on the same page with a button which links to the wikipedia page of a respective result. The project also consists of a translator which uses Google Translate Api for autodetecting the language of entered text and translates it into required language. 9 | 10 | ## Technologies Used 11 | 12 | - React.js 13 | - CSS 14 | - JavaScript 15 | - HTML 16 | - API 17 | - Postman 18 | - Netlify 19 | 20 | #### You can check the deployed version of the project [here](https://wizardly-hoover-38f71b.netlify.app/) and if you want to contribute to the project then checkout [CONTRIBUTING.md](https://github.com/vishal-codes/react-widgets/blob/main/CONTRIBUTING.md) . There are begineer friendly issues listed in the [issues](https://github.com/vishal-codes/react-widgets/issues) section. 21 | 22 |
23 | 24 | ## Project Maintainers 🛠 25 | 26 |
27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
github profile
Vishal Shinde

Web Developer
github profile
Saksham Gurbhele

Android Developer
36 |
37 | 38 | ## Valuable Contributors👩‍💻👨‍💻 : 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/components/pages/Dropdown.js: -------------------------------------------------------------------------------- 1 | import React, {useState, useEffect, useRef} from "react"; 2 | 3 | const Dropdown = ({options, selected, onSelectedChange, label, demo}) => { 4 | const [open, setOpen] = useState(false); 5 | const ref = useRef(); 6 | // console.log(open); 7 | 8 | useEffect(() => { 9 | 10 | const onBodyClick = (event) => { 11 | if(ref.current.contains(event.target)){ 12 | return; 13 | } 14 | setOpen(false); 15 | // console.log("Body ", open); 16 | }; 17 | 18 | document.body.addEventListener("click", onBodyClick,{ 19 | capture:true 20 | }); 21 | 22 | return () => { 23 | document.body.removeEventListener("click", onBodyClick, { 24 | capture: true, 25 | }); 26 | } 27 | },[]); 28 | 29 | const renderedOptions = options.map((option)=>{ 30 | if(option.value === selected.value){ 31 | return null; 32 | } 33 | return( 34 |
{ 38 | onSelectedChange(option); 39 | // console.log("Each item ",open); 40 | }} 41 | > 42 | {option.label} 43 |
44 | ); 45 | }); 46 | 47 | return( 48 |
49 | 50 |
51 |

52 |
{ 54 | // console.log("Before Dropdown ",open); 55 | setOpen(!open); 56 | }} 57 | className={`ui selection dropdown ${open ? 'visible active' : ''}`} 58 | > 59 | 60 |
61 | {selected.label} 62 |
63 |
66 | {renderedOptions} 67 |
68 |
69 |
70 |

73 | {demo} 74 |

75 |
76 | ); 77 | } 78 | 79 | export default Dropdown; -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | - Using welcoming and inclusive language 18 | - Being respectful of differing viewpoints and experiences 19 | - Gracefully accepting constructive criticism 20 | - Focusing on what is best for the community 21 | - Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | - The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | - Trolling, insulting/derogatory comments, and personal or political attacks 28 | - Public or private harassment 29 | - Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | - Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## My Responsibilities 35 | 36 | Project maintainer(me) is responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainer has the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainer. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the me at itsvishal2417@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. I am 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | 65 | ## Attribution 66 | 67 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 68 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 69 | 70 | [homepage]: https://www.contributor-covenant.org 71 | 72 | For answers to common questions about this code of conduct, see 73 | https://www.contributor-covenant.org/faq 74 | -------------------------------------------------------------------------------- /src/components/pages/TextUtils.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | 3 | // Buttons Style 4 | const btnStyle = { 5 | backgroundColor: "#0d6efd", 6 | color: "white", 7 | padding: "12px", 8 | borderRadius: "8px", 9 | marginRight: "10px", 10 | cursor: "pointer" 11 | } 12 | 13 | // TextArea Style 14 | const TextAreaStyle = { 15 | backgroundColor: "white", 16 | color:"black", 17 | width: "715px", 18 | resize:"none", 19 | borderRadius: "6px", 20 | fontSize: "20px", 21 | marginBottom: "7px" 22 | } 23 | 24 | // Alert Component 25 | function Alert(props) { 26 | const capitalize =(word)=>{ 27 | const lower = word.toLowerCase(); 28 | return lower.charAt(0).toUpperCase() + lower.slice(1); 29 | } 30 | 31 | return ( 32 | props.alert &&
33 | {capitalize(props.alert.type)} : {props.alert.msg} 34 |
35 | ); 36 | } 37 | 38 | // TextForm Component 39 | function TextForm(props) { 40 | 41 | const handleUpClick = () => { 42 | let newText = text.toUpperCase(); 43 | setText(newText); 44 | props.showAlert("Converted to UPPERCASE","success"); 45 | } 46 | 47 | const handleLowClick = () => { 48 | let newText = text.toLowerCase(); 49 | setText(newText); 50 | props.showAlert("Converted to lowercase","success"); 51 | } 52 | 53 | const handleClearClick = () => { 54 | let newText = ''; 55 | setText(newText); 56 | props.showAlert("Text Cleard!","success"); 57 | } 58 | 59 | const handleCopy = () => { 60 | let text = document.getElementById("myBox"); 61 | text.select(); 62 | navigator.clipboard.writeText(text.value); 63 | props.showAlert("Copied to Clipboard!","success"); 64 | } 65 | 66 | const handleExtraSpaces = () => { 67 | let newText = text.split(/[ ]+/); 68 | setText(newText.join(" ")) 69 | props.showAlert("Extra spaces Removed!","success"); 70 | } 71 | 72 | const handleOnChange = (event) => { 73 | setText(event.target.value); 74 | } 75 | 76 | const [text,setText] = useState('') 77 | 78 | return ( 79 | <> 80 |
81 |

{props.heading}

82 |
83 | 84 |
85 | 86 | 87 | 88 | 89 | 90 |
91 |
92 |

Your Text Summary

93 |

{text.split(" ").length} Words and {text.length} Characters

94 |

{0.008 * text.split(" ").length} Minutes read

95 |

Preview

96 |

{text.length>0 ? text:"Enter Something in the Text Box Above To Preview It Here ..."}

97 |
98 | 99 | ); 100 | } 101 | 102 | const TextUtils = () => { 103 | 104 | const [alert, setAlert] = useState(null); 105 | 106 | const showAlert=(message,type)=>{ 107 | setAlert({ 108 | msg: message, 109 | type: type 110 | }) 111 | setTimeout(() => { 112 | setAlert(null); 113 | }, 2000); 114 | } 115 | 116 | return ( 117 | <> 118 |

TextUtils : A Way To Analyze Your Text Quickly And Efficiently.

119 | 120 | 121 | 122 | ); 123 | } 124 | 125 | export default TextUtils; -------------------------------------------------------------------------------- /src/components/pages/Search.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { createMarkup, debounce } from '../../commons/utils'; 3 | import axios from 'axios'; 4 | 5 | const Search = () => { 6 | 7 | const [results, setResults] = useState([]); 8 | const [errorInfo, setErrorInfo] = useState({ 9 | isShow: false, 10 | message: '', 11 | code: '', 12 | moreInfo: '', 13 | }) 14 | 15 | const search = async (term) => { 16 | // check whether the search sentence exists or not 17 | if (term) { 18 | const { data } = await axios.get('https://en.wikipedia.org/w/api.php', { 19 | params: { 20 | action: 'query', 21 | list: 'search', 22 | origin: '*', 23 | format: 'json', 24 | srsearch: term 25 | }, 26 | }); 27 | // cek result from fetch api 28 | if (data.hasOwnProperty("error")) { 29 | // result is error 30 | setErrorInfo({ 31 | isShow: true, 32 | message: data.error.info, 33 | code: data.error.code, 34 | moreInfo: data.error["*"], 35 | }); 36 | setResults([]); 37 | } else { 38 | // result is success 39 | setResults(data.query.search); 40 | } 41 | } else { 42 | // clear state results 43 | setResults([]); 44 | } 45 | }; 46 | 47 | const onSearchInputChange = debounce(function (event) { 48 | search(event.target.value); 49 | errorInfo.isShow && handleClearErrorInfo(); // clear state errorInfo 50 | }, 1000); 51 | 52 | const handleClearErrorInfo = () => { 53 | setErrorInfo({ 54 | isShow: false, 55 | message: '', 56 | code: '', 57 | moreInfo: '', 58 | }); 59 | } 60 | 61 | const renderedResults = results.map((result) => { 62 | return ( 63 |
64 |
65 | 66 | GO 67 | 68 |
69 |
70 |
71 | {result.title} 72 |
73 | 74 |
75 |
76 | ); 77 | }); 78 | 79 | return ( 80 |
81 |
82 |
83 | 84 | 85 | onSearchInputChange(event)} 87 | className="input" 88 | placeholder="Search awesome term" 89 | /> 90 |
91 |
92 | {errorInfo.isShow && ( 93 |
94 |
95 | 96 |
97 | There were some errors with your submission 98 |
99 |
    100 |
  • Error Message: {errorInfo.message}
  • 101 |
  • Error Code: {errorInfo.code}
  • 102 |
  • See More Details: 103 | 104 |
  • 105 |
106 |
107 |
108 | )} 109 |
110 | {!errorInfo.isShow && 111 | <> 112 |

Found: {results.length} {results.length < 1 ? 'result' : 'results'}

113 | {renderedResults} 114 | 115 | } 116 |
117 |
118 | ); 119 | 120 | }; 121 | 122 | export default Search; -------------------------------------------------------------------------------- /src/data/translateOptions.js: -------------------------------------------------------------------------------- 1 | export const translateOptions = [ 2 | 3 | { 4 | label: 'Afrikaans', 5 | value: 'af' 6 | }, 7 | { 8 | label: 'Albanian', 9 | value: 'sq' 10 | }, 11 | { 12 | label: 'Amharic', 13 | value: 'am' 14 | }, 15 | { 16 | label: 'Arabic', 17 | value: 'ar' 18 | }, 19 | { 20 | label: 'Armenian', 21 | value: 'hy' 22 | }, 23 | { 24 | label: 'Azerbaijani', 25 | value: 'az' 26 | }, 27 | { 28 | label: 'Basque', 29 | value: 'eu' 30 | }, 31 | { 32 | label: 'Belarusian', 33 | value: 'be', 34 | }, 35 | { 36 | label: 'Bengali', 37 | value: 'bn' 38 | }, 39 | { 40 | label: 'Bosnian', 41 | value: 'bs' 42 | }, 43 | { 44 | label: 'Bulgarian', 45 | value: 'bg' 46 | }, 47 | { 48 | label: 'Catalan', 49 | value: 'ca' 50 | }, 51 | { 52 | label: 'Croatian', 53 | value: 'hr' 54 | }, 55 | { 56 | label: 'Czech', 57 | value: 'cs' 58 | }, 59 | { 60 | label: 'Danish', 61 | value: 'da' 62 | }, 63 | { 64 | label: 'Dutch', 65 | value: 'nl' 66 | }, 67 | { 68 | label: 'English', 69 | value: 'en' 70 | }, 71 | { 72 | label: 'Esperanto', 73 | value: 'eo' 74 | }, 75 | { 76 | label: 'Finnish', 77 | value: 'fi' 78 | }, 79 | { 80 | label: 'French', 81 | value: 'fr' 82 | }, 83 | { 84 | label: 'Frisian', 85 | value: 'fy' 86 | }, 87 | { 88 | label: 'Galician', 89 | value: 'gl' 90 | }, 91 | { 92 | label: 'German', 93 | value: 'de' 94 | }, 95 | { 96 | label: 'Gujarati', 97 | value: 'gu' 98 | }, 99 | { 100 | label: 'Hausa', 101 | value: 'ha' 102 | }, 103 | { 104 | label: 'Hindi', 105 | value: 'hi', 106 | }, 107 | { 108 | label: 'Indonesian', 109 | value: 'id' 110 | }, 111 | { 112 | label: 'Igbo', 113 | value: 'ig' 114 | }, 115 | { 116 | label: 'Italian', 117 | value: 'it' 118 | }, 119 | { 120 | label: 'Japanese', 121 | value: 'ja' 122 | }, 123 | { 124 | label: 'Khmer', 125 | value: 'km' 126 | }, 127 | { 128 | label: 'Korean', 129 | value: 'ko' 130 | }, 131 | { 132 | label: 'Kurdish', 133 | value: 'ku' 134 | }, 135 | { 136 | label: 'Kyrgyz', 137 | value: 'ky' 138 | }, 139 | { 140 | label: 'Latvian', 141 | value: 'lv' 142 | }, 143 | { 144 | label: 'Luxembourgish', 145 | value: 'lb' 146 | }, 147 | { 148 | label: 'Malayalam', 149 | value: 'ml' 150 | }, 151 | { 152 | label: 'Nepali', 153 | value: 'ne' 154 | }, 155 | { 156 | label: 'Norwegian', 157 | value: 'no' 158 | }, 159 | { 160 | label: 'Persian', 161 | value: 'fa' 162 | }, 163 | { 164 | label: 'Polish', 165 | value: 'pl' 166 | }, 167 | { 168 | label: 'Punjabi', 169 | value: 'pa' 170 | }, 171 | { 172 | label: 'Russian', 173 | value: 'ru' 174 | }, 175 | { 176 | label: 'Serbian', 177 | value: 'sr' 178 | }, 179 | { 180 | label: 'Sesotho', 181 | value: 'st' 182 | }, 183 | { 184 | label: 'Sinhala', 185 | value: 'si' 186 | }, 187 | { 188 | label: 'Slovenian', 189 | value: 'sl' 190 | }, 191 | { 192 | label: 'Somalia', 193 | value: 'so' 194 | }, 195 | { 196 | label: 'Spanish', 197 | value: 'es' 198 | }, 199 | { 200 | label: 'Swahili', 201 | value: 'sw' 202 | }, 203 | { 204 | label: 'Swedish', 205 | value: 'sv' 206 | }, 207 | { 208 | label: 'Tagalog (Filipino)', 209 | value: 'tl' 210 | }, 211 | { 212 | label: 'Tajik', 213 | value: 'tg' 214 | }, 215 | { 216 | label: 'Tamil', 217 | value: 'ta' 218 | }, 219 | { 220 | label: 'Telugu', 221 | value: 'te' 222 | }, 223 | { 224 | label: 'Turkish', 225 | value: 'tr' 226 | }, 227 | { 228 | label: 'Urdu', 229 | value: 'ur' 230 | }, 231 | { 232 | label: 'Uyghur', 233 | value: 'ug' 234 | }, 235 | { 236 | label: 'Uzbek', 237 | value: 'uz' 238 | }, 239 | { 240 | label: 'Vietnamese', 241 | value: 'vi' 242 | }, 243 | { 244 | label: 'Welsh', 245 | value: 'cy' 246 | }, 247 | { 248 | label: 'Xhosa', 249 | value: 'xh' 250 | }, 251 | { 252 | label: 'Yiddish', 253 | value: 'yi' 254 | }, 255 | { 256 | label: 'Yoruba', 257 | value: 'yo' 258 | }, 259 | { 260 | label: 'Zulu', 261 | value: 'zu' 262 | }, 263 | 264 | ]; 265 | -------------------------------------------------------------------------------- /src/data/colorOptions.js: -------------------------------------------------------------------------------- 1 | export const colorOptions = [ 2 | 3 | { 4 | label: 'AntiqueWhite', 5 | value: 'AntiqueWhite', 6 | }, 7 | { 8 | label: 'Aqua', 9 | value: 'Aqua', 10 | }, 11 | { 12 | label: 'Aquamarine', 13 | value: 'Aquamarine', 14 | }, 15 | { 16 | label: 'Blue', 17 | value: 'Blue', 18 | }, 19 | { 20 | label: 'BlueViolet', 21 | value: 'BlueViolet', 22 | }, 23 | { 24 | label: 'Brown', 25 | value: 'Brown', 26 | }, 27 | { 28 | label: 'CadetBlue', 29 | value: 'CadetBlue', 30 | }, 31 | { 32 | label: 'Chartreuse', 33 | value: 'Chartreuse', 34 | }, 35 | { 36 | label: 'Chocolate', 37 | value: 'Chocolate', 38 | }, 39 | { 40 | label: 'Coral', 41 | value: 'Coral', 42 | }, 43 | { 44 | label: 'CornflowerBlue', 45 | value: 'CornflowerBlue', 46 | }, 47 | { 48 | label: 'Crimson', 49 | value: 'Crimson', 50 | }, 51 | { 52 | label: 'Cyan', 53 | value: 'Cyan', 54 | }, 55 | { 56 | label: 'DarkBlue', 57 | value: 'DarkBlue', 58 | }, 59 | { 60 | label: 'DarkCyan', 61 | value: 'DarkCyan', 62 | }, 63 | { 64 | label: 'DarkGoldenRed', 65 | value: 'DarkGoldenRed', 66 | }, 67 | { 68 | label: 'DarkGray', 69 | value: 'DarkGray', 70 | }, 71 | { 72 | label: 'DarkGreen', 73 | value: 'DarkGreen', 74 | }, 75 | { 76 | label: 'DarkKhaki', 77 | value: 'DarkKhaki', 78 | }, 79 | { 80 | label: 'DarkMagenta', 81 | value: 'DarkMagenta', 82 | }, 83 | { 84 | label: 'DarkOliveGreen', 85 | value: 'DarkOliveGreen', 86 | }, 87 | { 88 | label: 'DarkOrange', 89 | value: 'DarkOrange', 90 | }, 91 | { 92 | label: 'DarkOrchid', 93 | value: 'DarkOrchid', 94 | }, 95 | { 96 | label: 'DarkRed', 97 | value: 'Darkred', 98 | }, 99 | { 100 | label: 'DarkSlateBlue', 101 | value: 'DarkSlateBlue', 102 | }, 103 | { 104 | label: 'DarkSalmon', 105 | value: 'DarkSalmon', 106 | }, 107 | { 108 | label: 'DarkTurquoise', 109 | value: 'DarkTurquoise', 110 | }, 111 | { 112 | label: 'DarkViolet', 113 | value: 'DarkViolet', 114 | }, 115 | { 116 | label: 'DeepPink', 117 | value: 'DeepPink', 118 | }, 119 | { 120 | label: 'DeepSkyBlue', 121 | value: 'DeepSkyBlue', 122 | }, 123 | { 124 | label: 'DimGray', 125 | value: 'DimGray', 126 | }, 127 | { 128 | label: 'DodgerBlue', 129 | value: 'DodgerBlue', 130 | }, 131 | { 132 | label: 'ForestGreen', 133 | value: 'ForestGreen', 134 | }, 135 | { 136 | label: 'Fuchsia', 137 | value: 'Fuchsia', 138 | }, 139 | { 140 | label: 'Gold', 141 | value: 'Gold', 142 | }, 143 | { 144 | label: 'Green', 145 | value: 'Green', 146 | }, 147 | { 148 | label: 'GreenYellow', 149 | value: 'GreenYellow', 150 | }, 151 | { 152 | label: 'Grey', 153 | value: 'Grey', 154 | }, 155 | { 156 | label: 'HotPink', 157 | value: 'HotPink', 158 | }, 159 | { 160 | label: 'IndigoRed', 161 | value: 'IndigoRed', 162 | }, 163 | { 164 | label: 'Indigo', 165 | value: 'Indigo', 166 | }, 167 | { 168 | label: 'Khaki', 169 | value: 'Khaki', 170 | }, 171 | { 172 | label: 'Lavender', 173 | value: 'Lavender', 174 | }, 175 | { 176 | label: 'LightBlue', 177 | value: 'LightBlue', 178 | }, 179 | { 180 | label: 'LightCoral', 181 | value: 'LightCoral', 182 | }, 183 | { 184 | label: 'LightGreen', 185 | value: 'LightGreen', 186 | }, 187 | { 188 | label: 'LightPink', 189 | value: 'LightPink', 190 | }, 191 | { 192 | label: 'LightSalmon', 193 | value: 'LightSalmon', 194 | }, 195 | { 196 | label: 'LightSeaGreen', 197 | value: 'LightSeaGreen', 198 | }, 199 | { 200 | label: 'Lime', 201 | value: 'Lime', 202 | }, 203 | { 204 | label: 'Linen', 205 | value: 'Linen', 206 | }, 207 | { 208 | label: 'Magenta', 209 | value: 'Magenta', 210 | }, 211 | { 212 | label: 'Maroon', 213 | value: 'Maroon', 214 | }, 215 | { 216 | label: 'MediumBlue', 217 | value: 'MediumBlue', 218 | }, 219 | { 220 | label: 'MidnightBlue', 221 | value: 'MidnightBlue', 222 | }, 223 | { 224 | label: 'NavajoWhite', 225 | value: 'NavajoWhite', 226 | }, 227 | { 228 | label: 'Navy', 229 | value: 'Navy', 230 | }, 231 | { 232 | label: 'Olive', 233 | value: 'Olive', 234 | }, 235 | { 236 | label: 'OrangeRed', 237 | value: 'OrangeRed', 238 | }, 239 | { 240 | label: 'Orchid', 241 | value: 'Orchid', 242 | }, 243 | { 244 | label: 'PaleGreen', 245 | value: 'PaleGreen', 246 | }, 247 | { 248 | label: 'PaleVioletRed', 249 | value: 'PaleVioletRed', 250 | }, 251 | { 252 | label: 'Peach', 253 | value: 'Peach', 254 | }, 255 | { 256 | label: 'Peru', 257 | value: 'Peru', 258 | }, 259 | { 260 | label: 'Pink', 261 | value: 'Pink', 262 | }, 263 | { 264 | label: 'Plum', 265 | value: 'Plum', 266 | }, 267 | { 268 | label: 'Purple', 269 | value: 'Purple', 270 | }, 271 | { 272 | label: 'Red', 273 | value: 'Red', 274 | }, 275 | { 276 | label: 'SandyBrown', 277 | value: 'SandyBrown', 278 | }, 279 | { 280 | label: 'Silver', 281 | value: 'Silver', 282 | }, 283 | { 284 | label: 'Snow', 285 | value: 'Snow', 286 | }, 287 | { 288 | label: 'Teal', 289 | value: 'Teal', 290 | }, 291 | { 292 | label: 'Tomato', 293 | value: 'Tomato', 294 | }, 295 | { 296 | label: 'Turquoise', 297 | value: 'Turquoise', 298 | }, 299 | 300 | { 301 | label: 'Violet', 302 | value: 'Violet', 303 | }, 304 | { 305 | label: 'WhiteSmoke', 306 | value: 'WhiteSmoke', 307 | }, 308 | { 309 | label: 'Yellow', 310 | value: 'Yellow', 311 | }, 312 | { 313 | label: 'YellowGreen', 314 | value: 'YellowGreen', 315 | }, 316 | 317 | ]; 318 | --------------------------------------------------------------------------------