@@ -46,21 +46,24 @@ const propTypes = {
46
46
* @param {function } Translation function returning the translated string.
47
47
*/
48
48
t : PropTypes . func ,
49
- } ;
50
49
51
- const defaultProps = {
52
- className : "rs-base-layer-switcher" ,
53
- altText : "Source not found" ,
54
- titles : {
55
- button : "Base layers" ,
56
- openSwitcher : "Open Baselayer-Switcher" ,
57
- closeSwitcher : "Close Baselayer-Switcher" ,
58
- } ,
59
- closeButtonImage : < FaChevronLeft /> ,
60
- layerImages : undefined ,
61
- t : ( s ) => {
62
- return s ;
63
- } ,
50
+ /**
51
+ * Callback function on close button click.
52
+ * @param {function } Callback function triggered when a switcher button is clicked. Takes the event as argument.
53
+ */
54
+ onCloseButtonClick : PropTypes . func ,
55
+
56
+ /**
57
+ * Callback function on layer button click.
58
+ * @param {function } Callback function triggered when a switcher button is clicked. Takes the event and the layer as arguments.
59
+ */
60
+ onLayerButtonClick : PropTypes . func ,
61
+
62
+ /**
63
+ * Callback function on main switcher button click.
64
+ * @param {function } Callback function triggered when a switcher button is clicked. Takes the event as argument.
65
+ */
66
+ onSwitcherButtonClick : PropTypes . func ,
64
67
} ;
65
68
66
69
const getVisibleLayer = ( layers ) => {
@@ -90,6 +93,31 @@ const getImageStyle = (url) => {
90
93
: null ;
91
94
} ;
92
95
96
+ function CloseButton ( { onClick, tabIndex, title, children } ) {
97
+ return (
98
+ < div
99
+ className = "rs-base-layer-switcher-close-btn"
100
+ role = "button"
101
+ onClick = { onClick }
102
+ onKeyPress = { ( e ) => {
103
+ return e . which === 13 && onClick ( ) ;
104
+ } }
105
+ tabIndex = { tabIndex }
106
+ aria-label = { title }
107
+ title = { title }
108
+ >
109
+ { children }
110
+ </ div >
111
+ ) ;
112
+ }
113
+
114
+ CloseButton . propTypes = {
115
+ onClick : PropTypes . func . isRequired ,
116
+ tabIndex : PropTypes . string . isRequired ,
117
+ title : PropTypes . string . isRequired ,
118
+ children : PropTypes . node . isRequired ,
119
+ } ;
120
+
93
121
/**
94
122
* The BaseLayerSwitcher component renders a button interface for switching the visible
95
123
* [mobility-toolbox-js layer](https://mobility-toolbox-js.geops.io/api/identifiers%20html#ol-layers)
@@ -98,33 +126,26 @@ const getImageStyle = (url) => {
98
126
99
127
function BaseLayerSwitcher ( {
100
128
layers,
101
- layerImages,
102
- className,
103
- altText,
104
- titles,
105
- closeButtonImage,
106
- t,
129
+ layerImages = undefined ,
130
+ className = "rs-base-layer-switcher" ,
131
+ altText = "Source not found" ,
132
+ titles = {
133
+ button : "Base layers" ,
134
+ openSwitcher : "Open Baselayer-Switcher" ,
135
+ closeSwitcher : "Close Baselayer-Switcher" ,
136
+ } ,
137
+ closeButtonImage = < FaChevronLeft /> ,
138
+ onCloseButtonClick = null ,
139
+ onLayerButtonClick = null ,
140
+ onSwitcherButtonClick = null ,
141
+ t = ( s ) => s ,
107
142
} ) {
108
143
const [ switcherOpen , setSwitcherOpen ] = useState ( false ) ;
109
144
const [ isClosed , setIsClosed ] = useState ( true ) ;
110
145
const [ currentLayer , setCurrentLayer ] = useState (
111
146
getVisibleLayer ( layers ) || layers [ 0 ] ,
112
147
) ;
113
148
114
- useEffect ( ( ) => {
115
- // Update the layer selected when a visibility changes.
116
- const olKeys = ( layers || [ ] ) . map ( ( layer ) => {
117
- return layer . on ( "change:visible" , ( evt ) => {
118
- if ( evt . target . visible && currentLayer !== evt . target ) {
119
- setCurrentLayer ( evt . target ) ;
120
- }
121
- } ) ;
122
- } ) ;
123
- return ( ) => {
124
- unByKey ( olKeys ) ;
125
- } ;
126
- } , [ currentLayer , layers ] ) ;
127
-
128
149
/* Images are loaded from props if provided, fallback from layer */
129
150
const images = layerImages
130
151
? Object . keys ( layerImages ) . map ( ( layerImage ) => {
@@ -137,12 +158,17 @@ function BaseLayerSwitcher({
137
158
const openClass = switcherOpen ? " rs-open" : "" ;
138
159
const hiddenStyle = switcherOpen && ! isClosed ? "visible" : "hidden" ;
139
160
140
- const handleSwitcherClick = ( ) => {
161
+ const handleSwitcherClick = ( evt ) => {
162
+ const nextLayer = layers . find ( ( layer ) => {
163
+ return ! layer . visible ;
164
+ } ) ;
165
+ const onButtonClick =
166
+ layers . length === 2 ? onLayerButtonClick : onSwitcherButtonClick ;
167
+ if ( onButtonClick ) {
168
+ onButtonClick ( evt , nextLayer ) ;
169
+ }
141
170
if ( layers . length === 2 ) {
142
171
/* On only two layer options the opener becomes a layer toggle button */
143
- const nextLayer = layers . find ( ( layer ) => {
144
- return ! layer . visible ;
145
- } ) ;
146
172
if ( currentLayer . setVisible ) {
147
173
currentLayer . setVisible ( false ) ;
148
174
} else {
@@ -160,7 +186,10 @@ function BaseLayerSwitcher({
160
186
return setSwitcherOpen ( true ) && setIsClosed ( false ) ;
161
187
} ;
162
188
163
- const onLayerSelect = ( layer ) => {
189
+ const onLayerSelect = ( layer , evt ) => {
190
+ if ( onLayerButtonClick ) {
191
+ onLayerButtonClick ( evt , layer ) ;
192
+ }
164
193
if ( ! switcherOpen ) {
165
194
setSwitcherOpen ( true ) ;
166
195
return ;
@@ -214,30 +243,24 @@ function BaseLayerSwitcher({
214
243
} ;
215
244
} , [ switcherOpen ] ) ;
216
245
246
+ useEffect ( ( ) => {
247
+ // Update the layer selected when a visibility changes.
248
+ const olKeys = ( layers || [ ] ) . map ( ( layer ) => {
249
+ return layer . on ( "change:visible" , ( evt ) => {
250
+ if ( evt . target . visible && currentLayer !== evt . target ) {
251
+ setCurrentLayer ( evt . target ) ;
252
+ }
253
+ } ) ;
254
+ } ) ;
255
+ return ( ) => {
256
+ unByKey ( olKeys ) ;
257
+ } ;
258
+ } , [ currentLayer , layers ] ) ;
259
+
217
260
if ( ! layers || layers . length < 2 || ! currentLayer ) {
218
261
return null ;
219
262
}
220
263
221
- const toggleBtn = (
222
- < div className = "rs-base-layer-switcher-btn-wrapper" >
223
- < div
224
- className = "rs-base-layer-switcher-close-btn"
225
- role = "button"
226
- onClick = { ( ) => {
227
- return setSwitcherOpen ( false ) ;
228
- } }
229
- onKeyPress = { ( e ) => {
230
- return e . which === 13 && setSwitcherOpen ( false ) ;
231
- } }
232
- tabIndex = { switcherOpen ? "0" : "-1" }
233
- aria-label = { titles . closeSwitcher }
234
- title = { titles . closeSwitcher }
235
- >
236
- { closeButtonImage }
237
- </ div >
238
- </ div >
239
- ) ;
240
-
241
264
return (
242
265
< div className = { `${ className } ${ openClass } ` } >
243
266
< div
@@ -290,12 +313,12 @@ function BaseLayerSwitcher({
290
313
role = "button"
291
314
title = { t ( layerName ) }
292
315
aria-label = { t ( layerName ) }
293
- onClick = { ( ) => {
294
- return onLayerSelect ( layer ) ;
316
+ onClick = { ( evt ) => {
317
+ return onLayerSelect ( layer , evt ) ;
295
318
} }
296
- onKeyPress = { ( e ) => {
297
- if ( e . which === 13 ) {
298
- onLayerSelect ( layer ) ;
319
+ onKeyPress = { ( evt ) => {
320
+ if ( evt . which === 13 ) {
321
+ onLayerSelect ( layer , evt ) ;
299
322
}
300
323
} }
301
324
style = { imageStyle }
@@ -311,12 +334,22 @@ function BaseLayerSwitcher({
311
334
</ div >
312
335
) ;
313
336
} ) }
314
- { toggleBtn }
337
+ < CloseButton
338
+ onClick = { ( evt ) => {
339
+ if ( onCloseButtonClick ) {
340
+ onCloseButtonClick ( evt ) ;
341
+ }
342
+ setSwitcherOpen ( false ) ;
343
+ } }
344
+ tabIndex = { switcherOpen ? "0" : "-1" }
345
+ title = { titles . closeSwitcher }
346
+ >
347
+ { closeButtonImage }
348
+ </ CloseButton >
315
349
</ div >
316
350
) ;
317
351
}
318
352
319
353
BaseLayerSwitcher . propTypes = propTypes ;
320
- BaseLayerSwitcher . defaultProps = defaultProps ;
321
354
322
355
export default BaseLayerSwitcher ;
0 commit comments