mirror of
https://github.com/vercel/commerce.git
synced 2025-05-18 15:36:58 +00:00
Merge branch 'main' of https://github.com/vercel/commerce into turbo
This commit is contained in:
commit
0c8c668fdd
@ -146,7 +146,7 @@ If your project was started with a "Deploy with Vercel" button, you can use Verc
|
||||
2. Link local instance with Vercel and Github accounts (creates .vercel file): `vercel link`
|
||||
3. Download your environment variables: `vercel env pull .env.local`
|
||||
|
||||
Next, you're free to customize the starter. More updates coming soon. Stay tuned.
|
||||
Next, you're free to customize the starter. More updates coming soon. Stay tuned..
|
||||
|
||||
</details>
|
||||
|
||||
|
24506
package-lock.json
generated
24506
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -27,15 +27,15 @@ export const handler: MutationHook<LoginHook> = {
|
||||
useHook:
|
||||
({ fetch }) =>
|
||||
() => {
|
||||
const { revalidate } = useCustomer()
|
||||
const { mutate } = useCustomer()
|
||||
|
||||
return useCallback(
|
||||
async function login(input) {
|
||||
const data = await fetch({ input })
|
||||
await revalidate()
|
||||
await mutate()
|
||||
return data
|
||||
},
|
||||
[fetch, revalidate]
|
||||
[fetch, mutate]
|
||||
)
|
||||
},
|
||||
}
|
||||
|
@ -32,15 +32,15 @@ export const handler: MutationHook<SignupHook> = {
|
||||
useHook:
|
||||
({ fetch }) =>
|
||||
() => {
|
||||
const { revalidate } = useCustomer()
|
||||
const { mutate } = useCustomer()
|
||||
|
||||
return useCallback(
|
||||
async function signup(input) {
|
||||
const data = await fetch({ input })
|
||||
await revalidate()
|
||||
await mutate()
|
||||
return data
|
||||
},
|
||||
[fetch, revalidate]
|
||||
[fetch, mutate]
|
||||
)
|
||||
},
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ export const handler: MutationHook<AddItemHook> = {
|
||||
({ fetch }) =>
|
||||
() => {
|
||||
const { data: customer } = useCustomer()
|
||||
const { revalidate } = useWishlist()
|
||||
const { mutate } = useWishlist()
|
||||
|
||||
return useCallback(
|
||||
async function addItem(item) {
|
||||
@ -30,10 +30,10 @@ export const handler: MutationHook<AddItemHook> = {
|
||||
|
||||
// TODO: add validations before doing the fetch
|
||||
const data = await fetch({ input: { item } })
|
||||
await revalidate()
|
||||
await mutate()
|
||||
return data
|
||||
},
|
||||
[fetch, revalidate, customer]
|
||||
[fetch, mutate, customer]
|
||||
)
|
||||
},
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ export const handler: MutationHook<RemoveItemHook> = {
|
||||
({ fetch }) =>
|
||||
({ wishlist } = {}) => {
|
||||
const { data: customer } = useCustomer()
|
||||
const { revalidate } = useWishlist(wishlist)
|
||||
const { mutate } = useWishlist(wishlist)
|
||||
|
||||
return useCallback(
|
||||
async function removeItem(input) {
|
||||
@ -31,10 +31,10 @@ export const handler: MutationHook<RemoveItemHook> = {
|
||||
}
|
||||
|
||||
const data = await fetch({ input: { itemId: String(input.id) } })
|
||||
await revalidate()
|
||||
await mutate()
|
||||
return data
|
||||
},
|
||||
[fetch, revalidate, customer]
|
||||
[fetch, mutate, customer]
|
||||
)
|
||||
},
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type { ConfigInterface } from 'swr'
|
||||
import type { SWRConfiguration } from 'swr'
|
||||
import type { CommerceError } from './errors'
|
||||
import type { ResponseState } from './use-data'
|
||||
|
||||
@ -10,10 +10,9 @@ export type Override<T, K> = Omit<T, keyof K> & K
|
||||
/**
|
||||
* Returns the properties in T with the properties in type K changed from optional to required
|
||||
*/
|
||||
export type PickRequired<T, K extends keyof T> = Omit<T, K> &
|
||||
{
|
||||
[P in K]-?: NonNullable<T[P]>
|
||||
}
|
||||
export type PickRequired<T, K extends keyof T> = Omit<T, K> & {
|
||||
[P in K]-?: NonNullable<T[P]>
|
||||
}
|
||||
|
||||
/**
|
||||
* Core fetcher added by CommerceProvider
|
||||
@ -141,7 +140,7 @@ export type MutationHookContext<H extends MutationSchemaBase> = {
|
||||
: (context: { input: H['fetcherInput'] }) => H['data'] | Promise<H['data']>
|
||||
}
|
||||
|
||||
export type SwrOptions<Data, Input = null, Result = any> = ConfigInterface<
|
||||
export type SwrOptions<Data, Input = null, Result = any> = SWRConfiguration<
|
||||
Data,
|
||||
CommerceError,
|
||||
HookFetcher<Data, Input, Result>
|
||||
|
@ -18,7 +18,7 @@ export default function getAllProductsOperation({
|
||||
})
|
||||
|
||||
const productsFormatted =
|
||||
data?.map((product) => normalizeProduct(product)) || []
|
||||
data?.map((product: any) => normalizeProduct(product)) || []
|
||||
|
||||
return {
|
||||
products: productsFormatted,
|
||||
|
@ -12,8 +12,10 @@ export default async function sdkFetch<
|
||||
>(
|
||||
resource: Resource,
|
||||
method: Method,
|
||||
...variables: Parameters<Commerce[Resource][Method]>
|
||||
): Promise<ReturnType<Commerce[Resource][Method]>> {
|
||||
...variables: Parameters<Commerce[Resource][Method] | any>
|
||||
): Promise<ReturnType<Commerce[Resource][Method] | any>> {
|
||||
//@ts-ignore
|
||||
// Provider TODO: Fix types here.
|
||||
const data = await commerce[resource][method](...variables)
|
||||
return data
|
||||
}
|
||||
|
@ -11,13 +11,12 @@ export default useLogin as UseLogin<typeof handler>
|
||||
export const handler: MutationHook<LoginHook> = {
|
||||
fetchOptions: {
|
||||
url: '/api/login',
|
||||
method: 'POST'
|
||||
method: 'POST',
|
||||
},
|
||||
async fetcher({ input: { email, password }, options, fetch }) {
|
||||
if (!(email && password)) {
|
||||
throw new CommerceError({
|
||||
message:
|
||||
'An email and password are required to login',
|
||||
message: 'An email and password are required to login',
|
||||
})
|
||||
}
|
||||
|
||||
@ -26,17 +25,19 @@ export const handler: MutationHook<LoginHook> = {
|
||||
body: { email, password },
|
||||
})
|
||||
},
|
||||
useHook: ({ fetch }) => () => {
|
||||
const { revalidate } = useCustomer()
|
||||
const {revalidate: revalidateCart} = useCart()
|
||||
return useCallback(
|
||||
async function login(input) {
|
||||
const data = await fetch({ input })
|
||||
await revalidate()
|
||||
await revalidateCart()
|
||||
return data
|
||||
},
|
||||
[fetch, revalidate, revalidateCart]
|
||||
)
|
||||
},
|
||||
useHook:
|
||||
({ fetch }) =>
|
||||
() => {
|
||||
const { mutate } = useCustomer()
|
||||
const { mutate: mutateCart } = useCart()
|
||||
return useCallback(
|
||||
async function login(input) {
|
||||
const data = await fetch({ input })
|
||||
await mutate()
|
||||
await mutateCart()
|
||||
return data
|
||||
},
|
||||
[fetch, mutate, mutateCart]
|
||||
)
|
||||
},
|
||||
}
|
||||
|
@ -29,16 +29,18 @@ export const handler: MutationHook<SignupHook> = {
|
||||
body: { firstName, lastName, email, password },
|
||||
})
|
||||
},
|
||||
useHook: ({ fetch }) => () => {
|
||||
const { revalidate } = useCustomer()
|
||||
useHook:
|
||||
({ fetch }) =>
|
||||
() => {
|
||||
const { mutate } = useCustomer()
|
||||
|
||||
return useCallback(
|
||||
async function signup(input) {
|
||||
const data = await fetch({ input })
|
||||
await revalidate()
|
||||
return data
|
||||
},
|
||||
[fetch, revalidate]
|
||||
)
|
||||
},
|
||||
return useCallback(
|
||||
async function signup(input) {
|
||||
const data = await fetch({ input })
|
||||
await mutate()
|
||||
return data
|
||||
},
|
||||
[fetch, mutate]
|
||||
)
|
||||
},
|
||||
}
|
||||
|
@ -13,24 +13,26 @@ export const handler: MutationHook<AddItemHook> = {
|
||||
url: '/api/wishlist',
|
||||
method: 'POST',
|
||||
},
|
||||
useHook: ({ fetch }) => () => {
|
||||
const { data: customer } = useCustomer()
|
||||
const { revalidate } = useWishlist()
|
||||
useHook:
|
||||
({ fetch }) =>
|
||||
() => {
|
||||
const { data: customer } = useCustomer()
|
||||
const { mutate } = useWishlist()
|
||||
|
||||
return useCallback(
|
||||
async function addItem(item) {
|
||||
if (!customer) {
|
||||
// A signed customer is required in order to have a wishlist
|
||||
throw new CommerceError({
|
||||
message: 'Signed customer not found',
|
||||
})
|
||||
}
|
||||
// TODO: add validations before doing the fetch
|
||||
const data = await fetch({ input: { item } })
|
||||
await revalidate()
|
||||
return data
|
||||
},
|
||||
[fetch, revalidate, customer]
|
||||
)
|
||||
},
|
||||
return useCallback(
|
||||
async function addItem(item) {
|
||||
if (!customer) {
|
||||
// A signed customer is required in order to have a wishlist
|
||||
throw new CommerceError({
|
||||
message: 'Signed customer not found',
|
||||
})
|
||||
}
|
||||
// TODO: add validations before doing the fetch
|
||||
const data = await fetch({ input: { item } })
|
||||
await mutate()
|
||||
return data
|
||||
},
|
||||
[fetch, mutate, customer]
|
||||
)
|
||||
},
|
||||
}
|
||||
|
@ -15,24 +15,26 @@ export const handler: MutationHook<RemoveItemHook> = {
|
||||
url: '/api/wishlist',
|
||||
method: 'DELETE',
|
||||
},
|
||||
useHook: ({ fetch }) => ({ wishlist } = {}) => {
|
||||
const { data: customer } = useCustomer()
|
||||
const { revalidate } = useWishlist(wishlist)
|
||||
useHook:
|
||||
({ fetch }) =>
|
||||
({ wishlist } = {}) => {
|
||||
const { data: customer } = useCustomer()
|
||||
const { mutate } = useWishlist(wishlist)
|
||||
|
||||
return useCallback(
|
||||
async function removeItem(input) {
|
||||
if (!customer) {
|
||||
// A signed customer is required in order to have a wishlist
|
||||
throw new CommerceError({
|
||||
message: 'Signed customer not found',
|
||||
})
|
||||
}
|
||||
return useCallback(
|
||||
async function removeItem(input) {
|
||||
if (!customer) {
|
||||
// A signed customer is required in order to have a wishlist
|
||||
throw new CommerceError({
|
||||
message: 'Signed customer not found',
|
||||
})
|
||||
}
|
||||
|
||||
const data = await fetch({ input: { itemId: String(input.id) } })
|
||||
await revalidate()
|
||||
return data
|
||||
},
|
||||
[fetch, revalidate, customer]
|
||||
)
|
||||
},
|
||||
const data = await fetch({ input: { itemId: String(input.id) } })
|
||||
await mutate()
|
||||
return data
|
||||
},
|
||||
[fetch, mutate, customer]
|
||||
)
|
||||
},
|
||||
}
|
||||
|
@ -49,15 +49,15 @@ export const handler: MutationHook<LoginHook> = {
|
||||
useHook:
|
||||
({ fetch }) =>
|
||||
() => {
|
||||
const { revalidate } = useCustomer()
|
||||
const { mutate } = useCustomer()
|
||||
|
||||
return useCallback(
|
||||
async function login(input) {
|
||||
const data = await fetch({ input })
|
||||
await revalidate()
|
||||
await mutate()
|
||||
return data
|
||||
},
|
||||
[fetch, revalidate]
|
||||
[fetch, mutate]
|
||||
)
|
||||
},
|
||||
}
|
||||
|
@ -42,15 +42,15 @@ export const handler: MutationHook<SignupHook> = {
|
||||
useHook:
|
||||
({ fetch }) =>
|
||||
() => {
|
||||
const { revalidate } = useCustomer()
|
||||
const { mutate } = useCustomer()
|
||||
|
||||
return useCallback(
|
||||
async function signup(input) {
|
||||
const data = await fetch({ input })
|
||||
await revalidate()
|
||||
await mutate()
|
||||
return data
|
||||
},
|
||||
[fetch, revalidate]
|
||||
[fetch, mutate]
|
||||
)
|
||||
},
|
||||
}
|
||||
|
@ -49,15 +49,15 @@ export const handler: MutationHook<LoginHook> = {
|
||||
useHook:
|
||||
({ fetch }) =>
|
||||
() => {
|
||||
const { revalidate } = useCustomer()
|
||||
const { mutate } = useCustomer()
|
||||
|
||||
return useCallback(
|
||||
async function login(input) {
|
||||
const data = await fetch({ input })
|
||||
await revalidate()
|
||||
await mutate()
|
||||
return data
|
||||
},
|
||||
[fetch, revalidate]
|
||||
[fetch, mutate]
|
||||
)
|
||||
},
|
||||
}
|
||||
|
@ -53,15 +53,15 @@ export const handler: MutationHook<SignupHook> = {
|
||||
useHook:
|
||||
({ fetch }) =>
|
||||
() => {
|
||||
const { revalidate } = useCustomer()
|
||||
const { mutate } = useCustomer()
|
||||
|
||||
return useCallback(
|
||||
async function signup(input) {
|
||||
const data = await fetch({ input })
|
||||
await revalidate()
|
||||
await mutate()
|
||||
return data
|
||||
},
|
||||
[fetch, revalidate]
|
||||
[fetch, mutate]
|
||||
)
|
||||
},
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ An integration of [Spree Commerce](https://spreecommerce.org/) within NextJS Com
|
||||
- They rely on [taxonomies'](https://dev-docs.spreecommerce.org/internals/products#taxons-and-taxonomies) permalinks in Spree.
|
||||
- Go to the Spree admin panel and create `Categories` and `Brands` taxonomies if they don't exist and copy their permalinks into `.env.local` in NextJS Commerce.
|
||||
|
||||
1. Finally, run `yarn dev` :tada:
|
||||
1. Finally, run `npm run dev` :tada:
|
||||
|
||||
[1]: https://spreecommerce.org/
|
||||
[2]: https://github.com/vercel/commerce
|
||||
|
@ -71,9 +71,9 @@ export const handler: MutationHook<LoginHook> = {
|
||||
async function login(input) {
|
||||
const data = await fetch({ input })
|
||||
|
||||
await customer.revalidate()
|
||||
await cart.revalidate()
|
||||
await wishlist.revalidate()
|
||||
await customer.mutate()
|
||||
await cart.mutate()
|
||||
await wishlist.mutate()
|
||||
|
||||
return data
|
||||
},
|
||||
|
@ -81,9 +81,9 @@ export const handler: MutationHook<SignupHook> = {
|
||||
async (input) => {
|
||||
const data = await fetch({ input })
|
||||
|
||||
await customer.revalidate()
|
||||
await cart.revalidate()
|
||||
await wishlist.revalidate()
|
||||
await customer.mutate()
|
||||
await cart.mutate()
|
||||
await wishlist.mutate()
|
||||
|
||||
return data
|
||||
},
|
||||
|
@ -75,7 +75,7 @@ export const handler: MutationHook<ExplicitWishlistAddItemHook> = {
|
||||
},
|
||||
})
|
||||
|
||||
await wishlist.revalidate()
|
||||
await wishlist.mutate()
|
||||
|
||||
return data
|
||||
},
|
||||
|
@ -62,7 +62,7 @@ export const handler: MutationHook<ExplicitWishlistRemoveItemHook> = {
|
||||
},
|
||||
})
|
||||
|
||||
await wishlist.revalidate()
|
||||
await wishlist.mutate()
|
||||
|
||||
return data
|
||||
},
|
||||
|
@ -62,15 +62,15 @@ export const handler: MutationHook<LoginHook> = {
|
||||
useHook:
|
||||
({ fetch }) =>
|
||||
() => {
|
||||
const { revalidate } = useCustomer()
|
||||
const { mutate } = useCustomer()
|
||||
|
||||
return useCallback(
|
||||
async function login(input) {
|
||||
const data = await fetch({ input })
|
||||
await revalidate()
|
||||
await mutate()
|
||||
return data
|
||||
},
|
||||
[fetch, revalidate]
|
||||
[fetch, mutate]
|
||||
)
|
||||
},
|
||||
}
|
||||
|
@ -47,15 +47,15 @@ export const handler: MutationHook<SignupHook> = {
|
||||
useHook:
|
||||
({ fetch }) =>
|
||||
() => {
|
||||
const { revalidate } = useCustomer()
|
||||
const { mutate } = useCustomer()
|
||||
|
||||
return useCallback(
|
||||
async function signup(input) {
|
||||
const data = await fetch({ input })
|
||||
await revalidate()
|
||||
await mutate()
|
||||
return data
|
||||
},
|
||||
[fetch, revalidate]
|
||||
[fetch, mutate]
|
||||
)
|
||||
},
|
||||
}
|
||||
|
@ -39,15 +39,15 @@ export const handler: MutationHook<LoginHook> = {
|
||||
useHook:
|
||||
({ fetch }) =>
|
||||
() => {
|
||||
const { revalidate } = useCustomer()
|
||||
const { mutate } = useCustomer()
|
||||
|
||||
return useCallback(
|
||||
async function login(input) {
|
||||
const data = await fetch({ input })
|
||||
await revalidate()
|
||||
await mutate()
|
||||
return data
|
||||
},
|
||||
[fetch, revalidate]
|
||||
[fetch, mutate]
|
||||
)
|
||||
},
|
||||
}
|
||||
|
@ -57,15 +57,15 @@ export const handler: MutationHook<SignupHook> = {
|
||||
useHook:
|
||||
({ fetch }) =>
|
||||
() => {
|
||||
const { revalidate } = useCustomer()
|
||||
const { mutate } = useCustomer()
|
||||
|
||||
return useCallback(
|
||||
async function signup(input) {
|
||||
const data = await fetch({ input })
|
||||
await revalidate()
|
||||
await mutate()
|
||||
return data
|
||||
},
|
||||
[fetch, revalidate]
|
||||
[fetch, mutate]
|
||||
)
|
||||
},
|
||||
}
|
||||
|
@ -4,9 +4,7 @@ import useLogin from '@framework/auth/use-login'
|
||||
import { useUI } from '@components/ui/context'
|
||||
import { validate } from 'email-validator'
|
||||
|
||||
interface Props {}
|
||||
|
||||
const LoginView: FC<Props> = () => {
|
||||
const LoginView: React.FC = () => {
|
||||
// Form State
|
||||
const [email, setEmail] = useState('')
|
||||
const [password, setPassword] = useState('')
|
||||
@ -35,8 +33,8 @@ const LoginView: FC<Props> = () => {
|
||||
})
|
||||
setLoading(false)
|
||||
closeModal()
|
||||
} catch ({ errors }) {
|
||||
setMessage(errors[0].message)
|
||||
} catch (e: any) {
|
||||
setMessage(e.errors[0].message)
|
||||
setLoading(false)
|
||||
setDisabled(false)
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ import { useCheckoutContext } from '../context'
|
||||
const CheckoutSidebarView: FC = () => {
|
||||
const [loadingSubmit, setLoadingSubmit] = useState(false)
|
||||
const { setSidebarView, closeSidebar } = useUI()
|
||||
const { data: cartData, revalidate: refreshCart } = useCart()
|
||||
const { data: cartData, mutate: refreshCart } = useCart()
|
||||
const { data: checkoutData, submit: onCheckout } = useCheckout()
|
||||
const { clearCheckoutFields } = useCheckoutContext()
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
.root {
|
||||
@apply text-center p-6 bg-primary text-sm flex-row justify-center items-center font-medium fixed bottom-0 w-full z-30 transition-all duration-300 ease-out;
|
||||
|
||||
@screen md {
|
||||
@apply flex text-left;
|
||||
}
|
||||
@apply text-center p-6 bg-primary text-sm flex-row
|
||||
justify-center items-center font-medium fixed bottom-0
|
||||
w-full z-30 transition-all duration-300 ease-out
|
||||
md:flex md:text-left;
|
||||
}
|
||||
|
@ -16,16 +16,6 @@
|
||||
|
||||
.dropdownMenu {
|
||||
@apply fixed right-0 top-12 mt-2 origin-top-right outline-none bg-primary z-40 w-full h-full;
|
||||
|
||||
@screen lg {
|
||||
@apply absolute border border-accent-1 shadow-lg w-56 h-auto;
|
||||
}
|
||||
}
|
||||
|
||||
.closeButton {
|
||||
@screen md {
|
||||
@apply hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
@ -44,3 +34,15 @@
|
||||
.icon.active {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
@screen lg {
|
||||
.dropdownMenu {
|
||||
@apply absolute border border-accent-1 shadow-lg w-56 h-auto;
|
||||
}
|
||||
}
|
||||
|
||||
@screen md {
|
||||
.closeButton {
|
||||
@apply hidden;
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
.dropdownMenu {
|
||||
@apply fixed right-0 mt-2 origin-top-right outline-none bg-primary z-40 w-full h-full;
|
||||
|
||||
@screen lg {
|
||||
@screen lg {
|
||||
.dropdownMenu {
|
||||
@apply absolute top-10 border border-accent-1 shadow-lg w-56 h-auto;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdownMenu {
|
||||
@apply fixed right-0 mt-2 origin-top-right outline-none bg-primary z-40 w-full h-full;
|
||||
}
|
||||
|
||||
.link {
|
||||
@apply text-primary flex cursor-pointer px-6 py-3 flex transition ease-in-out duration-150 leading-6 font-medium items-center;
|
||||
text-transform: capitalize;
|
||||
|
@ -13,52 +13,50 @@ interface SwatchProps {
|
||||
label?: string | null
|
||||
}
|
||||
|
||||
const Swatch: React.FC<Omit<ButtonProps, 'variant'> & SwatchProps> = React.memo(
|
||||
({
|
||||
active,
|
||||
className,
|
||||
color = '',
|
||||
label = null,
|
||||
variant = 'size',
|
||||
...props
|
||||
}) => {
|
||||
variant = variant?.toLowerCase()
|
||||
const Swatch: React.FC<Omit<ButtonProps, 'variant'> & SwatchProps> = ({
|
||||
active,
|
||||
className,
|
||||
color = '',
|
||||
label = null,
|
||||
variant = 'size',
|
||||
...props
|
||||
}) => {
|
||||
variant = variant?.toLowerCase()
|
||||
|
||||
if (label) {
|
||||
label = label?.toLowerCase()
|
||||
}
|
||||
|
||||
const swatchClassName = cn(
|
||||
s.swatch,
|
||||
{
|
||||
[s.color]: color,
|
||||
[s.active]: active,
|
||||
[s.size]: variant === 'size',
|
||||
[s.dark]: color ? isDark(color) : false,
|
||||
[s.textLabel]: !color && label && label.length > 3,
|
||||
},
|
||||
className
|
||||
)
|
||||
|
||||
return (
|
||||
<Button
|
||||
role="option"
|
||||
aria-selected={active}
|
||||
aria-label={variant && label ? `${variant} ${label}` : 'Variant Swatch'}
|
||||
className={swatchClassName}
|
||||
{...(label && color && { title: label })}
|
||||
style={color ? { backgroundColor: color } : {}}
|
||||
{...props}
|
||||
>
|
||||
{color && active && (
|
||||
<span>
|
||||
<Check />
|
||||
</span>
|
||||
)}
|
||||
{!color ? label : null}
|
||||
</Button>
|
||||
)
|
||||
if (label) {
|
||||
label = label?.toLowerCase()
|
||||
}
|
||||
)
|
||||
|
||||
export default Swatch
|
||||
const swatchClassName = cn(
|
||||
s.swatch,
|
||||
{
|
||||
[s.color]: color,
|
||||
[s.active]: active,
|
||||
[s.size]: variant === 'size',
|
||||
[s.dark]: color ? isDark(color) : false,
|
||||
[s.textLabel]: !color && label && label.length > 3,
|
||||
},
|
||||
className
|
||||
)
|
||||
|
||||
return (
|
||||
<Button
|
||||
role="option"
|
||||
aria-selected={active}
|
||||
aria-label={variant && label ? `${variant} ${label}` : 'Variant Swatch'}
|
||||
className={swatchClassName}
|
||||
{...(label && color && { title: label })}
|
||||
style={color ? { backgroundColor: color } : {}}
|
||||
{...props}
|
||||
>
|
||||
{color && active && (
|
||||
<span>
|
||||
<Check />
|
||||
</span>
|
||||
)}
|
||||
{!color ? label : null}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(Swatch)
|
||||
|
@ -21,6 +21,7 @@ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
disabled?: boolean
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react/display-name
|
||||
const Button: React.FC<ButtonProps> = forwardRef((props, buttonRef) => {
|
||||
const {
|
||||
className,
|
||||
|
@ -10,7 +10,7 @@ export interface CollapseProps {
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
const Collapse: FC<CollapseProps> = React.memo(({ title, children }) => {
|
||||
const Collapse: FC<CollapseProps> = ({ title, children }) => {
|
||||
const [isActive, setActive] = useState(false)
|
||||
const [ref, { height: viewHeight }] = useMeasure()
|
||||
|
||||
@ -41,6 +41,6 @@ const Collapse: FC<CollapseProps> = React.memo(({ title, children }) => {
|
||||
</a.div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
export default Collapse
|
||||
export default React.memo(Collapse)
|
||||
|
@ -1,53 +1,25 @@
|
||||
.root {
|
||||
@apply grid grid-cols-1 gap-0;
|
||||
|
||||
@screen lg {
|
||||
@apply grid-cols-3 grid-rows-2;
|
||||
}
|
||||
|
||||
& > * {
|
||||
@apply row-span-1 bg-transparent box-border overflow-hidden;
|
||||
height: 500px;
|
||||
max-height: 800px;
|
||||
|
||||
@screen lg {
|
||||
@apply col-span-1;
|
||||
height: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
.root > * {
|
||||
@apply row-span-1 bg-transparent box-border overflow-hidden;
|
||||
height: 500px;
|
||||
max-height: 800px;
|
||||
}
|
||||
|
||||
.default {
|
||||
& > * {
|
||||
@apply bg-transparent;
|
||||
}
|
||||
.default > * {
|
||||
@apply bg-transparent;
|
||||
}
|
||||
|
||||
.layoutNormal {
|
||||
@apply gap-3;
|
||||
}
|
||||
|
||||
@screen md {
|
||||
.layoutNormal > * {
|
||||
max-height: min-content !important;
|
||||
}
|
||||
}
|
||||
|
||||
@screen lg {
|
||||
.layoutNormal > * {
|
||||
max-height: 400px;
|
||||
}
|
||||
}
|
||||
|
||||
.layoutA {
|
||||
& > *:nth-child(6n + 1),
|
||||
& > *:nth-child(6n + 5) {
|
||||
@apply row-span-2;
|
||||
@apply row-span-2 lg:col-span-2;
|
||||
height: var(--row-height);
|
||||
|
||||
@screen lg {
|
||||
@apply col-span-2;
|
||||
}
|
||||
}
|
||||
|
||||
&.filled {
|
||||
@ -72,12 +44,8 @@
|
||||
.layoutB {
|
||||
& > *:nth-child(6n + 2),
|
||||
& > *:nth-child(6n + 4) {
|
||||
@apply row-span-2;
|
||||
@apply row-span-2 lg:col-span-2;
|
||||
height: var(--row-height);
|
||||
|
||||
@screen lg {
|
||||
@apply col-span-2;
|
||||
}
|
||||
}
|
||||
|
||||
&.filled {
|
||||
@ -102,12 +70,8 @@
|
||||
.layoutC {
|
||||
& > *:nth-child(12n + 1),
|
||||
& > *:nth-child(12n + 8) {
|
||||
@apply row-span-2;
|
||||
@apply row-span-2 lg:col-span-2;
|
||||
height: var(--row-height);
|
||||
|
||||
@screen lg {
|
||||
@apply col-span-2;
|
||||
}
|
||||
}
|
||||
|
||||
&.filled {
|
||||
@ -130,12 +94,8 @@
|
||||
.layoutD {
|
||||
& > *:nth-child(12n + 2),
|
||||
& > *:nth-child(12n + 7) {
|
||||
@apply row-span-2;
|
||||
@apply row-span-2 lg:col-span-2;
|
||||
height: var(--row-height);
|
||||
|
||||
@screen lg {
|
||||
@apply col-span-2;
|
||||
}
|
||||
}
|
||||
|
||||
&.filled {
|
||||
@ -152,3 +112,24 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@screen md {
|
||||
.layoutNormal > * {
|
||||
max-height: min-content !important;
|
||||
}
|
||||
}
|
||||
|
||||
@screen lg {
|
||||
.root {
|
||||
@apply grid-cols-3 grid-rows-2;
|
||||
}
|
||||
|
||||
.root > * {
|
||||
@apply col-span-1;
|
||||
height: inherit;
|
||||
}
|
||||
|
||||
.layoutNormal > * {
|
||||
max-height: 400px;
|
||||
}
|
||||
}
|
||||
|
@ -31,8 +31,8 @@ const WishlistButton: FC<Props> = ({
|
||||
const itemInWishlist = data?.items?.find(
|
||||
// @ts-ignore Wishlist is not always enabled
|
||||
(item) =>
|
||||
item.product_id === Number(productId) &&
|
||||
(item.variant_id as any) === Number(variant.id)
|
||||
item.product_id === productId &&
|
||||
item.variant_id === variant.id
|
||||
)
|
||||
|
||||
const handleWishlistChange = async (e: any) => {
|
||||
|
@ -48,6 +48,7 @@ export default function Home({
|
||||
imgProps={{
|
||||
width: i === 0 ? 1080 : 540,
|
||||
height: i === 0 ? 1080 : 540,
|
||||
priority: true,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
|
@ -1,7 +1,8 @@
|
||||
module.exports = {
|
||||
plugins: [
|
||||
'tailwindcss/nesting',
|
||||
'tailwindcss',
|
||||
'postcss-nesting',
|
||||
'autoprefixer',
|
||||
'postcss-flexbugs-fixes',
|
||||
[
|
||||
'postcss-preset-env',
|
||||
|
@ -1,19 +1,9 @@
|
||||
module.exports = {
|
||||
future: {
|
||||
purgeLayersByDefault: true,
|
||||
applyComplexClasses: true,
|
||||
},
|
||||
purge: {
|
||||
content: [
|
||||
'./pages/**/*.{js,ts,jsx,tsx}',
|
||||
'./components/**/*.{js,ts,jsx,tsx}',
|
||||
],
|
||||
options: {
|
||||
safelist: {
|
||||
standard: ['outline-none'],
|
||||
},
|
||||
},
|
||||
},
|
||||
content: [
|
||||
'./pages/**/*.{js,ts,jsx,tsx}',
|
||||
'./components/**/*.{js,ts,jsx,tsx}',
|
||||
],
|
||||
safelist: ['outline-none'],
|
||||
theme: {
|
||||
extend: {
|
||||
maxWidth: {
|
||||
|
@ -15,6 +15,7 @@
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"incremental": true,
|
||||
"useUnknownInCatchVariables": false,
|
||||
"paths": {
|
||||
"@lib/*": ["lib/*"],
|
||||
"@utils/*": ["utils/*"],
|
||||
|
Loading…
x
Reference in New Issue
Block a user