1
- import React , { useRef , useCallback , useState } from 'react' ;
2
- import { eventMap } from '@testing-library/dom/dist/event-map' ;
1
+ import React , { useRef } from 'react' ;
3
2
import { ChevronUpIcon , ChevronDownIcon } from '@primer/octicons-react' ;
4
- import throttle from 'lodash.throttle' ;
3
+
5
4
import AutoSizer from 'react-virtualized-auto-sizer' ;
6
5
import { TrashcanIcon } from '@primer/octicons-react' ;
7
6
8
- import Preview from './Preview' ;
9
- import MarkupEditor from './MarkupEditor' ;
10
- import usePlayground from '../hooks/usePlayground' ;
11
7
import { VirtualScrollable } from './Scrollable' ;
12
8
import IconButton from './IconButton' ;
13
9
import CopyButton from './CopyButton' ;
14
10
import EmptyStreetImg from '../images/EmptyStreetImg' ;
15
11
import StickyList from './StickyList' ;
16
- import Layout from './Layout' ;
17
- import { useParams } from 'react-router-dom' ;
18
-
19
- function targetToString ( ) {
20
- return [
21
- this . tagName . toLowerCase ( ) ,
22
- this . id && `#${ this . id } ` ,
23
- this . name && `[name="${ this . name } "]` ,
24
- this . htmlFor && `[for="${ this . htmlFor } "]` ,
25
- this . value && `[value="${ this . value } "]` ,
26
- this . checked !== null && `[checked=${ this . checked } ]` ,
27
- ]
28
- . filter ( Boolean )
29
- . join ( '' ) ;
30
- }
31
-
32
- function getElementData ( element ) {
33
- const value =
34
- element . tagName === 'SELECT' && element . multiple
35
- ? element . selectedOptions . length > 0
36
- ? JSON . stringify (
37
- Array . from ( element . selectedOptions ) . map ( ( o ) => o . value ) ,
38
- )
39
- : null
40
- : element . value ;
41
-
42
- const hasChecked = element . type === 'checkbox' || element . type === 'radio' ;
43
-
44
- return {
45
- tagName : element . tagName . toLowerCase ( ) ,
46
- id : element . id || null ,
47
- name : element . name || null ,
48
- htmlFor : element . htmlFor || null ,
49
- value : value || null ,
50
- checked : hasChecked ? ! ! element . checked : null ,
51
- toString : targetToString ,
52
- } ;
53
- }
54
-
55
- function addLoggingEvents ( node , log ) {
56
- function createEventLogger ( eventType ) {
57
- return function logEvent ( event ) {
58
- if ( event . target === event . currentTarget ) {
59
- return ;
60
- }
61
-
62
- log ( {
63
- event : eventType ,
64
- target : getElementData ( event . target ) ,
65
- } ) ;
66
- } ;
67
- }
68
- const eventListeners = [ ] ;
69
- Object . keys ( eventMap ) . forEach ( ( name ) => {
70
- eventListeners . push ( {
71
- name : name . toLowerCase ( ) ,
72
- listener : node . addEventListener (
73
- name . toLowerCase ( ) ,
74
- createEventLogger ( { name, ...eventMap [ name ] } ) ,
75
- true ,
76
- ) ,
77
- } ) ;
78
- } ) ;
79
-
80
- return eventListeners ;
81
- }
12
+ import {
13
+ usePreviewEvents ,
14
+ usePreviewEventsActions ,
15
+ } from '../context/PreviewEvents' ;
82
16
83
17
function EventRecord ( { index, style, data } ) {
84
18
const { id, type, name, element, selector } = data [ index ] ;
@@ -102,19 +36,9 @@ function EventRecord({ index, style, data }) {
102
36
}
103
37
104
38
function DomEvents ( ) {
105
- const { gistId, gistVersion } = useParams ( ) ;
106
-
107
- const buffer = useRef ( [ ] ) ;
108
- const previewRef = useRef ( ) ;
109
39
const listRef = useRef ( ) ;
110
-
111
- const sortDirection = useRef ( 'asc' ) ;
112
- const [ appendMode , setAppendMode ] = useState ( 'bottom' ) ;
113
- const [ state , dispatch ] = usePlayground ( { gistId, gistVersion } ) ;
114
- const { markup, result, status, dirty, settings } = state ;
115
-
116
- const [ eventCount , setEventCount ] = useState ( 0 ) ;
117
- const [ eventListeners , setEventListeners ] = useState ( [ ] ) ;
40
+ const { sortDirection, buffer, appendMode, eventCount } = usePreviewEvents ( ) ;
41
+ const { changeSortDirection, reset } = usePreviewEventsActions ( ) ;
118
42
119
43
const getSortIcon = ( ) => (
120
44
< IconButton >
@@ -126,143 +50,67 @@ function DomEvents() {
126
50
</ IconButton >
127
51
) ;
128
52
129
- const changeSortDirection = ( ) => {
130
- const newDirection = sortDirection . current === 'desc' ? 'asc' : 'desc' ;
131
- buffer . current = buffer . current . reverse ( ) ;
132
- setAppendMode ( newDirection === 'desc' ? 'top' : 'bottom' ) ;
133
- sortDirection . current = newDirection ;
134
- } ;
135
-
136
- const reset = ( ) => {
137
- buffer . current = [ ] ;
138
- setEventCount ( 0 ) ;
139
- } ;
140
-
141
53
const getTextToCopy = ( ) =>
142
54
buffer . current
143
55
. map ( ( log ) => `${ log . target . toString ( ) } - ${ log . event . EventType } ` )
144
56
. join ( '\n' ) ;
145
57
146
- const flush = useCallback (
147
- throttle ( ( ) => setEventCount ( buffer . current . length ) , 16 , {
148
- leading : false ,
149
- } ) ,
150
- [ setEventCount ] ,
151
- ) ;
152
-
153
- const setPreviewRef = useCallback ( ( node ) => {
154
- if ( node ) {
155
- previewRef . current = node ;
156
- const eventListeners = addLoggingEvents ( node , ( event ) => {
157
- const log = {
158
- id : buffer . current . length + 1 ,
159
- type : event . event . EventType ,
160
- name : event . event . name ,
161
- element : event . target . tagName ,
162
- selector : event . target . toString ( ) ,
163
- } ;
164
- if ( sortDirection . current === 'desc' ) {
165
- buffer . current . splice ( 0 , 0 , log ) ;
166
- } else {
167
- buffer . current . push ( log ) ;
168
- }
169
-
170
- setTimeout ( flush , 0 ) ;
171
- } ) ;
172
- setEventListeners ( eventListeners ) ;
173
- } else if ( previewRef . current ) {
174
- eventListeners . forEach ( ( event ) =>
175
- previewRef . current . removeEventListener ( event . name , event . listener ) ,
176
- ) ;
177
- previewRef . current = null ;
178
- }
179
- } , [ ] ) ;
180
-
181
58
return (
182
- < Layout
183
- dispatch = { dispatch }
184
- gistId = { gistId }
185
- dirty = { dirty }
186
- status = { status }
187
- settings = { settings }
188
- >
189
- < div className = "flex flex-col h-auto md:h-full w-full" >
190
- < div className = "editor p-4 markup-editor gap-4 md:gap-8 md:h-56 flex-auto grid-cols-1 md:grid-cols-2" >
191
- < div className = "flex-auto relative h-56 md:h-full" >
192
- < MarkupEditor markup = { markup } dispatch = { dispatch } />
59
+ < div className = "editor p-4 h-56 flex-auto overflow-hidden" >
60
+ < div className = "h-full w-full flex flex-col" >
61
+ < div className = "h-8 flex items-center w-full text-sm font-bold" >
62
+ < div
63
+ className = "p-2 w-16 cursor-pointer flex justify-between items-center"
64
+ onClick = { changeSortDirection }
65
+ >
66
+ # { getSortIcon ( ) }
193
67
</ div >
194
68
195
- < div className = "flex-auto h-56 md:h-full" >
196
- < Preview
197
- forwardedRef = { setPreviewRef }
198
- markup = { markup }
199
- elements = { result ?. elements }
200
- accessibleRoles = { result ?. accessibleRoles }
201
- dispatch = { dispatch }
202
- variant = "minimal"
203
- />
69
+ < div className = "p-2 w-32 " > type</ div >
70
+ < div className = "p-2 w-32 " > name</ div >
71
+
72
+ < div className = "p-2 w-40 " > element</ div >
73
+ < div className = "flex-auto p-2 flex justify-between" >
74
+ < span > selector</ span >
75
+ < div >
76
+ < CopyButton
77
+ text = { getTextToCopy }
78
+ title = "copy log"
79
+ className = "mr-5"
80
+ />
81
+ < IconButton title = "clear event log" onClick = { reset } >
82
+ < TrashcanIcon />
83
+ </ IconButton >
84
+ </ div >
204
85
</ div >
205
86
</ div >
206
87
207
- < div className = "flex-none h-8" />
208
-
209
- < div className = "editor p-4 md:h-56 flex-auto overflow-hidden" >
210
- < div className = "h-56 md:h-full w-full flex flex-col" >
211
- < div className = "h-8 flex items-center w-full text-sm font-bold" >
212
- < div
213
- className = "p-2 w-16 cursor-pointer flex justify-between items-center"
214
- onClick = { changeSortDirection }
215
- >
216
- # { getSortIcon ( ) }
217
- </ div >
218
-
219
- < div className = "p-2 w-32 " > type</ div >
220
- < div className = "p-2 w-32 " > name</ div >
221
-
222
- < div className = "p-2 w-40 " > element</ div >
223
- < div className = "flex-auto p-2 flex justify-between" >
224
- < span > selector</ span >
225
- < div >
226
- < CopyButton
227
- text = { getTextToCopy }
228
- title = "copy log"
229
- className = "mr-5"
230
- />
231
- < IconButton title = "clear event log" onClick = { reset } >
232
- < TrashcanIcon />
233
- </ IconButton >
234
- </ div >
235
- </ div >
88
+ < div className = "flex-auto relative overflow-hidden" >
89
+ { buffer . current . length === 0 ? (
90
+ < div className = "flex w-full h-full opacity-50 items-end justify-center" >
91
+ < EmptyStreetImg height = "80%" />
236
92
</ div >
237
-
238
- < div className = "flex-auto relative overflow-hidden" >
239
- { buffer . current . length === 0 ? (
240
- < div className = "flex w-full h-full opacity-50 items-end justify-center" >
241
- < EmptyStreetImg height = "80%" />
242
- </ div >
243
- ) : (
244
- < AutoSizer >
245
- { ( { width, height } ) => (
246
- < StickyList
247
- mode = { appendMode }
248
- ref = { listRef }
249
- height = { height }
250
- itemCount = { eventCount }
251
- itemData = { buffer . current }
252
- itemSize = { 32 }
253
- width = { width }
254
- outerElementType = { VirtualScrollable }
255
- >
256
- { EventRecord }
257
- </ StickyList >
258
- ) }
259
- </ AutoSizer >
93
+ ) : (
94
+ < AutoSizer >
95
+ { ( { width, height } ) => (
96
+ < StickyList
97
+ mode = { appendMode }
98
+ ref = { listRef }
99
+ height = { height }
100
+ itemCount = { eventCount }
101
+ itemData = { buffer . current }
102
+ itemSize = { 32 }
103
+ width = { width }
104
+ outerElementType = { VirtualScrollable }
105
+ >
106
+ { EventRecord }
107
+ </ StickyList >
260
108
) }
261
- </ div >
262
- </ div >
109
+ </ AutoSizer >
110
+ ) }
263
111
</ div >
264
112
</ div >
265
- </ Layout >
113
+ </ div >
266
114
) ;
267
115
}
268
116
0 commit comments