@ -1,59 +1,3 @@ |
|||||||
.App { |
body{ |
||||||
text-align: center; |
|
||||||
direction: rtl; |
direction: rtl; |
||||||
padding: 10px; |
|
||||||
} |
|
||||||
|
|
||||||
.App-logo { |
|
||||||
height: 40vmin; |
|
||||||
pointer-events: none; |
|
||||||
} |
|
||||||
|
|
||||||
.en { |
|
||||||
direction: ltr; |
|
||||||
text-align: left; |
|
||||||
} |
|
||||||
|
|
||||||
.fa { |
|
||||||
direction: rtl; |
|
||||||
text-align: right; |
|
||||||
} |
|
||||||
|
|
||||||
@media (prefers-reduced-motion: no-preference) { |
|
||||||
.App-logo { |
|
||||||
animation: App-logo-spin infinite 20s linear; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/* clears the ‘X’ from Internet Explorer */ |
|
||||||
input[type=search]::-ms-clear { display: none; width : 0; height: 0; } |
|
||||||
input[type=search]::-ms-reveal { display: none; width : 0; height: 0; } |
|
||||||
/* clears the ‘X’ from Chrome */ |
|
||||||
input[type="search"]::-webkit-search-decoration, |
|
||||||
input[type="search"]::-webkit-search-cancel-button, |
|
||||||
input[type="search"]::-webkit-search-results-button, |
|
||||||
input[type="search"]::-webkit-search-results-decoration { display: none; } |
|
||||||
|
|
||||||
.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); |
|
||||||
} |
|
||||||
} |
} |
@ -0,0 +1,51 @@ |
|||||||
|
import React from "react"; |
||||||
|
import { connect } from "react-redux"; |
||||||
|
import Code from "../../../components/Code"; |
||||||
|
|
||||||
|
function Main({ activeComponent }) { |
||||||
|
return ( |
||||||
|
<div className="lg:flex lg:flex-col lg:w-5/6 lg:h-full border-r border-gray-200"> |
||||||
|
<header className="w-full flex flex-row items-center h-16 px-1 py-4 bg-gray-700"></header> |
||||||
|
<section className="w-full lg:overflow-y-scroll py-5 px-10 flex-1 flex-col"> |
||||||
|
<h1 className="font-bold text-3xl mb-10 text-left"> |
||||||
|
{activeComponent?.content?.name} |
||||||
|
</h1> |
||||||
|
{activeComponent?.content?.component} |
||||||
|
{activeComponent?.content?.code && ( |
||||||
|
<Code code={activeComponent?.content?.code} /> |
||||||
|
)} |
||||||
|
{/* <h2>Props</h2> */} |
||||||
|
{activeComponent?.props?.length > 0 && ( |
||||||
|
<table className="w-full" style={{ direction: "ltr" }}> |
||||||
|
<thead> |
||||||
|
<tr> |
||||||
|
<th className="font-bold text-lg">Name</th> |
||||||
|
<th className="font-bold text-lg">Type</th> |
||||||
|
<th className="font-bold text-lg">Required</th> |
||||||
|
<th className="font-bold text-lg">Default value</th> |
||||||
|
<th className="font-bold text-lg">Description</th> |
||||||
|
</tr> |
||||||
|
</thead> |
||||||
|
<tbody className="w-full divided divide-y"> |
||||||
|
{activeComponent?.props?.map((prop, index) => ( |
||||||
|
<tr key={index} className=""> |
||||||
|
<td className="py-3 text-center">{prop.name}</td> |
||||||
|
<td className="py-3 text-center">{prop.type}</td> |
||||||
|
<td className="py-3 text-center">{prop.required}</td> |
||||||
|
<td className="py-3 text-center">{prop.defaultValue}</td> |
||||||
|
<td className="py-3 text-center">{prop.description}</td> |
||||||
|
</tr> |
||||||
|
))} |
||||||
|
</tbody> |
||||||
|
</table> |
||||||
|
)} |
||||||
|
</section> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
const mapStateToProps = (state) => ({ |
||||||
|
activeComponent: state.components.activeComponent, |
||||||
|
}); |
||||||
|
|
||||||
|
export default connect(mapStateToProps, {})(Main); |
@ -0,0 +1,119 @@ |
|||||||
|
import React from "react"; |
||||||
|
import { connect } from "react-redux"; |
||||||
|
import { components } from "../../../redux/actions"; |
||||||
|
|
||||||
|
function Sidebar({ list, setActive }) { |
||||||
|
return ( |
||||||
|
<div className="lg:flex lg:flex-col lg:w-1/6 lg:h-full" style={{ direction: 'ltr' }}> |
||||||
|
<header className="w-full flex flex-row items-center h-16 px-1 py-4 bg-gray-700"> |
||||||
|
<img |
||||||
|
src={"https://barnamenegar.ir/static/media/white logo 2.7ffbddbc.svg"} |
||||||
|
alt="logo" |
||||||
|
className="w-full" |
||||||
|
/> |
||||||
|
</header> |
||||||
|
<ul className="w-full flex-1 p-0 m-0 list-none divided divide-y max-h-full lg:overflow-y-scroll divide-blue-100 border-r border-gray-200"> |
||||||
|
{list.map((material, index) => ( |
||||||
|
<li |
||||||
|
key={index} |
||||||
|
className="w-full py-3 px-3 font-medium text-md cursor-pointer h-12" |
||||||
|
onClick={() => setActive(material)} |
||||||
|
> |
||||||
|
{material.name} |
||||||
|
</li> |
||||||
|
))} |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
const mapStateToProps = (state) => ({ |
||||||
|
list: state.components.list, |
||||||
|
}); |
||||||
|
|
||||||
|
export default connect(mapStateToProps, { |
||||||
|
setActive: components.activeComponent, |
||||||
|
})(Sidebar); |
||||||
|
|
||||||
|
Sidebar.defaultProps = { |
||||||
|
materials: [ |
||||||
|
{ |
||||||
|
name: "Button", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "TextInput", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Search", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Radio", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Check Box", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Select Box", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Category", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Tag", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Slider", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Counters", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Features", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Calendar", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Date Picker", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Alert", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Reaction", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Step", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Vote Status", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Comment", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Info Box", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Quote", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Blog", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Percent", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Chart", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Bottom Navigation", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Navbar", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Product", |
||||||
|
}, |
||||||
|
], |
||||||
|
}; |
@ -0,0 +1,16 @@ |
|||||||
|
import React from "react"; |
||||||
|
import Sidebar from "./Sidebar"; |
||||||
|
import Main from "./Main"; |
||||||
|
|
||||||
|
function Home() { |
||||||
|
return ( |
||||||
|
<div className="flex lg:w-full lg:flex-col lg:h-screen lg:overflow-hidden"> |
||||||
|
<div className="lg:w-full h-full lg:flex lg:flex-row"> |
||||||
|
<Main /> |
||||||
|
<Sidebar /> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
export default Home; |
@ -0,0 +1,11 @@ |
|||||||
|
import React from 'react' |
||||||
|
|
||||||
|
function Alert() { |
||||||
|
return ( |
||||||
|
<div> |
||||||
|
|
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default Alert; |
After Width: | Height: | Size: 658 B |
After Width: | Height: | Size: 642 B |
After Width: | Height: | Size: 658 B |
After Width: | Height: | Size: 385 B |
@ -0,0 +1,139 @@ |
|||||||
|
import React from "react"; |
||||||
|
|
||||||
|
import whiteLeftArrow from "./white-left-arrow.svg"; |
||||||
|
import whiteRightArrow from "./white-right-arrow.svg"; |
||||||
|
import whiteUpwardArrow from "./white-upward-arrow.svg"; |
||||||
|
import whiteDownwardArrow from "./white-downward-arrow.svg"; |
||||||
|
|
||||||
|
import blackRightArrow from "./black-right-arrow.svg"; |
||||||
|
import blackLeftArrow from "./black-left-arrow.svg"; |
||||||
|
import blackUpwardArrow from "./black-upward-arrow.png"; |
||||||
|
import blackDownwardArrow from "./black-downward-arrow.svg"; |
||||||
|
|
||||||
|
const Button = ({ |
||||||
|
buttonBgColor, |
||||||
|
circleArrowBgClr, |
||||||
|
buttonTextColor, |
||||||
|
buttonBorder, |
||||||
|
buttonBorderColor, |
||||||
|
buttonBorderRadius, |
||||||
|
imageMarginRight, |
||||||
|
imageWidth, |
||||||
|
imageHeight, |
||||||
|
// icons
|
||||||
|
leftArrowWhite, |
||||||
|
rightArrowWhite, |
||||||
|
upwardArrowWhite, |
||||||
|
downwardArrowWhite, |
||||||
|
leftArrowBlack, |
||||||
|
rightArrowBlack, |
||||||
|
upwardArrowBlack, |
||||||
|
downwardArrowBlack, |
||||||
|
circleArrow, |
||||||
|
}) => { |
||||||
|
return ( |
||||||
|
<button |
||||||
|
className={`flex items-center border-none cursor-pointer py-2.5 px-2 text-sm ${buttonBgColor} ${buttonTextColor} ${buttonBorder} ${buttonBorderColor} ${buttonBorderRadius}`} |
||||||
|
> |
||||||
|
اطلاعات بیشتر |
||||||
|
{leftArrowWhite && ( |
||||||
|
<img |
||||||
|
src={whiteLeftArrow} |
||||||
|
alt="" |
||||||
|
className={`${imageMarginRight} ${imageWidth} ${imageHeight} `} |
||||||
|
/> |
||||||
|
)} |
||||||
|
{rightArrowWhite && ( |
||||||
|
<img |
||||||
|
src={whiteRightArrow} |
||||||
|
alt="" |
||||||
|
className={`${imageMarginRight} ${imageWidth} ${imageHeight} `} |
||||||
|
/> |
||||||
|
)} |
||||||
|
{upwardArrowWhite && ( |
||||||
|
<img |
||||||
|
src={whiteUpwardArrow} |
||||||
|
alt="" |
||||||
|
className={`${imageMarginRight} ${imageWidth} ${imageHeight} `} |
||||||
|
/> |
||||||
|
)} |
||||||
|
{downwardArrowWhite && ( |
||||||
|
<img |
||||||
|
src={whiteDownwardArrow} |
||||||
|
alt="" |
||||||
|
className={`${imageMarginRight} ${imageWidth} ${imageHeight} `} |
||||||
|
/> |
||||||
|
)} |
||||||
|
{leftArrowBlack && ( |
||||||
|
<img |
||||||
|
src={blackLeftArrow} |
||||||
|
alt="" |
||||||
|
className={`${imageMarginRight} ${imageWidth} ${imageHeight} `} |
||||||
|
/> |
||||||
|
)} |
||||||
|
{rightArrowBlack && ( |
||||||
|
<img |
||||||
|
src={blackRightArrow} |
||||||
|
alt="" |
||||||
|
className={`${imageMarginRight} ${imageWidth} ${imageHeight} `} |
||||||
|
/> |
||||||
|
)} |
||||||
|
{upwardArrowBlack && ( |
||||||
|
<img |
||||||
|
src={blackUpwardArrow} |
||||||
|
alt="" |
||||||
|
className={`${imageMarginRight} ${imageWidth} ${imageHeight} `} |
||||||
|
/> |
||||||
|
)} |
||||||
|
{downwardArrowBlack && ( |
||||||
|
<img |
||||||
|
src={blackDownwardArrow} |
||||||
|
alt="" |
||||||
|
className={`${imageMarginRight} ${imageWidth} ${imageHeight} `} |
||||||
|
/> |
||||||
|
)} |
||||||
|
{circleArrow && ( |
||||||
|
<span className={`rounded-full p-2 mr-2 ${circleArrowBgClr} `}> |
||||||
|
<img src={whiteLeftArrow} alt="" className="w-4" /> |
||||||
|
</span> |
||||||
|
)} |
||||||
|
</button> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
export default Button; |
||||||
|
|
||||||
|
// color classes that i defined in tailwind.config.js and we can use for text color:
|
||||||
|
// ----> text-grayTextColor
|
||||||
|
// ----> text-white
|
||||||
|
|
||||||
|
// color classes that i defined in tailwind.config.js and we can use for background color:
|
||||||
|
// ----> bg-darkGreenBg
|
||||||
|
// ----> bg-midGrayBgColor
|
||||||
|
|
||||||
|
// color classes that i defined in tailwind.config.js and we can use for border color:
|
||||||
|
// ----> border-lightBlueBorderColor
|
||||||
|
|
||||||
|
Button.defaultProps = { |
||||||
|
buttonBgColor: "bg-darkGreenBg", |
||||||
|
circleArrowBgClr: "bg-darkGreenBg", |
||||||
|
buttonTextColor: "text-white", |
||||||
|
buttonBorder: "border-b-4", |
||||||
|
buttonBorderColor: "border-lightBlueBorderColor", |
||||||
|
buttonBorderRadius: "rounded", |
||||||
|
buttonPaddingX: "px-6", |
||||||
|
buttonPaddingY: "py-4", |
||||||
|
imageMarginRight: "mr-1", |
||||||
|
imageWidth: "w-4", |
||||||
|
imageHeight: "h-4", |
||||||
|
// icons
|
||||||
|
leftArrowWhite: false, |
||||||
|
rightArrowWhite: false, |
||||||
|
upwardArrowWhite: false, |
||||||
|
downwardArrowWhite: false, |
||||||
|
leftArrowBlack: false, |
||||||
|
rightArrowBlack: false, |
||||||
|
upwardArrowBlack: false, |
||||||
|
downwardArrowBlack: false, |
||||||
|
circleArrow: false, |
||||||
|
}; |
After Width: | Height: | Size: 343 B |
After Width: | Height: | Size: 587 B |
After Width: | Height: | Size: 655 B |
After Width: | Height: | Size: 329 B |
@ -0,0 +1,38 @@ |
|||||||
|
import React from "react"; |
||||||
|
import { |
||||||
|
CircularProgressbar, |
||||||
|
buildStyles, |
||||||
|
CircularProgressbarWithChildren, |
||||||
|
} from "react-circular-progressbar"; |
||||||
|
|
||||||
|
function CustomCircularProgressbar() { |
||||||
|
const percentage = 66; |
||||||
|
|
||||||
|
return ( |
||||||
|
<> |
||||||
|
<div style={{ width: 200, height: 200 }}> |
||||||
|
<CircularProgressbar value={percentage} text={`${percentage}%`} /> |
||||||
|
</div> |
||||||
|
<div style={{ width: 200, height: 200, marginTop : 20 }}> |
||||||
|
<CircularProgressbarWithChildren |
||||||
|
value={80} |
||||||
|
styles={buildStyles({ |
||||||
|
pathColor: "#f00", |
||||||
|
trailColor: "transparent", |
||||||
|
// strokeLinecap: "butt",
|
||||||
|
})} |
||||||
|
> |
||||||
|
<CircularProgressbar |
||||||
|
value={70} |
||||||
|
styles={buildStyles({ |
||||||
|
trailColor: "transparent", |
||||||
|
// strokeLinecap: "butt",
|
||||||
|
})} |
||||||
|
/> |
||||||
|
</CircularProgressbarWithChildren> |
||||||
|
</div> |
||||||
|
</> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
export default CustomCircularProgressbar; |
After Width: | Height: | Size: 7.6 KiB |
@ -0,0 +1,74 @@ |
|||||||
|
import { useState } from "react"; |
||||||
|
import copyIcon from "./copy.png"; |
||||||
|
|
||||||
|
function Code({ code }) { |
||||||
|
const [copied, setCopied] = useState(false); |
||||||
|
const [height, setHeight] = useState(350); |
||||||
|
const copyToClipboard = () => { |
||||||
|
setCopied(true); |
||||||
|
let copyText = document.getElementById(code).innerText; |
||||||
|
/* Select the text field */ |
||||||
|
// copyText.setSelectionRange(0, 99999); /* For mobile devices */
|
||||||
|
|
||||||
|
/* Copy the text inside the text field */ |
||||||
|
navigator.clipboard.writeText(copyText); |
||||||
|
}; |
||||||
|
return ( |
||||||
|
<div className="flex flex-col w-full my-10"> |
||||||
|
<div className="w-full flex flex-row items-center justify-between"> |
||||||
|
<div className="flex flex-row items-center"> |
||||||
|
<img |
||||||
|
src={copyIcon} |
||||||
|
alt="copy" |
||||||
|
className="w-8 h-8 hover:bg-purple-300 p-1 rounded-md ml-2 cursor-pointer" |
||||||
|
onClick={() => copyToClipboard()} |
||||||
|
/> |
||||||
|
<span |
||||||
|
className={`transition-all duration-500 text-md font-medium text-green-600 ${ |
||||||
|
copied ? "opacity-100" : "opacity-0" |
||||||
|
}`}
|
||||||
|
> |
||||||
|
Copied! |
||||||
|
</span> |
||||||
|
</div> |
||||||
|
<div |
||||||
|
className={`font-bold text-lg cursor-pointer ${ |
||||||
|
height === 350 ? "text-blue-500" : "text-red-500" |
||||||
|
}`}
|
||||||
|
onClick={() => setHeight(() => (height == 350 ? "auto" : 350))} |
||||||
|
> |
||||||
|
{height === 350 ? "Read more" : "Close"} |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<pre |
||||||
|
className="bg-gray-900 text-green-200 p-3 rounded-md select-text cursor-pointer relative mt-1 h-72 overflow-y-scroll" |
||||||
|
id={code} |
||||||
|
style={{ height: height, direction: "ltr" }} |
||||||
|
> |
||||||
|
{code} |
||||||
|
</pre> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
Code.defaultProps = { |
||||||
|
code: `class HelloMessage extends React.Component {
|
||||||
|
handlePress = () => { |
||||||
|
alert('Hello') |
||||||
|
} |
||||||
|
render() { |
||||||
|
return ( |
||||||
|
<div> |
||||||
|
<p>Hello {this.props.name}</p> |
||||||
|
<button onClick={this.handlePress}>Say Hello</button> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
ReactDOM.render( |
||||||
|
<HelloMessage name="Taylor" />, |
||||||
|
mountNode |
||||||
|
);`,
|
||||||
|
}; |
||||||
|
|
||||||
|
export default Code; |
@ -0,0 +1,11 @@ |
|||||||
|
import React from 'react' |
||||||
|
|
||||||
|
function Counter({}) { |
||||||
|
return ( |
||||||
|
<div> |
||||||
|
|
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default Counter |
@ -0,0 +1,9 @@ |
|||||||
|
import { Range } from 'rc-slider'; |
||||||
|
|
||||||
|
function RcRange({}) { |
||||||
|
return ( |
||||||
|
<Range /> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default RcRange; |
@ -0,0 +1,32 @@ |
|||||||
|
import React from "react"; |
||||||
|
import { LineChart, XAxis, Tooltip, CartesianGrid, Line } from "recharts"; |
||||||
|
|
||||||
|
function Recharts({ data }) { |
||||||
|
return ( |
||||||
|
<LineChart |
||||||
|
width={400} |
||||||
|
height={400} |
||||||
|
data={data} |
||||||
|
margin={{ top: 5, right: 20, left: 10, bottom: 5 }} |
||||||
|
> |
||||||
|
<XAxis dataKey="name" /> |
||||||
|
<Tooltip /> |
||||||
|
<CartesianGrid stroke="#f5f5f5" /> |
||||||
|
{/* <Line type="monotone" dataKey="uv" stroke="#ff7300" yAxisId={0} /> */} |
||||||
|
<Line type="monotone" dataKey="pv" stroke="#387908" yAxisId={1} /> |
||||||
|
</LineChart> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
export default Recharts; |
||||||
|
|
||||||
|
Recharts.defaultProps = { |
||||||
|
data: [ |
||||||
|
{ name: "", uv: 400, pv: 100, amt: 600 }, |
||||||
|
{ name: "", uv: 400, pv: 200, amt: 500 }, |
||||||
|
{ name: "", uv: 400, pv: 300, amt: 400 }, |
||||||
|
{ name: "", uv: 400, pv: 400, amt: 300 }, |
||||||
|
{ name: "", uv: 400, pv: 500, amt: 200 }, |
||||||
|
{ name: "", uv: 400, pv: 600, amt: 100 }, |
||||||
|
], |
||||||
|
}; |
@ -0,0 +1,8 @@ |
|||||||
|
import React from "react"; |
||||||
|
import Slider from "rc-slider"; |
||||||
|
|
||||||
|
function RcSlider({}) { |
||||||
|
return <Slider />; |
||||||
|
} |
||||||
|
|
||||||
|
export default RcSlider; |
@ -0,0 +1,16 @@ |
|||||||
|
import React, { useState } from "react"; |
||||||
|
import StarRatingComponent from "react-star-rating-component"; |
||||||
|
|
||||||
|
function StarRating() { |
||||||
|
const [rate, setRating] = useState(2); |
||||||
|
return ( |
||||||
|
<StarRatingComponent |
||||||
|
name="rate1" |
||||||
|
starCount={5} |
||||||
|
value={rate} |
||||||
|
onStarHover={(value) => setRating(value)} |
||||||
|
/> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
export default StarRating; |
@ -0,0 +1,84 @@ |
|||||||
|
import React from "react"; |
||||||
|
|
||||||
|
function Stepper({ |
||||||
|
direction, |
||||||
|
activeColor, |
||||||
|
deactiveColor, |
||||||
|
count, |
||||||
|
currentStep, |
||||||
|
}) { |
||||||
|
const array = Array(count); |
||||||
|
return ( |
||||||
|
<div |
||||||
|
className={`flex items-center ${ |
||||||
|
direction === "horizontal" ? "flex-row" : "flex-col" |
||||||
|
}`}
|
||||||
|
> |
||||||
|
{[1,2,3,4,5,6,7].map((item, index) => ( |
||||||
|
<Step |
||||||
|
index={index} |
||||||
|
currentStep={currentStep} |
||||||
|
direction={direction} |
||||||
|
activeColor={activeColor} |
||||||
|
deactiveColor={deactiveColor} |
||||||
|
count={count} |
||||||
|
/> |
||||||
|
))} |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
const Step = ({ |
||||||
|
index, |
||||||
|
currentStep, |
||||||
|
direction, |
||||||
|
activeColor, |
||||||
|
deactiveColor, |
||||||
|
count, |
||||||
|
}) => { |
||||||
|
return ( |
||||||
|
<div |
||||||
|
className={`flex items-center relative ${ |
||||||
|
direction === "horizontal" ? "flex-row" : "flex-col" |
||||||
|
}`}
|
||||||
|
> |
||||||
|
<div |
||||||
|
className="w-12 h-12 text-white text-sm rounded-full flex justify-center items-center" |
||||||
|
style={{ |
||||||
|
backgroundColor: |
||||||
|
currentStep === Number(index) ? activeColor : deactiveColor, |
||||||
|
}} |
||||||
|
> |
||||||
|
{Number(index) + 1} |
||||||
|
</div> |
||||||
|
{count !== (Number(index) + 1) && ( |
||||||
|
<span |
||||||
|
className={`transform ${ |
||||||
|
direction === "horizontal" |
||||||
|
? "w-10 h-1" |
||||||
|
: "h-10 w-1" |
||||||
|
}`}
|
||||||
|
style={{ |
||||||
|
borderTop: direction === "horizontal" ? `2px dotted ${ |
||||||
|
currentStep === Number(index) ? activeColor : deactiveColor |
||||||
|
}` : '',
|
||||||
|
borderRight: direction === "vertical" ? `2px dotted ${ |
||||||
|
currentStep === Number(index) ? activeColor : deactiveColor |
||||||
|
}` : '',
|
||||||
|
transform : `${direction === "horizontal" ? 'translateY(1px)' : 'translateX(-1px)'}` |
||||||
|
}} |
||||||
|
></span> |
||||||
|
)} |
||||||
|
</div> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
export default Stepper; |
||||||
|
|
||||||
|
Stepper.defaultProps = { |
||||||
|
direction: "vertical", |
||||||
|
activeColor: "#06BACE", |
||||||
|
deactiveColor: "#DBDBDB", |
||||||
|
count: 7, |
||||||
|
currentStep : 4, |
||||||
|
}; |
After Width: | Height: | Size: 558 B |
@ -0,0 +1,25 @@ |
|||||||
|
import React from "react"; |
||||||
|
|
||||||
|
import blackCancleIcon from "./black-cancle-icon.svg"; |
||||||
|
|
||||||
|
const ProductTags = ({ titleColor,title, tagBgColor, tagBorderColor, icon }) => { |
||||||
|
return ( |
||||||
|
<button |
||||||
|
className={`flex flex-row items-center rounded border-2 m-1 px-2 py-0.5 text-base ${titleColor} ${tagBorderColor} ${tagBgColor} `} |
||||||
|
> |
||||||
|
{title} |
||||||
|
{icon && <img src={icon} alt="" className="mr-5 w-2.5" />} |
||||||
|
</button> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
export default ProductTags; |
||||||
|
|
||||||
|
ProductTags.defaultProps = { |
||||||
|
title : 'کتاب', |
||||||
|
titleColor: "text-blue-600", |
||||||
|
tagBgColor: "bg-blue-300 bg-opacity-10", |
||||||
|
tagBorderColor: "border-blue-200", |
||||||
|
// for icons
|
||||||
|
icon: blackCancleIcon, |
||||||
|
}; |
@ -0,0 +1,11 @@ |
|||||||
|
import React from 'react' |
||||||
|
|
||||||
|
function Toast({}) { |
||||||
|
return ( |
||||||
|
<div> |
||||||
|
|
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default Toast |
@ -0,0 +1,12 @@ |
|||||||
|
const components = { |
||||||
|
list: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => |
||||||
|
await dispatch({ type: "components/list", data }), |
||||||
|
activeComponent: |
||||||
|
(data = {}) => |
||||||
|
async (dispatch) => |
||||||
|
await dispatch({ type: "components/activeComponent", data }), |
||||||
|
}; |
||||||
|
|
||||||
|
export default components; |
@ -0,0 +1 @@ |
|||||||
|
export { default as components} from './components'; |
@ -0,0 +1,450 @@ |
|||||||
|
import Button from '../components/Button'; |
||||||
|
import Tag from '../components/Tag'; |
||||||
|
import Counter from '../components/Counter'; |
||||||
|
import Input from "../components/Input"; |
||||||
|
import Search from "../components/Search"; |
||||||
|
import SearchWidthSuggest from "../components/search-with-suggest"; |
||||||
|
import Radio from "../components/Radio"; |
||||||
|
import Checkbox from "../components/Checkbox"; |
||||||
|
import SelectRadio from "../components/SelectRadio"; |
||||||
|
import SelectCheckbox from "../components/SelectCheckbox"; |
||||||
|
import Switch from "../components/Switch"; |
||||||
|
import VerticalExpandableProductFilter from "../components/VerticalExpandableProductFilter"; |
||||||
|
import SidebarCategoryHover from "../components/SidebarCategoryHover"; |
||||||
|
import Slider from '../components/Slider'; |
||||||
|
import Range from "../components/Range"; |
||||||
|
import Alert from "../components/Alert"; |
||||||
|
import Toast from "../components/Toast"; |
||||||
|
import StarRating from '../components/StarRating'; |
||||||
|
import Chart from "../components/Recharts"; |
||||||
|
import CircularProgressbar from "../components/CircularProgressbar"; |
||||||
|
import Stepper from "../components/Stepper"; |
||||||
|
|
||||||
|
const components = [ |
||||||
|
{ |
||||||
|
name : "Button", |
||||||
|
props : [ |
||||||
|
|
||||||
|
], |
||||||
|
content : { |
||||||
|
name : "Button", |
||||||
|
component : <Button buttonBgColor="bg-blue-500" />, |
||||||
|
code : null, |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
name : "Tag", |
||||||
|
props : [ |
||||||
|
|
||||||
|
], |
||||||
|
content : { |
||||||
|
name : "Tag", |
||||||
|
component : <Tag />, |
||||||
|
code : null, |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Input", |
||||||
|
props: [ |
||||||
|
{ |
||||||
|
name: "maxLength", |
||||||
|
type: "string", |
||||||
|
required: "false", |
||||||
|
description: "بیشترین تعداد کاراکتری که میتوان استفاده کرد.", |
||||||
|
defaultValue: "", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "lang", |
||||||
|
type: "string", |
||||||
|
required: "false", |
||||||
|
description: "زبان سایت", |
||||||
|
defaultValue: "fa", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "inputMode", |
||||||
|
type: "string", |
||||||
|
required: "false", |
||||||
|
description: "با تعیین این مقدار نوع کیبرد مشخص میشود.", |
||||||
|
defaultValue: "text", |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "label", |
||||||
|
type: "string", |
||||||
|
required: "false", |
||||||
|
description: "", |
||||||
|
defaultValue: "label", |
||||||
|
}, |
||||||
|
], |
||||||
|
content: { |
||||||
|
name: "Input", |
||||||
|
component: <Input />, |
||||||
|
code: `import React, { useState } from "react";
|
||||||
|
import _ from "lodash"; |
||||||
|
import "./index.scss"; |
||||||
|
|
||||||
|
import tick from "./tick.png"; |
||||||
|
import danger from "./danger.png"; |
||||||
|
|
||||||
|
const langDetector = (lang, option1, option2) => { |
||||||
|
return lang === "fa" ? option1 : option2; |
||||||
|
}; |
||||||
|
|
||||||
|
const inputStatusHandler = (value, focus, status, primary, success, danger) => { |
||||||
|
if (!focus) { |
||||||
|
return ""; |
||||||
|
} else { |
||||||
|
if (!value) { |
||||||
|
return primary; |
||||||
|
} else { |
||||||
|
if (status) { |
||||||
|
return success; |
||||||
|
} else { |
||||||
|
return danger; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
export default function Input(props) { |
||||||
|
const [value, setValue] = useState(""); |
||||||
|
const [focusToggle, setFocusToggle] = useState(false); |
||||||
|
|
||||||
|
const { lang, theme, inputMode, label, status, maxLength, message } = props; |
||||||
|
|
||||||
|
const onChange = (val) => { |
||||||
|
setValue(val); |
||||||
|
}; |
||||||
|
|
||||||
|
return ( |
||||||
|
<div |
||||||
|
className={_.join( |
||||||
|
["input flex flex-col relative my-2", langDetector(lang, "fa", "en")], |
||||||
|
" " |
||||||
|
)} |
||||||
|
> |
||||||
|
<label |
||||||
|
className={_.join( |
||||||
|
[ |
||||||
|
"absolute top-1/2 transform -translate-y-1/2 text-gray-500 bg-white px-2 text-xs transition-all duration-300", |
||||||
|
langDetector(lang, "right-2", "left-2"), |
||||||
|
inputStatusHandler( |
||||||
|
value, |
||||||
|
focusToggle, |
||||||
|
status, |
||||||
|
"input__labelFocus", |
||||||
|
"input__labelSuccess", |
||||||
|
"input__labelDanger" |
||||||
|
), |
||||||
|
], |
||||||
|
" " |
||||||
|
)} |
||||||
|
onClick={() => setFocusToggle(true)} |
||||||
|
> |
||||||
|
{label} |
||||||
|
</label> |
||||||
|
<input |
||||||
|
type="text" |
||||||
|
inputMode={inputMode} |
||||||
|
className={_.join( |
||||||
|
[ |
||||||
|
"flex-1 border rounded-md outline-none p-2", |
||||||
|
inputStatusHandler( |
||||||
|
value, |
||||||
|
focusToggle, |
||||||
|
status, |
||||||
|
"input__inputActive", |
||||||
|
"input__inputSuccess", |
||||||
|
"input__inputDanger" |
||||||
|
), |
||||||
|
"transition", |
||||||
|
], |
||||||
|
" " |
||||||
|
)} |
||||||
|
onChange={(e) => onChange(e.target.value)} |
||||||
|
value={value} |
||||||
|
onFocus={() => setFocusToggle(true)} |
||||||
|
onBlur={() => !value ? setFocusToggle(false) : setFocusToggle(true)} |
||||||
|
maxLength={maxLength} |
||||||
|
/> |
||||||
|
{!status && value && ( |
||||||
|
<img |
||||||
|
src={danger} |
||||||
|
alt={langDetector(lang, "اشتباه", "wrong")} |
||||||
|
className={_.join( |
||||||
|
[ |
||||||
|
"w-4 h-4 absolute top-1/2 transform -translate-y-1/2", |
||||||
|
langDetector(lang, "left-2", "right-2"), |
||||||
|
], |
||||||
|
" " |
||||||
|
)} |
||||||
|
/> |
||||||
|
)} |
||||||
|
{status && value && ( |
||||||
|
<img |
||||||
|
src={tick} |
||||||
|
alt={langDetector(lang, "درست", "right")} |
||||||
|
className={_.join( |
||||||
|
[ |
||||||
|
"w-4 h-4 absolute top-1/2 transform -translate-y-1/2", |
||||||
|
langDetector(lang, "left-2", "right-2"), |
||||||
|
], |
||||||
|
" " |
||||||
|
)} |
||||||
|
/> |
||||||
|
)} |
||||||
|
|
||||||
|
{value && !status && ( |
||||||
|
<span |
||||||
|
className={_.join( |
||||||
|
[ |
||||||
|
"input__message text-xs absolute -bottom-5", |
||||||
|
langDetector(lang, "right-2", "left-2"), |
||||||
|
inputStatusHandler( |
||||||
|
value, |
||||||
|
focusToggle, |
||||||
|
status, |
||||||
|
"", |
||||||
|
"input__messageSuccess", |
||||||
|
"input__messageDanger" |
||||||
|
), |
||||||
|
"transition", |
||||||
|
], |
||||||
|
" " |
||||||
|
)} |
||||||
|
> |
||||||
|
{message} |
||||||
|
</span> |
||||||
|
)} |
||||||
|
{value && ( |
||||||
|
<span |
||||||
|
className={_.join( |
||||||
|
[ |
||||||
|
"input__length absolute -bottom-5 text-xs", |
||||||
|
langDetector(lang, "left-2", "right-2"), |
||||||
|
inputStatusHandler( |
||||||
|
value, |
||||||
|
focusToggle, |
||||||
|
status, |
||||||
|
"", |
||||||
|
"input__lengthSuccess", |
||||||
|
"input__lengthDanger" |
||||||
|
), |
||||||
|
"transition", |
||||||
|
], |
||||||
|
" " |
||||||
|
)} |
||||||
|
> |
||||||
|
{value.length + "/" + maxLength} |
||||||
|
</span> |
||||||
|
)} |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
Input.defaultProps = { |
||||||
|
lang : 'fa', |
||||||
|
inputMode : 'string', |
||||||
|
label : '', |
||||||
|
status : '', |
||||||
|
maxLength : '', |
||||||
|
message : '', |
||||||
|
}`,
|
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Search", |
||||||
|
props: [], |
||||||
|
content: { |
||||||
|
name: "Search", |
||||||
|
component: <Search />, |
||||||
|
code: null, |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
name: "Search with suggestion", |
||||||
|
props: [], |
||||||
|
content: { |
||||||
|
name: "Search with suggestion", |
||||||
|
component: <SearchWidthSuggest />, |
||||||
|
code: null, |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
name : "Radio", |
||||||
|
props : [ |
||||||
|
|
||||||
|
], |
||||||
|
content : { |
||||||
|
name : "Radio", |
||||||
|
component : <Radio />, |
||||||
|
code : null, |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
name : "Checkbox", |
||||||
|
props : [ |
||||||
|
|
||||||
|
], |
||||||
|
content : { |
||||||
|
name : "Checkbox", |
||||||
|
component : <Checkbox />, |
||||||
|
code : null, |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
name : "Select box - Radio", |
||||||
|
props : [ |
||||||
|
|
||||||
|
], |
||||||
|
content : { |
||||||
|
name : "Select box - Radio", |
||||||
|
component : <SelectRadio />, |
||||||
|
code : null, |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
name : "Select box - Checkbox", |
||||||
|
props : [ |
||||||
|
|
||||||
|
], |
||||||
|
content : { |
||||||
|
name : "Select box - Checkbox", |
||||||
|
component : <SelectCheckbox />, |
||||||
|
code : null, |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
name : "Switch", |
||||||
|
props : [ |
||||||
|
|
||||||
|
], |
||||||
|
content : { |
||||||
|
name : "Switch", |
||||||
|
component : <Switch />, |
||||||
|
code : null, |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
name : "Expandable products filter", |
||||||
|
props : [ |
||||||
|
|
||||||
|
], |
||||||
|
content : { |
||||||
|
name : "Expandable products filter", |
||||||
|
component : <VerticalExpandableProductFilter />, |
||||||
|
code : null, |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
name : "Sidebar catergory", |
||||||
|
props : [ |
||||||
|
|
||||||
|
], |
||||||
|
content : { |
||||||
|
name : "Sidebar category", |
||||||
|
component : <SidebarCategoryHover />, |
||||||
|
code : null, |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
name : "Slider", |
||||||
|
props : [ |
||||||
|
|
||||||
|
], |
||||||
|
content : { |
||||||
|
name : "Slider", |
||||||
|
component : <Slider />, |
||||||
|
code : null, |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
name : "Range", |
||||||
|
props : [ |
||||||
|
|
||||||
|
], |
||||||
|
content : { |
||||||
|
name : "Range", |
||||||
|
component : <Range />, |
||||||
|
code : null, |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
name : "Counter", |
||||||
|
props : [ |
||||||
|
|
||||||
|
], |
||||||
|
content : { |
||||||
|
name : "Counter", |
||||||
|
component : <Counter />, |
||||||
|
code : null, |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
name : "Alert", |
||||||
|
props : [ |
||||||
|
|
||||||
|
], |
||||||
|
content : { |
||||||
|
name : "Alert", |
||||||
|
component : <Alert />, |
||||||
|
code : null, |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
name : "Toast", |
||||||
|
props : [ |
||||||
|
|
||||||
|
], |
||||||
|
content : { |
||||||
|
name : "Toast", |
||||||
|
component : <Toast />, |
||||||
|
code : null, |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
name : "Star rating", |
||||||
|
props : [ |
||||||
|
|
||||||
|
], |
||||||
|
content : { |
||||||
|
name : "Star rating", |
||||||
|
component : <StarRating />, |
||||||
|
code : null, |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
name : "Chart", |
||||||
|
props : [ |
||||||
|
|
||||||
|
], |
||||||
|
content : { |
||||||
|
name : "Chart", |
||||||
|
component : <Chart />, |
||||||
|
code : null, |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
name : "Circular progressbar", |
||||||
|
props : [ |
||||||
|
|
||||||
|
], |
||||||
|
content : { |
||||||
|
name : "Circular progressbar", |
||||||
|
component : <CircularProgressbar />, |
||||||
|
code : null, |
||||||
|
} |
||||||
|
},
|
||||||
|
{ |
||||||
|
name : "Stepper", |
||||||
|
props : [ |
||||||
|
|
||||||
|
], |
||||||
|
content : { |
||||||
|
name : "Stepper", |
||||||
|
component : <Stepper />, |
||||||
|
code : null, |
||||||
|
} |
||||||
|
},
|
||||||
|
]; |
||||||
|
|
||||||
|
export default components; |
@ -0,0 +1,6 @@ |
|||||||
|
// @create-index
|
||||||
|
|
||||||
|
export { default as actions } from './actions'; |
||||||
|
export { default as reducers } from './reducers'; |
||||||
|
export { default as store } from './store.js'; |
||||||
|
|
@ -0,0 +1,16 @@ |
|||||||
|
import data from '../data'; |
||||||
|
const initialState = { |
||||||
|
list: data, |
||||||
|
activeComponent : {}, |
||||||
|
}; |
||||||
|
export default function components(state = initialState, action) { |
||||||
|
let { type, data } = action; |
||||||
|
switch (type) { |
||||||
|
case "components/list": |
||||||
|
return { ...state, list : data }; |
||||||
|
case "components/activeComponent": |
||||||
|
return {...state, activeComponent : data} |
||||||
|
default: |
||||||
|
return state; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
export { default as components} from './components'; |
@ -0,0 +1,14 @@ |
|||||||
|
import { createStore, applyMiddleware } from 'redux'; |
||||||
|
import { composeWithDevTools } from 'redux-devtools-extension'; |
||||||
|
import { combineReducers } from 'redux'; |
||||||
|
import * as reducers from './reducers'; |
||||||
|
import thunk from 'redux-thunk'; |
||||||
|
const initialState = {}; |
||||||
|
const middleware = [thunk]; |
||||||
|
const store = createStore( |
||||||
|
combineReducers(reducers), |
||||||
|
initialState, |
||||||
|
composeWithDevTools(applyMiddleware(...middleware)) |
||||||
|
); |
||||||
|
export default store; |
||||||
|
|
@ -0,0 +1,45 @@ |
|||||||
|
import React from "react"; |
||||||
|
import { BrowserRouter, Routes, Route } from "react-router-dom"; |
||||||
|
|
||||||
|
import _ from "lodash"; |
||||||
|
import Home from './Views/Home'; |
||||||
|
// import VideoTube from "./views/Home/VideoTube";
|
||||||
|
|
||||||
|
function Router({ isDark }) { |
||||||
|
return ( |
||||||
|
<div className={_.join([isDark ? "dark" : ""], " ")}> |
||||||
|
<div |
||||||
|
className={_.join( |
||||||
|
[ |
||||||
|
"min-h-screen min-w-screen rtl overflow-x-hidden", |
||||||
|
isDark ? "bg-dark" : "bg-white", |
||||||
|
], |
||||||
|
" " |
||||||
|
)} |
||||||
|
> |
||||||
|
<BrowserRouter> |
||||||
|
<Routes> |
||||||
|
<Route path="/" element={<Home />} /> |
||||||
|
{/* <Route path="/vod" element={<VideoTube />} /> */} |
||||||
|
<Route |
||||||
|
path="*" |
||||||
|
element={ |
||||||
|
<main> |
||||||
|
<h1>No matches routes.</h1> |
||||||
|
</main> |
||||||
|
} |
||||||
|
/> |
||||||
|
</Routes> |
||||||
|
</BrowserRouter> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
Router.defaultProps = { |
||||||
|
isDark : false, |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export default Router; |