1
+ import Tippy from '@tippyjs/react' ;
2
+ import { navigate } from 'gatsby' ;
1
3
import React from 'react' ;
4
+ import { Instance } from 'tippy.js' ;
5
+ import { useDarkMode } from '../../../context/DarkModeContext' ;
2
6
import useUserSolutionsForProblem from '../../../hooks/useUserSolutionsForProblem' ;
3
7
import { isUsaco } from '../../../models/problem' ;
4
8
import TextTooltip from '../../Tooltip/TextTooltip' ;
5
9
import ProblemListItemSolution from './ProblemListItemSolution' ;
6
10
import { ProblemsListItemProps } from './ProblemsListItem' ;
7
11
8
12
export default function ProblemsListItemDropdown (
9
- props : ProblemsListItemProps & { onViewProblemSolutions : ( ) => void }
13
+ props : ProblemsListItemProps & { isFocusProblem : boolean }
10
14
) {
11
15
const [ copied , setCopied ] = React . useState ( false ) ;
12
16
13
17
const problem = props . problem ;
18
+ const isFocusProblem = props . isFocusProblem ;
19
+ console . log ( isFocusProblem ) ;
14
20
const { solutions, currentUserSolutions } =
15
21
useUserSolutionsForProblem ( problem ) ;
16
22
17
23
let viewSolutionsContent = (
18
24
< > View User Solutions ({ solutions ?. length ?? '...' } )</ >
19
25
) ;
26
+
27
+ const darkMode = useDarkMode ( ) ;
20
28
if ( currentUserSolutions ?. length ) {
21
29
viewSolutionsContent = (
22
30
< >
@@ -40,47 +48,99 @@ export default function ProblemsListItemDropdown(
40
48
</ >
41
49
) ;
42
50
}
51
+ let solutionContent = < > </ > ;
52
+ if ( ! isFocusProblem ) {
53
+ solutionContent = (
54
+ < ProblemListItemSolution
55
+ problem = { props . problem }
56
+ onShowSolutionSketch = { props . onShowSolutionSketch }
57
+ />
58
+ ) ;
59
+ }
60
+
61
+ const tippyRef = React . useRef < Instance > ( ) ;
62
+ const [ isDropdownShown , setIsDropdownShown ] = React . useState ( false ) ;
63
+
64
+ const onViewProblemSolutions = ( ) => {
65
+ tippyRef . current . hide ( ) ;
66
+ navigate ( '/problem-solutions/' , {
67
+ state : {
68
+ problem,
69
+ } ,
70
+ } ) ;
71
+ } ;
72
+
43
73
return (
44
74
< div className = "-mx-2 text-left" >
45
75
< div >
46
- < ProblemListItemSolution
47
- problem = { props . problem }
48
- onShowSolutionSketch = { props . onShowSolutionSketch }
49
- />
50
- < button
51
- type = "button"
52
- className = "focus:outline-none block w-full text-left px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-gray-900"
53
- onClick = { props . onViewProblemSolutions }
54
- >
55
- { viewSolutionsContent }
56
- </ button >
57
- < button
58
- type = "button"
59
- className = "focus:outline-none block w-full text-left px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-gray-900"
60
- onClick = { e => {
61
- e . preventDefault ( ) ;
62
- setCopied ( true ) ;
63
- navigator . clipboard . writeText (
64
- window . location . href . split ( / [ ? # ] / ) [ 0 ] +
65
- '#problem-' +
66
- problem . uniqueId
67
- ) ;
68
- } }
76
+ < Tippy
77
+ onCreate = { tippy => ( tippyRef . current = tippy ) }
78
+ content = {
79
+ isDropdownShown ? (
80
+ < div >
81
+ { solutionContent }
82
+
83
+ < button
84
+ type = "button"
85
+ className = "focus:outline-none block w-full text-left px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-gray-900"
86
+ onClick = { onViewProblemSolutions }
87
+ >
88
+ { viewSolutionsContent }
89
+ </ button >
90
+ < button
91
+ type = "button"
92
+ className = "focus:outline-none block w-full text-left px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-gray-900"
93
+ onClick = { e => {
94
+ e . preventDefault ( ) ;
95
+ setCopied ( true ) ;
96
+ navigator . clipboard . writeText (
97
+ window . location . href . split ( / [ ? # ] / ) [ 0 ] +
98
+ '#problem-' +
99
+ problem . uniqueId
100
+ ) ;
101
+ } }
102
+ >
103
+ { copied ? 'Copied!' : 'Copy Permalink' }
104
+ </ button >
105
+ { isUsaco ( problem . source ) && (
106
+ < a
107
+ className = "!font-normal focus:outline-none block w-full text-left px-4 py-2 text-sm !text-gray-700 dark:!text-gray-300 hover:!bg-gray-100 dark:hover:!bg-gray-800 hover:!text-gray-900"
108
+ href = { `https://ide.usaco.guide/usaco/${ problem . uniqueId . substring (
109
+ problem . uniqueId . indexOf ( '-' ) + 1
110
+ ) } `}
111
+ target = "_blank"
112
+ rel = "noreferrer"
113
+ >
114
+ Open in IDE
115
+ </ a >
116
+ ) }
117
+ </ div >
118
+ ) : (
119
+ ''
120
+ )
121
+ }
122
+ theme = { darkMode ? 'dark' : 'light' }
123
+ placement = "bottom-end"
124
+ arrow = { true }
125
+ animation = "fade"
126
+ trigger = "click"
127
+ interactive = { true }
128
+ onShow = { ( ) => setIsDropdownShown ( true ) }
129
+ onHidden = { ( ) => setIsDropdownShown ( false ) }
69
130
>
70
- { copied ? 'Copied!' : 'Copy Permalink' }
71
- </ button >
72
- { isUsaco ( problem . source ) && (
73
- < a
74
- className = "!font-normal focus:outline-none block w-full text-left px-4 py-2 text-sm !text-gray-700 dark:!text-gray-300 hover:!bg-gray-100 dark:hover:!bg-gray-800 hover:!text-gray-900"
75
- href = { `https://ide.usaco.guide/usaco/${ problem . uniqueId . substring (
76
- problem . uniqueId . indexOf ( '-' ) + 1
77
- ) } `}
78
- target = "_blank"
79
- rel = "noreferrer"
80
- >
81
- Open in IDE
82
- </ a >
83
- ) }
131
+ < button className = "focus:outline-none w-8 h-8 inline-flex items-center justify-center text-gray-400 rounded-full bg-transparent hover:text-gray-500 dark:hover:text-gray-300" >
132
+ { /* Heroicon name: solid/dots-vertical */ }
133
+ < svg
134
+ className = "w-5 h-5"
135
+ xmlns = "http://www.w3.org/2000/svg"
136
+ viewBox = "0 0 20 20"
137
+ fill = "currentColor"
138
+ aria-hidden = "true"
139
+ >
140
+ < path d = "M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z" />
141
+ </ svg >
142
+ </ button >
143
+ </ Tippy >
84
144
</ div >
85
145
</ div >
86
146
) ;
0 commit comments