1
- import { useCallback , useEffect , useState } from 'react '
1
+ import { isBrowser } from '@/lib/utils '
2
2
import throttle from 'lodash.throttle'
3
3
import { uuidToId } from 'notion-utils'
4
- import { isBrowser } from '@/lib/utils '
4
+ import { useCallback , useEffect , useState } from 'react '
5
5
6
6
/**
7
7
* 目录导航组件
@@ -24,66 +24,78 @@ const Catalog = ({ post }) => {
24
24
} , [ post ] )
25
25
26
26
const throttleMs = 200
27
- const actionSectionScrollSpy = useCallback ( throttle ( ( ) => {
28
- const sections = document . getElementsByClassName ( 'notion-h' )
29
- let prevBBox = null
30
- let currentSectionId = null
31
- for ( let i = 0 ; i < sections . length ; ++ i ) {
32
- const section = sections [ i ]
33
- if ( ! section || ! ( section instanceof Element ) ) continue
34
- if ( ! currentSectionId ) {
35
- currentSectionId = section . getAttribute ( 'data-id' )
27
+ const actionSectionScrollSpy = useCallback (
28
+ throttle ( ( ) => {
29
+ const sections = document . getElementsByClassName ( 'notion-h' )
30
+ let prevBBox = null
31
+ let currentSectionId = null
32
+ for ( let i = 0 ; i < sections . length ; ++ i ) {
33
+ const section = sections [ i ]
34
+ if ( ! section || ! ( section instanceof Element ) ) continue
35
+ if ( ! currentSectionId ) {
36
+ currentSectionId = section . getAttribute ( 'data-id' )
37
+ }
38
+ const bbox = section . getBoundingClientRect ( )
39
+ const prevHeight = prevBBox ? bbox . top - prevBBox . bottom : 0
40
+ const offset = Math . max ( 150 , prevHeight / 4 )
41
+ // GetBoundingClientRect returns values relative to viewport
42
+ if ( bbox . top - offset < 0 ) {
43
+ currentSectionId = section . getAttribute ( 'data-id' )
44
+ prevBBox = bbox
45
+ continue
46
+ }
47
+ // No need to continue loop, if last element has been detected
48
+ break
36
49
}
37
- const bbox = section . getBoundingClientRect ( )
38
- const prevHeight = prevBBox ? bbox . top - prevBBox . bottom : 0
39
- const offset = Math . max ( 150 , prevHeight / 4 )
40
- // GetBoundingClientRect returns values relative to viewport
41
- if ( bbox . top - offset < 0 ) {
42
- currentSectionId = section . getAttribute ( 'data-id' )
43
- prevBBox = bbox
44
- continue
50
+ setActiveSection ( currentSectionId )
51
+ const tocIds = post ?. toc ?. map ( t => uuidToId ( t . id ) ) || [ ]
52
+ const index = tocIds . indexOf ( currentSectionId ) || 0
53
+ if ( isBrowser && tocIds ?. length > 0 ) {
54
+ for ( const tocWrapper of document ?. getElementsByClassName (
55
+ 'toc-wrapper'
56
+ ) ) {
57
+ tocWrapper ?. scrollTo ( { top : 28 * index , behavior : 'smooth' } )
58
+ }
45
59
}
46
- // No need to continue loop, if last element has been detected
47
- break
48
- }
49
- setActiveSection ( currentSectionId )
50
- const tocIds = post ?. toc ?. map ( ( t ) => uuidToId ( t . id ) ) || [ ]
51
- const index = tocIds . indexOf ( currentSectionId ) || 0
52
- if ( isBrowser && tocIds ?. length > 0 ) {
53
- for ( const tocWrapper of document ?. getElementsByClassName ( 'toc-wrapper' ) ) {
54
- tocWrapper ?. scrollTo ( { top : 28 * index , behavior : 'smooth' } )
55
- }
56
- }
57
- } , throttleMs ) )
60
+ } , throttleMs )
61
+ )
58
62
59
63
// 无目录就直接返回空
60
- if ( ! toc || toc . length < 1 ) {
61
- return null
64
+ if ( ! toc || toc ? .length < 1 ) {
65
+ return < > </ >
62
66
}
63
67
64
- return < >
65
- < div id = 'toc-wrapper' className = 'toc-wrapper overflow-y-auto my-2 max-h-80 overscroll-none scroll-hidden' >
66
- < nav className = 'h-full text-black' >
67
- { toc . map ( ( tocItem ) => {
68
- const id = uuidToId ( tocItem . id )
69
- return (
70
- < a
71
- key = { id }
72
- href = { `#${ id } ` }
73
- className = { `notion-table-of-contents-item duration-300 transform font-light dark:text-gray-300
74
- notion-table-of-contents-item-indent-level-${ tocItem . indentLevel } ` }
75
- >
76
- < span style = { { display : 'inline-block' , marginLeft : tocItem . indentLevel * 16 } }
77
- className = { `truncate ${ activeSection === id ? 'font-bold text-gray-500 underline' : '' } ` }
78
- >
79
- { tocItem . text }
80
- </ span >
81
- </ a >
82
- )
83
- } ) }
84
- </ nav >
85
- </ div >
86
- </ >
68
+ console . log ( '渲染toc' , toc )
69
+
70
+ return (
71
+ < >
72
+ < div
73
+ id = 'toc-wrapper'
74
+ className = 'toc-wrapper overflow-y-auto my-2 max-h-80 overscroll-none scroll-hidden' >
75
+ < nav className = 'h-full text-black' >
76
+ { toc ?. map ( tocItem => {
77
+ const id = uuidToId ( tocItem . id )
78
+ return (
79
+ < a
80
+ key = { id }
81
+ href = { `#${ id } ` }
82
+ className = { `notion-table-of-contents-item duration-300 transform font-light dark:text-gray-300
83
+ notion-table-of-contents-item-indent-level-${ tocItem . indentLevel } ` } >
84
+ < span
85
+ style = { {
86
+ display : 'inline-block' ,
87
+ marginLeft : tocItem . indentLevel * 16
88
+ } }
89
+ className = { `truncate ${ activeSection === id ? 'font-bold text-gray-500 underline' : '' } ` } >
90
+ { tocItem . text }
91
+ </ span >
92
+ </ a >
93
+ )
94
+ } ) }
95
+ </ nav >
96
+ </ div >
97
+ </ >
98
+ )
87
99
}
88
100
89
101
export default Catalog
0 commit comments