@@ -9,7 +9,9 @@ import * as Blockly from 'blockly/core';
99/**
1010 * Class for zoom to fit control.
1111 */
12- export class ZoomToFitControl implements Blockly . IPositionable {
12+ export class ZoomToFitControl
13+ implements Blockly . IComponent , Blockly . IPositionable , Blockly . IFocusableNode
14+ {
1315 /**
1416 * The unique id for this component.
1517 */
@@ -72,7 +74,10 @@ export class ZoomToFitControl implements Blockly.IPositionable {
7274 this . workspace . getComponentManager ( ) . addComponent ( {
7375 component : this ,
7476 weight : 2 ,
75- capabilities : [ Blockly . ComponentManager . Capability . POSITIONABLE ] ,
77+ capabilities : [
78+ Blockly . ComponentManager . Capability . POSITIONABLE ,
79+ Blockly . ComponentManager . Capability . FOCUSABLE ,
80+ ] ,
7681 } ) ;
7782 this . createDom ( ) ;
7883 this . initialized = true ;
@@ -97,15 +102,46 @@ export class ZoomToFitControl implements Blockly.IPositionable {
97102 * Creates DOM for ui element.
98103 */
99104 private createDom ( ) {
100- this . svgGroup = Blockly . utils . dom . createSvgElement (
105+ this . svgGroup = Blockly . utils . dom . createSvgElement ( Blockly . utils . Svg . G , {
106+ height : `${ this . height } px` ,
107+ width : `${ this . width } px` ,
108+ class : 'zoomToFit' ,
109+ id : Blockly . utils . idGenerator . getNextUniqueId ( ) ,
110+ tabindex : '0' ,
111+ } ) ;
112+ Blockly . utils . aria . setState (
113+ this . svgGroup ,
114+ Blockly . utils . aria . State . LABEL ,
115+ Blockly . Msg [ 'ZOOM_TO_FIT_ARIA_LABEL' ] ,
116+ ) ;
117+ Blockly . utils . aria . setRole ( this . svgGroup , Blockly . utils . aria . Role . BUTTON ) ;
118+
119+ Blockly . utils . dom . createSvgElement (
120+ Blockly . utils . Svg . RECT ,
121+ {
122+ width : 40 ,
123+ height : 40 ,
124+ x : - 4 ,
125+ y : - 4 ,
126+ rx : 2 ,
127+ ry : 2 ,
128+ fill : 'none' ,
129+ class : 'blocklyFocusRing' ,
130+ } ,
131+ this . svgGroup ,
132+ ) ;
133+
134+ const image = Blockly . utils . dom . createSvgElement (
101135 Blockly . utils . Svg . IMAGE ,
102136 {
103137 height : `${ this . height } px` ,
104138 width : `${ this . width } px` ,
105- class : 'zoomToFit ' ,
139+ class : 'zoomToFitIcon ' ,
106140 } ,
141+ this . svgGroup ,
107142 ) ;
108- this . svgGroup . setAttributeNS (
143+
144+ image . setAttributeNS (
109145 Blockly . utils . dom . XLINK_NS ,
110146 'xlink:href' ,
111147 zoomToFitSvgDataUri ,
@@ -130,16 +166,16 @@ export class ZoomToFitControl implements Blockly.IPositionable {
130166 *
131167 * @param e A pointer down event.
132168 */
133- private onClick ( e : PointerEvent ) {
169+ private onClick ( e ?: Event ) {
134170 this . workspace . zoomToFit ( ) ;
135171 const uiEvent = new ( Blockly . Events . get ( Blockly . Events . CLICK ) ) (
136172 null ,
137173 this . workspace . id ,
138174 'zoom_reset_control' ,
139175 ) ;
140176 Blockly . Events . fire ( uiEvent ) ;
141- e . stopPropagation ( ) ; // avoid to also fire workspace click event
142- e . preventDefault ( ) ;
177+ e ? .stopPropagation ( ) ; // avoid to also fire workspace click event
178+ e ? .preventDefault ( ) ;
143179 }
144180
145181 /**
@@ -241,6 +277,29 @@ export class ZoomToFitControl implements Blockly.IPositionable {
241277 `translate(${ this . left } , ${ this . top } )` ,
242278 ) ;
243279 }
280+
281+ getFocusableElement ( ) : HTMLElement | SVGElement {
282+ if ( ! this . svgGroup ) {
283+ throw new Error ( 'Tried to focus an uninitialized zoom to fit control' ) ;
284+ }
285+ return this . svgGroup ;
286+ }
287+
288+ getFocusableTree ( ) : Blockly . IFocusableTree {
289+ return this . workspace ;
290+ }
291+
292+ onNodeFocus ( ) : void { }
293+
294+ onNodeBlur ( ) : void { }
295+
296+ canBeFocused ( ) : boolean {
297+ return true ;
298+ }
299+
300+ performAction ( e ?: Event ) : void {
301+ this . onClick ( e ) ;
302+ }
244303}
245304
246305/**
@@ -256,13 +315,13 @@ const zoomToFitSvgDataUri =
256315 'E0LjVMNSAxNy41OVYxNUgzdjZoNnYtMkg2LjQybDMuMDgtMy4wOXoiLz48L3N2Zz4=' ;
257316
258317Blockly . Css . register ( `
259- .zoomToFit {
318+ .zoomToFitIcon {
260319 opacity: 0.4;
261320}
262- .zoomToFit :hover {
321+ .zoomToFitIcon :hover, .zoomToFit:focus .zoomToFitIcon {
263322 opacity: 0.6;
264323}
265- .zoomToFit :active {
324+ .zoomToFitIcon :active {
266325 opacity: 0.8;
267326}
268327` ) ;
0 commit comments