Skip to content

Commit eac19c2

Browse files
committed
build: add example
1 parent 81b819c commit eac19c2

23 files changed

+2195
-1323
lines changed

.gitignore

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
# misc
1212
.DS_Store
1313

14-
/example
15-
1614
/**/.cache
1715
/**/.parcel-cache
1816
npm-debug.log*

example/index.html

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="utf-8" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1" />
7+
<meta name="theme-color" content="#000000" />
8+
<meta name="description"
9+
content="Web site with infinite scroll examples created by using react-scroll-percentage-hook" />
10+
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
11+
<title>react-scroll-percentage-hook</title>
12+
</head>
13+
14+
<body>
15+
<div id="root"></div>
16+
<script type="module" src="/src/index.tsx"></script>
17+
</body>
18+
19+
</html>

example/package.json

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"name": "example",
3+
"version": "1.0.0",
4+
"license": "MIT",
5+
"homepage": "https://vdmrgv.github.io/react-scroll-percentage-hook",
6+
"type": "module",
7+
"scripts": {
8+
"dev": "vite",
9+
"build": "tsc && vite build",
10+
"preview": "vite preview",
11+
"predeploy": "yarn build",
12+
"deploy": "gh-pages -d dist"
13+
},
14+
"alias": {
15+
"react": "../node_modules/react",
16+
"react-dom": "../node_modules/react-dom"
17+
},
18+
"dependencies": {
19+
"@emotion/react": "^11.10.4",
20+
"@emotion/styled": "^11.10.4",
21+
"@mui/icons-material": "^5.10.9",
22+
"@mui/material": "^5.10.9",
23+
"react-router-dom": "^6.4.2",
24+
"react-scroll-percentage-hook": "^1.0.2"
25+
},
26+
"devDependencies": {
27+
"@types/node": "^18.8.5",
28+
"@types/react": "^18.0.21",
29+
"@types/react-dom": "^18.0.6",
30+
"@vitejs/plugin-react": "^2.0.0",
31+
"gh-pages": "^4.0.0",
32+
"process": "^0.11.10",
33+
"typescript": "^4.8.4",
34+
"vite": "^3.0.2"
35+
}
36+
}

example/src/App.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { HashRouter, Routes, Route } from 'react-router-dom';
2+
import Layout from './components/Layout';
3+
import { Home } from './pages';
4+
import { sidebarNavs, routes } from './routes';
5+
6+
const App = () => (
7+
<HashRouter>
8+
<Layout sidebar={{ navs: sidebarNavs }}>
9+
<Routes>
10+
{routes.map(({ path, Component }) => (
11+
<Route key={path} path={path} element={<Component />} />
12+
))}
13+
<Route path="/" element={<Home />} />
14+
<Route path="*" element={<Home />} />
15+
</Routes>
16+
</Layout>
17+
</HashRouter>
18+
);
19+
20+
export default App;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import React from 'react';
2+
import Typography from '@mui/material/Typography';
3+
import { Link } from '@mui/material';
4+
5+
interface ExampleCardProps {
6+
children: React.ReactNode;
7+
title?: string;
8+
description?: string;
9+
source?: string;
10+
}
11+
12+
const ExampleCard = ({ children, title, description, source }: ExampleCardProps) => (
13+
<>
14+
{title && (
15+
<Typography variant="h6" fontWeight="bold">
16+
{title}{' '}
17+
{source && (
18+
<Link variant="body2" target="_blank" href={source} rel="noreferrer noopener">
19+
Source
20+
</Link>
21+
)}
22+
</Typography>
23+
)}
24+
{description && <Typography variant="body2">{description}</Typography>}
25+
{children}
26+
</>
27+
);
28+
29+
export default ExampleCard;

example/src/components/Header.tsx

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { Link } from '@mui/material';
2+
import { gitHubLink, npmLink } from '../links';
3+
4+
const links = [
5+
{
6+
url: gitHubLink,
7+
label: 'GitHub',
8+
},
9+
{
10+
url: npmLink,
11+
label: 'npm',
12+
},
13+
];
14+
15+
const Header = () => (
16+
<header className="App-header">
17+
<span className="App-header-content">
18+
<Link href="#" color="inherit" variant="body1" fontWeight="bold" underline="none">
19+
react-scroll-percentage-hook
20+
</Link>
21+
</span>
22+
<span className="App-header-content">
23+
{links.map(({ label, url }) => (
24+
<Link
25+
key={label}
26+
className="App-link"
27+
target="_blank"
28+
href={url}
29+
rel="noreferrer noopener"
30+
color="inherit"
31+
variant="body2"
32+
>
33+
{label}
34+
</Link>
35+
))}
36+
</span>
37+
</header>
38+
);
39+
40+
export default Header;

example/src/components/Item.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import React from 'react';
2+
import Typography from '@mui/material/Typography';
3+
4+
interface ItemProps {
5+
index: number | string;
6+
content: string;
7+
className?: string;
8+
style?: React.CSSProperties;
9+
}
10+
11+
const Item = ({ index, content, className, style }: ItemProps) => {
12+
return (
13+
<div className={`Item ${className ? className : ''}`} style={style}>
14+
<Typography className="Item-index" variant="caption">
15+
#{index}
16+
</Typography>
17+
<Typography>{content}</Typography>
18+
</div>
19+
);
20+
};
21+
22+
export default Item;

example/src/components/Layout.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import Box from '@mui/material/Box';
2+
import Paper from '@mui/material/Paper';
3+
import Grid from '@mui/material/Grid';
4+
import Header from './Header';
5+
import Sidebar, { SidebarProps } from './Sidebar';
6+
7+
interface LayoutProps {
8+
children: React.ReactNode;
9+
sidebar: SidebarProps;
10+
}
11+
12+
const Layout = ({ children, sidebar }: LayoutProps) => {
13+
return (
14+
<>
15+
<Header />
16+
<main className="App-layout">
17+
<Box className="App-layout-container" sx={{ flexGrow: 1 }}>
18+
<Grid container spacing={0}>
19+
<Grid item xs={12} md={2}>
20+
<Sidebar {...sidebar} />
21+
</Grid>
22+
<Grid item xs={12} md="auto">
23+
<Paper className="App-layout-paper" elevation={0}>
24+
{children}
25+
</Paper>
26+
</Grid>
27+
</Grid>
28+
</Box>
29+
</main>
30+
</>
31+
);
32+
};
33+
34+
export default Layout;

example/src/components/Sidebar.tsx

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { Fragment, useState } from 'react';
2+
import { useNavigate, useLocation } from 'react-router-dom';
3+
import ListSubheader from '@mui/material/ListSubheader';
4+
import List from '@mui/material/List';
5+
import ListItemButton from '@mui/material/ListItemButton';
6+
import ListItemText from '@mui/material/ListItemText';
7+
import { Collapse } from '@mui/material';
8+
import ExpandLess from '@mui/icons-material/ExpandLess';
9+
import ExpandMore from '@mui/icons-material/ExpandMore';
10+
11+
interface NavInfo {
12+
name: string;
13+
path: string;
14+
}
15+
16+
type NavItem = NavInfo & {
17+
subs: NavInfo[];
18+
};
19+
20+
export interface SidebarProps {
21+
navs: NavItem[];
22+
}
23+
24+
const Sidebar = ({ navs }: SidebarProps) => {
25+
const navigate = useNavigate();
26+
const location = useLocation();
27+
28+
const isCurrentNavSubOpen = (path: string, subs: NavInfo[]) =>
29+
subs.some((s) => `${path}${s.path}` === location.pathname);
30+
31+
const getOpenedNav = (): string => {
32+
const nav = navs.find((n) => isCurrentNavSubOpen(n.path, n.subs));
33+
34+
return nav ? nav.path : navs.length ? navs[0].path : '';
35+
};
36+
37+
const [open, setOpen] = useState(getOpenedNav());
38+
const isCurrentNav = (path: string) => open === path;
39+
40+
const handleOpenNavGroup = (path: string) => () => {
41+
setOpen((prev) => (prev !== path ? path : ''));
42+
};
43+
44+
const handleGoToNav = (path: string) => () => navigate(path);
45+
46+
return (
47+
<List
48+
sx={{ width: '100%', height: '100%', bgcolor: '#f9f7f4' }}
49+
component="nav"
50+
aria-labelledby="nested-list-subheader"
51+
subheader={
52+
<ListSubheader sx={{ position: 'inherit', bgcolor: '#f9f7f4' }} component="div" id="nested-list-subheader">
53+
Examples
54+
</ListSubheader>
55+
}
56+
>
57+
{navs.map((n) => (
58+
<Fragment key={n.path}>
59+
<ListItemButton
60+
onClick={handleOpenNavGroup(n.path)}
61+
selected={!isCurrentNav(n.path) && isCurrentNavSubOpen(n.path, n.subs)}
62+
>
63+
<ListItemText primary={n.name} primaryTypographyProps={{ variant: 'body2' }} />
64+
{isCurrentNav(n.path) ? <ExpandLess fontSize="small" /> : <ExpandMore fontSize="small" />}
65+
</ListItemButton>
66+
<Collapse in={isCurrentNav(n.path)} timeout="auto" unmountOnExit>
67+
<List component="div" disablePadding>
68+
{n.subs.map((s) => (
69+
<ListItemButton
70+
key={s.path}
71+
sx={{ pl: 4 }}
72+
onClick={handleGoToNav(`${n.path}${s.path}`)}
73+
selected={isCurrentNavSubOpen(n.path, [s])}
74+
>
75+
<ListItemText primary={s.name} primaryTypographyProps={{ variant: 'body2' }} />
76+
</ListItemButton>
77+
))}
78+
</List>
79+
</Collapse>
80+
</Fragment>
81+
))}
82+
</List>
83+
);
84+
};
85+
86+
export default Sidebar;

0 commit comments

Comments
 (0)