@@ -11,6 +11,7 @@ import { __ } from '@wordpress/i18n';
11
11
import { useRef , useState , useEffect } from '@wordpress/element' ;
12
12
import { focus } from '@wordpress/dom' ;
13
13
import { ENTER } from '@wordpress/keycodes' ;
14
+ import { isShallowEqualObjects } from '@wordpress/is-shallow-equal' ;
14
15
15
16
/**
16
17
* Internal dependencies
@@ -19,7 +20,7 @@ import LinkControlSettingsDrawer from './settings-drawer';
19
20
import LinkControlSearchInput from './search-input' ;
20
21
import LinkPreview from './link-preview' ;
21
22
import useCreatePage from './use-create-page' ;
22
- import useInternalInputValue from './use-internal-input -value' ;
23
+ import useInternalValue from './use-internal-value' ;
23
24
import { ViewerFill } from './viewer-slot' ;
24
25
import { DEFAULT_LINK_SETTINGS } from './constants' ;
25
26
@@ -136,13 +137,20 @@ function LinkControl( {
136
137
const textInputRef = useRef ( ) ;
137
138
const isEndingEditWithFocus = useRef ( false ) ;
138
139
140
+ const settingsKeys = settings . map ( ( { id } ) => id ) ;
141
+
139
142
const [ settingsOpen , setSettingsOpen ] = useState ( false ) ;
140
143
141
- const [ internalUrlInputValue , setInternalUrlInputValue ] =
142
- useInternalInputValue ( value ?. url || '' ) ;
144
+ const [
145
+ internalControlValue ,
146
+ setInternalControlValue ,
147
+ setInternalURLInputValue ,
148
+ setInternalTextInputValue ,
149
+ createSetInternalSettingValueHandler ,
150
+ ] = useInternalValue ( value ) ;
143
151
144
- const [ internalTextInputValue , setInternalTextInputValue ] =
145
- useInternalInputValue ( value ?. title || '' ) ;
152
+ const valueHasChanges =
153
+ value && ! isShallowEqualObjects ( internalControlValue , value ) ;
146
154
147
155
const [ isEditingLink , setIsEditingLink ] = useState (
148
156
forceIsEditingLink !== undefined
@@ -160,6 +168,8 @@ function LinkControl( {
160
168
) {
161
169
setIsEditingLink ( forceIsEditingLink ) ;
162
170
}
171
+ // Todo: bug if the missing dep is introduced. Will need a fix.
172
+ // eslint-disable-next-line react-hooks/exhaustive-deps
163
173
} , [ forceIsEditingLink ] ) ;
164
174
165
175
useEffect ( ( ) => {
@@ -208,29 +218,47 @@ function LinkControl( {
208
218
} ;
209
219
210
220
const handleSelectSuggestion = ( updatedValue ) => {
221
+ // Suggestions may contains "settings" values (e.g. `opensInNewTab`)
222
+ // which should not overide any existing settings values set by the
223
+ // user. This filters out any settings values from the suggestion.
224
+ const nonSettingsChanges = Object . keys ( updatedValue ) . reduce (
225
+ ( acc , key ) => {
226
+ if ( ! settingsKeys . includes ( key ) ) {
227
+ acc [ key ] = updatedValue [ key ] ;
228
+ }
229
+ return acc ;
230
+ } ,
231
+ { }
232
+ ) ;
233
+
211
234
onChange ( {
212
- ...updatedValue ,
213
- title : internalTextInputValue || updatedValue ?. title ,
235
+ ...internalControlValue ,
236
+ ...nonSettingsChanges ,
237
+ // As title is not a setting, it must be manually applied
238
+ // in such a way as to preserve the users changes over
239
+ // any "title" value provided by the "suggestion".
240
+ title : internalControlValue ?. title || updatedValue ?. title ,
214
241
} ) ;
242
+
215
243
stopEditing ( ) ;
216
244
} ;
217
245
218
246
const handleSubmit = ( ) => {
219
- if (
220
- currentUrlInputValue !== value ?. url ||
221
- internalTextInputValue !== value ?. title
222
- ) {
247
+ if ( valueHasChanges ) {
248
+ // Submit the original value with new stored values applied
249
+ // on top. URL is a special case as it may also be a prop.
223
250
onChange ( {
224
251
...value ,
252
+ ...internalControlValue ,
225
253
url : currentUrlInputValue ,
226
- title : internalTextInputValue ,
227
254
} ) ;
228
255
}
229
256
stopEditing ( ) ;
230
257
} ;
231
258
232
259
const handleSubmitWithEnter = ( event ) => {
233
260
const { keyCode } = event ;
261
+
234
262
if (
235
263
keyCode === ENTER &&
236
264
! currentInputIsEmpty // Disallow submitting empty values.
@@ -241,8 +269,7 @@ function LinkControl( {
241
269
} ;
242
270
243
271
const resetInternalValues = ( ) => {
244
- setInternalUrlInputValue ( value ?. url ) ;
245
- setInternalTextInputValue ( value ?. title ) ;
272
+ setInternalControlValue ( value ) ;
246
273
} ;
247
274
248
275
const handleCancel = ( event ) => {
@@ -263,7 +290,8 @@ function LinkControl( {
263
290
onCancel ?. ( ) ;
264
291
} ;
265
292
266
- const currentUrlInputValue = propInputValue || internalUrlInputValue ;
293
+ const currentUrlInputValue =
294
+ propInputValue || internalControlValue ?. url || '' ;
267
295
268
296
const currentInputIsEmpty = ! currentUrlInputValue ?. trim ( ) ?. length ;
269
297
@@ -306,7 +334,7 @@ function LinkControl( {
306
334
value = { currentUrlInputValue }
307
335
withCreateSuggestion = { withCreateSuggestion }
308
336
onCreateSuggestion = { createPage }
309
- onChange = { setInternalUrlInputValue }
337
+ onChange = { setInternalURLInputValue }
310
338
onSelect = { handleSelectSuggestion }
311
339
showInitialSuggestions = { showInitialSuggestions }
312
340
allowDirectEntry = { ! noDirectEntry }
@@ -351,14 +379,18 @@ function LinkControl( {
351
379
showTextControl = { showTextControl }
352
380
showSettings = { showSettings }
353
381
textInputRef = { textInputRef }
354
- internalTextInputValue = { internalTextInputValue }
382
+ internalTextInputValue = {
383
+ internalControlValue ?. title
384
+ }
355
385
setInternalTextInputValue = {
356
386
setInternalTextInputValue
357
387
}
358
388
handleSubmitWithEnter = { handleSubmitWithEnter }
359
- value = { value }
389
+ value = { internalControlValue }
360
390
settings = { settings }
361
- onChange = { onChange }
391
+ onChange = { createSetInternalSettingValueHandler (
392
+ settingsKeys
393
+ ) }
362
394
/>
363
395
) }
364
396
@@ -367,7 +399,9 @@ function LinkControl( {
367
399
variant = "primary"
368
400
onClick = { handleSubmit }
369
401
className = "block-editor-link-control__search-submit"
370
- disabled = { currentInputIsEmpty } // Disallow submitting empty values.
402
+ disabled = {
403
+ ! valueHasChanges || currentInputIsEmpty
404
+ }
371
405
>
372
406
{ __ ( 'Apply' ) }
373
407
</ Button >
0 commit comments