vigor-moon 1.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/README.md +9 -0
- package/bin/vigor.js +2 -0
- package/dist/chunk-2M2XJKGT.js +607 -0
- package/dist/chunk-3EAR5BNQ.js +610 -0
- package/dist/chunk-3ZCIQMBL.js +608 -0
- package/dist/chunk-6SPQ2G5U.js +611 -0
- package/dist/chunk-7V4TYSIZ.mjs +619 -0
- package/dist/chunk-AT54N5D7.js +611 -0
- package/dist/chunk-BBRRUMIN.js +616 -0
- package/dist/chunk-BE2AQAQS.mjs +608 -0
- package/dist/chunk-BS6X4ZCI.js +608 -0
- package/dist/chunk-CG4W75R5.mjs +622 -0
- package/dist/chunk-D2WJMNSR.js +618 -0
- package/dist/chunk-DTA4ZJEQ.mjs +606 -0
- package/dist/chunk-ECPJL6H6.js +618 -0
- package/dist/chunk-EU5K7BUZ.mjs +612 -0
- package/dist/chunk-FAELXJ3Z.mjs +605 -0
- package/dist/chunk-GBGTGHKN.js +621 -0
- package/dist/chunk-HW7CAZGA.js +611 -0
- package/dist/chunk-IDQ7PFDG.mjs +619 -0
- package/dist/chunk-IPVDS3I7.mjs +609 -0
- package/dist/chunk-JHZIOXVJ.js +605 -0
- package/dist/chunk-KRBN43PO.js +606 -0
- package/dist/chunk-KTIICQHT.mjs +622 -0
- package/dist/chunk-KZQIA6WA.js +604 -0
- package/dist/chunk-L4MZ52TR.mjs +609 -0
- package/dist/chunk-LEOZIK2T.mjs +607 -0
- package/dist/chunk-LS3TOABU.js +61 -0
- package/dist/chunk-MHZT64KI.mjs +605 -0
- package/dist/chunk-NTJI6VKJ.mjs +619 -0
- package/dist/chunk-NWZZITYZ.mjs +606 -0
- package/dist/chunk-OS3F7QDD.js +606 -0
- package/dist/chunk-PJPXX4UA.mjs +605 -0
- package/dist/chunk-PW73M55D.mjs +611 -0
- package/dist/chunk-R6L6GYA4.mjs +607 -0
- package/dist/chunk-RNUPZ4CR.mjs +612 -0
- package/dist/chunk-SEIXDGYJ.mjs +615 -0
- package/dist/chunk-SO47EKIV.mjs +69 -0
- package/dist/chunk-SYCZ35ZW.js +604 -0
- package/dist/chunk-THZGRR4I.js +611 -0
- package/dist/chunk-TJ5NMLCW.js +614 -0
- package/dist/chunk-TYBNSCBA.mjs +611 -0
- package/dist/chunk-UGBCHWPA.js +621 -0
- package/dist/chunk-VD42YO6T.mjs +622 -0
- package/dist/chunk-VMNTKZYD.js +604 -0
- package/dist/chunk-W6MHPTGR.js +605 -0
- package/dist/chunk-WBSL45KV.mjs +617 -0
- package/dist/chunk-X5IY67V6.js +621 -0
- package/dist/chunk-XFGBQ3QD.mjs +612 -0
- package/dist/chunk-ZBAZASII.js +618 -0
- package/dist/chunk-ZGLENLKC.js +610 -0
- package/dist/chunk-ZN4CSBNG.mjs +612 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +296 -0
- package/dist/cli.mjs +296 -0
- package/dist/dev.d.ts +5 -0
- package/dist/dev.js +7 -0
- package/dist/dev.mjs +7 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.js +6 -0
- package/dist/index.mjs +6 -0
- package/package.json +97 -0
- package/src/core/cli.ts +0 -0
- package/src/runtime/App.tsx +38 -0
- package/src/runtime/Content.tsx +27 -0
- package/src/runtime/client-entry.tsx +30 -0
- package/src/runtime/hooks.ts +8 -0
- package/src/runtime/index.ts +2 -0
- package/src/runtime/ssr-entry.tsx +24 -0
- package/src/theme-default/Layout/doc/doc.tsx +46 -0
- package/src/theme-default/Layout/doc/index.module.scss +154 -0
- package/src/theme-default/Layout/home/home.tsx +16 -0
- package/src/theme-default/Layout/index.tsx +38 -0
- package/src/theme-default/Layout/notFound/index.module.scss +7 -0
- package/src/theme-default/Layout/notFound/index.tsx +30 -0
- package/src/theme-default/component/Button/index.module.scss +36 -0
- package/src/theme-default/component/Button/index.tsx +42 -0
- package/src/theme-default/component/Link/index.module.scss +10 -0
- package/src/theme-default/component/Link/index.tsx +28 -0
- package/src/theme-default/component/feature/index.module.scss +10 -0
- package/src/theme-default/component/feature/index.tsx +28 -0
- package/src/theme-default/component/footer/index.module.scss +4 -0
- package/src/theme-default/component/footer/index.tsx +13 -0
- package/src/theme-default/component/hero/index.module.scss +5 -0
- package/src/theme-default/component/hero/index.tsx +48 -0
- package/src/theme-default/component/nav/index.module.scss +24 -0
- package/src/theme-default/component/nav/index.tsx +43 -0
- package/src/theme-default/component/nextPage/index.module.scss +43 -0
- package/src/theme-default/component/nextPage/index.tsx +64 -0
- package/src/theme-default/component/sidebar/index.module.scss +22 -0
- package/src/theme-default/component/sidebar/index.tsx +52 -0
- package/src/theme-default/component/switchTheme/index.module.scss +0 -0
- package/src/theme-default/component/switchTheme/index.tsx +9 -0
- package/src/theme-default/component/toc/activeScroll.ts +37 -0
- package/src/theme-default/component/toc/index.module.scss +7 -0
- package/src/theme-default/component/toc/index.tsx +60 -0
- package/src/theme-default/styles/base.css +92 -0
- package/src/theme-default/styles/vars.css +111 -0
- package/src/types/attributify-shims.d.ts +5 -0
- package/src/types/index.ts +129 -0
- package/src/types/types.d.ts +16 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Feature } from "../../../types";
|
|
2
|
+
import styles from "./index.module.scss";
|
|
3
|
+
|
|
4
|
+
export function FeatureComponent(props: {features: Feature[]}) {
|
|
5
|
+
|
|
6
|
+
return (
|
|
7
|
+
<div flex="~ wrap" justify="between" pt="20" className="divider-bottom pb-10">
|
|
8
|
+
{
|
|
9
|
+
props.features.map((feature) => {
|
|
10
|
+
const {
|
|
11
|
+
title,
|
|
12
|
+
details,
|
|
13
|
+
icon = ""
|
|
14
|
+
} = feature;
|
|
15
|
+
return (
|
|
16
|
+
<div key={title} border="rounded-md" pb="1.3%" w="32.4%">
|
|
17
|
+
<article p="6" className={styles.bg} h-full="true" >
|
|
18
|
+
<div className={`flex-center text-3xl w-13 h-11 ${styles.iconBg}`} border="rounded-xl solid">{ icon }</div>
|
|
19
|
+
<h2 className="font-semibold py-4">{ title }</h2>
|
|
20
|
+
<p className="text-3.5 font-medium opacity-90">{ details }</p>
|
|
21
|
+
</article>
|
|
22
|
+
</div>
|
|
23
|
+
)
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
</div>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { FooterConfig } from "types";
|
|
2
|
+
import styles from "./index.module.scss";
|
|
3
|
+
|
|
4
|
+
export function FooterComponent(props: { footer: FooterConfig }) {
|
|
5
|
+
const { footer } = props;
|
|
6
|
+
|
|
7
|
+
return (
|
|
8
|
+
<div className={`py-5 ${styles.footer}`}>
|
|
9
|
+
<p className="flex-center">{footer.message}</p>
|
|
10
|
+
<span className="flex-center">Copyright © 2023-present {footer.copyright}</span>
|
|
11
|
+
</div>
|
|
12
|
+
)
|
|
13
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Hero } from "types";
|
|
2
|
+
import { Button } from "../Button";
|
|
3
|
+
|
|
4
|
+
import styles from "./index.module.scss";
|
|
5
|
+
|
|
6
|
+
// hero组件
|
|
7
|
+
// hero组件是主页的标题介绍和图片展示。
|
|
8
|
+
|
|
9
|
+
// Hero Image通常指的是一种大尺寸横幅图片展示在网页上,
|
|
10
|
+
// 通常放在靠前并居中的位置。它囊括了网站中最重要的内容。
|
|
11
|
+
// Hero image通常由图像和文本组成
|
|
12
|
+
export function HeroComponent(props: { hero: Hero }) {
|
|
13
|
+
const { hero } = props;
|
|
14
|
+
return (
|
|
15
|
+
<div flex="~">
|
|
16
|
+
<div className="w-1/2">
|
|
17
|
+
<div>
|
|
18
|
+
<h1 className="text-5xl font-semibold pb-5">
|
|
19
|
+
<span className={styles.title}> {hero.name} </span>
|
|
20
|
+
</h1>
|
|
21
|
+
<p className="text-6xl font-semibold"> { hero.text } </p>
|
|
22
|
+
<p className="text-2xl pt-3 pb-6 opacity-65"> { hero.tagline } </p>
|
|
23
|
+
</div>
|
|
24
|
+
<div flex="~">
|
|
25
|
+
{hero.actions.map((action) => (
|
|
26
|
+
<div key={action.link} className="pr-3">
|
|
27
|
+
<Button
|
|
28
|
+
type="a"
|
|
29
|
+
text={action.text}
|
|
30
|
+
href={action.link}
|
|
31
|
+
theme={action.theme}
|
|
32
|
+
/>
|
|
33
|
+
</div>
|
|
34
|
+
))}
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
<div w="1/2" flex="center" >
|
|
38
|
+
{
|
|
39
|
+
hero.image && (
|
|
40
|
+
<div>
|
|
41
|
+
<img h="85" src={ hero.image.src } alt={ hero.image.alt } />
|
|
42
|
+
</div>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
)
|
|
48
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
.link:hover {
|
|
2
|
+
color: var(--vigor-link-onfocus);
|
|
3
|
+
transition: color 0.2s;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.link {
|
|
7
|
+
display: block;
|
|
8
|
+
font-size: 14px;
|
|
9
|
+
font-weight: 500;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.social-link-icon {
|
|
13
|
+
display: flex;
|
|
14
|
+
fill: currentColor;
|
|
15
|
+
transition: color 0.2s;
|
|
16
|
+
color: var(--vigor-c-light-black);
|
|
17
|
+
&:hover {
|
|
18
|
+
color: var(--vigor-c-black);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.bg-color {
|
|
23
|
+
background-color: var(--vigor-c-bg-main);
|
|
24
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { useContextData } from "@runtime";
|
|
2
|
+
import { NavItemsConfig } from "types";
|
|
3
|
+
import styles from "./index.module.scss";
|
|
4
|
+
|
|
5
|
+
// github链接地址
|
|
6
|
+
export const GITHUB_LINK_HREF = "https://github.com/Flandre3569/vigor.js";
|
|
7
|
+
|
|
8
|
+
function MenuItem(item: NavItemsConfig) {
|
|
9
|
+
return (
|
|
10
|
+
<div className="text-sm font-medium mx-3">
|
|
11
|
+
<a href={item.link} className={styles.link}> {item.text} </a>
|
|
12
|
+
</div>
|
|
13
|
+
)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function Nav() {
|
|
17
|
+
const { siteData } = useContextData();
|
|
18
|
+
const nav = siteData?.themeConfig?.nav || [];
|
|
19
|
+
return (
|
|
20
|
+
<header fixed="~" w="full" z="10" className={styles.bgColor}>
|
|
21
|
+
<div flex="~" justify="between" items="center" className="px-8 h-14 divider-bottom">
|
|
22
|
+
<div>
|
|
23
|
+
<a href="/" className="w-full h-full text-1rem flex items-center" hover="opacity-60">vigor.js</a>
|
|
24
|
+
</div>
|
|
25
|
+
<div flex="~">
|
|
26
|
+
<div flex="~">
|
|
27
|
+
{
|
|
28
|
+
nav.map(item => (
|
|
29
|
+
<MenuItem {...item} key={item.text} />
|
|
30
|
+
))
|
|
31
|
+
}
|
|
32
|
+
</div>
|
|
33
|
+
<div>{ /*主题切换按钮*/ }</div>
|
|
34
|
+
<div className={styles.socialLinkIcon}>
|
|
35
|
+
<a href = { GITHUB_LINK_HREF } >
|
|
36
|
+
<div className="i-carbon-logo-github w-5 h-5 fill-current"></div>
|
|
37
|
+
</a>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
</header>
|
|
42
|
+
)
|
|
43
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
.prev-page {
|
|
2
|
+
float: left;
|
|
3
|
+
border: 1px solid;
|
|
4
|
+
border-radius: 5px;
|
|
5
|
+
&:hover {
|
|
6
|
+
border-color: var(--vigor-c-nextPage-border);
|
|
7
|
+
}
|
|
8
|
+
transform: border-color 0.2s;
|
|
9
|
+
padding: 1vh 19vw 1vh 1vw;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.next-page {
|
|
13
|
+
float: right;
|
|
14
|
+
border: 1px solid;
|
|
15
|
+
border-radius: 5px;
|
|
16
|
+
&:hover {
|
|
17
|
+
border-color: var(--vigor-c-nextPage-border);
|
|
18
|
+
}
|
|
19
|
+
transform: border-color 0.2s;
|
|
20
|
+
padding: 1vh 1vw 1vh 19vw;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.prev-page-title {
|
|
24
|
+
display: flex;
|
|
25
|
+
opacity: 70%;
|
|
26
|
+
font-size: 0.8rem;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.next-page-title {
|
|
30
|
+
display: flex;
|
|
31
|
+
opacity: 70%;
|
|
32
|
+
font-size: 0.8rem;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.prev-page-content {
|
|
36
|
+
font-size: 0.9rem;
|
|
37
|
+
color: var(--vigor-c-nextPage-content);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.next-page-content {
|
|
41
|
+
color: var(--vigor-c-nextPage-content);
|
|
42
|
+
font-size: 0.9rem;
|
|
43
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { useContextData } from "@runtime";
|
|
2
|
+
import { useLocation } from "react-router-dom";
|
|
3
|
+
|
|
4
|
+
import styles from "./index.module.scss";
|
|
5
|
+
|
|
6
|
+
export function getNextPageData() {
|
|
7
|
+
// 拿到当前页面的路由
|
|
8
|
+
const { pathname } = useLocation();
|
|
9
|
+
const { siteData } = useContextData();
|
|
10
|
+
|
|
11
|
+
const sidebar = siteData.themeConfig?.sidebar || {};
|
|
12
|
+
const itemArray = [];
|
|
13
|
+
|
|
14
|
+
// 把sidebar中的数据拍平并放到一个数组中
|
|
15
|
+
Object.keys(sidebar).forEach((key) => {
|
|
16
|
+
const itemGroup = sidebar[key] || [];
|
|
17
|
+
itemGroup.forEach(group => {
|
|
18
|
+
group.items.forEach(item => {
|
|
19
|
+
itemArray.push(item);
|
|
20
|
+
})
|
|
21
|
+
})
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
// 从sidebar数据的数组中拿到当前页面的索引号
|
|
25
|
+
const pageIndex = itemArray.findIndex((item) => item.link === pathname);
|
|
26
|
+
// 上一页就是索引号的上一个
|
|
27
|
+
const prevPage = itemArray[pageIndex - 1] || null;
|
|
28
|
+
// 下一页就是索引号的下一个
|
|
29
|
+
const nextPage = itemArray[pageIndex + 1] || null;
|
|
30
|
+
return {
|
|
31
|
+
prevPage,
|
|
32
|
+
nextPage
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
export function NextPage() {
|
|
38
|
+
const { prevPage, nextPage } = getNextPageData();
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<footer>
|
|
42
|
+
<div flex="~" justify="between" className="py-5">
|
|
43
|
+
<div>
|
|
44
|
+
{
|
|
45
|
+
prevPage &&
|
|
46
|
+
<a href={prevPage.link} className={styles.prevPage} >
|
|
47
|
+
<span mr="5" className={styles.prevPageTitle}>上一页</span>
|
|
48
|
+
<span className={ styles.prevPageContent }>{ prevPage.text }</span>
|
|
49
|
+
</a>
|
|
50
|
+
}
|
|
51
|
+
</div>
|
|
52
|
+
<div>
|
|
53
|
+
{
|
|
54
|
+
nextPage &&
|
|
55
|
+
<a href={nextPage.link} className={styles.nextPage} >
|
|
56
|
+
<span mr="5" className={styles.nextPageTitle}>下一页</span>
|
|
57
|
+
<span className={ styles.nextPageContent }>{ nextPage.text } </span>
|
|
58
|
+
</a>
|
|
59
|
+
}
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
</footer>
|
|
63
|
+
)
|
|
64
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
.sidebar {
|
|
2
|
+
position: fixed;
|
|
3
|
+
top: 0;
|
|
4
|
+
bottom: 0;
|
|
5
|
+
left: 0;
|
|
6
|
+
padding: 80px 32px 96px;
|
|
7
|
+
width: var(--vigor-sidebar-width);
|
|
8
|
+
max-width: 320px;
|
|
9
|
+
background-color: var(--vigor-c-bg-soft);
|
|
10
|
+
overflow-x: hidden;
|
|
11
|
+
overflow-y: auto;
|
|
12
|
+
transition: transform 0.25s ease;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.item-onfocus {
|
|
16
|
+
color: var(--vigor-link-onfocus);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.item {
|
|
20
|
+
opacity: 70%;
|
|
21
|
+
color: var(--vigor-c-text-main);
|
|
22
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { SidebarItem } from "types";
|
|
2
|
+
import { SidebarGroup } from "types";
|
|
3
|
+
import { Link } from '../Link/index';
|
|
4
|
+
import styles from "./index.module.scss";
|
|
5
|
+
interface SidebarType {
|
|
6
|
+
sidebarData: SidebarGroup[];
|
|
7
|
+
pathname: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function Sidebar(props: SidebarType) {
|
|
11
|
+
const { sidebarData, pathname } = props;
|
|
12
|
+
|
|
13
|
+
// 渲染每个sidebar的item
|
|
14
|
+
const renderItem = (item: SidebarItem) => {
|
|
15
|
+
// 判断当前的路由是不是正在访问的页面路由
|
|
16
|
+
const onFocus = item.link === pathname;
|
|
17
|
+
return (
|
|
18
|
+
<div pl="2" pt="2">
|
|
19
|
+
<div className={`${onFocus ? styles.itemOnfocus : styles.item}`}>
|
|
20
|
+
<Link href={item.link}>{ item.text }</Link>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// 渲染一个sidebar组
|
|
27
|
+
const renderItems = (item: SidebarGroup) => {
|
|
28
|
+
return (
|
|
29
|
+
<section key={item.text} className="divider-bottom pb-3">
|
|
30
|
+
<div>
|
|
31
|
+
<h2 className="font-semibold">{ item.text }</h2>
|
|
32
|
+
</div>
|
|
33
|
+
<div>
|
|
34
|
+
{
|
|
35
|
+
item.items?.map((item) => (
|
|
36
|
+
<div key={item.link}>
|
|
37
|
+
{renderItem(item)}
|
|
38
|
+
</div>
|
|
39
|
+
))
|
|
40
|
+
}
|
|
41
|
+
</div>
|
|
42
|
+
</section>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// 渲染整个sidebar
|
|
47
|
+
return (
|
|
48
|
+
<aside className={styles.sidebar}>
|
|
49
|
+
<nav>{sidebarData.map(renderItems)}</nav>
|
|
50
|
+
</aside>
|
|
51
|
+
)
|
|
52
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const NAV_HEIGHT = 60;
|
|
2
|
+
|
|
3
|
+
export function activeScroll() {
|
|
4
|
+
const container = document.querySelector("#toc-container");
|
|
5
|
+
const marker = document.querySelector("#toc-marker");
|
|
6
|
+
|
|
7
|
+
if (!container) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const setHeaderLink = () => {};
|
|
12
|
+
window.addEventListener("scroll", setHeaderLink);
|
|
13
|
+
|
|
14
|
+
// 最后的时候解除事件绑定,防止内存泄露
|
|
15
|
+
return () => {
|
|
16
|
+
window.removeEventListener("scroll", setHeaderLink);
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function scrollToTarget(target: HTMLElement, isSmooth: boolean) {
|
|
21
|
+
// getComputedStyle是拿到指定元素的计算属性,也就是拿到css样式里的数据,然后.paddingTop就获取到元素的上padding值。
|
|
22
|
+
const targetPadding = parseInt(window.getComputedStyle(target).paddingTop, 10);
|
|
23
|
+
// scrollY是返回文档在垂直方向已滚动的像素值。
|
|
24
|
+
// getBoundingClientRect().top是返回元素距离可视窗口上方的距离。
|
|
25
|
+
// NAV_HEIGHT本意是定义一个变量让其和nav的height值相同,nav是3.5rem,无法直接进行相减,因此我稍作了修改,改为了60像素。
|
|
26
|
+
// scrollTo() 方法可以使界面滚动到给定元素的指定坐标位置。
|
|
27
|
+
|
|
28
|
+
// 其实scrollY+getBoundingClientRect().top+targetpadding计算的就是一开始target元素距离顶端的height值。
|
|
29
|
+
// 而需要移动的距离就是用这个值减去nav的height值。
|
|
30
|
+
const targetTop =
|
|
31
|
+
window.scrollY + target.getBoundingClientRect().top + targetPadding - NAV_HEIGHT;
|
|
32
|
+
window.scrollTo({
|
|
33
|
+
left: 0,
|
|
34
|
+
top: targetTop,
|
|
35
|
+
behavior: isSmooth ? "smooth" : "auto",
|
|
36
|
+
});
|
|
37
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { useContextData } from "@runtime"
|
|
2
|
+
import { useRef } from "react";
|
|
3
|
+
import { TocTree } from "types";
|
|
4
|
+
import styles from "./index.module.scss";
|
|
5
|
+
|
|
6
|
+
import { scrollToTarget } from "./activeScroll";
|
|
7
|
+
|
|
8
|
+
export interface TocType {
|
|
9
|
+
headers: TocTree[]
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function TocComponent(props: TocType) {
|
|
13
|
+
const { headers = [] } = props;
|
|
14
|
+
// 大纲的长度
|
|
15
|
+
const tocLength = headers.length > 0;
|
|
16
|
+
|
|
17
|
+
const markRef = useRef<HTMLDivElement>(null);
|
|
18
|
+
|
|
19
|
+
const renderToc = (tocTree: TocTree) => {
|
|
20
|
+
return (
|
|
21
|
+
<li key={tocTree.id}>
|
|
22
|
+
<a
|
|
23
|
+
href={`#${tocTree.id}`}
|
|
24
|
+
className={`block leading-7 ${styles.tocLink} opacity-70`}
|
|
25
|
+
transition="color duration-300"
|
|
26
|
+
style={{
|
|
27
|
+
paddingLeft: (tocTree.depth - 2) * 12
|
|
28
|
+
}}
|
|
29
|
+
onClick={(e) => {
|
|
30
|
+
e.preventDefault();
|
|
31
|
+
const target = document.getElementById(tocTree.id);
|
|
32
|
+
target && scrollToTarget(target, false);
|
|
33
|
+
}}
|
|
34
|
+
>
|
|
35
|
+
{tocTree.text}
|
|
36
|
+
</a>
|
|
37
|
+
</li>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
return (
|
|
41
|
+
<div>
|
|
42
|
+
<div>
|
|
43
|
+
{
|
|
44
|
+
tocLength && (
|
|
45
|
+
<div id="toc-container" className="relative divider-left pl-4 text-13px font-medium">
|
|
46
|
+
<div
|
|
47
|
+
ref={markRef}
|
|
48
|
+
id="toc-maker" >
|
|
49
|
+
</div>
|
|
50
|
+
<div leading-7="~" text="13px" font="semibold">On this Page</div>
|
|
51
|
+
<nav>
|
|
52
|
+
<ul relative="~">{ headers.map(renderToc) }</ul>
|
|
53
|
+
</nav>
|
|
54
|
+
</div>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
)
|
|
60
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
*{
|
|
2
|
+
padding: 0;
|
|
3
|
+
margin: 0;
|
|
4
|
+
}
|
|
5
|
+
/* 样式 */
|
|
6
|
+
body {
|
|
7
|
+
margin: 0;
|
|
8
|
+
width: 100%;
|
|
9
|
+
min-width: 320px;
|
|
10
|
+
min-height: 100vh;
|
|
11
|
+
line-height: 24px;
|
|
12
|
+
font-family: var(--vigor-font-family);
|
|
13
|
+
font-size: 16px;
|
|
14
|
+
font-weight: 400;
|
|
15
|
+
color: var(--vigor-c-text-main);
|
|
16
|
+
background-color: var(--vigor-c-bg-main);
|
|
17
|
+
direction: ltr;
|
|
18
|
+
font-synthesis: none;
|
|
19
|
+
text-rendering: optimizeLegibility;
|
|
20
|
+
-webkit-font-smoothing: antialiased;
|
|
21
|
+
-moz-osx-font-smoothing: grayscale;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
a {
|
|
25
|
+
transition: 0.2s;
|
|
26
|
+
color: inherit;
|
|
27
|
+
text-decoration: inherit;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
a,
|
|
31
|
+
area,
|
|
32
|
+
button,
|
|
33
|
+
[role='button'],
|
|
34
|
+
input,
|
|
35
|
+
label,
|
|
36
|
+
select,
|
|
37
|
+
summary,
|
|
38
|
+
textarea {
|
|
39
|
+
touch-action: manipulation;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
h1,
|
|
43
|
+
h2,
|
|
44
|
+
h3,
|
|
45
|
+
h4,
|
|
46
|
+
h5,
|
|
47
|
+
h6 {
|
|
48
|
+
margin: 0;
|
|
49
|
+
line-height: 24px;
|
|
50
|
+
font-size: 16px;
|
|
51
|
+
font-weight: 400;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
p {
|
|
55
|
+
margin: 0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
strong,
|
|
59
|
+
b {
|
|
60
|
+
font-weight: 600;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
button,
|
|
64
|
+
input,
|
|
65
|
+
optgroup,
|
|
66
|
+
select,
|
|
67
|
+
textarea {
|
|
68
|
+
border: 0;
|
|
69
|
+
padding: 0;
|
|
70
|
+
line-height: inherit;
|
|
71
|
+
color: inherit;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
button {
|
|
75
|
+
padding: 0;
|
|
76
|
+
font-family: inherit;
|
|
77
|
+
background-color: transparent;
|
|
78
|
+
background-image: none;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
button,
|
|
82
|
+
[role='button'] {
|
|
83
|
+
cursor: pointer;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/* 把列表前面的小符号消除 */
|
|
87
|
+
ol,
|
|
88
|
+
ul {
|
|
89
|
+
list-style: none;
|
|
90
|
+
margin: 0;
|
|
91
|
+
padding: 0;
|
|
92
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
|
|
2
|
+
:root {
|
|
3
|
+
/* 基础颜色 */
|
|
4
|
+
--vigor-c-white: #ffffff;
|
|
5
|
+
--vigor-c-lynx-white: #f5f6fa;
|
|
6
|
+
--vigor-c-soft-white: #fffffe;
|
|
7
|
+
--vigor-c-soft-pink: #f3d2c1;
|
|
8
|
+
--vigor-c-swan-white: #f7f1e3;
|
|
9
|
+
|
|
10
|
+
--vigor-c-flower-red: #e84118;
|
|
11
|
+
--vigor-c-flower-deep-red: #c23616;
|
|
12
|
+
|
|
13
|
+
--vigor-c-light-blue: #00a8ff;
|
|
14
|
+
--vigor-c-blue: #0097e6;
|
|
15
|
+
|
|
16
|
+
--vigor-c-light-purple: #9c88ff;
|
|
17
|
+
--vigor-c-purple: #8c7ae6;
|
|
18
|
+
|
|
19
|
+
--vigor-c-light-yellow: #fbc531;
|
|
20
|
+
--vigor-c-deep-yellow: #e1b12c;
|
|
21
|
+
|
|
22
|
+
--vigor-c-azure: #5FFBF1;
|
|
23
|
+
--vigor-c-deep-azure: #19CFC4;
|
|
24
|
+
--vigor-c-azure-light: #35CFC6;
|
|
25
|
+
--vigor-c-light-green: #4cd137;
|
|
26
|
+
--vigor-c-deep-green: #44bd32;
|
|
27
|
+
--vigor-c-deep-mo-green: #008080;
|
|
28
|
+
|
|
29
|
+
--vigor-c-grey-blue: #487eb0;
|
|
30
|
+
--vigor-c-grey-deep-blue: #40739e;
|
|
31
|
+
|
|
32
|
+
--vigor-c-light-grey: #dcdde1;
|
|
33
|
+
--vigor-c-grey: #7f8fa6;
|
|
34
|
+
--vigor-c-deep-grey: #718093;
|
|
35
|
+
|
|
36
|
+
--vigor-c-mazaline-blue: #273c75;
|
|
37
|
+
--vigor-c-pico-void-blue: #192a56;
|
|
38
|
+
--vigor-c-headling-blue: #001858;
|
|
39
|
+
|
|
40
|
+
--vigor-c-light-black: #353b48;
|
|
41
|
+
--vigor-c-grey-black: #2f3640;
|
|
42
|
+
--vigor-c-moon-black: #1e272e;
|
|
43
|
+
--vigor-c-black: #0a0a0a;
|
|
44
|
+
|
|
45
|
+
--vigor-c-divider-light-1: rgba(60, 60, 60, 0.12);
|
|
46
|
+
|
|
47
|
+
--vigor-c-progress-pink-blue: linear-gradient(to right top, #d16ba5, #c777b9, #ba83ca, #aa8fd8, #9a9ae1, #8aa7ec, #79b3f4, #69bff8, #52cffe, #41dfff, #46eefa, #5ffbf1);
|
|
48
|
+
--vigor-c-progress-black-white: linear-gradient(to right top, #070707, #100e19, #131326, #141833, #131c42, #1b2f57, #23436c, #2c5881, #55819d, #87aab9, #bed3d7, #f9fcfc);
|
|
49
|
+
}
|
|
50
|
+
:root {
|
|
51
|
+
--vigor-font-family: Arial, sans-serif;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* 主题配色 */
|
|
55
|
+
:root {
|
|
56
|
+
/* 下划线 */
|
|
57
|
+
--vigor-c-divider-light: var(--vigor-c-divider-light-1);
|
|
58
|
+
|
|
59
|
+
/* 背景颜色 */
|
|
60
|
+
--vigor-c-bg-main: var(--vigor-c-soft-white);
|
|
61
|
+
--vigor-c-bg-soft: var(--vigor-c-lynx-white);
|
|
62
|
+
/* 主页icon背景颜色 */
|
|
63
|
+
--vigor-c-icon-bg: var(--vigor-c-swan-white);
|
|
64
|
+
|
|
65
|
+
/* 按钮brand主题配色 */
|
|
66
|
+
--vigor-bg-brand: var(--vigor-c-purple);
|
|
67
|
+
--vigor-bg-alt: var(--vigor-c-deep-grey);
|
|
68
|
+
--vigor-bg-brand-light: var(--vigor-c-azure-light);
|
|
69
|
+
--vigor-text-brand: var(--vigor-c-azure);
|
|
70
|
+
/* 按钮alt主题配色 */
|
|
71
|
+
--vigor-c-alt: var(--vigor-c-deep-grey);
|
|
72
|
+
|
|
73
|
+
/* 标题配色 */
|
|
74
|
+
--vigor-c-title: var(--vigor-c-progress-pink-blue);
|
|
75
|
+
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/* 主题长度 */
|
|
79
|
+
:root {
|
|
80
|
+
/* 侧边栏宽度 */
|
|
81
|
+
--vigor-sidebar-width: 13vw;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* 文本配色 */
|
|
85
|
+
:root {
|
|
86
|
+
--vigor-c-text-main: var(--vigor-c-moon-black);
|
|
87
|
+
/* nav hover配色 */
|
|
88
|
+
--vigor-link-onfocus: var(--vigor-c-deep-green);
|
|
89
|
+
|
|
90
|
+
/* toc文件hover配色 */
|
|
91
|
+
--vigor-toc-hover: var(--vigor-c-black);
|
|
92
|
+
|
|
93
|
+
/* 404 - h1 */
|
|
94
|
+
--vigor-c-404-h1: var(--vigor-c-grey-blue);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* markdown doc配色 */
|
|
98
|
+
:root {
|
|
99
|
+
--main-color: #008080; /* 主色调 */
|
|
100
|
+
--light-color: #f2f2f2; /* 浅色背景 */
|
|
101
|
+
--dark-color: #262626; /* 深色背景 */
|
|
102
|
+
--text-color: #333; /* 正文文本颜色 */
|
|
103
|
+
--link-color: #008080; /* 链接文本颜色 */
|
|
104
|
+
|
|
105
|
+
--vigor-c-lang: var(--vigor-c-soft-pink);
|
|
106
|
+
|
|
107
|
+
--vigor-c-h1-text: var(--vigor-c-headling-blue);
|
|
108
|
+
|
|
109
|
+
--vigor-c-nextPage-content: var(--vigor-c-deep-mo-green);
|
|
110
|
+
--vigor-c-nextPage-border: var(--vigor-c-deep-mo-green);
|
|
111
|
+
}
|