├── README.md ├── Wordart ├── index.jsx └── style.css ├── clock ├── index.jsx └── style.css ├── iconInput ├── index.jsx └── style.css ├── imageInput ├── index.jsx └── style.css ├── itemList ├── index.jsx └── style.css ├── searchBar ├── index.jsx └── style.css ├── select-search ├── index.jsx └── style.css ├── switch ├── index.jsx └── style.css └── table ├── index.jsx └── style.css /README.md: -------------------------------------------------------------------------------- 1 |

React-Components

2 |

It has some React components I built in my previous jobs

3 |

I hope you can get some help here

4 |

Let's make our git community richer

5 |

Thanks

6 | -------------------------------------------------------------------------------- /Wordart/index.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * REACT WORDART EDITOR 3 | * @author Victor Philamon & Jiners Enoheart 4 | * @published Feb 01, 2023 5 | * @modified Jul 06, 2023 6 | */ 7 | 8 | import React from "react" 9 | import { Editor } from "react-draft-wysiwyg" 10 | import "react-draft-wysiwyg/dist/react-draft-wysiwyg.css" 11 | import "./style.css" 12 | 13 | /** 14 | * Method to load file into 15 | * @param {string} path 16 | * @returns Promise to read file 17 | */ 18 | export default (props) => { 19 | if (!props.Contents) return <> 20 | 21 | const onEditorStateChange = state => props.setContents ? props.setContents(state) : false 22 | 23 | return 35 | } -------------------------------------------------------------------------------- /Wordart/style.css: -------------------------------------------------------------------------------- 1 | .rdw-editor-wrapper { 2 | display: flex; 3 | flex-direction: column; 4 | justify-content: center; 5 | } 6 | 7 | .rdw-editor-main { 8 | width: 100%; 9 | min-height: 5em; 10 | } 11 | 12 | .rdw-option-wrapper[title="Embedded"], 13 | .rdw-option-wrapper[title="Image"], 14 | .rdw-option-wrapper[title="Remove"] { 15 | display: none; 16 | } 17 | 18 | .rdw-colorpicker-wrapper { 19 | order: 1; 20 | } 21 | .rdw-inline-wrapper { 22 | order: 2; 23 | } 24 | .rdw-block-wrapper { 25 | order: 3; 26 | } 27 | .rdw-fontsize-wrapper { 28 | order: 4; 29 | } 30 | .rdw-fontfamily-wrapper { 31 | order: 5; 32 | } 33 | .rdw-list-wrapper { 34 | order: 6; 35 | } 36 | .rdw-text-align-wrapper { 37 | order: 7; 38 | } 39 | .rdw-link-wrapper { 40 | order: 8; 41 | } 42 | .rdw-emoji-wrapper { 43 | order: 9; 44 | } 45 | .rdw-history-wrapper { 46 | order: 10; 47 | } 48 | -------------------------------------------------------------------------------- /clock/index.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @description Component as Home page 3 | * @author Jiners Enoheart 4 | * @published June 09, 2023 5 | * @modified June 09, 2023 6 | */ 7 | 8 | import React from "react" 9 | import { now } from "../../../resource/time" 10 | import "./style.css" 11 | 12 | class Clock extends React.Component { 13 | constructor() { 14 | super() 15 | this.state = { 16 | time: [now("d H"), now("M"), now("N D, Y")], 17 | timerID: setInterval(() => 18 | this.setState({ time: [now("d H"), now("M"), now("N D, Y")] }), 30000) 19 | } 20 | } 21 | 22 | componentWillUnmount() { 23 | clearInterval(this.state.timerID) 24 | } 25 | 26 | render = () =>
27 |
28 | {this.state.time[0]} 29 | : 30 | {this.state.time[1]} 31 |
32 |
{this.state.time[2]}
33 |
34 | } 35 | 36 | export default Clock -------------------------------------------------------------------------------- /clock/style.css: -------------------------------------------------------------------------------- 1 | .clock { 2 | text-align: center; 3 | font-size: 1em; 4 | font-weight: bold; 5 | } 6 | 7 | @keyframes fading { 8 | from { 9 | opacity: 0; 10 | } 11 | to { 12 | opacity: 1; 13 | } 14 | } 15 | 16 | .symbol { 17 | animation-name: fading; 18 | animation-duration: 1s; 19 | animation-iteration-count: infinite; 20 | } 21 | -------------------------------------------------------------------------------- /iconInput/index.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @description Input text with ICON 3 | * @author Jiners Enoheart 4 | * @published June 02, 2023 5 | * @modified June 02, 2023 6 | */ 7 | 8 | import React, { useRef, useEffect } from "react" 9 | import "./style.css" 10 | 11 | export default (props) => { 12 | const input = useRef(null) 13 | 14 | /** 15 | * Function to get all the valid chars from val: ex: 0->9a->9 16 | * ex: 0->9 => 0123456789 17 | * @param {string} valid 18 | */ 19 | const calcValid = (valid) => { 20 | if (!valid) return 21 | let i = 0, j, k, before, after, direction = 1, temp 22 | 23 | while ((i = valid.indexOf("->")) > 0) { 24 | before = valid.substring(0, i) 25 | after = valid.substring(i + 2) 26 | j = valid.charAt(i - 1).charCodeAt(0) 27 | k = valid.charAt(i + 2).charCodeAt(0) 28 | direction = j < k ? 1 : -1 29 | temp = "" 30 | for (j = j + 1; j !== k; j += direction) temp += String.fromCharCode(j) 31 | valid = before + temp + after 32 | } 33 | return valid 34 | } 35 | let valid = calcValid(props.valid) 36 | 37 | // catch enter keyCode and handle login method recieved as props 38 | const keyDown = (event) => 39 | event.keyCode === 13 && props.handler !== undefined ? props.handler() : false 40 | 41 | //Function to check input valid 42 | const keyPress = (evt) => 43 | valid ? valid.indexOf(evt.key) >= 0 ? true : evt.preventDefault() 44 | : props.invalid ? props.invalid.indexOf(evt.key) >= 0 ? evt.preventDefault() : true 45 | : true 46 | 47 | useEffect(() => { 48 | if (props.bind) props.bind(input.current) 49 | }) 50 | 51 | useEffect(() => { 52 | if (props.autoFocus && !props.readOnly) input.current.focus() 53 | }, [props.autoFocus, props.readOnly]) 54 | 55 | return
56 | props.onChange(e.target.value)} 60 | readOnly={props.readOnly ? true : false} 61 | ref={input} 62 | /> 63 | 64 | {props.tooltip ? {props.message} : ""} 65 |
66 | }; 67 | -------------------------------------------------------------------------------- /iconInput/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | .icon-input { 6 | position: relative; 7 | } 8 | 9 | .icon-input > input { 10 | border: none; 11 | outline: none; 12 | font-size: 0.75em; 13 | padding: 0.2em; 14 | padding-left: 2.2em; 15 | border-radius: 0.2em; 16 | width: 100%; 17 | } 18 | 19 | .icon-input > i { 20 | position: absolute; 21 | left: 0.2em; 22 | top:0.2em; 23 | } -------------------------------------------------------------------------------- /imageInput/index.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @description Image Input Component 3 | * @published Jan 31, 2023 4 | * @modified Jun 16, 2023 5 | * @author Davies Martines & Jiners Enoheart 6 | */ 7 | 8 | import React, { useRef } from "react" 9 | import "./style.css" 10 | 11 | export default (props) => { 12 | const reader = new FileReader() //Processor loading image 13 | const image = useRef() 14 | const file = useRef() 15 | 16 | /** 17 | * @description function to apply buffer of image file 18 | * @param {object} event 19 | */ 20 | reader.onload = (event) => { 21 | image.current.src = event.target.result 22 | if (props.buffer) props.buffer(event.target.result) 23 | } 24 | 25 | /** 26 | * Action processor when click on component 27 | */ 28 | const handleInputFile = () => file.current.click() 29 | 30 | /** 31 | * Processor when change its image 32 | */ 33 | const handleChangeFile = () => { 34 | if (file.current.files[0]) { 35 | reader.readAsDataURL(file.current.files[0]) 36 | if (props.onChange) props.onChange(file.current.files[0]) 37 | } 38 | } 39 | 40 | return ( 41 |
42 | ... 44 | 46 |
47 | ); 48 | }; 49 | -------------------------------------------------------------------------------- /imageInput/style.css: -------------------------------------------------------------------------------- 1 | .image-input { 2 | position: relative; 3 | margin: auto; 4 | } 5 | 6 | .image-input img { 7 | width: 100%; 8 | height: 100%; 9 | border: none; 10 | border-radius: 50%; 11 | padding: 0.2em; 12 | cursor: pointer; 13 | } 14 | 15 | .image-input .desc { 16 | text-align: center; 17 | position: absolute; 18 | top: 50%; 19 | left: 50%; 20 | visibility: hidden; 21 | } 22 | 23 | .image-input input[type="file"] { 24 | display: none; 25 | } 26 | 27 | .image-input:hover img { 28 | opacity: 0.5; 29 | } 30 | 31 | .image-input:hover desc { 32 | visibility: visible; 33 | } 34 | -------------------------------------------------------------------------------- /itemList/index.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @description Item-list component 3 | * @author Jiners Enoheart 4 | * @published Jul 07, 2023 5 | * @modified Jul 16, 2023 6 | */ 7 | 8 | import React, { useState, useEffect } from "react" 9 | import "./style.css" 10 | 11 | export default (props) => { 12 | let nothing =
Nothing yet
13 | if (!props.Data || props.Data <= 0) 14 | return nothing 15 | 16 | const [PageNo, setPageNo] = useState(props.PageNo) 17 | if (props.PageCount < PageNo) setPageNo(1) 18 | 19 | useEffect((PageNo) => { 20 | if(props.PageNo !== PageNo) setPageNo(props.PageNo) 21 | }, [props.PageNo]) 22 | 23 | return
24 |
25 | {props.Data.map((item, index) => 26 | props.Method.Render ? props.Method.Render(item, index) : "...")} 27 |
28 | {props.StatusEl ? props.StatusEl : " "} 29 |
30 | 31 | PageNo > 1 ? (setPageNo(1), props.Method.Refresh(1)) : false} /> 32 | PageNo > 1 ? (setPageNo(PageNo - 1), props.Method.Refresh(PageNo - 1)) : false} /> 34 | setPageNo(evt.target.value)} 36 | onKeyPress={(evt) => evt.key >= '0' && evt.key <= '9' ? true : evt.preventDefault()} 37 | onKeyDown={(evt) => { 38 | if (evt.keyCode === 13) { 39 | let pn = evt.target.value < 1 ? 1 : 40 | evt.target.value > props.PageCount ? 41 | props.PageCount : 42 | evt.target.value 43 | setPageNo(pn) 44 | if (props.Method.Refresh) props.Method.Refresh(pn) 45 | } 46 | }} /> 47 |  /  48 | {props.PageCount ? props.PageCount : 0} 49 | 50 | PageNo < props.PageCount ? 51 | (setPageNo(PageNo + 1), props.Method.Refresh(parseInt(PageNo) + 1)) : 52 | false} /> 53 | 55 | PageNo < props.PageCount ? 56 | (setPageNo(props.PageCount), props.Method.Refresh(props.PageCount)) : 57 | false} /> 58 |
59 |
60 | } -------------------------------------------------------------------------------- /itemList/style.css: -------------------------------------------------------------------------------- 1 | .item-list { 2 | flex-grow: 100; 3 | display: flex; 4 | flex-direction: column; 5 | } 6 | 7 | .nothing { 8 | text-align: center; 9 | font-weight: bold; 10 | font-size: 1em; 11 | } 12 | 13 | .item-list > .list { 14 | display: flex; 15 | flex-direction: row; 16 | flex-wrap: wrap; 17 | flex-grow: 100; 18 | } 19 | 20 | .item-list > .pagenation { 21 | padding-top: 0.5em; 22 | padding-bottom: 0.2em; 23 | text-align: center; 24 | font-size: 0.8em; 25 | } 26 | 27 | .item-list > .pagenation input { 28 | text-align: center; 29 | width: 3em; 30 | } 31 | 32 | .item-list > .pagenation i { 33 | cursor: pointer; 34 | } 35 | 36 | .item-list .item .header > span { 37 | float: left; 38 | font-size: 1em; 39 | width: calc(100% - 1.2em); 40 | height: 1.2em; 41 | overflow: hidden; 42 | cursor: pointer; 43 | } 44 | 45 | .item-list .item .date { 46 | font-size: 0.5em; 47 | font-weight: bold; 48 | text-align: right; 49 | } 50 | 51 | .item-list .item .header > i { 52 | font-size: 0.8em; 53 | font-weight: bold; 54 | float: right; 55 | cursor: pointer; 56 | } 57 | -------------------------------------------------------------------------------- /searchBar/index.jsx: -------------------------------------------------------------------------------- 1 | import React, { useRef } from "react" 2 | import "./style.css" 3 | 4 | export default (props) => { 5 | const input = useRef(null) 6 | 7 | return
8 | props.setSearch ? props.setSearch(evt.target.value) : false} 10 | onKeyDown={(evt) => evt.keyCode === 13 && props.doing ? props.doing() : false} 11 | placeholder={props.placeholder ? props.placeholder : ""} /> 12 | props.doing ? props.doing() : false} /> 14 |
15 | } -------------------------------------------------------------------------------- /searchBar/style.css: -------------------------------------------------------------------------------- 1 | .search-bar { 2 | width: 100%; 3 | } 4 | 5 | .search-bar input { 6 | font-size: 1em; 7 | width: calc(100% - 1.5em); 8 | } 9 | 10 | 11 | -------------------------------------------------------------------------------- /select-search/index.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Jiners Enoheart 3 | * @published Jun 27, 2023 4 | * @modified Jun 27, 2023 5 | * @description Component as select with function to search by text input 6 | */ 7 | 8 | import React, { useState, useRef, useEffect } from "react" 9 | import "./style.css" 10 | 11 | export default (props) => { 12 | let selectedItem = props.list && props.value ? props.list.find(item => item.value === props.value) : null 13 | const [search, setSearch] = useState(selectedItem ? selectedItem.Name : "") 14 | const [typing, setTyping] = useState(false) 15 | const [visibleList, setVisibleList] = useState(false) 16 | let input = useRef() 17 | 18 | useEffect(() => { 19 | if (props.bind) props.bind(input.current) 20 | if (!typing && !props.value) setSearch("") 21 | }, [props, typing, setSearch]) 22 | 23 | return
24 |
25 |
26 | {!props.value ? : 27 | selectedItem ? 28 | selectedItem.img ? 29 | ... : 30 | 31 | : ""} 32 |
33 |
34 | { 37 | setSearch(evt.target.value) 38 | setVisibleList(true) 39 | }} 40 | onFocus={() => { 41 | setTyping(true) 42 | setVisibleList(true) 43 | }} 44 | onClick={() => setVisibleList(true)} 45 | onBlur={(evt) => { 46 | setTyping(false) 47 | if (!evt.target.value && props.onChange) props.onChange() 48 | }} /> 49 |
50 | 51 |
52 |
53 | 54 |
55 | 56 |
setVisibleList(false)}> 58 |
{ 60 | if (props.onChange) props.onChange() 61 | setSearch("") 62 | setVisibleList(false) 63 | }} 64 | > 65 | { } {"..."} 66 |
67 | {props.list && props.list.length > 0 68 | ? props.list.filter(item => search ? 69 | item.Name.toLowerCase().indexOf(search.toLowerCase()) >= 0 : 70 | true) 71 | .map((item, index) => { 72 | let icon = item.img ? ... : 73 | 74 | return
{ 76 | if (props.onChange) props.onChange(item.value) 77 | setSearch(item.Name) 78 | setVisibleList(false) 79 | }} 80 | key={`item-${index}`}> 81 | {icon} {item.Name} 82 |
83 | }) 84 | : '' 85 | } 86 |
87 |
88 | } -------------------------------------------------------------------------------- /select-search/style.css: -------------------------------------------------------------------------------- 1 | .select-search { 2 | position: relative; 3 | } 4 | 5 | .select-search .header input { 6 | width: 100%; 7 | text-align: center; 8 | } 9 | 10 | .select-search .list { 11 | max-height: 6em; 12 | overflow: auto; 13 | position: absolute; 14 | top: 1.2em; 15 | width: 100%; 16 | } 17 | 18 | .select-search .header i { 19 | cursor: pointer; 20 | } 21 | 22 | .select-search .header img { 23 | height: 1.1em; 24 | width: 1.1em; 25 | } 26 | 27 | .select-search .header i:hover { 28 | opacity: 0.9; 29 | } 30 | 31 | .select-search .header input { 32 | padding: 0px; 33 | border: none; 34 | outline: none; 35 | font-size: 1em; 36 | background: none; 37 | } 38 | 39 | .select-search .list img { 40 | border-radius: 50%; 41 | height: 1.5em; 42 | } 43 | 44 | .select-search .list .item { 45 | cursor: pointer; 46 | } 47 | -------------------------------------------------------------------------------- /switch/index.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import "./style.css" 3 | 4 | export default (props) => { 5 | return
props.set ? props.set(!props.value) : false}> 6 |
8 | {props.icons.true} 9 |
10 |
12 | {props.icons.false}
13 |
14 |
15 | } -------------------------------------------------------------------------------- /switch/style.css: -------------------------------------------------------------------------------- 1 | .switch { 2 | width: 70px; 3 | height: 20px; 4 | font-weight: bold; 5 | cursor: pointer; 6 | border-radius: 10px; 7 | padding: 2px; 8 | } 9 | 10 | .switch div { 11 | width: 50%; 12 | height: 16px; 13 | display: flex; 14 | justify-content: center; 15 | align-items: center; 16 | font-size: 12px; 17 | } 18 | 19 | .switch div:nth-child(1) { 20 | border-radius: 8px 0px 0px 8px; 21 | float: left; 22 | } 23 | 24 | .switch div:nth-child(2) { 25 | border-radius: 0px 8px 8px 0px; 26 | float: right; 27 | } 28 | -------------------------------------------------------------------------------- /table/index.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @description Table component 3 | * @author Jiners Enoheart 4 | * @published June 02, 2023 5 | * @modified June 16, 2023 6 | */ 7 | 8 | import React, { useState } from "react" 9 | import "./style.css" 10 | 11 | export default (props) => { 12 | let nothing =
 
13 | if (!props || !props.Field || !Array.isArray(props.Field)) 14 | return nothing 15 | 16 | const [PageNo, setPageNo] = useState(props.PageNo) 17 | 18 | return 19 | 20 | 21 | 25 | 26 | {props.Field.map((item, index) => { 27 | return 55 | })} 56 | 60 | 61 | 62 | 64 | 65 | {props.Field.map((item, index) => item.Searchable ? 66 | : 82 | )} 83 | 85 | 86 | 87 | 88 | 89 | {props.Data && Array.isArray(props.Data) && props.Data.length > 0 ? 90 | props.Data.map((item, index) => 91 | 94 | 96 | {props.Field.map((field, n) => 97 | )} 108 | 112 | ) : 113 | 114 | 115 | } 116 | {props.StatusEl ? 117 | : 120 | } 121 | 122 | 126 | 152 | 156 | 157 | 158 |
22 | 24 |  No 28 | {item.Name} 29 | {item.Order && props.Order ? 30 | item.Key ? 31 | Array.isArray(item.Key) ? 32 | !props.Order[item.Key[0]] || props.Order[item.Key[0]] === 'ASC' ? 33 | < i className="icon-down-dir" onClick={() => 34 | props.Method && props.Method.SetOrder ? 35 | props.Method.SetOrder(item.Key[0], 'DESC') : false} /> : 36 | < i className="icon-up-dir" onClick={() => 37 | props.Method && props.Method.SetOrder ? 38 | props.Method.SetOrder(item.Key[0], 'ASC') : false} /> : 39 | !props.Order[item.Key] || props.Order[item.Key] === 'ASC' ? 40 | < i className="icon-down-dir" onClick={() => 41 | props.Method && props.Method.SetOrder ? 42 | props.Method.SetOrder(item.Key, 'DESC') : false} /> : 43 | < i className="icon-up-dir" onClick={() => 44 | props.Method && props.Method.SetOrder ? 45 | props.Method.SetOrder(item.Key, 'ASC') : false} /> : 46 | !props.Order[item.Name] || props.Order[item.Name] === 'ASC' ? 47 | < i className="icon-down-dir" onClick={() => 48 | props.Method && props.Method.SetOrder ? 49 | props.Method.SetOrder(item.Name, 'DESC') : false} /> : 50 | < i className="icon-up-dir" onClick={() => 51 | props.Method && props.Method.SetOrder ? 52 | props.Method.SetOrder(item.Name, 'ASC') : false} /> : 53 | ""} 54 | 57 | 59 |
63 | props.Method.Refresh ? (props.Method.Refresh(1), setPageNo(1)) : false} /> 67 | {item.Type === "select" ? 68 | : 78 | props.Method.SetSearch ? 79 | props.Method.SetSearch(item.Key ? Array.isArray(item.Key) ? item.Key[0] : item.Key : item.Name, 80 | evt.target.value) : false} />} 81 | 84 | props.Method.Refresh ? (props.Method.Refresh(1), setPageNo(1)) : false} />
{props.Method.Edit ? 92 | props.Method.Edit(index, item.ID)} /> : <>} 93 | 95 | {(props.PageNo - 1) * props.CountPerPage + index + 1} 98 | {field.Render ? 99 | field.Render(Array.isArray(field.Key) ? 100 | field.Key.map(id => item[id]) : 101 | field.Key ? 102 | item[field.Key] : 103 | item[field.Name]) : 104 | field.Key ? 105 | item[field.Key] : 106 | item[field.Name]} 107 | {props.Method.Delete ? 109 | props.Method.Delete(index, item.ID)} /> : 110 | props.Method.Edit ? 111 | props.Method.Edit(index, item.ID)} /> : ""}
None
118 | {props.StatusEl ? props.StatusEl : " "} 119 |
123 | 125 | 127 | 128 | PageNo > 1 ? (setPageNo(1), props.Method.Refresh(1)) : false} /> 129 | PageNo > 1 ? (setPageNo(PageNo - 1), props.Method.Refresh(PageNo - 1)) : false} /> 131 | setPageNo(evt.target.value)} 133 | onKeyPress={(evt) => evt.key >= '0' && evt.key <= '9' ? true : evt.preventDefault()} 134 | onKeyDown={(evt) => { 135 | if (evt.keyCode === 13) { 136 | let pn = evt.target.value < 1 ? 1 : 137 | evt.target.value > props.PageCount ? 138 | props.PageCount : 139 | evt.target.value 140 | setPageNo(pn) 141 | if (props.Method.Refresh) props.Method.Refresh(pn) 142 | } 143 | }} 144 | /> 145 |  /  146 | {props.PageCount ? props.PageCount : 0} 147 | 148 | PageNo < props.PageCount ? (setPageNo(PageNo + 1), props.Method.Refresh(PageNo + 1)) : false} /> 149 | 150 | PageNo < props.PageCount ? (setPageNo(props.PageCount), props.Method.Refresh(props.PageCount)) : false} /> 151 | 153 | 155 |
159 | } -------------------------------------------------------------------------------- /table/style.css: -------------------------------------------------------------------------------- 1 | table.itct { 2 | border-radius: 0.45em; 3 | width: 100%; 4 | } 5 | 6 | table.itct td { 7 | margin: 0.1em; 8 | } 9 | 10 | table.itct thead td { 11 | font-size: 0.75em; 12 | font-weight: bold; 13 | text-align: center; 14 | } 15 | 16 | table.itct thead td input { 17 | width: 100%; 18 | font-size: 0.8em; 19 | text-align: center; 20 | } 21 | 22 | table.itct i { 23 | cursor: pointer; 24 | } 25 | 26 | table.itct i:hover { 27 | opacity: 0.75; 28 | } 29 | 30 | table.itct .status, 31 | table.itct .pagenation { 32 | font-size: 0.9em; 33 | background: none; 34 | } 35 | 36 | table.itct .PageInput { 37 | padding: 0px 0.1em 0px 0.1em; 38 | } 39 | --------------------------------------------------------------------------------