4
0
forked from crowetic/commerce

Apply prettier over all files

This commit is contained in:
Luis Alvarez 2020-10-01 20:40:40 -05:00
parent 2314ad760a
commit 0ef6449aff
72 changed files with 648 additions and 652 deletions

View File

@ -1,2 +1,3 @@
node_modules node_modules
.next .next
public

View File

@ -1 +1 @@
# e-comm-example # e-comm-example

View File

@ -1,99 +1,99 @@
/* latin */ /* latin */
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 100; font-weight: 100;
font-display: block; font-display: block;
src: url(https://assets.vercel.com/raw/upload/v1587415301/fonts/2/inter-var-latin.woff2) src: url(https://assets.vercel.com/raw/upload/v1587415301/fonts/2/inter-var-latin.woff2)
format("woff2"); format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
U+FEFF, U+FFFD; U+FEFF, U+FFFD;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 200; font-weight: 200;
font-display: block; font-display: block;
src: url(https://assets.vercel.com/raw/upload/v1587415301/fonts/2/inter-var-latin.woff2) src: url(https://assets.vercel.com/raw/upload/v1587415301/fonts/2/inter-var-latin.woff2)
format("woff2"); format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
U+FEFF, U+FFFD; U+FEFF, U+FFFD;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 300; font-weight: 300;
font-display: block; font-display: block;
src: url(https://assets.vercel.com/raw/upload/v1587415301/fonts/2/inter-var-latin.woff2) src: url(https://assets.vercel.com/raw/upload/v1587415301/fonts/2/inter-var-latin.woff2)
format("woff2"); format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
U+FEFF, U+FFFD; U+FEFF, U+FFFD;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
font-display: block; font-display: block;
src: url(https://assets.vercel.com/raw/upload/v1587415301/fonts/2/inter-var-latin.woff2) src: url(https://assets.vercel.com/raw/upload/v1587415301/fonts/2/inter-var-latin.woff2)
format("woff2"); format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
U+FEFF, U+FFFD; U+FEFF, U+FFFD;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 500; font-weight: 500;
font-display: block; font-display: block;
src: url(https://assets.vercel.com/raw/upload/v1587415301/fonts/2/inter-var-latin.woff2) src: url(https://assets.vercel.com/raw/upload/v1587415301/fonts/2/inter-var-latin.woff2)
format("woff2"); format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
U+FEFF, U+FFFD; U+FEFF, U+FFFD;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 600; font-weight: 600;
font-display: block; font-display: block;
src: url(https://assets.vercel.com/raw/upload/v1587415301/fonts/2/inter-var-latin.woff2) src: url(https://assets.vercel.com/raw/upload/v1587415301/fonts/2/inter-var-latin.woff2)
format("woff2"); format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
U+FEFF, U+FFFD; U+FEFF, U+FFFD;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 700; font-weight: 700;
font-display: block; font-display: block;
src: url(https://assets.vercel.com/raw/upload/v1587415301/fonts/2/inter-var-latin.woff2) src: url(https://assets.vercel.com/raw/upload/v1587415301/fonts/2/inter-var-latin.woff2)
format("woff2"); format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
U+FEFF, U+FFFD; U+FEFF, U+FFFD;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 800; font-weight: 800;
font-display: block; font-display: block;
src: url(https://assets.vercel.com/raw/upload/v1587415301/fonts/2/inter-var-latin.woff2) src: url(https://assets.vercel.com/raw/upload/v1587415301/fonts/2/inter-var-latin.woff2)
format("woff2"); format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
U+FEFF, U+FFFD; U+FEFF, U+FFFD;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 900; font-weight: 900;
font-display: block; font-display: block;
src: url(https://assets.vercel.com/raw/upload/v1587415301/fonts/2/inter-var-latin.woff2) src: url(https://assets.vercel.com/raw/upload/v1587415301/fonts/2/inter-var-latin.woff2)
format("woff2"); format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
U+FEFF, U+FFFD; U+FEFF, U+FFFD;
@ -104,525 +104,525 @@ in most cases, they are not downloaded at all */
/* latin-ext */ /* latin-ext */
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 100; font-weight: 100;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-latin-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-latin-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB,
U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 200; font-weight: 200;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-latin-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-latin-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB,
U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 300; font-weight: 300;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-latin-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-latin-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB,
U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-latin-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-latin-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB,
U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 500; font-weight: 500;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-latin-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-latin-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB,
U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 600; font-weight: 600;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-latin-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-latin-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB,
U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 700; font-weight: 700;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-latin-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-latin-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB,
U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 800; font-weight: 800;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-latin-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-latin-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB,
U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 900; font-weight: 900;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-latin-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-latin-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB,
U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
} }
/* cyrillic */ /* cyrillic */
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 100; font-weight: 100;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-cyrillic.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-cyrillic.woff2)
format("woff2"); format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 200; font-weight: 200;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-cyrillic.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-cyrillic.woff2)
format("woff2"); format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 300; font-weight: 300;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-cyrillic.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-cyrillic.woff2)
format("woff2"); format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-cyrillic.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-cyrillic.woff2)
format("woff2"); format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 500; font-weight: 500;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-cyrillic.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-cyrillic.woff2)
format("woff2"); format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 600; font-weight: 600;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-cyrillic.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-cyrillic.woff2)
format("woff2"); format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 700; font-weight: 700;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-cyrillic.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-cyrillic.woff2)
format("woff2"); format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 800; font-weight: 800;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-cyrillic.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-cyrillic.woff2)
format("woff2"); format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 900; font-weight: 900;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-cyrillic.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-cyrillic.woff2)
format("woff2"); format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
} }
/* cyrillic-ext */ /* cyrillic-ext */
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: swap; font-style: swap;
font-weight: 100; font-weight: 100;
font-display: block; font-display: block;
src: url(https://assets.vercel.com/raw/upload/v1587418127/fonts/2/inter-var-cyrillic-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418127/fonts/2/inter-var-cyrillic-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F,
U+FE2E-FE2F; U+FE2E-FE2F;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: swap; font-style: swap;
font-weight: 200; font-weight: 200;
font-display: block; font-display: block;
src: url(https://assets.vercel.com/raw/upload/v1587418127/fonts/2/inter-var-cyrillic-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418127/fonts/2/inter-var-cyrillic-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F,
U+FE2E-FE2F; U+FE2E-FE2F;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: swap; font-style: swap;
font-weight: 300; font-weight: 300;
font-display: block; font-display: block;
src: url(https://assets.vercel.com/raw/upload/v1587418127/fonts/2/inter-var-cyrillic-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418127/fonts/2/inter-var-cyrillic-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F,
U+FE2E-FE2F; U+FE2E-FE2F;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: swap; font-style: swap;
font-weight: 400; font-weight: 400;
font-display: block; font-display: block;
src: url(https://assets.vercel.com/raw/upload/v1587418127/fonts/2/inter-var-cyrillic-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418127/fonts/2/inter-var-cyrillic-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F,
U+FE2E-FE2F; U+FE2E-FE2F;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: swap; font-style: swap;
font-weight: 500; font-weight: 500;
font-display: block; font-display: block;
src: url(https://assets.vercel.com/raw/upload/v1587418127/fonts/2/inter-var-cyrillic-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418127/fonts/2/inter-var-cyrillic-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F,
U+FE2E-FE2F; U+FE2E-FE2F;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: swap; font-style: swap;
font-weight: 600; font-weight: 600;
font-display: block; font-display: block;
src: url(https://assets.vercel.com/raw/upload/v1587418127/fonts/2/inter-var-cyrillic-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418127/fonts/2/inter-var-cyrillic-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F,
U+FE2E-FE2F; U+FE2E-FE2F;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: swap; font-style: swap;
font-weight: 700; font-weight: 700;
font-display: block; font-display: block;
src: url(https://assets.vercel.com/raw/upload/v1587418127/fonts/2/inter-var-cyrillic-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418127/fonts/2/inter-var-cyrillic-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F,
U+FE2E-FE2F; U+FE2E-FE2F;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: swap; font-style: swap;
font-weight: 800; font-weight: 800;
font-display: block; font-display: block;
src: url(https://assets.vercel.com/raw/upload/v1587418127/fonts/2/inter-var-cyrillic-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418127/fonts/2/inter-var-cyrillic-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F,
U+FE2E-FE2F; U+FE2E-FE2F;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: swap; font-style: swap;
font-weight: 900; font-weight: 900;
font-display: block; font-display: block;
src: url(https://assets.vercel.com/raw/upload/v1587418127/fonts/2/inter-var-cyrillic-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418127/fonts/2/inter-var-cyrillic-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F,
U+FE2E-FE2F; U+FE2E-FE2F;
} }
/* greek */ /* greek */
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 100; font-weight: 100;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-greek.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-greek.woff2)
format("woff2"); format('woff2');
unicode-range: U+0370-03FF; unicode-range: U+0370-03FF;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 200; font-weight: 200;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-greek.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-greek.woff2)
format("woff2"); format('woff2');
unicode-range: U+0370-03FF; unicode-range: U+0370-03FF;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 300; font-weight: 300;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-greek.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-greek.woff2)
format("woff2"); format('woff2');
unicode-range: U+0370-03FF; unicode-range: U+0370-03FF;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-greek.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-greek.woff2)
format("woff2"); format('woff2');
unicode-range: U+0370-03FF; unicode-range: U+0370-03FF;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 500; font-weight: 500;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-greek.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-greek.woff2)
format("woff2"); format('woff2');
unicode-range: U+0370-03FF; unicode-range: U+0370-03FF;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 600; font-weight: 600;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-greek.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-greek.woff2)
format("woff2"); format('woff2');
unicode-range: U+0370-03FF; unicode-range: U+0370-03FF;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 700; font-weight: 700;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-greek.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-greek.woff2)
format("woff2"); format('woff2');
unicode-range: U+0370-03FF; unicode-range: U+0370-03FF;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 800; font-weight: 800;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-greek.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-greek.woff2)
format("woff2"); format('woff2');
unicode-range: U+0370-03FF; unicode-range: U+0370-03FF;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 900; font-weight: 900;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-greek.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418276/fonts/2/inter-var-greek.woff2)
format("woff2"); format('woff2');
unicode-range: U+0370-03FF; unicode-range: U+0370-03FF;
} }
/* greek-ext */ /* greek-ext */
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 100; font-weight: 100;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-greek-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-greek-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+1F00-1FFF; unicode-range: U+1F00-1FFF;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 200; font-weight: 200;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-greek-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-greek-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+1F00-1FFF; unicode-range: U+1F00-1FFF;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 300; font-weight: 300;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-greek-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-greek-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+1F00-1FFF; unicode-range: U+1F00-1FFF;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-greek-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-greek-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+1F00-1FFF; unicode-range: U+1F00-1FFF;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 500; font-weight: 500;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-greek-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-greek-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+1F00-1FFF; unicode-range: U+1F00-1FFF;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 600; font-weight: 600;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-greek-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-greek-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+1F00-1FFF; unicode-range: U+1F00-1FFF;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 700; font-weight: 700;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-greek-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-greek-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+1F00-1FFF; unicode-range: U+1F00-1FFF;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 800; font-weight: 800;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-greek-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-greek-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+1F00-1FFF; unicode-range: U+1F00-1FFF;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 900; font-weight: 900;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-greek-ext.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-greek-ext.woff2)
format("woff2"); format('woff2');
unicode-range: U+1F00-1FFF; unicode-range: U+1F00-1FFF;
} }
/* vietnamese */ /* vietnamese */
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 100; font-weight: 100;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-vietnamese.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-vietnamese.woff2)
format("woff2"); format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1,
U+01AF-01B0, U+1EA0-1EF9, U+20AB; U+01AF-01B0, U+1EA0-1EF9, U+20AB;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 200; font-weight: 200;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-vietnamese.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-vietnamese.woff2)
format("woff2"); format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1,
U+01AF-01B0, U+1EA0-1EF9, U+20AB; U+01AF-01B0, U+1EA0-1EF9, U+20AB;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 300; font-weight: 300;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-vietnamese.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-vietnamese.woff2)
format("woff2"); format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1,
U+01AF-01B0, U+1EA0-1EF9, U+20AB; U+01AF-01B0, U+1EA0-1EF9, U+20AB;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-vietnamese.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-vietnamese.woff2)
format("woff2"); format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1,
U+01AF-01B0, U+1EA0-1EF9, U+20AB; U+01AF-01B0, U+1EA0-1EF9, U+20AB;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 500; font-weight: 500;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-vietnamese.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-vietnamese.woff2)
format("woff2"); format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1,
U+01AF-01B0, U+1EA0-1EF9, U+20AB; U+01AF-01B0, U+1EA0-1EF9, U+20AB;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 600; font-weight: 600;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-vietnamese.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-vietnamese.woff2)
format("woff2"); format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1,
U+01AF-01B0, U+1EA0-1EF9, U+20AB; U+01AF-01B0, U+1EA0-1EF9, U+20AB;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 700; font-weight: 700;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-vietnamese.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-vietnamese.woff2)
format("woff2"); format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1,
U+01AF-01B0, U+1EA0-1EF9, U+20AB; U+01AF-01B0, U+1EA0-1EF9, U+20AB;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 800; font-weight: 800;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-vietnamese.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-vietnamese.woff2)
format("woff2"); format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1,
U+01AF-01B0, U+1EA0-1EF9, U+20AB; U+01AF-01B0, U+1EA0-1EF9, U+20AB;
} }
@font-face { @font-face {
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: 900; font-weight: 900;
font-display: swap; font-display: swap;
src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-vietnamese.woff2) src: url(https://assets.vercel.com/raw/upload/v1587418275/fonts/2/inter-var-vietnamese.woff2)
format("woff2"); format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1,
U+01AF-01B0, U+1EA0-1EF9, U+20AB; U+01AF-01B0, U+1EA0-1EF9, U+20AB;
} }

View File

@ -1,4 +1,4 @@
@import "./font.css"; @import './font.css';
@tailwind base; @tailwind base;
@tailwind components; @tailwind components;
@ -61,8 +61,8 @@
--geist-marketing-radius: 8px; --geist-marketing-radius: 8px;
/* Fonts */ /* Fonts */
--font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto',
"Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif; sans-serif;
--font-mono: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, --font-mono: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
Bitstream Vera Sans Mono, Courier New, monospace; Bitstream Vera Sans Mono, Courier New, monospace;
@ -164,7 +164,7 @@ html {
height: 100%; height: 100%;
box-sizing: border-box; box-sizing: border-box;
touch-action: manipulation; touch-action: manipulation;
font-feature-settings: "case" 1, "rlig" 1, "calt" 0; font-feature-settings: 'case' 1, 'rlig' 1, 'calt' 0;
text-rendering: optimizeLegibility; text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;

View File

@ -1,11 +1,11 @@
import React, { FunctionComponent } from "react"; import React, { FunctionComponent } from 'react'
import { UserNav } from "@components/core"; import { UserNav } from '@components/core'
import { Button } from "@components/ui"; import { Button } from '@components/ui'
import { Trash, Cross } from "@components/icon"; import { Trash, Cross } from '@components/icon'
import { useUI } from "@components/ui/context"; import { useUI } from '@components/ui/context'
const CartSidebarView: FunctionComponent = () => { const CartSidebarView: FunctionComponent = () => {
const { closeSidebar } = useUI(); const { closeSidebar } = useUI()
return ( return (
<> <>
<header className="px-4 py-6 sm:px-6 border-b border-gray-200"> <header className="px-4 py-6 sm:px-6 border-b border-gray-200">
@ -57,7 +57,7 @@ const CartSidebarView: FunctionComponent = () => {
<Button>Proceed to Checkout</Button> <Button>Proceed to Checkout</Button>
</div> </div>
</> </>
); )
}; }
export default CartSidebarView; export default CartSidebarView

View File

@ -1 +1 @@
export { default } from "./CartSidebarView"; export { default } from './CartSidebarView'

View File

@ -1 +1 @@
export { default as CartSidebarView } from "./CartSidebarView"; export { default as CartSidebarView } from './CartSidebarView'

View File

@ -1,14 +1,14 @@
import cn from "classnames"; import cn from 'classnames'
import React, { FunctionComponent } from "react"; import React, { FunctionComponent } from 'react'
import s from "./Avatar.module.css"; import s from './Avatar.module.css'
interface Props { interface Props {
className?: string; className?: string
children?: any; children?: any
} }
const Avatar: FunctionComponent<Props> = ({ className }) => { const Avatar: FunctionComponent<Props> = ({ className }) => {
const rootClassName = cn(s.root, className); const rootClassName = cn(s.root, className)
return ( return (
<div className={rootClassName}> <div className={rootClassName}>
<img <img
@ -17,7 +17,7 @@ const Avatar: FunctionComponent<Props> = ({ className }) => {
alt="" alt=""
></img> ></img>
</div> </div>
); )
}; }
export default Avatar; export default Avatar

View File

@ -1 +1 @@
export { default } from "./Avatar"; export { default } from './Avatar'

View File

@ -13,7 +13,7 @@
} }
.separator:before { .separator:before {
content: ""; content: '';
} }
.description { .description {

View File

@ -1,11 +1,11 @@
import cn from "classnames"; import cn from 'classnames'
import { FunctionComponent } from "react"; import { FunctionComponent } from 'react'
import s from "./Featurebar.module.css"; import s from './Featurebar.module.css'
interface Props { interface Props {
className?: string; className?: string
title: string; title: string
description: string; description: string
} }
const Featurebar: FunctionComponent<Props> = ({ const Featurebar: FunctionComponent<Props> = ({
@ -13,14 +13,14 @@ const Featurebar: FunctionComponent<Props> = ({
description, description,
className, className,
}) => { }) => {
const rootClassName = cn(s.root, className); const rootClassName = cn(s.root, className)
return ( return (
<div className={rootClassName}> <div className={rootClassName}>
<span className={s.title}>{title}</span> <span className={s.title}>{title}</span>
<span className={s.separator} /> <span className={s.separator} />
<span className={s.description}>{description}</span> <span className={s.description}>{description}</span>
</div> </div>
); )
}; }
export default Featurebar; export default Featurebar

View File

@ -1 +1 @@
export { default } from "./Featurebar"; export { default } from './Featurebar'

View File

@ -1,20 +1,20 @@
import cn from "classnames"; import cn from 'classnames'
import React, { FunctionComponent } from "react"; import React, { FunctionComponent } from 'react'
import s from "./Footer.module.css"; import s from './Footer.module.css'
import { Container } from "@components/ui"; import { Container } from '@components/ui'
interface Props { interface Props {
className?: string; className?: string
children?: any; children?: any
} }
const Footer: FunctionComponent<Props> = ({ className }) => { const Footer: FunctionComponent<Props> = ({ className }) => {
const rootClassName = cn(s.root, className); const rootClassName = cn(s.root, className)
return ( return (
<footer className={rootClassName}> <footer className={rootClassName}>
<Container className={s.container}></Container> <Container className={s.container}></Container>
</footer> </footer>
); )
}; }
export default Footer; export default Footer

View File

@ -1 +1 @@
export { default } from "./Footer"; export { default } from './Footer'

View File

@ -1,19 +1,19 @@
import cn from "classnames"; import cn from 'classnames'
import React, { FunctionComponent } from "react"; import React, { FunctionComponent } from 'react'
import s from "./Layout.module.css"; import s from './Layout.module.css'
import { Navbar, Featurebar } from "@components/core"; import { Navbar, Featurebar } from '@components/core'
import { Container, Sidebar } from "@components/ui"; import { Container, Sidebar } from '@components/ui'
import { CartSidebarView } from "@components/cart"; import { CartSidebarView } from '@components/cart'
import { useUI } from "@components/ui/context"; import { useUI } from '@components/ui/context'
interface Props { interface Props {
className?: string; className?: string
children?: any; children?: any
} }
const Layout: FunctionComponent<Props> = ({ className, children }) => { const Layout: FunctionComponent<Props> = ({ className, children }) => {
const rootClassName = cn(s.root, className); const rootClassName = cn(s.root, className)
const { displaySidebar } = useUI(); const { displaySidebar } = useUI()
return ( return (
<div className={rootClassName}> <div className={rootClassName}>
<Featurebar <Featurebar
@ -30,7 +30,7 @@ const Layout: FunctionComponent<Props> = ({ className, children }) => {
</Sidebar> </Sidebar>
)} )}
</div> </div>
); )
}; }
export default Layout; export default Layout

View File

@ -1 +1 @@
export { default } from "./Layout"; export { default } from './Layout'

View File

@ -1,15 +1,15 @@
import cn from "classnames"; import cn from 'classnames'
import React, { FunctionComponent } from "react"; import React, { FunctionComponent } from 'react'
import s from "./Navbar.module.css"; import s from './Navbar.module.css'
import { Logo, Container } from "@components/ui"; import { Logo, Container } from '@components/ui'
import { Searchbar } from "@components/core"; import { Searchbar } from '@components/core'
import { UserNav } from "@components/core"; import { UserNav } from '@components/core'
interface Props { interface Props {
className?: string; className?: string
} }
const Navbar: FunctionComponent<Props> = ({ className }) => { const Navbar: FunctionComponent<Props> = ({ className }) => {
const rootClassName = cn(s.root, className); const rootClassName = cn(s.root, className)
return ( return (
<Container className={rootClassName}> <Container className={rootClassName}>
<Logo /> <Logo />
@ -23,7 +23,7 @@ const Navbar: FunctionComponent<Props> = ({ className }) => {
</div> </div>
<UserNav /> <UserNav />
</Container> </Container>
); )
}; }
export default Navbar; export default Navbar

View File

@ -1 +1 @@
export { default } from "./Navbar"; export { default } from './Navbar'

View File

@ -1,14 +1,14 @@
import cn from "classnames"; import cn from 'classnames'
import React, { FunctionComponent } from "react"; import React, { FunctionComponent } from 'react'
import s from "./Searchbar.module.css"; import s from './Searchbar.module.css'
interface Props { interface Props {
className?: string; className?: string
children?: any; children?: any
} }
const Searchbar: FunctionComponent<Props> = ({ className }) => { const Searchbar: FunctionComponent<Props> = ({ className }) => {
const rootClassName = cn(s.root, className); const rootClassName = cn(s.root, className)
return ( return (
<div className={rootClassName}> <div className={rootClassName}>
<div className="flex-1 flex justify-between px-2"> <div className="flex-1 flex justify-between px-2">
@ -26,7 +26,7 @@ const Searchbar: FunctionComponent<Props> = ({ className }) => {
</div> </div>
</div> </div>
</div> </div>
); )
}; }
export default Searchbar; export default Searchbar

View File

@ -1 +1 @@
export { default } from "./Searchbar"; export { default } from './Searchbar'

View File

@ -1,17 +1,17 @@
import cn from "classnames"; import cn from 'classnames'
import React, { FunctionComponent } from "react"; import React, { FunctionComponent } from 'react'
import s from "./UserNav.module.css"; import s from './UserNav.module.css'
import { Avatar } from "@components/core"; import { Avatar } from '@components/core'
import { Heart, Bag } from "@components/icon"; import { Heart, Bag } from '@components/icon'
import { useUI } from "@components/ui/context"; import { useUI } from '@components/ui/context'
interface Props { interface Props {
className?: string; className?: string
} }
const UserNav: FunctionComponent<Props> = ({ className }) => { const UserNav: FunctionComponent<Props> = ({ className }) => {
const rootClassName = cn(s.root, className); const rootClassName = cn(s.root, className)
const { openSidebar } = useUI(); const { openSidebar } = useUI()
return ( return (
<nav className={rootClassName}> <nav className={rootClassName}>
@ -30,7 +30,7 @@ const UserNav: FunctionComponent<Props> = ({ className }) => {
</li> </li>
</ul> </ul>
</nav> </nav>
); )
}; }
export default UserNav; export default UserNav

View File

@ -1 +1 @@
export { default } from "./UserNav"; export { default } from './UserNav'

View File

@ -1,7 +1,7 @@
export { default as Avatar } from "./Avatar"; export { default as Avatar } from './Avatar'
export { default as Featurebar } from "./Featurebar"; export { default as Featurebar } from './Featurebar'
export { default as Footer } from "./Footer"; export { default as Footer } from './Footer'
export { default as Layout } from "./Layout"; export { default as Layout } from './Layout'
export { default as Navbar } from "./Navbar"; export { default as Navbar } from './Navbar'
export { default as Searchbar } from "./Searchbar"; export { default as Searchbar } from './Searchbar'
export { default as UserNav } from "./UserNav"; export { default as UserNav } from './UserNav'

View File

@ -1,4 +1,4 @@
import React from "react"; import React from 'react'
const Bag = ({ ...props }) => { const Bag = ({ ...props }) => {
return ( return (
@ -32,7 +32,7 @@ const Bag = ({ ...props }) => {
strokeLinejoin="round" strokeLinejoin="round"
/> />
</svg> </svg>
); )
}; }
export default Bag; export default Bag

View File

@ -1,4 +1,4 @@
import React from "react"; import React from 'react'
const Cross = ({ ...props }) => { const Cross = ({ ...props }) => {
return ( return (
@ -10,7 +10,7 @@ const Cross = ({ ...props }) => {
d="M6 18L18 6M6 6l12 12" d="M6 18L18 6M6 6l12 12"
/> />
</svg> </svg>
); )
}; }
export default Cross; export default Cross

View File

@ -1,4 +1,4 @@
import React from "react"; import React from 'react'
const Heart = ({ ...props }) => { const Heart = ({ ...props }) => {
return ( return (
@ -18,7 +18,7 @@ const Heart = ({ ...props }) => {
strokeLinejoin="round" strokeLinejoin="round"
/> />
</svg> </svg>
); )
}; }
export default Heart; export default Heart

View File

@ -1,4 +1,4 @@
import React from "react"; import React from 'react'
const Trash = ({ ...props }) => { const Trash = ({ ...props }) => {
return ( return (
@ -39,7 +39,7 @@ const Trash = ({ ...props }) => {
strokeLinejoin="round" strokeLinejoin="round"
/> />
</svg> </svg>
); )
}; }
export default Trash; export default Trash

View File

@ -1,4 +1,4 @@
export { default as Bag } from "./Bag"; export { default as Bag } from './Bag'
export { default as Heart } from "./Heart"; export { default as Heart } from './Heart'
export { default as Trash } from "./Trash"; export { default as Trash } from './Trash'
export { default as Cross } from "./Cross"; export { default as Cross } from './Cross'

View File

@ -1,14 +1,14 @@
import cn from "classnames"; import cn from 'classnames'
import s from "./ProductCard.module.css"; import s from './ProductCard.module.css'
import React, { FunctionComponent } from "react"; import React, { FunctionComponent } from 'react'
import { Heart } from "@components/icon"; import { Heart } from '@components/icon'
interface Props { interface Props {
className?: string; className?: string
children?: any; children?: any
} }
const ProductCard: FunctionComponent<Props> = ({ className }) => { const ProductCard: FunctionComponent<Props> = ({ className }) => {
const rootClassName = cn(s.root, className); const rootClassName = cn(s.root, className)
return ( return (
<div className={rootClassName}> <div className={rootClassName}>
<div className="absolute"> <div className="absolute">
@ -26,7 +26,7 @@ const ProductCard: FunctionComponent<Props> = ({ className }) => {
<div className="bg-violet h-full"></div> <div className="bg-violet h-full"></div>
</div> </div>
</div> </div>
); )
}; }
export default ProductCard; export default ProductCard

View File

@ -1 +1 @@
export { default } from "./ProductCard"; export { default } from './ProductCard'

View File

@ -1,15 +1,15 @@
import cn from "classnames"; import cn from 'classnames'
import React, { FunctionComponent } from "react"; import React, { FunctionComponent } from 'react'
import s from "./ProductGrid.module.css"; import s from './ProductGrid.module.css'
import ProductCard from "@components/ProductCard"; import ProductCard from '@components/ProductCard'
interface Props { interface Props {
className?: string; className?: string
children?: any; children?: any
products: [any]; products: [any]
} }
const ProductView: FunctionComponent<Props> = ({ products, className }) => { const ProductView: FunctionComponent<Props> = ({ products, className }) => {
const rootClassName = cn(s.root, className); const rootClassName = cn(s.root, className)
return ( return (
<div className={rootClassName}> <div className={rootClassName}>
<div className="row-span-2 lg:col-span-2 bg-violet h-full"></div> <div className="row-span-2 lg:col-span-2 bg-violet h-full"></div>
@ -19,7 +19,7 @@ const ProductView: FunctionComponent<Props> = ({ products, className }) => {
<div className="row-span-2 lg:col-span-2 bg-blue h-full"></div> <div className="row-span-2 lg:col-span-2 bg-blue h-full"></div>
<div className="row-span-1 lg:col-span-1 bg-cyan"></div> <div className="row-span-1 lg:col-span-1 bg-cyan"></div>
</div> </div>
); )
}; }
export default ProductView; export default ProductView

View File

@ -1 +1 @@
export { default } from "./ProductGrid"; export { default } from './ProductGrid'

View File

@ -1,18 +1,18 @@
import cn from "classnames"; import cn from 'classnames'
import React, { FunctionComponent } from "react"; import React, { FunctionComponent } from 'react'
import s from "./ProductView.module.css"; import s from './ProductView.module.css'
import { Button } from "@components/ui"; import { Button } from '@components/ui'
import { Swatch } from "@components/product"; import { Swatch } from '@components/product'
interface Props { interface Props {
className?: string; className?: string
children?: any; children?: any
productData: ProductData; productData: ProductData
} }
const ProductView: FunctionComponent<Props> = ({ productData, className }) => { const ProductView: FunctionComponent<Props> = ({ productData, className }) => {
const rootClassName = cn(s.root, className); const rootClassName = cn(s.root, className)
console.log(productData); console.log(productData)
return ( return (
<div className={rootClassName}> <div className={rootClassName}>
<div className="absolute"> <div className="absolute">
@ -53,7 +53,7 @@ const ProductView: FunctionComponent<Props> = ({ productData, className }) => {
</section> </section>
</div> </div>
</div> </div>
); )
}; }
export default ProductView; export default ProductView

View File

@ -1 +1 @@
export { default } from "./ProductView"; export { default } from './ProductView'

View File

@ -1,14 +1,14 @@
import cn from "classnames"; import cn from 'classnames'
import React, { FunctionComponent } from "react"; import React, { FunctionComponent } from 'react'
import s from "./Swatch.module.css"; import s from './Swatch.module.css'
import { Colors } from "@components/ui/types"; import { Colors } from '@components/ui/types'
interface Props { interface Props {
className?: string; className?: string
children?: any; children?: any
active?: boolean; active?: boolean
color?: Colors; color?: Colors
size?: string; size?: string
} }
const Swatch: FunctionComponent<Props> = ({ const Swatch: FunctionComponent<Props> = ({
@ -22,14 +22,14 @@ const Swatch: FunctionComponent<Props> = ({
{ {
[s.active]: active, [s.active]: active,
[s.size]: size, [s.size]: size,
[s.colorPink]: color === "pink", [s.colorPink]: color === 'pink',
[s.colorWhite]: color === "white", [s.colorWhite]: color === 'white',
[s.colorBlack]: color === "black", [s.colorBlack]: color === 'black',
[s.colorViolet]: color === "violet", [s.colorViolet]: color === 'violet',
}, },
className className
); )
return <span className={rootClassName}>{size ? size : null}</span>; return <span className={rootClassName}>{size ? size : null}</span>
}; }
export default Swatch; export default Swatch

View File

@ -1 +1 @@
export { default } from "./Swatch"; export { default } from './Swatch'

View File

@ -1,4 +1,4 @@
export { default as Swatch } from "./Swatch"; export { default as Swatch } from './Swatch'
export { default as ProductView } from "./ProductView"; export { default as ProductView } from './ProductView'
export { default as ProductCard } from "./ProductCard"; export { default as ProductCard } from './ProductCard'
export { default as ProductGrid } from "./ProductGrid"; export { default as ProductGrid } from './ProductGrid'

View File

@ -1,5 +1,5 @@
import { Colors } from "@components/ui/types"; import { Colors } from '@components/ui/types'
export { Product } from "@lib/bigcommerce"; export { Product } from '@lib/bigcommerce'
// export type ProductData = { // export type ProductData = {
// title: string; // title: string;

View File

@ -1,43 +1,43 @@
import cn from "classnames"; import cn from 'classnames'
import React, { ButtonHTMLAttributes } from "react"; import React, { ButtonHTMLAttributes } from 'react'
import s from "./Button.module.css"; import s from './Button.module.css'
interface Props extends ButtonHTMLAttributes<HTMLButtonElement> { interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
href?: string; href?: string
className?: string; className?: string
variant?: "filled" | "outlined" | "flat" | "none"; variant?: 'filled' | 'outlined' | 'flat' | 'none'
active?: boolean; active?: boolean
type?: "submit" | "reset" | "button"; type?: 'submit' | 'reset' | 'button'
} }
export default class Button extends React.Component<Props> { export default class Button extends React.Component<Props> {
public render() { public render() {
const { const {
className, className,
variant = "filled", variant = 'filled',
children, children,
disabled = false, disabled = false,
href, href,
active, active,
...rest ...rest
} = this.props; } = this.props
let Component: React.ComponentType< let Component: React.ComponentType<
React.AnchorHTMLAttributes< React.AnchorHTMLAttributes<
HTMLAnchorElement | HTMLButtonElement | HTMLDivElement HTMLAnchorElement | HTMLButtonElement | HTMLDivElement
> & > &
React.ClassAttributes<HTMLButtonElement | HTMLAnchorElement> React.ClassAttributes<HTMLButtonElement | HTMLAnchorElement>
> = "a" as any; > = 'a' as any
// Catch for buttons / span / stc. // Catch for buttons / span / stc.
const rootClassName = cn( const rootClassName = cn(
s.root, s.root,
{ {
[s.filled]: variant === "filled", [s.filled]: variant === 'filled',
}, },
className className
); )
return ( return (
<Component <Component
@ -49,6 +49,6 @@ export default class Button extends React.Component<Props> {
> >
{children} {children}
</Component> </Component>
); )
} }
} }

View File

@ -1 +1 @@
export { default } from "./Button"; export { default } from './Button'

View File

@ -3,47 +3,47 @@ import React, {
MutableRefObject, MutableRefObject,
useEffect, useEffect,
useRef, useRef,
} from "react"; } from 'react'
import { Component } from "react"; import { Component } from 'react'
import PropTypes from "prop-types"; import PropTypes from 'prop-types'
export interface ClickOutsideProps { export interface ClickOutsideProps {
onClickOutside: (e?: MouseEvent) => void; onClickOutside: (e?: MouseEvent) => void
children: React.ReactNode | any; children: React.ReactNode | any
render: () => void; render: () => void
} }
export default class ClickOutside extends Component<ClickOutsideProps> { export default class ClickOutside extends Component<ClickOutsideProps> {
public domNode: Element | null = null; public domNode: Element | null = null
handleRef = (element) => { handleRef = (element) => {
this.domNode = element; this.domNode = element
}; }
public componentDidMount() { public componentDidMount() {
document.addEventListener("click", this.handleClick, true); document.addEventListener('click', this.handleClick, true)
} }
public componentWillUnmount() { public componentWillUnmount() {
document.removeEventListener("mousedown", this.handleClick, true); document.removeEventListener('mousedown', this.handleClick, true)
document.removeEventListener("touchstart", this.handleClick, true); document.removeEventListener('touchstart', this.handleClick, true)
} }
public handleClick = (event) => { public handleClick = (event) => {
function hasParent(element, root) { function hasParent(element, root) {
return root && root.contains(element); return root && root.contains(element)
} }
if (!hasParent(event.target, this.domNode)) { if (!hasParent(event.target, this.domNode)) {
if (typeof this.props.onClickOutside === "function") { if (typeof this.props.onClickOutside === 'function') {
this.props.onClickOutside(event); this.props.onClickOutside(event)
} }
} }
}; }
render() { render() {
return null; return null
// return this.props.render({ // return this.props.render({
// innerRef: this.handleRef, // innerRef: this.handleRef,
// }); // });

View File

@ -1 +1 @@
export { default } from "./ClickOutside"; export { default } from './ClickOutside'

View File

@ -1,25 +1,25 @@
import cn from "classnames"; import cn from 'classnames'
import { FunctionComponent } from "react"; import { FunctionComponent } from 'react'
import s from "./Container.module.css"; import s from './Container.module.css'
interface Props { interface Props {
className?: string; className?: string
children?: any; children?: any
el?: HTMLElement; el?: HTMLElement
} }
const Container: FunctionComponent<Props> = ({ const Container: FunctionComponent<Props> = ({
children, children,
className, className,
el = "div", el = 'div',
}) => { }) => {
const rootClassName = cn(s.root, className); const rootClassName = cn(s.root, className)
let Component: React.ComponentType<React.HTMLAttributes< let Component: React.ComponentType<React.HTMLAttributes<
HTMLDivElement HTMLDivElement
>> = el as any; >> = el as any
return <Component className={rootClassName}>{children}</Component>; return <Component className={rootClassName}>{children}</Component>
}; }
export default Container; export default Container

View File

@ -1 +1 @@
export { default } from "./Container"; export { default } from './Container'

View File

@ -35,6 +35,6 @@ const Logo = () => (
strokeWidth="0.30634" strokeWidth="0.30634"
/> />
</svg> </svg>
); )
export default Logo; export default Logo

View File

@ -1 +1 @@
export { default } from "./Logo"; export { default } from './Logo'

View File

@ -1,14 +1,14 @@
import cn from "classnames"; import cn from 'classnames'
import React, { FunctionComponent } from "react"; import React, { FunctionComponent } from 'react'
import s from "./Sidebar.module.css"; import s from './Sidebar.module.css'
interface Props { interface Props {
className?: string; className?: string
children?: any; children?: any
} }
const Sidebar: FunctionComponent<Props> = ({ className, children }) => { const Sidebar: FunctionComponent<Props> = ({ className, children }) => {
const rootClassName = cn(s.root, className); const rootClassName = cn(s.root, className)
return ( return (
<div className={rootClassName}> <div className={rootClassName}>
<div className="fixed inset-0 overflow-hidden shadow-sm bg-black bg-opacity-25"> <div className="fixed inset-0 overflow-hidden shadow-sm bg-black bg-opacity-25">
@ -23,7 +23,7 @@ const Sidebar: FunctionComponent<Props> = ({ className, children }) => {
</div> </div>
</div> </div>
</div> </div>
); )
}; }
export default Sidebar; export default Sidebar

View File

@ -1 +1 @@
export { default } from "./Sidebar"; export { default } from './Sidebar'

View File

@ -1,15 +1,15 @@
import cn from "classnames"; import cn from 'classnames'
import { FunctionComponent } from "react"; import { FunctionComponent } from 'react'
import s from "./Featurebar.module.css"; import s from './Featurebar.module.css'
interface Props { interface Props {
className?: string; className?: string
children?: any; children?: any
} }
const Featurebar: FunctionComponent<Props> = ({ children, className }) => { const Featurebar: FunctionComponent<Props> = ({ children, className }) => {
const rootClassName = cn(s.root, className); const rootClassName = cn(s.root, className)
return <div className={rootClassName}>{children}</div>; return <div className={rootClassName}>{children}</div>
}; }
export default Featurebar; export default Featurebar

View File

@ -1 +1 @@
export { default } from "./Featurebar"; export { default } from './Featurebar'

View File

@ -1,56 +1,56 @@
import React, { FunctionComponent } from "react"; import React, { FunctionComponent } from 'react'
export interface UIState { export interface UIState {
displaySidebar: boolean; displaySidebar: boolean
openSidebar: () => {}; openSidebar: () => {}
closeSidebar: () => {}; closeSidebar: () => {}
} }
const initialState = { const initialState = {
displaySidebar: false, displaySidebar: false,
openSidebar: null, openSidebar: null,
closeSidebar: null, closeSidebar: null,
}; }
export const UIContext = React.createContext(initialState); export const UIContext = React.createContext(initialState)
UIContext.displayName = "UIContext"; UIContext.displayName = 'UIContext'
export const UIProvider: FunctionComponent = (props) => { export const UIProvider: FunctionComponent = (props) => {
const [state, dispatch] = React.useReducer(uiReducer, initialState); const [state, dispatch] = React.useReducer(uiReducer, initialState)
const openSidebar = () => dispatch("OPEN_SIDEBAR"); const openSidebar = () => dispatch('OPEN_SIDEBAR')
const closeSidebar = () => dispatch("CLOSE_SIDEBAR"); const closeSidebar = () => dispatch('CLOSE_SIDEBAR')
const value = { const value = {
...state, ...state,
openSidebar, openSidebar,
closeSidebar, closeSidebar,
}; }
return <UIContext.Provider value={value} {...props} />; return <UIContext.Provider value={value} {...props} />
}; }
export const useUI = () => { export const useUI = () => {
const context = React.useContext(UIContext); const context = React.useContext(UIContext)
if (context === undefined) { if (context === undefined) {
throw new Error(`useUI must be used within a UIProvider`); throw new Error(`useUI must be used within a UIProvider`)
} }
return context; return context
}; }
function uiReducer(state, action) { function uiReducer(state, action) {
switch (action) { switch (action) {
case "OPEN_SIDEBAR": { case 'OPEN_SIDEBAR': {
return { return {
...state, ...state,
displaySidebar: true, displaySidebar: true,
}; }
} }
case "CLOSE_SIDEBAR": { case 'CLOSE_SIDEBAR': {
return { return {
...state, ...state,
displaySidebar: false, displaySidebar: false,
}; }
} }
} }
} }

View File

@ -1,4 +1,4 @@
export { default as Button } from "./Button"; export { default as Button } from './Button'
export { default as Container } from "./Container"; export { default as Container } from './Container'
export { default as Sidebar } from "./Sidebar"; export { default as Sidebar } from './Sidebar'
export { default as Logo } from "./Logo"; export { default as Logo } from './Logo'

View File

@ -1 +1 @@
export type Colors = "violet" | "black" | "pink" | "white"; export type Colors = 'violet' | 'black' | 'pink' | 'white'

View File

@ -5,7 +5,7 @@ export const responsiveImageFragment = /* GraphQL */ `
urlLarge: url(width: $imgLargeWidth, height: $imgLargeHeight) urlLarge: url(width: $imgLargeWidth, height: $imgLargeHeight)
urlXL: url(width: $imgXLWidth, height: $imgXLHeight) urlXL: url(width: $imgXLWidth, height: $imgXLHeight)
} }
`; `
export const productInfoFragment = /* GraphQL */ ` export const productInfoFragment = /* GraphQL */ `
fragment productInfo on Product { fragment productInfo on Product {
@ -63,4 +63,4 @@ export const productInfoFragment = /* GraphQL */ `
} }
${responsiveImageFragment} ${responsiveImageFragment}
`; `

View File

@ -1,17 +1,17 @@
import { CommerceAPIConfig } from 'lib/commerce/api'; import { CommerceAPIConfig } from 'lib/commerce/api'
import { GetAllProductsQueryVariables } from '../schema'; import { GetAllProductsQueryVariables } from '../schema'
import fetchAPI from './utils/fetch-api'; import fetchAPI from './utils/fetch-api'
export interface Images { export interface Images {
small?: ImageOptions; small?: ImageOptions
medium?: ImageOptions; medium?: ImageOptions
large?: ImageOptions; large?: ImageOptions
xl?: ImageOptions; xl?: ImageOptions
} }
export interface ImageOptions { export interface ImageOptions {
width: number; width: number
height?: number; height?: number
} }
export type ProductImageVariables = Pick< export type ProductImageVariables = Pick<
@ -24,39 +24,39 @@ export type ProductImageVariables = Pick<
| 'imgLargeHeight' | 'imgLargeHeight'
| 'imgXLWidth' | 'imgXLWidth'
| 'imgXLHeight' | 'imgXLHeight'
>; >
export interface BigcommerceConfigOptions extends CommerceAPIConfig { export interface BigcommerceConfigOptions extends CommerceAPIConfig {
images?: Images; images?: Images
} }
export interface BigcommerceConfig extends BigcommerceConfigOptions { export interface BigcommerceConfig extends BigcommerceConfigOptions {
readonly imageVariables?: ProductImageVariables; readonly imageVariables?: ProductImageVariables
} }
const API_URL = process.env.BIGCOMMERCE_STOREFRONT_API_URL; const API_URL = process.env.BIGCOMMERCE_STOREFRONT_API_URL
const API_TOKEN = process.env.BIGCOMMERCE_STOREFRONT_API_TOKEN; const API_TOKEN = process.env.BIGCOMMERCE_STOREFRONT_API_TOKEN
if (!API_URL) { if (!API_URL) {
throw new Error( throw new Error(
`The environment variable BIGCOMMERCE_STOREFRONT_API_URL is missing and it's required to access your store` `The environment variable BIGCOMMERCE_STOREFRONT_API_URL is missing and it's required to access your store`
); )
} }
if (!API_TOKEN) { if (!API_TOKEN) {
throw new Error( throw new Error(
`The environment variable BIGCOMMERCE_STOREFRONT_API_TOKEN is missing and it's required to access your store` `The environment variable BIGCOMMERCE_STOREFRONT_API_TOKEN is missing and it's required to access your store`
); )
} }
export class Config { export class Config {
private config: BigcommerceConfig; private config: BigcommerceConfig
constructor(config: BigcommerceConfigOptions) { constructor(config: BigcommerceConfigOptions) {
this.config = { this.config = {
...config, ...config,
get imageVariables() { get imageVariables() {
const { images } = this; const { images } = this
return images return images
? { ? {
imgSmallWidth: images.small?.width, imgSmallWidth: images.small?.width,
@ -68,17 +68,17 @@ export class Config {
imgXLWidth: images.xl?.height, imgXLWidth: images.xl?.height,
imgXLHeight: images.xl?.height, imgXLHeight: images.xl?.height,
} }
: undefined; : undefined
}, },
}; }
} }
getConfig() { getConfig() {
return this.config; return this.config
} }
setConfig(newConfig: Partial<BigcommerceConfig>) { setConfig(newConfig: Partial<BigcommerceConfig>) {
Object.assign(this.config, newConfig); Object.assign(this.config, newConfig)
} }
} }
@ -86,12 +86,12 @@ const config = new Config({
commerceUrl: API_URL, commerceUrl: API_URL,
apiToken: API_TOKEN, apiToken: API_TOKEN,
fetch: fetchAPI, fetch: fetchAPI,
}); })
export function getConfig() { export function getConfig() {
return config.getConfig(); return config.getConfig()
} }
export function setConfig(newConfig: Partial<BigcommerceConfig>) { export function setConfig(newConfig: Partial<BigcommerceConfig>) {
return config.setConfig(newConfig); return config.setConfig(newConfig)
} }

View File

@ -1,6 +1,6 @@
import type { GetAllProductPathsQuery } from 'lib/bigcommerce/schema'; import type { GetAllProductPathsQuery } from 'lib/bigcommerce/schema'
import type { RecursivePartial, RecursiveRequired } from '../utils/types'; import type { RecursivePartial, RecursiveRequired } from '../utils/types'
import { BigcommerceConfig, getConfig } from '..'; import { BigcommerceConfig, getConfig } from '..'
export const getAllProductPathsQuery = /* GraphQL */ ` export const getAllProductPathsQuery = /* GraphQL */ `
query getAllProductPaths { query getAllProductPaths {
@ -14,41 +14,41 @@ export const getAllProductPathsQuery = /* GraphQL */ `
} }
} }
} }
`; `
export interface GetAllProductPathsResult<T> { export interface GetAllProductPathsResult<T> {
products: T extends GetAllProductPathsQuery products: T extends GetAllProductPathsQuery
? NonNullable<T['site']['products']['edges']> ? NonNullable<T['site']['products']['edges']>
: unknown; : unknown
} }
async function getAllProductPaths(opts?: { async function getAllProductPaths(opts?: {
query?: string; query?: string
config?: BigcommerceConfig; config?: BigcommerceConfig
}): Promise<GetAllProductPathsResult<GetAllProductPathsQuery>>; }): Promise<GetAllProductPathsResult<GetAllProductPathsQuery>>
async function getAllProductPaths<T, V = any>(opts: { async function getAllProductPaths<T, V = any>(opts: {
query: string; query: string
config?: BigcommerceConfig; config?: BigcommerceConfig
}): Promise<GetAllProductPathsResult<T>>; }): Promise<GetAllProductPathsResult<T>>
async function getAllProductPaths({ async function getAllProductPaths({
query = getAllProductPathsQuery, query = getAllProductPathsQuery,
config = getConfig(), config = getConfig(),
}: { }: {
query?: string; query?: string
config?: BigcommerceConfig; config?: BigcommerceConfig
} = {}): Promise<GetAllProductPathsResult<GetAllProductPathsQuery>> { } = {}): Promise<GetAllProductPathsResult<GetAllProductPathsQuery>> {
// RecursivePartial forces the method to check for every prop in the data, which is // RecursivePartial forces the method to check for every prop in the data, which is
// required in case there's a custom `query` // required in case there's a custom `query`
const data = await config.fetch<RecursivePartial<GetAllProductPathsQuery>>( const data = await config.fetch<RecursivePartial<GetAllProductPathsQuery>>(
query query
); )
const products = data.site?.products?.edges; const products = data.site?.products?.edges
return { return {
products: (products as RecursiveRequired<typeof products>) ?? [], products: (products as RecursiveRequired<typeof products>) ?? [],
}; }
} }
export default getAllProductPaths; export default getAllProductPaths

View File

@ -1,15 +1,10 @@
import type { import type {
GetAllProductsQuery, GetAllProductsQuery,
GetAllProductsQueryVariables, GetAllProductsQueryVariables,
} from 'lib/bigcommerce/schema'; } from 'lib/bigcommerce/schema'
import type { RecursivePartial, RecursiveRequired } from '../utils/types'; import type { RecursivePartial, RecursiveRequired } from '../utils/types'
import { productInfoFragment } from '../fragments/product'; import { productInfoFragment } from '../fragments/product'
import { import { BigcommerceConfig, getConfig, Images, ProductImageVariables } from '..'
BigcommerceConfig,
getConfig,
Images,
ProductImageVariables,
} from '..';
export const getAllProductsQuery = /* GraphQL */ ` export const getAllProductsQuery = /* GraphQL */ `
query getAllProducts( query getAllProducts(
@ -40,53 +35,53 @@ export const getAllProductsQuery = /* GraphQL */ `
} }
${productInfoFragment} ${productInfoFragment}
`; `
export interface GetAllProductsResult<T> { export interface GetAllProductsResult<T> {
products: T extends GetAllProductsQuery products: T extends GetAllProductsQuery
? NonNullable<T['site']['products']['edges']> ? NonNullable<T['site']['products']['edges']>
: unknown; : unknown
} }
export type ProductVariables = Images & export type ProductVariables = Images &
Omit<GetAllProductsQueryVariables, keyof ProductImageVariables>; Omit<GetAllProductsQueryVariables, keyof ProductImageVariables>
async function getAllProducts(opts?: { async function getAllProducts(opts?: {
query?: string; query?: string
variables?: ProductVariables; variables?: ProductVariables
config?: BigcommerceConfig; config?: BigcommerceConfig
}): Promise<GetAllProductsResult<GetAllProductsQuery>>; }): Promise<GetAllProductsResult<GetAllProductsQuery>>
async function getAllProducts<T, V = any>(opts: { async function getAllProducts<T, V = any>(opts: {
query: string; query: string
variables?: V; variables?: V
config?: BigcommerceConfig; config?: BigcommerceConfig
}): Promise<GetAllProductsResult<T>>; }): Promise<GetAllProductsResult<T>>
async function getAllProducts({ async function getAllProducts({
query = getAllProductsQuery, query = getAllProductsQuery,
variables: vars, variables: vars,
config = getConfig(), config = getConfig(),
}: { }: {
query?: string; query?: string
variables?: ProductVariables; variables?: ProductVariables
config?: BigcommerceConfig; config?: BigcommerceConfig
} = {}): Promise<GetAllProductsResult<GetAllProductsQuery>> { } = {}): Promise<GetAllProductsResult<GetAllProductsQuery>> {
const variables: GetAllProductsQueryVariables = { const variables: GetAllProductsQueryVariables = {
...config.imageVariables, ...config.imageVariables,
...vars, ...vars,
}; }
// RecursivePartial forces the method to check for every prop in the data, which is // RecursivePartial forces the method to check for every prop in the data, which is
// required in case there's a custom `query` // required in case there's a custom `query`
const data = await config.fetch<RecursivePartial<GetAllProductsQuery>>( const data = await config.fetch<RecursivePartial<GetAllProductsQuery>>(
query, query,
{ variables } { variables }
); )
const products = data.site?.products?.edges; const products = data.site?.products?.edges
return { return {
products: (products as RecursiveRequired<typeof products>) ?? [], products: (products as RecursiveRequired<typeof products>) ?? [],
}; }
} }
export default getAllProducts; export default getAllProducts

View File

@ -1,10 +1,10 @@
import type { import type {
GetProductQuery, GetProductQuery,
GetProductQueryVariables, GetProductQueryVariables,
} from 'lib/bigcommerce/schema'; } from 'lib/bigcommerce/schema'
import type { RecursivePartial, RecursiveRequired } from '../utils/types'; import type { RecursivePartial, RecursiveRequired } from '../utils/types'
import { productInfoFragment } from '../fragments/product'; import { productInfoFragment } from '../fragments/product'
import { BigcommerceConfig, getConfig, Images } from '..'; import { BigcommerceConfig, getConfig, Images } from '..'
export const getProductQuery = /* GraphQL */ ` export const getProductQuery = /* GraphQL */ `
query getProduct( query getProduct(
@ -31,55 +31,55 @@ export const getProductQuery = /* GraphQL */ `
} }
${productInfoFragment} ${productInfoFragment}
`; `
export interface GetProductResult<T> { export interface GetProductResult<T> {
product?: T extends GetProductQuery product?: T extends GetProductQuery
? Extract<T['site']['route']['node'], { __typename: 'Product' }> ? Extract<T['site']['route']['node'], { __typename: 'Product' }>
: unknown; : unknown
} }
export type ProductVariables = Images & export type ProductVariables = Images &
({ path: string; slug?: never } | { path?: never; slug: string }); ({ path: string; slug?: never } | { path?: never; slug: string })
async function getProduct(opts: { async function getProduct(opts: {
query?: string; query?: string
variables: ProductVariables; variables: ProductVariables
config?: BigcommerceConfig; config?: BigcommerceConfig
}): Promise<GetProductResult<GetProductQuery>>; }): Promise<GetProductResult<GetProductQuery>>
async function getProduct<T, V = any>(opts: { async function getProduct<T, V = any>(opts: {
query: string; query: string
variables: V; variables: V
config?: BigcommerceConfig; config?: BigcommerceConfig
}): Promise<GetProductResult<T>>; }): Promise<GetProductResult<T>>
async function getProduct({ async function getProduct({
query = getProductQuery, query = getProductQuery,
variables: { slug, ...vars }, variables: { slug, ...vars },
config = getConfig(), config = getConfig(),
}: { }: {
query?: string; query?: string
variables: ProductVariables; variables: ProductVariables
config?: BigcommerceConfig; config?: BigcommerceConfig
}): Promise<GetProductResult<GetProductQuery>> { }): Promise<GetProductResult<GetProductQuery>> {
const variables: GetProductQueryVariables = { const variables: GetProductQueryVariables = {
...config.imageVariables, ...config.imageVariables,
...vars, ...vars,
path: slug ? `/${slug}/` : vars.path!, path: slug ? `/${slug}/` : vars.path!,
}; }
const data = await config.fetch<RecursivePartial<GetProductQuery>>(query, { const data = await config.fetch<RecursivePartial<GetProductQuery>>(query, {
variables, variables,
}); })
const product = data.site?.route?.node; const product = data.site?.route?.node
if (product?.__typename === 'Product') { if (product?.__typename === 'Product') {
return { return {
product: product as RecursiveRequired<typeof product>, product: product as RecursiveRequired<typeof product>,
}; }
} }
return {}; return {}
} }
export default getProduct; export default getProduct

View File

@ -1,11 +1,11 @@
import { CommerceAPIFetchOptions } from 'lib/commerce/api'; import { CommerceAPIFetchOptions } from 'lib/commerce/api'
import { getConfig } from '..'; import { getConfig } from '..'
export default async function fetchAPI<Q, V = any>( export default async function fetchAPI<Q, V = any>(
query: string, query: string,
{ variables, preview }: CommerceAPIFetchOptions<V> = {} { variables, preview }: CommerceAPIFetchOptions<V> = {}
): Promise<Q> { ): Promise<Q> {
const config = getConfig(); const config = getConfig()
const res = await fetch(config.commerceUrl + (preview ? '/preview' : ''), { const res = await fetch(config.commerceUrl + (preview ? '/preview' : ''), {
method: 'POST', method: 'POST',
headers: { headers: {
@ -16,12 +16,12 @@ export default async function fetchAPI<Q, V = any>(
query, query,
variables, variables,
}), }),
}); })
const json = await res.json(); const json = await res.json()
if (json.errors) { if (json.errors) {
console.error(json.errors); console.error(json.errors)
throw new Error('Failed to fetch API'); throw new Error('Failed to fetch API')
} }
return json.data; return json.data
} }

View File

@ -1,7 +1,7 @@
export type RecursivePartial<T> = { export type RecursivePartial<T> = {
[P in keyof T]?: RecursivePartial<T[P]>; [P in keyof T]?: RecursivePartial<T[P]>
}; }
export type RecursiveRequired<T> = { export type RecursiveRequired<T> = {
[P in keyof T]-?: RecursiveRequired<T[P]>; [P in keyof T]-?: RecursiveRequired<T[P]>
}; }

View File

@ -1,14 +1,14 @@
import { import {
CartProvider as CommerceCartProvider, CartProvider as CommerceCartProvider,
useCart as useCommerceCart, useCart as useCommerceCart,
} from 'lib/commerce/cart'; } from 'lib/commerce/cart'
export type Cart = any; export type Cart = any
export function CartProvider({ children }) { export function CartProvider({ children }) {
return <CommerceCartProvider>{children}</CommerceCartProvider>; return <CommerceCartProvider>{children}</CommerceCartProvider>
} }
export function useCart() { export function useCart() {
return useCommerceCart<Cart>(); return useCommerceCart<Cart>()
} }

View File

@ -2,38 +2,38 @@ import {
CommerceProvider as CoreCommerceProvider, CommerceProvider as CoreCommerceProvider,
Connector, Connector,
useCommerce as useCoreCommerce, useCommerce as useCoreCommerce,
} from 'lib/commerce'; } from 'lib/commerce'
async function getText(res: Response) { async function getText(res: Response) {
try { try {
return (await res.text()) || res.statusText; return (await res.text()) || res.statusText
} catch (error) { } catch (error) {
return res.statusText; return res.statusText
} }
} }
async function getError(res: Response) { async function getError(res: Response) {
if (res.headers.get('Content-Type')?.includes('application/json')) { if (res.headers.get('Content-Type')?.includes('application/json')) {
const data = await res.json(); const data = await res.json()
return data.errors[0]; return data.errors[0]
} }
return { message: await getText(res) }; return { message: await getText(res) }
} }
async function fetcher(url: string, query: string) { async function fetcher(url: string, query: string) {
const res = await fetch(url); const res = await fetch(url)
if (res.ok) { if (res.ok) {
return res.json(); return res.json()
} }
throw await getError(res); throw await getError(res)
} }
export const bigcommerce: Connector = { export const bigcommerce: Connector = {
locale: 'en-us', locale: 'en-us',
fetcher, fetcher,
}; }
// TODO: The connector should be extendable when a developer is using it // TODO: The connector should be extendable when a developer is using it
export function CommerceProvider({ children }) { export function CommerceProvider({ children }) {
@ -41,7 +41,7 @@ export function CommerceProvider({ children }) {
<CoreCommerceProvider connector={bigcommerce}> <CoreCommerceProvider connector={bigcommerce}>
{children} {children}
</CoreCommerceProvider> </CoreCommerceProvider>
); )
} }
export const useCommerce = () => useCoreCommerce(); export const useCommerce = () => useCoreCommerce()

View File

@ -1,105 +1,105 @@
import { useState, useCallback } from "react"; import { useState, useCallback } from 'react'
import useSWR, { mutate } from "swr"; import useSWR, { mutate } from 'swr'
async function getText(res) { async function getText(res) {
try { try {
return (await res.text()) || res.statusText; return (await res.text()) || res.statusText
} catch (error) { } catch (error) {
return res.statusText; return res.statusText
} }
} }
async function getError(res) { async function getError(res) {
if (res.headers.get("Content-Type")?.includes("application/json")) { if (res.headers.get('Content-Type')?.includes('application/json')) {
const data = await res.json(); const data = await res.json()
return data.errors[0]; return data.errors[0]
} }
return { message: await getText(res) }; return { message: await getText(res) }
} }
async function fetcher(url) { async function fetcher(url) {
const res = await fetch(url); const res = await fetch(url)
if (res.status === 200) { if (res.status === 200) {
return res.json(); return res.json()
} }
throw await getError(res); throw await getError(res)
} }
export function useCart() { export function useCart() {
return useSWR("/api/cart", fetcher); return useSWR('/api/cart', fetcher)
} }
export function useAddToCart() { export function useAddToCart() {
const [{ addingToCart, error }, setStatus] = useState({ const [{ addingToCart, error }, setStatus] = useState({
addingToCart: false, addingToCart: false,
}); })
const addToCart = useCallback(async ({ product }) => { const addToCart = useCallback(async ({ product }) => {
setStatus({ addingToCart: true }); setStatus({ addingToCart: true })
const res = await fetch("/api/cart", { const res = await fetch('/api/cart', {
method: "POST", method: 'POST',
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json',
}, },
body: JSON.stringify({ product }), body: JSON.stringify({ product }),
}); })
// Product added as expected // Product added as expected
if (res.status === 200) { if (res.status === 200) {
setStatus({ addingToCart: false }); setStatus({ addingToCart: false })
return mutate("/api/cart"); return mutate('/api/cart')
} }
const error = await getError(res); const error = await getError(res)
console.error("Adding product to cart failed with:", res.status, error); console.error('Adding product to cart failed with:', res.status, error)
setStatus({ addingToCart: false, error }); setStatus({ addingToCart: false, error })
}, []); }, [])
return { addToCart, addingToCart, error }; return { addToCart, addingToCart, error }
} }
export function useUpdateCart() { export function useUpdateCart() {
const [{ updatingCart, error }, setStatus] = useState({ const [{ updatingCart, error }, setStatus] = useState({
updatingCart: false, updatingCart: false,
}); })
const updateCart = useCallback(async ({ product, item }) => { const updateCart = useCallback(async ({ product, item }) => {
setStatus({ updatingCart: true }); setStatus({ updatingCart: true })
const res = await fetch( const res = await fetch(
`/api/cart?itemId=${item.id}`, `/api/cart?itemId=${item.id}`,
product.quantity < 1 product.quantity < 1
? { method: "DELETE" } ? { method: 'DELETE' }
: { : {
method: "PUT", method: 'PUT',
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json',
}, },
body: JSON.stringify({ product }), body: JSON.stringify({ product }),
} }
); )
// Product updated as expected // Product updated as expected
if (res.status === 200) { if (res.status === 200) {
setStatus({ updatingCart: false }); setStatus({ updatingCart: false })
return mutate("/api/cart"); return mutate('/api/cart')
} }
const error = await getError(res); const error = await getError(res)
console.error("Update to cart failed with:", res.status, error); console.error('Update to cart failed with:', res.status, error)
setStatus({ updatingCart: false, error }); setStatus({ updatingCart: false, error })
}, []); }, [])
return { updateCart, updatingCart, error }; return { updateCart, updatingCart, error }
} }
export function useRemoveFromCart() { export function useRemoveFromCart() {
const { updateCart, updatingCart, error } = useUpdateCart(); const { updateCart, updatingCart, error } = useUpdateCart()
const removeFromCart = async ({ item }) => { const removeFromCart = async ({ item }) => {
updateCart({ item, product: { quantity: 0 } }); updateCart({ item, product: { quantity: 0 } })
}; }
return { removeFromCart, removingFromCart: updatingCart, error }; return { removeFromCart, removingFromCart: updatingCart, error }
} }

View File

@ -1,15 +1,15 @@
export interface CommerceAPIConfig { export interface CommerceAPIConfig {
commerceUrl: string; commerceUrl: string
apiToken: string; apiToken: string
fetch<Q, V = any>( fetch<Q, V = any>(
query: string, query: string,
queryData?: CommerceAPIFetchOptions<V> queryData?: CommerceAPIFetchOptions<V>
): Promise<Q>; ): Promise<Q>
} }
export interface CommerceAPIFetchOptions<V> { export interface CommerceAPIFetchOptions<V> {
variables?: V; variables?: V
preview?: boolean; preview?: boolean
} }
// TODO: define interfaces for all the available operations // TODO: define interfaces for all the available operations

View File

@ -1,37 +1,37 @@
import { createContext, useContext } from 'react'; import { createContext, useContext } from 'react'
import useSWR, { responseInterface } from 'swr'; import useSWR, { responseInterface } from 'swr'
import { useCommerce } from '.'; import { useCommerce } from '.'
export type Cart = any; export type Cart = any
export type CartResponse<C extends Cart> = responseInterface<C, Error> & { export type CartResponse<C extends Cart> = responseInterface<C, Error> & {
isEmpty: boolean; isEmpty: boolean
}; }
const CartContext = createContext<CartResponse<Cart>>(null); const CartContext = createContext<CartResponse<Cart>>(null)
function getCartCookie() { function getCartCookie() {
// TODO: Figure how the cart should be persisted // TODO: Figure how the cart should be persisted
return null; return null
} }
export function CartProvider({ children }) { export function CartProvider({ children }) {
const { hooks, fetcher } = useCommerce<Cart>(); const { hooks, fetcher } = useCommerce<Cart>()
const { useCart } = hooks; const { useCart } = hooks
const cartId = getCartCookie(); const cartId = getCartCookie()
const response = useSWR( const response = useSWR(
() => (cartId ? [useCart.url, useCart.query, useCart.resolver] : null), () => (cartId ? [useCart.url, useCart.query, useCart.resolver] : null),
fetcher fetcher
); )
const isEmpty = true; const isEmpty = true
return ( return (
<CartContext.Provider value={{ ...response, isEmpty }}> <CartContext.Provider value={{ ...response, isEmpty }}>
{children} {children}
</CartContext.Provider> </CartContext.Provider>
); )
} }
export function useCart<C extends Cart>() { export function useCart<C extends Cart>() {
return useContext(CartContext) as CartResponse<C>; return useContext(CartContext) as CartResponse<C>
} }

View File

@ -1,29 +1,29 @@
import { createContext, ReactNode, useContext } from 'react'; import { createContext, ReactNode, useContext } from 'react'
const Commerce = createContext<Connector>(null); const Commerce = createContext<Connector>(null)
export type CommerceProps = { export type CommerceProps = {
children?: ReactNode; children?: ReactNode
connector: Connector; connector: Connector
}; }
export type Connector = { export type Connector = {
fetcher: Fetcher<any>; fetcher: Fetcher<any>
locale: string; locale: string
}; }
export type Fetcher<T> = (...args: any) => T | Promise<T>; export type Fetcher<T> = (...args: any) => T | Promise<T>
export function CommerceProvider({ children, connector }: CommerceProps) { export function CommerceProvider({ children, connector }: CommerceProps) {
if (!connector) { if (!connector) {
throw new Error( throw new Error(
'CommerceProvider requires a valid headless commerce connector' 'CommerceProvider requires a valid headless commerce connector'
); )
} }
return <Commerce.Provider value={connector}>{children}</Commerce.Provider>; return <Commerce.Provider value={connector}>{children}</Commerce.Provider>
} }
export function useCommerce<T extends Connector>() { export function useCommerce<T extends Connector>() {
return useContext(Commerce) as T; return useContext(Commerce) as T
} }

View File

@ -1,6 +1,6 @@
import "@assets/global.css"; import '@assets/global.css'
import React from "react"; import React from 'react'
import { UIProvider } from "@components/ui/context"; import { UIProvider } from '@components/ui/context'
export default function MyApp({ Component, pageProps }) { export default function MyApp({ Component, pageProps }) {
return ( return (
@ -9,5 +9,5 @@ export default function MyApp({ Component, pageProps }) {
<Component {...pageProps} /> <Component {...pageProps} />
</UIProvider> </UIProvider>
</> </>
); )
} }

View File

@ -1,4 +1,4 @@
import Document_, { Html, Head, Main, NextScript } from "next/document"; import Document_, { Html, Head, Main, NextScript } from 'next/document'
export default class Document extends Document_ { export default class Document extends Document_ {
render() { render() {
@ -13,6 +13,6 @@ export default class Document extends Document_ {
*/} */}
</body> </body>
</Html> </Html>
); )
} }
} }

View File

@ -1,22 +1,22 @@
import { GetStaticPropsContext, InferGetStaticPropsType } from "next"; import { GetStaticPropsContext, InferGetStaticPropsType } from 'next'
import getAllProducts from "lib/bigcommerce/api/operations/get-all-products"; import getAllProducts from 'lib/bigcommerce/api/operations/get-all-products'
import { Layout } from "@components/core"; import { Layout } from '@components/core'
import { ProductGrid } from "@components/product"; import { ProductGrid } from '@components/product'
export async function getStaticProps({ preview }: GetStaticPropsContext) { export async function getStaticProps({ preview }: GetStaticPropsContext) {
const { products } = await getAllProducts(); const { products } = await getAllProducts()
return { return {
props: { products }, props: { products },
}; }
} }
export default function Home({ export default function Home({
products, products,
}: InferGetStaticPropsType<typeof getStaticProps>) { }: InferGetStaticPropsType<typeof getStaticProps>) {
console.log("PRODUCTS", products); console.log('PRODUCTS', products)
return ( return (
<Layout> <Layout>
<ProductGrid products={products} /> <ProductGrid products={products} />
</Layout> </Layout>
); )
} }

View File

@ -1,14 +1,14 @@
import { GetStaticPropsContext, InferGetStaticPropsType } from 'next'; import { GetStaticPropsContext, InferGetStaticPropsType } from 'next'
import { useRouter } from 'next/router'; import { useRouter } from 'next/router'
import getProduct from 'lib/bigcommerce/api/operations/get-product'; import getProduct from 'lib/bigcommerce/api/operations/get-product'
import { Layout } from '@components/core'; import { Layout } from '@components/core'
import { ProductView } from '@components/product'; import { ProductView } from '@components/product'
import getAllProductPaths from '@lib/bigcommerce/api/operations/get-all-product-paths'; import getAllProductPaths from '@lib/bigcommerce/api/operations/get-all-product-paths'
export async function getStaticProps({ export async function getStaticProps({
params, params,
}: GetStaticPropsContext<{ slug: string }>) { }: GetStaticPropsContext<{ slug: string }>) {
const { product } = await getProduct({ variables: { slug: params!.slug } }); const { product } = await getProduct({ variables: { slug: params!.slug } })
const productData = { const productData = {
title: 'T-Shirt', title: 'T-Shirt',
description: ` description: `
@ -22,34 +22,34 @@ export async function getStaticProps({
price: '$50', price: '$50',
colors: ['black', 'white', 'pink'], colors: ['black', 'white', 'pink'],
sizes: ['s', 'm', 'l', 'xl', 'xxl'], sizes: ['s', 'm', 'l', 'xl', 'xxl'],
}; }
return { return {
props: { props: {
product, product,
productData, productData,
}, },
revalidate: 200, revalidate: 200,
}; }
} }
export async function getStaticPaths() { export async function getStaticPaths() {
const { products } = await getAllProductPaths(); const { products } = await getAllProductPaths()
return { return {
paths: products.map((product) => ({ paths: products.map((product) => ({
params: { slug: product!.node.path }, params: { slug: product!.node.path },
})), })),
fallback: 'unstable_blocking', fallback: 'unstable_blocking',
}; }
} }
export default function Home({ export default function Home({
product, product,
productData, productData,
}: InferGetStaticPropsType<typeof getStaticProps>) { }: InferGetStaticPropsType<typeof getStaticProps>) {
console.log('PRODUCT', product); console.log('PRODUCT', product)
const router = useRouter(); const router = useRouter()
return ( return (
<Layout> <Layout>
@ -59,5 +59,5 @@ export default function Home({
<ProductView productData={productData} /> <ProductView productData={productData} />
)} )}
</Layout> </Layout>
); )
} }

View File

@ -1,18 +1,18 @@
module.exports = { module.exports = {
plugins: [ plugins: [
"tailwindcss", 'tailwindcss',
"postcss-flexbugs-fixes", 'postcss-flexbugs-fixes',
[ [
"postcss-preset-env", 'postcss-preset-env',
{ {
autoprefixer: { autoprefixer: {
flexbox: "no-2009", flexbox: 'no-2009',
}, },
stage: 3, stage: 3,
features: { features: {
"custom-properties": false, 'custom-properties': false,
}, },
}, },
], ],
], ],
}; }

View File

@ -3,25 +3,25 @@ module.exports = {
removeDeprecatedGapUtilities: true, removeDeprecatedGapUtilities: true,
}, },
purge: [ purge: [
"./components/**/*.{js,ts,jsx,tsx}", './components/**/*.{js,ts,jsx,tsx}',
"./pages/**/*.{js,ts,jsx,tsx}", './pages/**/*.{js,ts,jsx,tsx}',
"./ui/**/*.{js,ts,jsx,tsx}", './ui/**/*.{js,ts,jsx,tsx}',
], ],
theme: { theme: {
extend: { extend: {
colors: { colors: {
"accent-1": "#FAFAFA", 'accent-1': '#FAFAFA',
"accent-4": "#888", 'accent-4': '#888',
violet: "#7928CA", violet: '#7928CA',
pink: "#FF0080", pink: '#FF0080',
cyan: "#50E3C2", cyan: '#50E3C2',
blue: "#0070F3", blue: '#0070F3',
}, },
}, },
}, },
variants: {}, variants: {},
plugins: [require("@tailwindcss/ui")], plugins: [require('@tailwindcss/ui')],
experimental: { experimental: {
applyComplexClasses: true, applyComplexClasses: true,
}, },
}; }