mirror of
https://github.com/vercel/commerce.git
synced 2025-07-29 05:01:22 +00:00
🔀 merge: Merge branch 'common' of https://github.com/KieIO/grocery-vercel-commerce into common
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import classNames from 'classnames'
|
||||
import React, { memo } from 'react'
|
||||
import { ButonType, ButtonSize } from 'src/utils/constanst.utils'
|
||||
import s from './ButtonCommon.module.scss'
|
||||
|
||||
interface Props {
|
||||
|
@@ -0,0 +1,5 @@
|
||||
.navigation_wrapper{
|
||||
@apply relative;
|
||||
min-height: theme("caroucel.arrow-height") ;
|
||||
|
||||
}
|
57
src/components/common/CarouselCommon/CarouselCommon.tsx
Normal file
57
src/components/common/CarouselCommon/CarouselCommon.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import { useKeenSlider } from 'keen-slider/react'
|
||||
import React from 'react'
|
||||
import 'keen-slider/keen-slider.min.css'
|
||||
import { CustomCarouselArrow } from './CustomArrow/CustomCarouselArrow';
|
||||
import s from "./CaroucelCommon.module.scss"
|
||||
interface CarouselCommonProps {
|
||||
children?: React.ReactNode
|
||||
data?: any[]
|
||||
Component: React.ComponentType<any>
|
||||
isArrow?:Boolean
|
||||
itemKey:String
|
||||
}
|
||||
|
||||
const CarouselCommon = ({ data, Component,itemKey }: CarouselCommonProps) => {
|
||||
const [currentSlide, setCurrentSlide] = React.useState(0)
|
||||
const [sliderRef, slider] = useKeenSlider<HTMLDivElement>({
|
||||
slidesPerView: 1,
|
||||
initial: 0,
|
||||
slideChanged(s) {
|
||||
setCurrentSlide(s.details().relativeSlide)
|
||||
},
|
||||
})
|
||||
const handleRightArrowClick = () => {
|
||||
slider.next()
|
||||
}
|
||||
|
||||
const handleLeftArrowClick = () => {
|
||||
slider.prev()
|
||||
}
|
||||
return (
|
||||
<div className={s.navigation_wrapper}>
|
||||
<div ref={sliderRef} className="keen-slider">
|
||||
{data?.map((props,index) => (
|
||||
<div className="keen-slider__slide" key={`${itemKey}-${index}`}>
|
||||
<Component {...props} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{slider && (
|
||||
<>
|
||||
<CustomCarouselArrow
|
||||
side="right"
|
||||
onClick={handleRightArrowClick}
|
||||
isDisabled={currentSlide === slider.details().size - 1}
|
||||
/>
|
||||
<CustomCarouselArrow
|
||||
side="left"
|
||||
onClick={handleLeftArrowClick}
|
||||
isDisabled={currentSlide === 0}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default CarouselCommon
|
@@ -0,0 +1,17 @@
|
||||
.custom_arrow{
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
&:focus{
|
||||
outline: none;
|
||||
}
|
||||
@apply absolute top-1/2 bg-background-arrow transform -translate-y-1/2 flex justify-center items-center transition duration-100;
|
||||
&.left{
|
||||
@apply left-0;
|
||||
}
|
||||
&.right{
|
||||
@apply right-0;
|
||||
}
|
||||
&.isDisabled{
|
||||
@apply hidden ;
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
import classNames from 'classnames'
|
||||
import React from 'react'
|
||||
import ArrowLeft from 'src/components/icons/ArrowLeft'
|
||||
import ArrowRight from 'src/components/icons/ArrowRight'
|
||||
import s from "./CustomCarouselArrow.module.scss"
|
||||
interface CustomCarouselArrowProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
side: 'left' | 'right'
|
||||
isDisabled:Boolean
|
||||
}
|
||||
|
||||
export const CustomCarouselArrow = ({
|
||||
side,isDisabled,
|
||||
...props
|
||||
}: CustomCarouselArrowProps) => {
|
||||
return (
|
||||
<button
|
||||
{...props}
|
||||
className={classNames(`${s.custom_arrow}`, { [`${s[side]}`]: side,[`${s.isDisabled}`]:isDisabled })}
|
||||
>
|
||||
{side==='left'?(<ArrowLeft/>):(<ArrowRight/>)}
|
||||
</button>
|
||||
)
|
||||
}
|
43
src/components/common/LabelCommon/LabelCommon.module.scss
Normal file
43
src/components/common/LabelCommon/LabelCommon.module.scss
Normal file
@@ -0,0 +1,43 @@
|
||||
.labelCommonWarper{
|
||||
display: inline-flex;
|
||||
align-items: flex-start;
|
||||
font-weight: bold;
|
||||
letter-spacing: 0.01em;
|
||||
@apply text-white text-right;
|
||||
&.defaultSize{
|
||||
min-height: 2rem;
|
||||
line-height: 2rem;
|
||||
font-size: 1.2rem;
|
||||
padding: 0 0.8rem;
|
||||
}
|
||||
&.largeSize{
|
||||
max-height: 2.4rem;
|
||||
line-height: 2.4rem;
|
||||
font-size: 1.6rem;
|
||||
padding: 0 1.8rem;
|
||||
}
|
||||
&.defaultType{
|
||||
@apply bg-positive-dark;
|
||||
}
|
||||
&.discountType{
|
||||
@apply bg-negative;
|
||||
}
|
||||
&.waitingType{
|
||||
@apply bg-warning;
|
||||
}
|
||||
&.deliveringType{
|
||||
@apply bg-info;
|
||||
}
|
||||
&.deliveredType{
|
||||
@apply bg-positive;
|
||||
}
|
||||
&.defaultShape{
|
||||
border-radius: 0.4rem;
|
||||
}
|
||||
&.halfShape{
|
||||
border-radius: 0px 1.4rem 1.4rem 0px;
|
||||
}
|
||||
&.roundShape{
|
||||
border-radius: 1.4rem;
|
||||
}
|
||||
}
|
30
src/components/common/LabelCommon/LabelCommon.tsx
Normal file
30
src/components/common/LabelCommon/LabelCommon.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import classNames from 'classnames'
|
||||
import React from 'react'
|
||||
import s from './LabelCommon.module.scss'
|
||||
interface LabelCommonProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
size?: 'default' | 'large'
|
||||
shape?: 'half' | 'round' | 'default'
|
||||
type?: 'default' | 'discount' | 'waiting' | 'delivering' | 'delivered'
|
||||
color?: string
|
||||
}
|
||||
|
||||
const LabelCommon = ({
|
||||
size = 'default',
|
||||
type = 'default',
|
||||
shape = "default",
|
||||
children,
|
||||
}: LabelCommonProps) => {
|
||||
return (
|
||||
<div
|
||||
className={classNames(s.labelCommonWarper, {
|
||||
[s[`${size}Size`]]: size,
|
||||
[s[`${type}Type`]]: type,
|
||||
[s[`${shape}Shape`]]: shape,
|
||||
})}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default LabelCommon
|
@@ -0,0 +1,39 @@
|
||||
@import '../../../styles/utilities';
|
||||
.quanittyInputWarper{
|
||||
border-color: theme("textColor.active");
|
||||
@apply border border-solid inline-flex justify-between items-center custom-border-radius;
|
||||
.plusIcon, .minusIcon{
|
||||
&:hover{
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
&.default{
|
||||
max-width: 18.4rem;
|
||||
min-height: 4rem;
|
||||
.plusIcon, .minusIcon{
|
||||
margin: 0.8rem;
|
||||
width: 2.4rem;
|
||||
height: 2.4rem;
|
||||
}
|
||||
}
|
||||
&.small{
|
||||
max-width: 10rem;
|
||||
min-height: 2.8rem;
|
||||
.plusIcon, .minusIcon{
|
||||
margin: 0 0.6rem;
|
||||
// width: 1rem;
|
||||
// height: 1rem;
|
||||
}
|
||||
}
|
||||
.quanittyInput{
|
||||
@apply bg-background outline-none w-1/2 text-center h-full font-bold;
|
||||
font-size: 20px;
|
||||
line-height: 28px;
|
||||
color: theme("textColor.active");
|
||||
&::-webkit-inner-spin-button, &::-webkit-inner-spin-button{
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
83
src/components/common/QuanittyInput/QuanittyInput.tsx
Normal file
83
src/components/common/QuanittyInput/QuanittyInput.tsx
Normal file
@@ -0,0 +1,83 @@
|
||||
import React, { ChangeEvent, useEffect, useState } from 'react'
|
||||
import s from './QuanittyInput.module.scss'
|
||||
import classNames from 'classnames'
|
||||
import { Minus, Plus } from '@components/icons'
|
||||
interface QuanittyInputProps
|
||||
extends Omit<
|
||||
React.InputHTMLAttributes<HTMLInputElement>,
|
||||
'onChange' | 'min' | 'max' | 'step' | "type" | "size"
|
||||
> {
|
||||
size?: 'default' | 'small'
|
||||
onChange?: (value: number) => void
|
||||
initValue?: number
|
||||
min?: number
|
||||
max?: number
|
||||
step?: number
|
||||
}
|
||||
|
||||
const QuanittyInput = ({
|
||||
size = 'default',
|
||||
onChange,
|
||||
initValue = 0,
|
||||
min,
|
||||
max,
|
||||
step = 1,
|
||||
...props
|
||||
}: QuanittyInputProps) => {
|
||||
const [value, setValue] = useState<number>(0)
|
||||
|
||||
useEffect(() => {
|
||||
onChange && onChange(value)
|
||||
}, [value])
|
||||
|
||||
useEffect(() => {
|
||||
initValue && setValue(initValue)
|
||||
}, [initValue])
|
||||
|
||||
const onPlusClick = () => {
|
||||
if (max && value + step > max) {
|
||||
setValue(max)
|
||||
} else {
|
||||
setValue(value + step)
|
||||
}
|
||||
}
|
||||
|
||||
const onMinusClick = () => {
|
||||
if (min && value - step < min) {
|
||||
setValue(min)
|
||||
} else {
|
||||
setValue(value - step)
|
||||
}
|
||||
}
|
||||
|
||||
const onValueChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
let value = Number(e.target.value) || 0
|
||||
if (min && value < min) {
|
||||
setValue(min)
|
||||
} else if (max && value > max) {
|
||||
setValue(max)
|
||||
} else {
|
||||
setValue(value)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classNames(s.quanittyInputWarper, { [s[size]]: size })}>
|
||||
<div className={s.minusIcon} onClick={onMinusClick}>
|
||||
<Minus />
|
||||
</div>
|
||||
<input
|
||||
{...props}
|
||||
type="number"
|
||||
value={value}
|
||||
onChange={onValueChange}
|
||||
className={s.quanittyInput}
|
||||
/>
|
||||
<div className={s.plusIcon} onClick={onPlusClick}>
|
||||
<Plus />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default QuanittyInput
|
@@ -1,5 +1,8 @@
|
||||
export { default as ButtonCommon } from './ButtonCommon/ButtonCommon'
|
||||
export { default as Layout } from './Layout/Layout'
|
||||
export { default as CarouselCommon } from './CarouselCommon/CarouselCommon'
|
||||
export { default as QuanittyInput } from './QuanittyInput/QuanittyInput'
|
||||
export { default as LabelCommon } from './LabelCommon/LabelCommon'
|
||||
export { default as Head } from './Head/Head'
|
||||
export { default as ViewAllItem} from './ViewAllItem/ViewAllItem'
|
||||
export { default as ItemWishList} from './ItemWishList/ItemWishList'
|
||||
|
Reference in New Issue
Block a user