mirror of
https://github.com/vercel/commerce.git
synced 2025-07-24 10:41:23 +00:00
Monorepo with Turborepo (#651)
* Moved everything * Figuring out how to make imports work * Updated exports * Added missing exports * Added @vercel/commerce-local to `site` * Updated commerce config * Updated exports and commerce config * Updated commerce hoc * Fixed exports in local * Added publish config * Updated imports in site * It's actually working * Don't use debugger in dev for better speeds * Improved DX when editing packages * Set up eslint with husky * Updated prettier config * Added prettier setup to every package * Moved bigcommerce * Moved Bigcommerce to src and package updates * Updated setup of bigcommerce * Moved definitions script * Moved commercejs * Move to src * Fixed types in commercejs * Moved kibocommerce * Moved kibocommerce to src * Added package/tsconfig to kibocommerce * Fixed imports and other things * Moved ordercloud * Moved ordercloud to src * Fixed imports * Added missing prettier files * Moved Saleor * Moved Saleor to src * Fixed imports * Replaced all imports to @commerce * Added prettierignore/rc to all providers * Moved shopify to src * Build shopify in packages * Moved Spree * Moved spree to src * Updated spree * Moved swell * Moved swell to src * Fixed type imports in swell * Moved Vendure to packages * Moved vendure to src * Fixed imports in vendure * Added codegen to saleor * Updated codegen setup for shopify * Added codegen to vendure * Added codegen to kibocommerce * Added all packages to site's deps * Updated codegen setup in bigcommerce * Minor fixes * Updated providers' names in site * Updated packages based on Bel's changes * Updated turbo to latest * Fixed ts complains * Set npm engine in root * New lockfile install * remove engines * Regen lockfile * Switched from npm to yarn * Updated typesVersions in all packages * Moved dep * Updated SWR to the just released 1.2.0 * Removed "isolatedModules" from packages * Updated list of providers and default * Updated swell declaration * Removed next import from kibocommerce * Added COMMERCE_PROVIDER log * Added another log * Updated turbo config * Updated docs * Removed test logs Co-authored-by: Jared Palmer <jared@jaredpalmer.com>
This commit is contained in:
@@ -1,3 +0,0 @@
|
||||
import { getCommerceApi } from '@framework/api'
|
||||
|
||||
export default getCommerceApi()
|
@@ -1,42 +0,0 @@
|
||||
import React, { useRef, useEffect, MouseEvent } from 'react'
|
||||
import hasParent from './has-parent'
|
||||
|
||||
interface ClickOutsideProps {
|
||||
active: boolean
|
||||
onClick: (e?: MouseEvent) => void
|
||||
children: any
|
||||
}
|
||||
|
||||
const ClickOutside = ({
|
||||
active = true,
|
||||
onClick,
|
||||
children,
|
||||
}: ClickOutsideProps) => {
|
||||
const innerRef = useRef()
|
||||
|
||||
const handleClick = (event: any) => {
|
||||
if (!hasParent(event.target, innerRef?.current)) {
|
||||
if (typeof onClick === 'function') {
|
||||
onClick(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (active) {
|
||||
document.addEventListener('mousedown', handleClick)
|
||||
document.addEventListener('touchstart', handleClick)
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (active) {
|
||||
document.removeEventListener('mousedown', handleClick)
|
||||
document.removeEventListener('touchstart', handleClick)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return React.cloneElement(children, { ref: innerRef })
|
||||
}
|
||||
|
||||
export default ClickOutside
|
@@ -1,5 +0,0 @@
|
||||
import isInDOM from './is-in-dom'
|
||||
|
||||
export default function hasParent(element, root) {
|
||||
return root && root.contains(element) && isInDOM(element)
|
||||
}
|
@@ -1 +0,0 @@
|
||||
export { default } from './click-outside'
|
@@ -1,3 +0,0 @@
|
||||
export default function isInDom(obj) {
|
||||
return Boolean(obj.closest('body'))
|
||||
}
|
206
lib/colors.ts
206
lib/colors.ts
@@ -1,206 +0,0 @@
|
||||
import random from 'lodash.random'
|
||||
|
||||
export function getRandomPairOfColors() {
|
||||
const colors = ['#37B679', '#DA3C3C', '#3291FF', '#7928CA', '#79FFE1']
|
||||
const getRandomIdx = () => random(0, colors.length - 1)
|
||||
let idx = getRandomIdx()
|
||||
let idx2 = getRandomIdx()
|
||||
|
||||
// Has to be a different color
|
||||
while (idx2 === idx) {
|
||||
idx2 = getRandomIdx()
|
||||
}
|
||||
|
||||
// Returns a pair of colors
|
||||
return [colors[idx], colors[idx2]]
|
||||
}
|
||||
|
||||
function hexToRgb(hex: string = '') {
|
||||
// @ts-ignore
|
||||
const match = hex.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i)
|
||||
|
||||
if (!match) {
|
||||
return [0, 0, 0]
|
||||
}
|
||||
|
||||
let colorString = match[0]
|
||||
|
||||
if (match[0].length === 3) {
|
||||
colorString = colorString
|
||||
.split('')
|
||||
.map((char: string) => {
|
||||
return char + char
|
||||
})
|
||||
.join('')
|
||||
}
|
||||
|
||||
const integer = parseInt(colorString, 16)
|
||||
const r = (integer >> 16) & 0xff
|
||||
const g = (integer >> 8) & 0xff
|
||||
const b = integer & 0xff
|
||||
|
||||
return [r, g, b]
|
||||
}
|
||||
|
||||
export const colorMap: Record<string, string> = {
|
||||
aliceblue: '#F0F8FF',
|
||||
antiquewhite: '#FAEBD7',
|
||||
aqua: '#00FFFF',
|
||||
aquamarine: '#7FFFD4',
|
||||
azure: '#F0FFFF',
|
||||
beige: '#F5F5DC',
|
||||
bisque: '#FFE4C4',
|
||||
black: '#000000',
|
||||
blanchedalmond: '#FFEBCD',
|
||||
blue: '#0000FF',
|
||||
blueviolet: '#8A2BE2',
|
||||
brown: '#A52A2A',
|
||||
burlywood: '#DEB887',
|
||||
burgandy: '#800020',
|
||||
burgundy: '#800020',
|
||||
cadetblue: '#5F9EA0',
|
||||
chartreuse: '#7FFF00',
|
||||
chocolate: '#D2691E',
|
||||
coral: '#FF7F50',
|
||||
cornflowerblue: '#6495ED',
|
||||
cornsilk: '#FFF8DC',
|
||||
crimson: '#DC143C',
|
||||
cyan: '#00FFFF',
|
||||
darkblue: '#00008B',
|
||||
darkcyan: '#008B8B',
|
||||
darkgoldenrod: '#B8860B',
|
||||
darkgray: '#A9A9A9',
|
||||
darkgreen: '#006400',
|
||||
darkgrey: '#A9A9A9',
|
||||
darkkhaki: '#BDB76B',
|
||||
darkmagenta: '#8B008B',
|
||||
darkolivegreen: '#556B2F',
|
||||
darkorange: '#FF8C00',
|
||||
darkorchid: '#9932CC',
|
||||
darkred: '#8B0000',
|
||||
darksalmon: '#E9967A',
|
||||
darkseagreen: '#8FBC8F',
|
||||
darkslateblue: '#483D8B',
|
||||
darkslategray: '#2F4F4F',
|
||||
darkslategrey: '#2F4F4F',
|
||||
darkturquoise: '#00CED1',
|
||||
darkviolet: '#9400D3',
|
||||
deeppink: '#FF1493',
|
||||
deepskyblue: '#00BFFF',
|
||||
dimgray: '#696969',
|
||||
dimgrey: '#696969',
|
||||
dodgerblue: '#1E90FF',
|
||||
firebrick: '#B22222',
|
||||
floralwhite: '#FFFAF0',
|
||||
forestgreen: '#228B22',
|
||||
fuchsia: '#FF00FF',
|
||||
gainsboro: '#DCDCDC',
|
||||
ghostwhite: '#F8F8FF',
|
||||
gold: '#FFD700',
|
||||
goldenrod: '#DAA520',
|
||||
gray: '#808080',
|
||||
green: '#008000',
|
||||
greenyellow: '#ADFF2F',
|
||||
grey: '#808080',
|
||||
honeydew: '#F0FFF0',
|
||||
hotpink: '#FF69B4',
|
||||
indianred: '#CD5C5C',
|
||||
indigo: '#4B0082',
|
||||
ivory: '#FFFFF0',
|
||||
khaki: '#F0E68C',
|
||||
lavender: '#E6E6FA',
|
||||
lavenderblush: '#FFF0F5',
|
||||
lawngreen: '#7CFC00',
|
||||
lemonchiffon: '#FFFACD',
|
||||
lightblue: '#ADD8E6',
|
||||
lightcoral: '#F08080',
|
||||
lightcyan: '#E0FFFF',
|
||||
lightgoldenrodyellow: '#FAFAD2',
|
||||
lightgray: '#D3D3D3',
|
||||
lightgreen: '#90EE90',
|
||||
lightgrey: '#D3D3D3',
|
||||
lightpink: '#FFB6C1',
|
||||
lightsalmon: '#FFA07A',
|
||||
lightseagreen: '#20B2AA',
|
||||
lightskyblue: '#87CEFA',
|
||||
lightslategray: '#778899',
|
||||
lightslategrey: '#778899',
|
||||
lightsteelblue: '#B0C4DE',
|
||||
lightyellow: '#FFFFE0',
|
||||
lime: '#00FF00',
|
||||
limegreen: '#32CD32',
|
||||
linen: '#FAF0E6',
|
||||
magenta: '#FF00FF',
|
||||
maroon: '#800000',
|
||||
mediumaquamarine: '#66CDAA',
|
||||
mediumblue: '#0000CD',
|
||||
mediumorchid: '#BA55D3',
|
||||
mediumpurple: '#9370DB',
|
||||
mediumseagreen: '#3CB371',
|
||||
mediumslateblue: '#7B68EE',
|
||||
mediumspringgreen: '#00FA9A',
|
||||
mediumturquoise: '#48D1CC',
|
||||
mediumvioletred: '#C71585',
|
||||
midnightblue: '#191970',
|
||||
mintcream: '#F5FFFA',
|
||||
mistyrose: '#FFE4E1',
|
||||
moccasin: '#FFE4B5',
|
||||
navajowhite: '#FFDEAD',
|
||||
navy: '#000080',
|
||||
oldlace: '#FDF5E6',
|
||||
olive: '#808000',
|
||||
olivedrab: '#6B8E23',
|
||||
orange: '#FFA500',
|
||||
orangered: '#FF4500',
|
||||
orchid: '#DA70D6',
|
||||
palegoldenrod: '#EEE8AA',
|
||||
palegreen: '#98FB98',
|
||||
paleturquoise: '#AFEEEE',
|
||||
palevioletred: '#DB7093',
|
||||
papayawhip: '#FFEFD5',
|
||||
peachpuff: '#FFDAB9',
|
||||
peru: '#CD853F',
|
||||
pink: '#FFC0CB',
|
||||
plum: '#DDA0DD',
|
||||
powderblue: '#B0E0E6',
|
||||
purple: '#800080',
|
||||
rebeccapurple: '#663399',
|
||||
red: '#FF0000',
|
||||
rosybrown: '#BC8F8F',
|
||||
royalblue: '#4169E1',
|
||||
saddlebrown: '#8B4513',
|
||||
salmon: '#FA8072',
|
||||
sandybrown: '#F4A460',
|
||||
seagreen: '#2E8B57',
|
||||
seashell: '#FFF5EE',
|
||||
sienna: '#A0522D',
|
||||
silver: '#C0C0C0',
|
||||
skyblue: '#87CEEB',
|
||||
slateblue: '#6A5ACD',
|
||||
slategray: '#708090',
|
||||
slategrey: '#708090',
|
||||
spacegrey: '#65737e',
|
||||
spacegray: '#65737e',
|
||||
snow: '#FFFAFA',
|
||||
springgreen: '#00FF7F',
|
||||
steelblue: '#4682B4',
|
||||
tan: '#D2B48C',
|
||||
teal: '#008080',
|
||||
thistle: '#D8BFD8',
|
||||
tomato: '#FF6347',
|
||||
turquoise: '#40E0D0',
|
||||
violet: '#EE82EE',
|
||||
wheat: '#F5DEB3',
|
||||
white: '#FFFFFF',
|
||||
whitesmoke: '#F5F5F5',
|
||||
yellow: '#FFFF00',
|
||||
yellowgreen: '#9ACD32',
|
||||
}
|
||||
|
||||
export function isDark(color: string = ''): boolean {
|
||||
color = color.toLowerCase()
|
||||
// Equation from http://24ways.org/2010/calculating-color-contrast
|
||||
let rgb = colorMap[color] ? hexToRgb(colorMap[color]) : hexToRgb(color)
|
||||
const res = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000
|
||||
return res < 128
|
||||
}
|
@@ -1,67 +0,0 @@
|
||||
import React, { useEffect, RefObject } from 'react'
|
||||
import { tabbable } from 'tabbable'
|
||||
|
||||
interface Props {
|
||||
children: React.ReactNode | any
|
||||
focusFirst?: boolean
|
||||
}
|
||||
|
||||
export default function FocusTrap({ children, focusFirst = false }: Props) {
|
||||
const root: RefObject<any> = React.useRef()
|
||||
const anchor: RefObject<any> = React.useRef(document.activeElement)
|
||||
|
||||
const returnFocus = () => {
|
||||
// Returns focus to the last focused element prior to trap.
|
||||
if (anchor) {
|
||||
anchor.current.focus()
|
||||
}
|
||||
}
|
||||
|
||||
const trapFocus = () => {
|
||||
// Focus the container element
|
||||
if (root.current) {
|
||||
root.current.focus()
|
||||
if (focusFirst) {
|
||||
selectFirstFocusableEl()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const selectFirstFocusableEl = () => {
|
||||
// Try to find focusable elements, if match then focus
|
||||
// Up to 6 seconds of load time threshold
|
||||
let match = false
|
||||
let end = 60 // Try to find match at least n times
|
||||
let i = 0
|
||||
const timer = setInterval(() => {
|
||||
if (!match !== i > end) {
|
||||
match = !!tabbable(root.current).length
|
||||
if (match) {
|
||||
// Attempt to focus the first el
|
||||
tabbable(root.current)[0].focus()
|
||||
}
|
||||
i = i + 1
|
||||
} else {
|
||||
// Clear interval after n attempts
|
||||
clearInterval(timer)
|
||||
}
|
||||
}, 100)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(trapFocus, 20)
|
||||
return () => {
|
||||
returnFocus()
|
||||
}
|
||||
}, [root, children])
|
||||
|
||||
return React.createElement(
|
||||
'div',
|
||||
{
|
||||
ref: root,
|
||||
className: 'outline-none focus-trap',
|
||||
tabIndex: -1,
|
||||
},
|
||||
children
|
||||
)
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
// Remove trailing and leading slash, usually included in nodes
|
||||
// returned by the BigCommerce API
|
||||
const getSlug = (path: string) => path.replace(/^\/|\/$/g, '')
|
||||
|
||||
export default getSlug
|
@@ -1,24 +0,0 @@
|
||||
import Cookies from 'js-cookie'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
const COOKIE_NAME = 'accept_cookies'
|
||||
|
||||
export const useAcceptCookies = () => {
|
||||
const [acceptedCookies, setAcceptedCookies] = useState(true)
|
||||
|
||||
useEffect(() => {
|
||||
if (!Cookies.get(COOKIE_NAME)) {
|
||||
setAcceptedCookies(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const acceptCookies = () => {
|
||||
setAcceptedCookies(true)
|
||||
Cookies.set(COOKIE_NAME, 'accepted', { expires: 365 })
|
||||
}
|
||||
|
||||
return {
|
||||
acceptedCookies,
|
||||
onAcceptCookies: acceptCookies,
|
||||
}
|
||||
}
|
@@ -1,26 +0,0 @@
|
||||
import { useEffect } from 'react'
|
||||
import { useUI } from '@components/ui/context'
|
||||
import { getRandomPairOfColors } from '@lib/colors'
|
||||
|
||||
export const useUserAvatar = (name = 'userAvatar') => {
|
||||
const { userAvatar, setUserAvatar } = useUI()
|
||||
|
||||
useEffect(() => {
|
||||
if (!userAvatar && localStorage.getItem(name)) {
|
||||
// Get bg from localStorage and push it to the context.
|
||||
setUserAvatar(localStorage.getItem(name))
|
||||
}
|
||||
if (!localStorage.getItem(name)) {
|
||||
// bg not set locally, generating one, setting localStorage and context to persist.
|
||||
const bg = getRandomPairOfColors()
|
||||
const value = `linear-gradient(140deg, ${bg[0]}, ${bg[1]} 100%)`
|
||||
localStorage.setItem(name, value)
|
||||
setUserAvatar(value)
|
||||
}
|
||||
}, [])
|
||||
|
||||
return {
|
||||
userAvatar,
|
||||
setUserAvatar,
|
||||
}
|
||||
}
|
@@ -1,7 +0,0 @@
|
||||
export default function rangeMap(n: number, fn: (i: number) => any) {
|
||||
const arr = []
|
||||
while (n > arr.length) {
|
||||
arr.push(fn(arr.length))
|
||||
}
|
||||
return arr
|
||||
}
|
@@ -1,27 +0,0 @@
|
||||
import type { GetStaticPropsContext, InferGetStaticPropsType } from 'next'
|
||||
|
||||
import commerce from '@lib/api/commerce'
|
||||
|
||||
export async function getSearchStaticProps({
|
||||
preview,
|
||||
locale,
|
||||
locales,
|
||||
}: GetStaticPropsContext) {
|
||||
const config = { locale, locales }
|
||||
const pagesPromise = commerce.getAllPages({ config, preview })
|
||||
const siteInfoPromise = commerce.getSiteInfo({ config, preview })
|
||||
const { pages } = await pagesPromise
|
||||
const { categories, brands } = await siteInfoPromise
|
||||
return {
|
||||
props: {
|
||||
pages,
|
||||
categories,
|
||||
brands,
|
||||
},
|
||||
revalidate: 200,
|
||||
}
|
||||
}
|
||||
|
||||
export type SearchPropsType = InferGetStaticPropsType<
|
||||
typeof getSearchStaticProps
|
||||
>
|
@@ -1,52 +0,0 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import getSlug from './get-slug'
|
||||
|
||||
export function useSearchMeta(asPath: string) {
|
||||
const [pathname, setPathname] = useState<string>('/search')
|
||||
const [category, setCategory] = useState<string | undefined>()
|
||||
const [brand, setBrand] = useState<string | undefined>()
|
||||
|
||||
useEffect(() => {
|
||||
// Only access asPath after hydration to avoid a server mismatch
|
||||
const path = asPath.split('?')[0]
|
||||
const parts = path.split('/')
|
||||
|
||||
let c = parts[2]
|
||||
let b = parts[3]
|
||||
|
||||
if (c === 'designers') {
|
||||
c = parts[4]
|
||||
}
|
||||
|
||||
if (path !== pathname) setPathname(path)
|
||||
if (c !== category) setCategory(c)
|
||||
if (b !== brand) setBrand(b)
|
||||
}, [asPath, pathname, category, brand])
|
||||
|
||||
return { pathname, category, brand }
|
||||
}
|
||||
|
||||
// Removes empty query parameters from the query object
|
||||
export const filterQuery = (query: any) =>
|
||||
Object.keys(query).reduce<any>((obj, key) => {
|
||||
if (query[key]?.length) {
|
||||
obj[key] = query[key]
|
||||
}
|
||||
return obj
|
||||
}, {})
|
||||
|
||||
export const getCategoryPath = (path: string, brand?: string) => {
|
||||
const category = getSlug(path)
|
||||
|
||||
return `/search${brand ? `/designers/${brand}` : ''}${
|
||||
category ? `/${category}` : ''
|
||||
}`
|
||||
}
|
||||
|
||||
export const getDesignerPath = (path: string, category?: string) => {
|
||||
const designer = getSlug(path).replace(/^brands/, 'designers')
|
||||
|
||||
return `/search${designer ? `/${designer}` : ''}${
|
||||
category ? `/${category}` : ''
|
||||
}`
|
||||
}
|
@@ -1,13 +0,0 @@
|
||||
// Convert numbers or strings to pixel value
|
||||
// Helpful for styled-jsx when using a prop
|
||||
// height: ${toPixels(height)}; (supports height={20} and height="20px")
|
||||
|
||||
const toPixels = (value: string | number) => {
|
||||
if (typeof value === 'number') {
|
||||
return `${value}px`
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
export default toPixels
|
@@ -1,26 +0,0 @@
|
||||
/**
|
||||
* The utils here are used to help developers use the example
|
||||
*/
|
||||
|
||||
export function missingLocaleInPages(): [string[], () => void] {
|
||||
const invalidPaths: string[] = []
|
||||
const log = () => {
|
||||
if (invalidPaths.length) {
|
||||
const single = invalidPaths.length === 1
|
||||
const pages = single ? 'page' : 'pages'
|
||||
|
||||
console.log(
|
||||
`The ${pages} "${invalidPaths.join(', ')}" ${
|
||||
single ? 'does' : 'do'
|
||||
} not include a locale, or the locale is not supported. When using i18n, web pages from
|
||||
BigCommerce are expected to have a locale or they will be ignored.\n
|
||||
Please update the ${pages} to include the default locale or make the ${pages} invisible by
|
||||
unchecking the "Navigation Menu" option in the settings of ${
|
||||
single ? 'the' : 'each'
|
||||
} web page\n`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return [invalidPaths, log]
|
||||
}
|
Reference in New Issue
Block a user