Skip to content

Commit

Permalink
Merge branch 'master' into feat-changeset
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaohuoni authored Nov 5, 2024
2 parents 714bf57 + 3f0e76f commit 8ef1093
Show file tree
Hide file tree
Showing 33 changed files with 1,016 additions and 2 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ $ npx @umijs/tnf create myapp --template=simple
$ cd myapp
$ npm install
$ npm run build
$ npx serve dist
$ npx serve dist -s
```

## Commands
Expand Down
20 changes: 20 additions & 0 deletions examples/hackernews/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "@examples/hackernews",
"private": true,
"scripts": {
"build": "tnf build",
"dev": "tnf dev",
"preview": "npx serve dist -s"
},
"dependencies": {
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@umijs/tnf": "workspace:*",
"classnames": "^2.5.1",
"firebase": "^2.4.2"
},
"devDependencies": {
"@total-typescript/tsconfig": "^1.0.4",
"typescript": "^5.6.3"
}
}
13 changes: 13 additions & 0 deletions examples/hackernews/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>tnf-hackernews</title>
<link href="/client.css" rel="stylesheet" />
</head>
<body>
<div id="root"></div>
<script src="/client.js"></script>
</body>
</html>
33 changes: 33 additions & 0 deletions examples/hackernews/src/components/comment/index.module.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
.normal {
border-top: 1px solid #eee;
position: relative;
}

.expand {
cursor: pointer;
}

.by,
.text {
font-size: 0.9em;
padding: 1em 0;
}

.by {
color: #999;
padding-bottom: 0;
a {
color: #999;
text-decoration: underline;
}
}

.text {
a:hover {
color: #ff6600;
}
}

.commentChildren {
margin-left: 1em;
}
55 changes: 55 additions & 0 deletions examples/hackernews/src/components/comment/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React, { useEffect, useState } from 'react';
import { Link } from '@umijs/tnf/router';
import { fetchItem } from '../../services';
import { pluralize, timeAgo } from '../../utils';
import styles from './index.module.less';

export default function Comment({ id, itemsById }) {
const [open, setOpen] = useState(true);
const [comment, setComment] = useState(null);

useEffect(() => {
async function fetchComments() {
setComment(await fetchItem(id));
}

fetchComments();
}, []);

if (!comment) return null;
return (
<div className={styles.normal}>
<div className={styles.by}>
<Link to={`/user/${comment.by}`}>{comment.by}</Link>
<span>{` ${timeAgo(comment.time)} ago`}</span>
{comment.kids ? (
<span>
{' '}
|{' '}
<a
href=""
className={styles.expand}
onClick={(e) => {
e.preventDefault();
setOpen(!open);
}}
>
{`${open ? 'collapse' : 'expand'} ${pluralize(comment.kids.length)}`}
</a>
</span>
) : null}
</div>
<div
className={styles.text}
dangerouslySetInnerHTML={{ __html: comment.text }}
/>
<div className={styles.commentChildren}>
{comment.kids && open
? comment.kids.map((id) => (
<Comment key={id} id={id} itemsById={itemsById} />
))
: null}
</div>
</div>
);
}
57 changes: 57 additions & 0 deletions examples/hackernews/src/components/item-list/index.module.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
.nav {
background-color: #fff;
border-radius: 2px;
padding: 15px 30px;
position: fixed;
text-align: center;
top: 55px;
left: 0;
right: 0;
z-index: 998;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);

a {
margin: 0 1em;
}
.disabled {
color: #ccc;
}
}

.list {
background-color: #fff;
border-radius: 2px;
position: absolute;
margin: 72px 0 30px;
width: 100%;
transition: all 0.5s cubic-bezier(0.55, 0, 0.1, 1);
}

@media (max-width: 600px) {
.list {
margin: 10px 0;
}
}

:global {
.list-leave.list-leave-active,
.list-enter {
opacity: 0.01;
}
.list-leave,
.list-enter.list-enter-active {
opacity: 1;
}

.item-leave.item-leave-active,
.item-enter {
opacity: 0.01;
transform: translate(30px, 0);
}
.item-leave,
.item-enter.item-enter-active {
opacity: 1;
transform: translate(0, 0);
transition: all 0.5s cubic-bezier(0.55, 0, 0.1, 1);
}
}
75 changes: 75 additions & 0 deletions examples/hackernews/src/components/item-list/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { useContext, useEffect, useMemo, useState } from 'react';
import { Link } from '@umijs/tnf/router';
import { Context } from '../../context';
import { fetchIdsByType, fetchItems } from '../../services';
import Item from '../item';
import Loading from '../loading';
import styles from './index.module.less';

export default function ItemList({ type, page }) {
const { dispatch } = useContext(Context);
const [lists, setLists] = useState({
top: [],
new: [],
show: [],
ask: [],
job: [],
});
const [items, setItems] = useState([]);
const [loading, setLoading] = useState(true);

const itemsPerPage = 20;
const maxPage = useMemo(
() => Math.ceil(lists[type].length / itemsPerPage),
[lists],
);

useEffect(() => {
async function fetchList() {
const ids = await fetchIdsByType(type);
setLists({ ...lists, [type]: ids });
const items = await fetchItems(
ids.slice(itemsPerPage * (page - 1), itemsPerPage * page),
);
const itemsById = items.reduce((_memo, item) => {
const memo = _memo;
memo[item.id] = item;
return memo;
}, {});
setLoading(false);
setItems(items);
dispatch({ type: 'saveItems', payload: itemsById });
}

fetchList();
}, [page]);

return (
<>
<div className={styles.nav}>
{page > 1 ? (
<Link to={`/${type}/$page`} params={{ page: page - 1 }}>
&lt; prev
</Link>
) : (
<a className={styles.disabled}>&lt; prev</a>
)}
<span>{`${page}/${maxPage}`}</span>
{page < maxPage ? (
<Link to={`/${type}/$page`} params={{ page: page + 1 }}>
more &gt;
</Link>
) : (
<a className={styles.disabled}>more &gt;</a>
)}
</div>

<div className={styles.list}>
<Loading loading={loading} />
{items.map((item) => (
<Item key={item.id} item={item} />
))}
</div>
</>
);
}
45 changes: 45 additions & 0 deletions examples/hackernews/src/components/item-page/index.module.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
.header {
background-color: #fff;
padding: 1.8em 2em 1em;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);

h1 {
display: inline;
font-size: 1.5em;
margin: 0;
margin-right: 0.5em;
}
}

.host,
.meta,
.meta a {
color: #999;
}
.meta a {
text-decoration: underline;
}

.comments {
background-color: #fff;
margin-top: 10px;
padding: 0 2em;
}

.commentsHeader {
margin: 0;
font-size: 1.1em;
padding: 1em 0;
}

.commentChildren {
list-style-type: none;
padding: 0;
margin: 0;
}

@media (max-width: 600px) {
.header h1 {
font-size: 1.25em;
}
}
37 changes: 37 additions & 0 deletions examples/hackernews/src/components/item-page/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Link } from '@umijs/tnf/router';
import { host, timeAgo } from '../../utils';
import Comment from '../comment';
import styles from './index.module.less';

export default function ItemPage({ item, itemsById }) {
if (!item) return null;
return (
<>
<div className={styles.header}>
<a href={item.url}>
<h1>{item.title}</h1>
</a>
{item.url ? (
<span className={styles.host}>{host(item.url)}</span>
) : null}
<p className={styles.meta}>
<span>{`${item.score} points | by `}</span>
<Link to={`/user/${item.by}`}>{item.by}</Link>
<span>{` ${timeAgo(item.time)} ago`}</span>
</p>
</div>
<div className={styles.comments}>
<p className={styles.commentsHeader}>
{item.kids ? `${item.descendants} comments` : 'No comments yet.'}
</p>
<div className={styles.commentChildren}>
{item.kids
? item.kids.map((id) => (
<Comment key={id} id={id} itemsById={itemsById} />
))
: null}
</div>
</div>
</>
);
}
34 changes: 34 additions & 0 deletions examples/hackernews/src/components/item/index.module.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
.normal {
background-color: #fff;
padding: 20px 30px 20px 80px;
border-bottom: 1px solid #eee;
position: relative;
line-height: 20px;
}

.score {
color: #ff6600;
font-size: 1.1em;
font-weight: 700;
position: absolute;
top: 50%;
left: 0;
width: 80px;
text-align: center;
margin-top: -10px;
}

.meta,
.host {
font-size: 0.85em;
color: #999;

a {
color: #999;
text-decoration: underline;

&:hover {
color: #ff6600;
}
}
}
Loading

0 comments on commit 8ef1093

Please sign in to comment.