@@ -67,8 +67,8 @@ export default class LinkInlineTool implements InlineTool {
6767 * Elements
6868 */
6969 private nodes : {
70- button : HTMLButtonElement ;
71- input : HTMLInputElement ;
70+ button : HTMLButtonElement | null ;
71+ input : HTMLInputElement | null ;
7272 } = {
7373 button : null ,
7474 input : null ,
@@ -147,49 +147,35 @@ export default class LinkInlineTool implements InlineTool {
147147
148148 /**
149149 * Handle clicks on the Inline Toolbar icon
150- *
151- * @param {Range } range - range to wrap with link
152150 */
153- public surround ( range : Range ) : void {
151+ public surround ( ) : void {
154152 /**
155153 * Range will be null when user makes second click on the 'link icon' to close opened input
156154 */
157- if ( range ) {
158- /**
159- * Save selection before change focus to the input
160- */
161- if ( ! this . inputOpened ) {
162- /** Create blue background instead of selection */
163- this . selection . setFakeBackground ( ) ;
164- this . selection . save ( ) ;
165- } else {
166- this . selection . restore ( ) ;
167- this . selection . removeFakeBackground ( ) ;
168- }
169- const parentAnchor = this . selection . findParentTag ( 'A' ) ;
155+ /**
156+ * Save selection before change focus to the input
157+ */
158+ if ( ! this . inputOpened ) {
159+ /** Create blue background instead of selection */
160+ this . selection . setFakeBackground ( ) ;
161+ this . selection . save ( ) ;
162+ } else {
163+ this . selection . restore ( ) ;
164+ this . selection . removeFakeBackground ( ) ;
165+ }
166+ const parentAnchor = this . selection . findParentTag ( 'A' ) ;
170167
171- /**
172- * Unlink icon pressed
173- */
174- if ( parentAnchor ) {
175- /**
176- * If input is not opened, treat click as explicit unlink action.
177- * If input is opened (e.g., programmatic close when switching tools), avoid unlinking.
178- */
179- if ( ! this . inputOpened ) {
180- this . selection . expandToTag ( parentAnchor ) ;
181- this . unlink ( ) ;
182- this . closeActions ( ) ;
183- this . checkState ( ) ;
184- this . toolbar . close ( ) ;
185- } else {
186- /** Only close actions without clearing saved selection to preserve user state */
187- this . closeActions ( false ) ;
188- this . checkState ( ) ;
189- }
190-
191- return ;
192- }
168+ /**
169+ * Unlink icon pressed
170+ */
171+ if ( parentAnchor ) {
172+ this . selection . expandToTag ( parentAnchor ) ;
173+ this . unlink ( ) ;
174+ this . closeActions ( ) ;
175+ this . checkState ( ) ;
176+ this . toolbar . close ( ) ;
177+
178+ return ;
193179 }
194180
195181 this . toggleActions ( ) ;
@@ -202,23 +188,30 @@ export default class LinkInlineTool implements InlineTool {
202188 const anchorTag = this . selection . findParentTag ( 'A' ) ;
203189
204190 if ( anchorTag ) {
205- this . nodes . button . innerHTML = IconUnlink ;
206- this . nodes . button . classList . add ( this . CSS . buttonUnlink ) ;
207- this . nodes . button . classList . add ( this . CSS . buttonActive ) ;
191+ if ( this . nodes . button ) {
192+ this . nodes . button . innerHTML = IconUnlink ;
193+ this . nodes . button . classList . add ( this . CSS . buttonUnlink ) ;
194+ this . nodes . button . classList . add ( this . CSS . buttonActive ) ;
195+ }
208196 this . openActions ( ) ;
209197
210198 /**
211199 * Fill input value with link href
212200 */
213201 const hrefAttr = anchorTag . getAttribute ( 'href' ) ;
214202
215- this . nodes . input . defaultValue = hrefAttr !== 'null' ? hrefAttr : '' ;
203+ if ( this . nodes . input ) {
204+ this . nodes . input . defaultValue =
205+ hrefAttr !== null && hrefAttr !== 'null' ? hrefAttr : '' ;
206+ }
216207
217208 this . selection . save ( ) ;
218209 } else {
219- this . nodes . button . innerHTML = IconLink ;
220- this . nodes . button . classList . remove ( this . CSS . buttonUnlink ) ;
221- this . nodes . button . classList . remove ( this . CSS . buttonActive ) ;
210+ if ( this . nodes . button ) {
211+ this . nodes . button . innerHTML = IconLink ;
212+ this . nodes . button . classList . remove ( this . CSS . buttonUnlink ) ;
213+ this . nodes . button . classList . remove ( this . CSS . buttonActive ) ;
214+ }
222215 }
223216
224217 return ! ! anchorTag ;
@@ -228,6 +221,16 @@ export default class LinkInlineTool implements InlineTool {
228221 * Function called with Inline Toolbar closing
229222 */
230223 public clear ( ) : void {
224+ /**
225+ * Restore the original text selection if fake background was set
226+ * (e.g. when user was typing a URL and switched to another tool).
227+ * This must happen before closeActions() so the browser selection
228+ * is on the text, not stuck in the input field.
229+ */
230+ if ( this . selection . isFakeBackgroundEnabled ) {
231+ this . selection . restore ( ) ;
232+ this . selection . removeFakeBackground ( ) ;
233+ }
231234 this . closeActions ( ) ;
232235 }
233236
@@ -253,9 +256,11 @@ export default class LinkInlineTool implements InlineTool {
253256 * @param {boolean } needFocus - on link creation we need to focus input. On editing - nope.
254257 */
255258 private openActions ( needFocus = false ) : void {
256- this . nodes . input . classList . add ( this . CSS . inputShowed ) ;
257- if ( needFocus ) {
258- this . nodes . input . focus ( ) ;
259+ if ( this . nodes . input ) {
260+ this . nodes . input . classList . add ( this . CSS . inputShowed ) ;
261+ if ( needFocus ) {
262+ this . nodes . input . focus ( ) ;
263+ }
259264 }
260265 this . inputOpened = true ;
261266 }
@@ -280,8 +285,10 @@ export default class LinkInlineTool implements InlineTool {
280285 currentSelection . restore ( ) ;
281286 }
282287
283- this . nodes . input . classList . remove ( this . CSS . inputShowed ) ;
284- this . nodes . input . value = '' ;
288+ if ( this . nodes . input ) {
289+ this . nodes . input . classList . remove ( this . CSS . inputShowed ) ;
290+ this . nodes . input . value = '' ;
291+ }
285292 if ( clearSavedSelection ) {
286293 this . selection . clearSaved ( ) ;
287294 }
@@ -294,7 +301,7 @@ export default class LinkInlineTool implements InlineTool {
294301 * @param {KeyboardEvent } event - enter keydown event
295302 */
296303 private enterPressed ( event : KeyboardEvent ) : void {
297- let value = this . nodes . input . value || '' ;
304+ let value = ( this . nodes . input && this . nodes . input . value ) || '' ;
298305
299306 if ( ! value . trim ( ) ) {
300307 this . selection . restore ( ) ;
0 commit comments