@@ -10,27 +10,27 @@ export const DashboardTableOfContents = component$(
10
10
return (
11
11
< div class = "space-y-2" >
12
12
< div class = "font-medium" > On This Page</ div >
13
- < TableOfContent headings = { headings } />
13
+ < TableOfContents headings = { headings } />
14
14
</ div >
15
15
) ;
16
16
} ,
17
17
) ;
18
18
19
- type TableOfContentProps = { headings : ContentHeading [ ] } ;
19
+ type TableOfContentsProps = { headings : ContentHeading [ ] } ;
20
+
20
21
interface Node extends ContentHeading {
21
- level : number ;
22
- children : Array < Node > ;
22
+ children : Node [ ] ;
23
23
activeItem : string ;
24
24
}
25
25
type Tree = Array < Node > ;
26
- export const TableOfContent = component$ < TableOfContentProps > ( ( props ) => {
27
- const inifiniteStopper = props . headings . map ( ( heading ) => {
28
- return { text : heading . text , id : heading . id , level : heading . level } ;
29
- } ) ;
30
- const itemIds = props . headings . map ( ( item ) => item . id ) ;
26
+
27
+ const TableOfContents = component$ < TableOfContentsProps > ( ( { headings } ) => {
28
+ const sanitizedHeadings = headings . map ( ( { text, id, level } ) => ( { text, id, level } ) ) ;
29
+ const itemIds = headings . map ( ( { id } ) => id ) ;
31
30
const activeHeading = useActiveItem ( itemIds ) ;
32
- const tree = getTree ( inifiniteStopper ) ;
33
- return < RecursiveJSX tree = { tree [ 0 ] } activeItem = { activeHeading . value } /> ;
31
+ const tree = buildTree ( sanitizedHeadings ) ;
32
+ const fixStartingBug : Node = { ...tree , children : [ tree ] } ;
33
+ return < RecursiveList tree = { fixStartingBug } activeItem = { activeHeading . value } /> ;
34
34
} ) ;
35
35
36
36
function deltaToStrg (
@@ -55,7 +55,8 @@ function deltaToStrg(
55
55
`bad headings: are downwards discontinous from: #${ currNode . id } to #${ nextNode . id } bc from ${ currNode . level } to ${ nextNode . level } ` ,
56
56
) ;
57
57
}
58
- function getTree ( nodes : ContentHeading [ ] ) {
58
+
59
+ function buildTree ( nodes : ContentHeading [ ] ) {
59
60
let currNode = nodes [ 0 ] as Node ;
60
61
currNode . children = [ ] ;
61
62
const tree = [ currNode ] ;
@@ -94,32 +95,31 @@ function getTree(nodes: ContentHeading[]) {
94
95
}
95
96
currNode = nextNode ;
96
97
}
97
- return tree ;
98
+ return tree [ 0 ] ;
98
99
}
99
- type RecursiveJSXProps = {
100
+
101
+ type RecursiveListProps = {
100
102
tree : Node ;
101
103
activeItem : string ;
102
104
limit ?: number ;
103
105
} ;
104
- const RecursiveJSX = component$ < RecursiveJSXProps > ( ( { tree , activeItem , limit = 3 } ) => {
105
- const currNode : Node = tree ;
106
- return currNode ?. children ?. length && currNode . level < limit ? (
107
- < ul class = { cn ( 'm-0 list-none' , { 'pl-4' : currNode . level !== 1 } ) } >
108
- { currNode . children . map ( ( childNode ) => {
109
- return (
110
- < li key = { currNode . id } class = { cn ( ' mt-0 list-none pt-2' ) } >
106
+
107
+ const RecursiveList = component$ < RecursiveListProps > (
108
+ ( { tree , activeItem , limit = 3 } ) => {
109
+ return tree ?. children ?. length && tree . level < limit ? (
110
+ < ul class = { cn ( 'm-0 list-none' , { 'pl-4' : tree . level !== 1 } ) } >
111
+ { tree . children . map ( ( childNode ) => (
112
+ < li key = { childNode . id } class = " mt-0 list-none pt-2" >
111
113
< Anchor node = { childNode } activeItem = { activeItem } />
112
- { childNode . children . length ? (
113
- < >
114
- < RecursiveJSX tree = { childNode } activeItem = { activeItem } />
115
- </ >
116
- ) : null }
114
+ { childNode . children . length > 0 && (
115
+ < RecursiveList tree = { childNode } activeItem = { activeItem } />
116
+ ) }
117
117
</ li >
118
- ) ;
119
- } ) }
120
- </ ul >
121
- ) : null ;
122
- } ) ;
118
+ ) ) }
119
+ </ ul >
120
+ ) : null ;
121
+ } ,
122
+ ) ;
123
123
124
124
const useActiveItem = ( itemIds : string [ ] ) => {
125
125
const activeId = useSignal < string > ( '' ) ;
@@ -133,7 +133,7 @@ const useActiveItem = (itemIds: string[]) => {
133
133
}
134
134
} ) ;
135
135
} ,
136
- { rootMargin : ` 0% 0% -85% 0%` } ,
136
+ { rootMargin : ' 0% 0% -85% 0%' } ,
137
137
) ;
138
138
139
139
itemIds . forEach ( ( id ) => {
@@ -155,35 +155,35 @@ const useActiveItem = (itemIds: string[]) => {
155
155
156
156
return activeId ;
157
157
} ;
158
- type AnchorThingProps = {
158
+
159
+ type AnchorProps = {
159
160
node : Node ;
160
161
activeItem : string ;
161
162
} ;
162
- export const Anchor = component$ < AnchorThingProps > ( ( props ) => {
163
- const currNode = props . node ;
164
- const activeItem = props . activeItem ;
165
- const isActiveItem = currNode . id === `${ activeItem } ` ;
163
+
164
+ const Anchor = component$ < AnchorProps > ( ( { node, activeItem } ) => {
165
+ const isActive = node . id === activeItem ;
166
166
return (
167
167
< a
168
- href = { `#${ currNode . id } ` }
168
+ href = { `#${ node . id } ` }
169
169
onClick$ = { [
170
170
$ ( ( ) => {
171
- const element = document . getElementById ( currNode . id ) ;
171
+ const element = document . getElementById ( node . id ) ;
172
172
if ( element ) {
173
173
const navbarHeight = 90 ;
174
- const elementPosition =
174
+ const position =
175
175
element . getBoundingClientRect ( ) . top + window . scrollY - navbarHeight ;
176
- window . scrollTo ( { top : elementPosition , behavior : 'auto' } ) ;
176
+ window . scrollTo ( { top : position , behavior : 'auto' } ) ;
177
177
}
178
178
} ) ,
179
179
] }
180
180
class = { cn (
181
- currNode . level > 2 ? 'ml-4' : null ,
181
+ node . level > 2 && 'ml-2' ,
182
182
'inline-block no-underline transition-colors hover:text-foreground' ,
183
- isActiveItem ? 'font-medium text-foreground' : 'text-muted-foreground' ,
183
+ isActive ? 'font-medium text-foreground' : 'text-muted-foreground' ,
184
184
) }
185
185
>
186
- { currNode . text }
186
+ { node . text }
187
187
</ a >
188
188
) ;
189
189
} ) ;
0 commit comments