1- import { ChangeEvent , JSX , useEffect , useState } from "react" ;
1+ import {
2+ ChangeEvent ,
3+ JSX ,
4+ RefObject ,
5+ useEffect ,
6+ useRef ,
7+ useState ,
8+ } from "react" ;
29import {
310 Link ,
411 Location ,
@@ -20,6 +27,36 @@ function Header({ menuOpen, menuOpenSetter }): JSX.Element {
2027 const urlQuery : string = new URLSearchParams ( location . search ) . get ( "q" ) || "" ;
2128 const [ query , setQuery ] = useState < string > ( "" ) ;
2229
30+ const [ historyMenu , setHistoryMenu ] = useState < "back" | "next" | null > ( null ) ;
31+ const backMenu : RefObject < HTMLUListElement > = useRef < HTMLUListElement > ( null ) ;
32+ const nextMenu : RefObject < HTMLUListElement > = useRef < HTMLUListElement > ( null ) ;
33+
34+ useEffect ( ( ) => {
35+ if ( ! historyMenu ) {
36+ return ;
37+ }
38+
39+ function handleClick ( ev : MouseEvent ) : void {
40+ if (
41+ historyMenu === "back" &&
42+ backMenu . current &&
43+ ! backMenu . current . contains ( ev . target as Node )
44+ ) {
45+ setHistoryMenu ( null ) ;
46+ }
47+ if (
48+ historyMenu === "next" &&
49+ nextMenu . current &&
50+ ! nextMenu . current . contains ( ev . target as Node )
51+ ) {
52+ setHistoryMenu ( null ) ;
53+ }
54+ }
55+
56+ document . addEventListener ( "mousedown" , handleClick ) ;
57+ return ( ) => document . removeEventListener ( "mousedown" , handleClick ) ;
58+ } , [ historyMenu ] ) ;
59+
2360 useEffect ( ( ) : void => {
2461 setQuery ( urlQuery ) ;
2562 } , [ urlQuery ] ) ;
@@ -101,62 +138,138 @@ function Header({ menuOpen, menuOpenSetter }): JSX.Element {
101138 </ Link >
102139 </ div >
103140 < div style = { { justifyContent : "center" } } >
104- < NavLink
105- className = "hoverHeaderButtonFill"
106- disabled = { appHistory . getPrevious ( ) . length === 0 }
107- onClick = {
108- appHistory . getPrevious ( ) . length > 0
109- ? ( ) : void => {
110- navigate ( - 1 ) ;
111- }
112- : null
113- }
114- to = { null }
115- style = { {
116- backgroundColor : "rgba(45, 45, 45, 0.7)" ,
117- borderRadius : "1.5rem" ,
118- display : "inline-block" ,
119- height : "40px" ,
120- marginRight : "10px" ,
121- textAlign : "center" ,
122- verticalAlign : "middle" ,
123- width : "40px" ,
124- } }
125- >
126- < CustomSVG
127- icon = "arrow-left"
128- viewBox = "0 0 24 24"
129- style = { { height : "18px" , padding : "11px 0" } }
130- />
131- </ NavLink >
132- < NavLink
133- className = "hoverHeaderButtonFill"
134- disabled = { appHistory . getNext ( ) . length === 0 }
135- onClick = {
136- appHistory . getNext ( ) . length > 0
137- ? ( ) : void => {
138- navigate ( 1 ) ;
139- }
140- : null
141- }
142- to = { null }
143- style = { {
144- backgroundColor : "rgba(45, 45, 45, 0.7)" ,
145- borderRadius : "1.5rem" ,
146- display : "inline-block" ,
147- height : "40px" ,
148- marginRight : "10px" ,
149- textAlign : "center" ,
150- verticalAlign : "middle" ,
151- width : "40px" ,
152- } }
153- >
154- < CustomSVG
155- icon = "arrow-right"
156- viewBox = "0 0 24 24"
157- style = { { height : "18px" , padding : "11px 0" } }
158- />
159- </ NavLink >
141+ < div style = { { display : "inline-block" } } >
142+ < div style = { { display : "inline-block" } } >
143+ < NavLink
144+ className = "hoverHeaderButtonFill"
145+ disabled = { appHistory . getPrevious ( ) . length === 0 }
146+ onClick = {
147+ appHistory . getPrevious ( ) . length > 0
148+ ? ( ) : void => {
149+ navigate ( - 1 ) ;
150+ }
151+ : null
152+ }
153+ onContextMenu = { ( ev : unknown ) : void => {
154+ ev . preventDefault ( ) ;
155+ setHistoryMenu ( "back" ) ;
156+ } }
157+ to = { null }
158+ style = { {
159+ backgroundColor : "rgba(45, 45, 45, 0.7)" ,
160+ borderRadius : "1.5rem" ,
161+ display : "inline-block" ,
162+ height : "40px" ,
163+ marginRight : "10px" ,
164+ textAlign : "center" ,
165+ verticalAlign : "middle" ,
166+ width : "40px" ,
167+ } }
168+ >
169+ < CustomSVG
170+ icon = "arrow-left"
171+ viewBox = "0 0 24 24"
172+ style = { { height : "18px" , padding : "11px 0" } }
173+ />
174+ </ NavLink >
175+ { historyMenu === "back" && appHistory . getPrevious ( ) . length ? (
176+ < ul
177+ ref = { backMenu }
178+ style = { {
179+ backgroundColor : "rgba(45, 45, 45, 0.9)" ,
180+ borderRadius : 6 ,
181+ listStyle : "none" ,
182+ margin : "0" ,
183+ maxHeight : "200px" ,
184+ overflowY : "auto" ,
185+ padding : 8 ,
186+ position : "absolute" ,
187+ top : "60px" ,
188+ } }
189+ >
190+ { appHistory . getPrevious ( ) . map ( ( item : object , i : number ) => (
191+ < li
192+ key = { i }
193+ onClick = { ( ) => navigate ( - ( i + 1 ) ) }
194+ style = { {
195+ backgroundColor : "rgb(63,63,70)" ,
196+ borderRadius : "6px" ,
197+ cursor : "pointer" ,
198+ padding : "6px" ,
199+ } }
200+ >
201+ { item [ "title" ] }
202+ </ li >
203+ ) ) }
204+ </ ul >
205+ ) : null }
206+ </ div >
207+ < div style = { { display : "inline-block" } } >
208+ < NavLink
209+ className = "hoverHeaderButtonFill"
210+ disabled = { appHistory . getNext ( ) . length === 0 }
211+ onClick = {
212+ appHistory . getNext ( ) . length > 0
213+ ? ( ) : void => {
214+ navigate ( 1 ) ;
215+ }
216+ : null
217+ }
218+ onContextMenu = { ( ev : unknown ) : void => {
219+ ev . preventDefault ( ) ;
220+ setHistoryMenu ( "next" ) ;
221+ } }
222+ to = { null }
223+ style = { {
224+ backgroundColor : "rgba(45, 45, 45, 0.7)" ,
225+ borderRadius : "1.5rem" ,
226+ display : "inline-block" ,
227+ height : "40px" ,
228+ marginRight : "10px" ,
229+ textAlign : "center" ,
230+ verticalAlign : "middle" ,
231+ width : "40px" ,
232+ } }
233+ >
234+ < CustomSVG
235+ icon = "arrow-right"
236+ viewBox = "0 0 24 24"
237+ style = { { height : "18px" , padding : "11px 0" } }
238+ />
239+ </ NavLink >
240+ { historyMenu === "next" && appHistory . getNext ( ) . length > 0 ? (
241+ < ul
242+ ref = { nextMenu }
243+ style = { {
244+ backgroundColor : "rgba(45, 45, 45, 0.9)" ,
245+ borderRadius : 6 ,
246+ listStyle : "none" ,
247+ margin : "0" ,
248+ maxHeight : "200px" ,
249+ overflowY : "auto" ,
250+ padding : 8 ,
251+ position : "absolute" ,
252+ top : "60px" ,
253+ } }
254+ >
255+ { appHistory . getNext ( ) . map ( ( item : object , i : number ) => (
256+ < li
257+ key = { i }
258+ onClick = { ( ) => navigate ( i + 1 ) }
259+ style = { {
260+ backgroundColor : "rgb(63,63,70)" ,
261+ borderRadius : "6px" ,
262+ cursor : "pointer" ,
263+ padding : "6px" ,
264+ } }
265+ >
266+ { item [ "title" ] }
267+ </ li >
268+ ) ) }
269+ </ ul >
270+ ) : null }
271+ </ div >
272+ </ div >
160273 < div style = { { display : "inline-block" , height : "40px" } } >
161274 < form
162275 action = "/search"
0 commit comments