mainstack-payments 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.sample +1 -0
- package/.eslintignore +5 -0
- package/.eslintrc.json +95 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +15 -0
- package/.husky/commit-msg +4 -0
- package/.husky/pre-commit +6 -0
- package/.prettierignore +7 -0
- package/.prettierrc +9 -0
- package/.vscode/extensions.json +10 -0
- package/README.md +113 -0
- package/build/_redirects +1 -0
- package/build/mainstack-payments.js +97183 -0
- package/build/manifest.json +15 -0
- package/build/robots.txt +3 -0
- package/build/style.css +6 -0
- package/build/vite.svg +1 -0
- package/commitlint.config.cjs +1 -0
- package/index.html +31 -0
- package/package.json +86 -0
- package/public/_redirects +1 -0
- package/public/manifest.json +15 -0
- package/public/robots.txt +3 -0
- package/public/vite.svg +1 -0
- package/src/api/config.ts +36 -0
- package/src/api/index.ts +84 -0
- package/src/app.tsx +39 -0
- package/src/assets/images/tired-emoji.png +0 -0
- package/src/assets/styles/index.css +26 -0
- package/src/assets/themes/baseThemes.ts +30 -0
- package/src/components/CheckoutForm.tsx +426 -0
- package/src/components/DrawerModal.tsx +63 -0
- package/src/components/Payment.tsx +772 -0
- package/src/components/PaystackPaymentErrorModal.tsx +120 -0
- package/src/components/PaystackPaymentModal.tsx +120 -0
- package/src/components/WalletPay.tsx +160 -0
- package/src/constants/index.ts +3 -0
- package/src/enums/currenciesEnums.ts +7 -0
- package/src/hooks/usePayment.ts +60 -0
- package/src/index.ts +3 -0
- package/src/pages/Home.tsx +97 -0
- package/src/pages/Index.tsx +23 -0
- package/src/pages/Login.tsx +13 -0
- package/src/pages/Page404.tsx +13 -0
- package/src/pages/PaymentRedirect.tsx +15 -0
- package/src/routes/index.tsx +8 -0
- package/src/types/index.ts +48 -0
- package/src/utils/countries-flag.json +1752 -0
- package/src/utils/countries_flag.json +1502 -0
- package/src/utils/countries_with_flags_and_currencies.json +4004 -0
- package/src/utils/formatUnderscoreText.ts +5 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/stringifyPrice.ts +37 -0
- package/src/utils/validations.ts +44 -0
- package/tsconfig.json +35 -0
- package/vite.config.ts +36 -0
package/build/vite.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = { extends: ['@commitlint/config-conventional'] }
|
package/index.html
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<!-- @format -->
|
|
2
|
+
|
|
3
|
+
<!DOCTYPE html>
|
|
4
|
+
<html lang="en">
|
|
5
|
+
<head>
|
|
6
|
+
<meta charset="UTF-8" />
|
|
7
|
+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
8
|
+
<meta
|
|
9
|
+
name="viewport"
|
|
10
|
+
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
|
|
11
|
+
/>
|
|
12
|
+
<meta
|
|
13
|
+
name="viewport"
|
|
14
|
+
content="height=device-height, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
|
|
15
|
+
/>
|
|
16
|
+
<title>Mainstach template</title>
|
|
17
|
+
<script>
|
|
18
|
+
let vh = window.innerHeight * 0.01;
|
|
19
|
+
document.documentElement.style.setProperty("--vh", `${vh}px`);
|
|
20
|
+
window.addEventListener("resize", () => {
|
|
21
|
+
let vh = window.innerHeight * 0.01;
|
|
22
|
+
document.documentElement.style.setProperty("--vh", `${vh}px`);
|
|
23
|
+
});
|
|
24
|
+
</script>
|
|
25
|
+
</head>
|
|
26
|
+
<body>
|
|
27
|
+
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
28
|
+
<div id="root"></div>
|
|
29
|
+
<script type="module" src="src/app.tsx"></script>
|
|
30
|
+
</body>
|
|
31
|
+
</html>
|
package/package.json
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mainstack-payments",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"main": "build/mainstack-payments.js",
|
|
6
|
+
"types": "build/src/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "vite",
|
|
9
|
+
"build": "tsc && vite build",
|
|
10
|
+
"preview": "vite preview --port 5001",
|
|
11
|
+
"format": "prettier src -c --write && pretty-quick --staged",
|
|
12
|
+
"lint": "eslint src --ext .js,.jsx,.ts,.tsx --quiet --fix",
|
|
13
|
+
"ts-error": "./node_modules/.bin/tsc",
|
|
14
|
+
"postinstall": "husky install",
|
|
15
|
+
"prepare": "husky install",
|
|
16
|
+
"scriptname": "cmd"
|
|
17
|
+
},
|
|
18
|
+
"browserslist": {
|
|
19
|
+
"production": [
|
|
20
|
+
">0.2%",
|
|
21
|
+
"not dead",
|
|
22
|
+
"not op_mini all"
|
|
23
|
+
],
|
|
24
|
+
"development": [
|
|
25
|
+
"last 1 chrome version",
|
|
26
|
+
"last 1 firefox version",
|
|
27
|
+
"last 1 safari version"
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@chakra-ui/react": "^2.5.1",
|
|
32
|
+
"@stripe/react-stripe-js": "^2.7.1",
|
|
33
|
+
"@stripe/stripe-js": "^4.0.0",
|
|
34
|
+
"@tanstack/react-query": "^5.45.1",
|
|
35
|
+
"axios": "^1.7.2",
|
|
36
|
+
"eslint-config-prettier": "^8.6.0",
|
|
37
|
+
"eslint-plugin-prettier": "^4.2.1",
|
|
38
|
+
"formik": "^2.4.6",
|
|
39
|
+
"framer-motion": "^10.0.1",
|
|
40
|
+
"mainstack-design-system": "^0.4.8",
|
|
41
|
+
"postcode-validator": "^3.8.21",
|
|
42
|
+
"prettier": "^2.8.4",
|
|
43
|
+
"pretty-quick": "^3.1.3",
|
|
44
|
+
"react": "^18.2.0",
|
|
45
|
+
"react-dom": "^18.2.0",
|
|
46
|
+
"react-paystack": "^5.0.0",
|
|
47
|
+
"react-router-dom": "^6.8.1",
|
|
48
|
+
"typescript": "^4.9.5",
|
|
49
|
+
"uuid": "^10.0.0",
|
|
50
|
+
"vite-plugin-env-compatible": "^1.1.1",
|
|
51
|
+
"vite-plugin-svgr": "^2.4.0",
|
|
52
|
+
"vite-tsconfig-paths": "^4.0.5",
|
|
53
|
+
"yup": "^1.4.0"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@commitlint/cli": "17.1.2",
|
|
57
|
+
"@commitlint/config-conventional": "17.1.0",
|
|
58
|
+
"@types/react": "^18.0.28",
|
|
59
|
+
"@types/react-dom": "^18.0.11",
|
|
60
|
+
"@types/uuid": "^10.0.0",
|
|
61
|
+
"@typescript-eslint/eslint-plugin": "^5.53.0",
|
|
62
|
+
"@typescript-eslint/parser": "^5.53.0",
|
|
63
|
+
"@vitejs/plugin-react": "^3.1.0",
|
|
64
|
+
"eslint": "^8.35.0",
|
|
65
|
+
"eslint-config-airbnb": "^19.0.4",
|
|
66
|
+
"eslint-config-airbnb-typescript": "^17.0.0",
|
|
67
|
+
"eslint-import-resolver-typescript": "^3.5.3",
|
|
68
|
+
"eslint-plugin-import": "^2.27.5",
|
|
69
|
+
"eslint-plugin-jsx-a11y": "^6.7.1",
|
|
70
|
+
"eslint-plugin-react": "^7.32.2",
|
|
71
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
|
72
|
+
"husky": "^8.0.3",
|
|
73
|
+
"vite": "^4.1.0"
|
|
74
|
+
},
|
|
75
|
+
"description": "A React library to use Mainstack Payments",
|
|
76
|
+
"repository": {
|
|
77
|
+
"type": "git",
|
|
78
|
+
"url": "git+https://D-Ajiva@github.com/The-Mainstack/mainstack-payments.git"
|
|
79
|
+
},
|
|
80
|
+
"author": "david-aji",
|
|
81
|
+
"license": "ISC",
|
|
82
|
+
"bugs": {
|
|
83
|
+
"url": "https://github.com/The-Mainstack/mainstack-payments/issues"
|
|
84
|
+
},
|
|
85
|
+
"homepage": "https://github.com/The-Mainstack/mainstack-payments#readme"
|
|
86
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/* /index.html 200
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"short_name": "Mainstack Template",
|
|
3
|
+
"name": "This is a template to build mainstack app going forward",
|
|
4
|
+
"icons": [
|
|
5
|
+
{
|
|
6
|
+
"src": "vite.svg",
|
|
7
|
+
"sizes": "64x64 32x32 24x24 16x16",
|
|
8
|
+
"type": "image/x-icon"
|
|
9
|
+
}
|
|
10
|
+
],
|
|
11
|
+
"start_url": ".",
|
|
12
|
+
"display": "standalone",
|
|
13
|
+
"theme_color": "#000000",
|
|
14
|
+
"background_color": "#ffffff"
|
|
15
|
+
}
|
package/public/vite.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** @format */
|
|
2
|
+
|
|
3
|
+
import axios, { AxiosHeaders, AxiosRequestConfig } from "axios";
|
|
4
|
+
|
|
5
|
+
const InitializeAPIConfig = (baseUrl: string, authMSUrl: string) => {
|
|
6
|
+
const Request = axios.create({
|
|
7
|
+
baseURL: baseUrl,
|
|
8
|
+
timeout: 30000,
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const AuthMSRequest = axios.create({
|
|
12
|
+
baseURL: authMSUrl,
|
|
13
|
+
timeout: 30000,
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const requestConfiguration = (config: AxiosRequestConfig) => {
|
|
17
|
+
return {
|
|
18
|
+
...config,
|
|
19
|
+
headers: {
|
|
20
|
+
Authorization: `Basic dXNlcm5hbWU6cGFzc3dvcmQ=`,
|
|
21
|
+
...config.headers,
|
|
22
|
+
} as unknown as AxiosHeaders,
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
Request.interceptors.request.use(requestConfiguration, (error) => {
|
|
27
|
+
return Promise.reject(error);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
AuthMSRequest.interceptors.request.use(requestConfiguration, (error) => {
|
|
31
|
+
return Promise.reject(error);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
return { Request, AuthMSRequest };
|
|
35
|
+
};
|
|
36
|
+
export default InitializeAPIConfig;
|
package/src/api/index.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/** @format */
|
|
2
|
+
|
|
3
|
+
import { useQuery, useMutation } from "@tanstack/react-query";
|
|
4
|
+
import axios from "axios";
|
|
5
|
+
import { TMetadata } from "types";
|
|
6
|
+
|
|
7
|
+
export const useGetTransactionFees = (
|
|
8
|
+
{
|
|
9
|
+
account_id,
|
|
10
|
+
currency,
|
|
11
|
+
amount,
|
|
12
|
+
slug,
|
|
13
|
+
}: {
|
|
14
|
+
account_id: string;
|
|
15
|
+
currency: string;
|
|
16
|
+
amount: number;
|
|
17
|
+
slug?: string;
|
|
18
|
+
},
|
|
19
|
+
AuthMSRequest: any
|
|
20
|
+
) =>
|
|
21
|
+
useQuery({
|
|
22
|
+
queryKey: ["getTransactionFees", account_id, currency, amount, slug],
|
|
23
|
+
queryFn: () =>
|
|
24
|
+
AuthMSRequest.get(
|
|
25
|
+
`/payments/fees?account_id=${account_id}¤cy=${currency}&amount=${amount}${
|
|
26
|
+
slug ? `&slug=${slug}` : ""
|
|
27
|
+
}`
|
|
28
|
+
)
|
|
29
|
+
.then((res: any) => res.data)
|
|
30
|
+
.catch((err: any) => {
|
|
31
|
+
throw err.response.data;
|
|
32
|
+
}),
|
|
33
|
+
enabled: !!(amount && amount > 0),
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
interface IInitPayment {
|
|
37
|
+
amount: number;
|
|
38
|
+
reference: string;
|
|
39
|
+
currency: string;
|
|
40
|
+
metadata: TMetadata;
|
|
41
|
+
}
|
|
42
|
+
export const useInitPayment = (Request: any) =>
|
|
43
|
+
useMutation({
|
|
44
|
+
mutationFn: async (data: IInitPayment) => {
|
|
45
|
+
try {
|
|
46
|
+
const res = await Request.post(`payments/init`, data);
|
|
47
|
+
return res.data;
|
|
48
|
+
} catch (error: any) {
|
|
49
|
+
throw error?.response?.data;
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
interface IChargePayment {
|
|
55
|
+
amount: number;
|
|
56
|
+
currency: string;
|
|
57
|
+
callback_url?: string;
|
|
58
|
+
metadata: TMetadata;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export const useChargePayment = (Request: any) =>
|
|
62
|
+
useMutation({
|
|
63
|
+
mutationFn: async (data: IChargePayment) => {
|
|
64
|
+
try {
|
|
65
|
+
const res = await Request.post("/payments/charge", data);
|
|
66
|
+
return res.data;
|
|
67
|
+
} catch (error: any) {
|
|
68
|
+
throw error?.response?.data;
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
export const useVerifyPayment = (reference: string, Request: any) =>
|
|
74
|
+
useQuery({
|
|
75
|
+
queryKey: ["verifyPayment", reference],
|
|
76
|
+
queryFn: () =>
|
|
77
|
+
Request.get(`payments/verify/${reference}`)
|
|
78
|
+
.then((res: any) => res?.data)
|
|
79
|
+
.catch((err: any) => {
|
|
80
|
+
throw err?.response?.data;
|
|
81
|
+
}),
|
|
82
|
+
enabled: false,
|
|
83
|
+
refetchOnWindowFocus: false,
|
|
84
|
+
});
|
package/src/app.tsx
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/** @format */
|
|
2
|
+
|
|
3
|
+
import { StrictMode } from "react";
|
|
4
|
+
import { createRoot } from "react-dom/client";
|
|
5
|
+
import Index from "pages/Index";
|
|
6
|
+
import "assets/styles/index.css";
|
|
7
|
+
import { ChakraProvider } from "@chakra-ui/react";
|
|
8
|
+
import { theme } from "assets/themes/baseThemes";
|
|
9
|
+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
10
|
+
import {
|
|
11
|
+
CustomSnackbarContainer,
|
|
12
|
+
MainstackProvider,
|
|
13
|
+
} from "mainstack-design-system";
|
|
14
|
+
|
|
15
|
+
const AppToRender = () => {
|
|
16
|
+
const queryClient = new QueryClient({
|
|
17
|
+
defaultOptions: {
|
|
18
|
+
queries: {
|
|
19
|
+
retry: 1,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
return (
|
|
24
|
+
<StrictMode>
|
|
25
|
+
<QueryClientProvider client={queryClient}>
|
|
26
|
+
<ChakraProvider theme={theme}>
|
|
27
|
+
<MainstackProvider>
|
|
28
|
+
<CustomSnackbarContainer />
|
|
29
|
+
<Index />
|
|
30
|
+
</MainstackProvider>
|
|
31
|
+
</ChakraProvider>
|
|
32
|
+
</QueryClientProvider>
|
|
33
|
+
</StrictMode>
|
|
34
|
+
);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const root = createRoot(document.getElementById("root") as Element);
|
|
38
|
+
|
|
39
|
+
root.render(<AppToRender />);
|
|
Binary file
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** @format */
|
|
2
|
+
|
|
3
|
+
@import url("https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;500;600;700&display=swap");
|
|
4
|
+
|
|
5
|
+
:root {
|
|
6
|
+
line-height: 1.5;
|
|
7
|
+
font-weight: 400;
|
|
8
|
+
font-synthesis: none;
|
|
9
|
+
text-rendering: optimizeLegibility;
|
|
10
|
+
-webkit-font-smoothing: antialiased;
|
|
11
|
+
-moz-osx-font-smoothing: grayscale;
|
|
12
|
+
-webkit-text-size-adjust: 100%;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
#root {
|
|
16
|
+
width: 100%;
|
|
17
|
+
min-height: 100vh;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
body {
|
|
21
|
+
margin: 0;
|
|
22
|
+
font-family: "Open Sans";
|
|
23
|
+
-webkit-font-smoothing: antialiased;
|
|
24
|
+
-moz-osx-font-smoothing: grayscale;
|
|
25
|
+
overscroll-behavior: none;
|
|
26
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** @format */
|
|
2
|
+
|
|
3
|
+
import { extendTheme } from "@chakra-ui/react";
|
|
4
|
+
|
|
5
|
+
// baseTheme.fonts?.heading
|
|
6
|
+
|
|
7
|
+
const config = {
|
|
8
|
+
initialColorMode: "light",
|
|
9
|
+
useSystemColorMode: false,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const theme = extendTheme({
|
|
13
|
+
config,
|
|
14
|
+
colors: {
|
|
15
|
+
//
|
|
16
|
+
},
|
|
17
|
+
fonts: {
|
|
18
|
+
//
|
|
19
|
+
},
|
|
20
|
+
fontSizes: {
|
|
21
|
+
h1: "40px",
|
|
22
|
+
h2: "24px",
|
|
23
|
+
h3: "24px",
|
|
24
|
+
p: "20px",
|
|
25
|
+
body: "16px",
|
|
26
|
+
button: "18px",
|
|
27
|
+
mini: "16px",
|
|
28
|
+
small: "14px",
|
|
29
|
+
},
|
|
30
|
+
});
|