Skip to content

Commit

Permalink
feat: update toc style & toc jump
Browse files Browse the repository at this point in the history
  • Loading branch information
aolyang committed Dec 13, 2024
1 parent 67261dd commit 2ad822a
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 58 deletions.
4 changes: 3 additions & 1 deletion example/src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@
import htmlRaw from "@/assets/explain.html?raw"
import ExportContent from "@/components/ExportContent.svelte"
import TableOfContents from "@/components/TableOfContents.svelte"
import ToggleLocale from "@/components/ToggleLocale.svelte"
import ToggleSparkLine from "@/components/ToggleSparkLine.svelte"
import ThemeMode from "@/components/ToggleTheme.svelte"
import ToggleToc from "@/components/ToggleToc.svelte"
import Toolbar from "@/components/Toolbar.svelte"
import { setEditorContext } from "@/states/toolbar"
import { createEditor } from "@/utils/editor"
import { aligns, headingLevels } from "@/utils/editor-presets"
import TableOfContents from "@/components/TableOfContents.svelte"
import { onMount } from "svelte"
/*
Expand Down Expand Up @@ -78,6 +79,7 @@
<div class="w-full min-h-[52px] px-4 shadow flex gap-3 items-center bg-background dark:bg-neutral-700">
<div class="flex-1"></div>
<ExportContent/>
<ToggleToc />
<ToggleLocale/>
<ToggleSparkLine/>
<ThemeMode/>
Expand Down
129 changes: 73 additions & 56 deletions example/src/components/TableOfContents.svelte
Original file line number Diff line number Diff line change
@@ -1,92 +1,109 @@
<script lang="ts">
import { onMount } from "svelte";
import { getEditorContext } from "@/states/toolbar";
import EditorTransactionEvent from "@/components/EditorTransactionEvent.svelte";
import EditorTransactionEvent from "@/components/EditorTransactionEvent.svelte"
import { globalState } from "@/states/global.svelte"
import { getEditorContext } from "@/states/toolbar"
const ctx = getEditorContext();
import { onMount } from "svelte"
let headings: { level: number; text: string }[] = [];
const ctx = getEditorContext()
type Heading = { level: number, text: string, pos: number }
let headings: Heading[] = []
const updateHeadings = () => {
const doc = ctx.editor.state.doc;
const newHeadings: { level: number; text: string }[] = [];
const doc = ctx.editor.state.doc
const newHeadings: Heading[] = []
doc.descendants((node) => {
doc.descendants((node, pos) => {
if (node.type.name === "heading") {
newHeadings.push({
level: node.attrs.level,
text: node.textContent,
});
pos
})
}
});
})
headings = newHeadings;
};
headings = newHeadings
}
const jump2Node = (heading: Heading) => {
const dom = ctx.editor.view.nodeDOM(heading.pos) as HTMLElement | null
dom?.scrollIntoView({ behavior: "smooth" })
}
onMount(() => {
updateHeadings();
});
updateHeadings()
})
</script>

<EditorTransactionEvent {updateHeadings} />
<EditorTransactionEvent handler={updateHeadings}/>

<div class="toc">
<h2>Table of Contents</h2>
<ul>
<div class="toc shadow-xl fixed bg-background" class:active={globalState.viewToc}>
<h1 class="px-4 py-2">Table of Contents</h1>
<hr/>
<ul class="overflow-y-auto px-4" style="height: calc(100% - 50px)">
{#each headings as heading}
<li class="heading-{heading.level}">
<a href="#">{heading.text}</a>
<li class={`my-2 h${heading.level} cursor-pointer`}>
<button class="text-left" onclick={() => jump2Node(heading)}>
<span>{heading.text}</span>
</button>
</li>
{/each}
</ul>
</div>

<style>
<style lang="scss">
.toc {
position: fixed;
z-index: 999;
top: 120px;
right: 20px;
width: 200px;
background: white;
border: 1px solid #ccc;
padding: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.toc h2 {
margin-top: 0;
}
.toc ul {
list-style: none;
padding-left: 0;
}
.toc li {
margin-bottom: 5px;
}
.toc .heading-1 {
font-weight: bold;
right: 10px;
width: 460px;
height: 70%;
transform: translateX(500px);
transition: transform 0.3s;
}
.toc .heading-2 {
padding-left: 10px;
.toc.active {
transform: translateX(0);
}
.toc .heading-3 {
padding-left: 20px;
.toc h1 {
font-size: 16px;
text-transform: uppercase;
font-weight: 900;
}
.toc .heading-4 {
padding-left: 30px;
}
.toc ul {
li {
border: 1px solid #00000000;
.toc .heading-5 {
padding-left: 40px;
&:hover {
border: 1px solid hsl(var(--primary) / 20);
}
}
li.h1 {
margin-bottom: 16px;
font-size: 18px;
font-weight: 900;
}
li.h2 {
font-weight: 600;
}
li.h3 {
font-size: 15px;
padding-left: 20px;
}
li.h4 {
font-size: 14px;
padding-left: 40px;
}
}
.toc .heading-6 {
padding-left: 50px;
}
</style>
19 changes: 19 additions & 0 deletions example/src/components/ToggleToc.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<script lang="ts">
import { Button } from "@/components/ui/button"
import { globalState } from "@/states/global.svelte"
import { t } from "@/utils/i18n"
const toggleToc = () => {
globalState.viewToc = !globalState.viewToc
}
</script>

<Button class="py-0 px-2 h-7 rounded" variant="secondary" on:click={toggleToc}>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 16 16">
<g fill="currentColor" transform="scale(1, 1.3) translate(0 -1.5)" stroke="currentColor" stroke-width="0.3">
<path d="M4 9h9v1H4zm0 3h7v1H4zm0-6h10v1H4zM1 3h11v1H1z" />
<path d="M4 4h1v9H4z" />
</g>
</svg>
<div class="w-16">{$t(globalState.viewToc ? "Close Toc" : "Open Toc")}</div>
</Button>
2 changes: 2 additions & 0 deletions example/src/locales/zh_CN.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"en_US": "English",
"zh_CN": "简体中文",
"Open Toc": "打开目录",
"Close Toc": "关闭目录",
"Undo": "撤销",
"Redo": "重做",
"Confirm": "确认",
Expand Down
3 changes: 2 additions & 1 deletion example/src/states/global.svelte.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export const globalState = $state({
viewSparkLines: localStorage.getItem("toolbar-spark-line") === "1"
viewSparkLines: localStorage.getItem("toolbar-spark-line") === "1",
viewToc: false
})

0 comments on commit 2ad822a

Please sign in to comment.