@wordpress/format-library 4.30.0 → 4.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 4.31.0 (2024-03-21)
6
+
5
7
  ## 4.30.0 (2024-03-06)
6
8
 
7
9
  ## 4.29.0 (2024-02-21)
@@ -17,8 +17,9 @@ var _superscript = require("./superscript");
17
17
  var _keyboard = require("./keyboard");
18
18
  var _unknown = require("./unknown");
19
19
  var _language = require("./language");
20
+ var _nonBreakingSpace = require("./non-breaking-space");
20
21
  /**
21
22
  * Internal dependencies
22
23
  */
23
- var _default = exports.default = [_bold.bold, _code.code, _image.image, _italic.italic, _link.link, _strikethrough.strikethrough, _underline.underline, _textColor.textColor, _subscript.subscript, _superscript.superscript, _keyboard.keyboard, _unknown.unknown, _language.language];
24
+ var _default = exports.default = [_bold.bold, _code.code, _image.image, _italic.italic, _link.link, _strikethrough.strikethrough, _underline.underline, _textColor.textColor, _subscript.subscript, _superscript.superscript, _keyboard.keyboard, _unknown.unknown, _language.language, _nonBreakingSpace.nonBreakingSpace];
24
25
  //# sourceMappingURL=default-formats.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_bold","require","_code","_image","_italic","_link","_strikethrough","_underline","_textColor","_subscript","_superscript","_keyboard","_unknown","_language","_default","exports","default","bold","code","image","italic","link","strikethrough","underline","textColor","subscript","superscript","keyboard","unknown","language"],"sources":["@wordpress/format-library/src/default-formats.js"],"sourcesContent":["/**\n * Internal dependencies\n */\nimport { bold } from './bold';\nimport { code } from './code';\nimport { image } from './image';\nimport { italic } from './italic';\nimport { link } from './link';\nimport { strikethrough } from './strikethrough';\nimport { underline } from './underline';\nimport { textColor } from './text-color';\nimport { subscript } from './subscript';\nimport { superscript } from './superscript';\nimport { keyboard } from './keyboard';\nimport { unknown } from './unknown';\nimport { language } from './language';\n\nexport default [\n\tbold,\n\tcode,\n\timage,\n\titalic,\n\tlink,\n\tstrikethrough,\n\tunderline,\n\ttextColor,\n\tsubscript,\n\tsuperscript,\n\tkeyboard,\n\tunknown,\n\tlanguage,\n];\n"],"mappings":";;;;;;AAGA,IAAAA,KAAA,GAAAC,OAAA;AACA,IAAAC,KAAA,GAAAD,OAAA;AACA,IAAAE,MAAA,GAAAF,OAAA;AACA,IAAAG,OAAA,GAAAH,OAAA;AACA,IAAAI,KAAA,GAAAJ,OAAA;AACA,IAAAK,cAAA,GAAAL,OAAA;AACA,IAAAM,UAAA,GAAAN,OAAA;AACA,IAAAO,UAAA,GAAAP,OAAA;AACA,IAAAQ,UAAA,GAAAR,OAAA;AACA,IAAAS,YAAA,GAAAT,OAAA;AACA,IAAAU,SAAA,GAAAV,OAAA;AACA,IAAAW,QAAA,GAAAX,OAAA;AACA,IAAAY,SAAA,GAAAZ,OAAA;AAfA;AACA;AACA;AAFA,IAAAa,QAAA,GAAAC,OAAA,CAAAC,OAAA,GAiBe,CACdC,UAAI,EACJC,UAAI,EACJC,YAAK,EACLC,cAAM,EACNC,UAAI,EACJC,4BAAa,EACbC,oBAAS,EACTC,oBAAS,EACTC,oBAAS,EACTC,wBAAW,EACXC,kBAAQ,EACRC,gBAAO,EACPC,kBAAQ,CACR"}
1
+ {"version":3,"names":["_bold","require","_code","_image","_italic","_link","_strikethrough","_underline","_textColor","_subscript","_superscript","_keyboard","_unknown","_language","_nonBreakingSpace","_default","exports","default","bold","code","image","italic","link","strikethrough","underline","textColor","subscript","superscript","keyboard","unknown","language","nonBreakingSpace"],"sources":["@wordpress/format-library/src/default-formats.js"],"sourcesContent":["/**\n * Internal dependencies\n */\nimport { bold } from './bold';\nimport { code } from './code';\nimport { image } from './image';\nimport { italic } from './italic';\nimport { link } from './link';\nimport { strikethrough } from './strikethrough';\nimport { underline } from './underline';\nimport { textColor } from './text-color';\nimport { subscript } from './subscript';\nimport { superscript } from './superscript';\nimport { keyboard } from './keyboard';\nimport { unknown } from './unknown';\nimport { language } from './language';\nimport { nonBreakingSpace } from './non-breaking-space';\n\nexport default [\n\tbold,\n\tcode,\n\timage,\n\titalic,\n\tlink,\n\tstrikethrough,\n\tunderline,\n\ttextColor,\n\tsubscript,\n\tsuperscript,\n\tkeyboard,\n\tunknown,\n\tlanguage,\n\tnonBreakingSpace,\n];\n"],"mappings":";;;;;;AAGA,IAAAA,KAAA,GAAAC,OAAA;AACA,IAAAC,KAAA,GAAAD,OAAA;AACA,IAAAE,MAAA,GAAAF,OAAA;AACA,IAAAG,OAAA,GAAAH,OAAA;AACA,IAAAI,KAAA,GAAAJ,OAAA;AACA,IAAAK,cAAA,GAAAL,OAAA;AACA,IAAAM,UAAA,GAAAN,OAAA;AACA,IAAAO,UAAA,GAAAP,OAAA;AACA,IAAAQ,UAAA,GAAAR,OAAA;AACA,IAAAS,YAAA,GAAAT,OAAA;AACA,IAAAU,SAAA,GAAAV,OAAA;AACA,IAAAW,QAAA,GAAAX,OAAA;AACA,IAAAY,SAAA,GAAAZ,OAAA;AACA,IAAAa,iBAAA,GAAAb,OAAA;AAhBA;AACA;AACA;AAFA,IAAAc,QAAA,GAAAC,OAAA,CAAAC,OAAA,GAkBe,CACdC,UAAI,EACJC,UAAI,EACJC,YAAK,EACLC,cAAM,EACNC,UAAI,EACJC,4BAAa,EACbC,oBAAS,EACTC,oBAAS,EACTC,oBAAS,EACTC,wBAAW,EACXC,kBAAQ,EACRC,gBAAO,EACPC,kBAAQ,EACRC,kCAAgB,CAChB"}
@@ -34,9 +34,37 @@ function Edit({
34
34
  onFocus,
35
35
  contentRef
36
36
  }) {
37
- const [addingLink, setAddingLink] = (0, _element.useState)(false);
37
+ const [editingLink, setEditingLink] = (0, _element.useState)(false);
38
+ const [creatingLink, setCreatingLink] = (0, _element.useState)(false);
39
+
38
40
  // We only need to store the button element that opened the popover. We can ignore the other states, as they will be handled by the onFocus prop to return to the rich text field.
39
41
  const [openedBy, setOpenedBy] = (0, _element.useState)(null);
42
+
43
+ // Manages whether the Link UI popover should autofocus when shown.
44
+ const [shouldAutoFocus, setShouldAutoFocus] = (0, _element.useState)(true);
45
+ function setIsEditingLink(isEditing, {
46
+ autoFocus = true
47
+ } = {}) {
48
+ setEditingLink(isEditing);
49
+ setShouldAutoFocus(autoFocus);
50
+ }
51
+ function setIsCreatingLink(isCreating) {
52
+ // Don't add a new link if there is already an active link.
53
+ // The two states are mutually exclusive.
54
+ if (isCreating === true && isActive) {
55
+ return;
56
+ }
57
+ setCreatingLink(isCreating);
58
+ }
59
+ (0, _element.useEffect)(() => {
60
+ // When the link becomes inactive (i.e. isActive is false), reset the editingLink state
61
+ // and the creatingLink state. This means that if the Link UI is displayed and the link
62
+ // becomes inactive (e.g. used arrow keys to move cursor outside of link bounds), the UI will close.
63
+ if (!isActive) {
64
+ setEditingLink(false);
65
+ setCreatingLink(false);
66
+ }
67
+ }, [isActive]);
40
68
  (0, _element.useLayoutEffect)(() => {
41
69
  const editableContentElement = contentRef.current;
42
70
  if (!editableContentElement) {
@@ -46,13 +74,18 @@ function Edit({
46
74
  // There is a situation whereby there is an existing link in the rich text
47
75
  // and the user clicks on the leftmost edge of that link and fails to activate
48
76
  // the link format, but the click event still fires on the `<a>` element.
49
- // This causes the `addingLink` state to be set to `true` and the link UI
77
+ // This causes the `editingLink` state to be set to `true` and the link UI
50
78
  // to be rendered in "creating" mode. We need to check isActive to see if
51
79
  // we have an active link format.
52
- if (event.target.tagName !== 'A' || !isActive) {
80
+ if (!event.target.closest('[contenteditable] a') ||
81
+ // other formats (e.g. bold) may be nested within the link.
82
+ !isActive) {
83
+ setIsEditingLink(false);
53
84
  return;
54
85
  }
55
- setAddingLink(true);
86
+ setIsEditingLink(true, {
87
+ autoFocus: false
88
+ });
56
89
  }
57
90
  editableContentElement.addEventListener('click', handleClick);
58
91
  return () => {
@@ -60,6 +93,7 @@ function Edit({
60
93
  };
61
94
  }, [contentRef, isActive]);
62
95
  function addLink(target) {
96
+ setShouldAutoFocus(true);
63
97
  const text = (0, _richText.getTextContent)((0, _richText.slice)(value));
64
98
  if (!isActive && text && (0, _url.isURL)(text) && (0, _utils.isValidHref)(text)) {
65
99
  onChange((0, _richText.applyFormat)(value, {
@@ -79,7 +113,11 @@ function Edit({
79
113
  if (target) {
80
114
  setOpenedBy(target);
81
115
  }
82
- setAddingLink(true);
116
+ if (!isActive) {
117
+ setIsCreatingLink(true);
118
+ } else {
119
+ setIsEditingLink(true);
120
+ }
83
121
  }
84
122
  }
85
123
 
@@ -98,7 +136,9 @@ function Edit({
98
136
  // Otherwise, we rely on the passed in onFocus to return focus to the rich text field.
99
137
 
100
138
  // Close the popover
101
- setAddingLink(false);
139
+ setIsEditingLink(false);
140
+ setIsCreatingLink(false);
141
+
102
142
  // Return focus to the toolbar button or the rich text field
103
143
  if (openedBy?.tagName === 'BUTTON') {
104
144
  openedBy.focus();
@@ -116,13 +156,15 @@ function Edit({
116
156
  // 4. Press Escape
117
157
  // 5. Focus should be on the Options button
118
158
  function onFocusOutside() {
119
- setAddingLink(false);
159
+ setIsEditingLink(false);
160
+ setIsCreatingLink(false);
120
161
  setOpenedBy(null);
121
162
  }
122
163
  function onRemoveFormat() {
123
164
  onChange((0, _richText.removeFormat)(value, name));
124
165
  (0, _a11y.speak)((0, _i18n.__)('Link removed.'), 'assertive');
125
166
  }
167
+ const isEditingActiveLink = editingLink && isActive;
126
168
  return (0, _react.createElement)(_react.Fragment, null, (0, _react.createElement)(_blockEditor.RichTextShortcut, {
127
169
  type: "primary",
128
170
  character: "k",
@@ -138,19 +180,20 @@ function Edit({
138
180
  onClick: event => {
139
181
  addLink(event.currentTarget);
140
182
  },
141
- isActive: isActive || addingLink,
183
+ isActive: isActive || editingLink,
142
184
  shortcutType: "primary",
143
185
  shortcutCharacter: "k",
144
186
  "aria-haspopup": "true",
145
- "aria-expanded": addingLink
146
- }), addingLink && (0, _react.createElement)(_inline.default, {
187
+ "aria-expanded": editingLink
188
+ }), (isEditingActiveLink || creatingLink) && (0, _react.createElement)(_inline.default, {
147
189
  stopAddingLink: stopAddingLink,
148
190
  onFocusOutside: onFocusOutside,
149
191
  isActive: isActive,
150
192
  activeAttributes: activeAttributes,
151
193
  value: value,
152
194
  onChange: onChange,
153
- contentRef: contentRef
195
+ contentRef: contentRef,
196
+ focusOnMount: shouldAutoFocus ? 'firstElement' : false
154
197
  }));
155
198
  }
156
199
  const link = exports.link = {
@@ -1 +1 @@
1
- {"version":3,"names":["_i18n","require","_element","_richText","_url","_blockEditor","_htmlEntities","_icons","_a11y","_inline","_interopRequireDefault","_utils","name","title","__","Edit","isActive","activeAttributes","value","onChange","onFocus","contentRef","addingLink","setAddingLink","useState","openedBy","setOpenedBy","useLayoutEffect","editableContentElement","current","handleClick","event","target","tagName","addEventListener","removeEventListener","addLink","text","getTextContent","slice","isURL","isValidHref","applyFormat","type","attributes","url","isEmail","stopAddingLink","focus","onFocusOutside","onRemoveFormat","removeFormat","speak","_react","createElement","Fragment","RichTextShortcut","character","onUse","RichTextToolbarButton","icon","linkIcon","onClick","currentTarget","shortcutType","shortcutCharacter","default","link","exports","className","id","_id","rel","__unstablePasteRule","html","plainText","pastedText","replace","trim","test","window","console","log","format","decodeEntities","isCollapsed","insert","create","length","edit"],"sources":["@wordpress/format-library/src/link/index.js"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\nimport { useState, useLayoutEffect } from '@wordpress/element';\nimport {\n\tgetTextContent,\n\tapplyFormat,\n\tremoveFormat,\n\tslice,\n\tisCollapsed,\n\tinsert,\n\tcreate,\n} from '@wordpress/rich-text';\nimport { isURL, isEmail } from '@wordpress/url';\nimport {\n\tRichTextToolbarButton,\n\tRichTextShortcut,\n} from '@wordpress/block-editor';\nimport { decodeEntities } from '@wordpress/html-entities';\nimport { link as linkIcon } from '@wordpress/icons';\nimport { speak } from '@wordpress/a11y';\n\n/**\n * Internal dependencies\n */\nimport InlineLinkUI from './inline';\nimport { isValidHref } from './utils';\n\nconst name = 'core/link';\nconst title = __( 'Link' );\n\nfunction Edit( {\n\tisActive,\n\tactiveAttributes,\n\tvalue,\n\tonChange,\n\tonFocus,\n\tcontentRef,\n} ) {\n\tconst [ addingLink, setAddingLink ] = useState( false );\n\t// We only need to store the button element that opened the popover. We can ignore the other states, as they will be handled by the onFocus prop to return to the rich text field.\n\tconst [ openedBy, setOpenedBy ] = useState( null );\n\n\tuseLayoutEffect( () => {\n\t\tconst editableContentElement = contentRef.current;\n\t\tif ( ! editableContentElement ) {\n\t\t\treturn;\n\t\t}\n\n\t\tfunction handleClick( event ) {\n\t\t\t// There is a situation whereby there is an existing link in the rich text\n\t\t\t// and the user clicks on the leftmost edge of that link and fails to activate\n\t\t\t// the link format, but the click event still fires on the `<a>` element.\n\t\t\t// This causes the `addingLink` state to be set to `true` and the link UI\n\t\t\t// to be rendered in \"creating\" mode. We need to check isActive to see if\n\t\t\t// we have an active link format.\n\t\t\tif ( event.target.tagName !== 'A' || ! isActive ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetAddingLink( true );\n\t\t}\n\n\t\teditableContentElement.addEventListener( 'click', handleClick );\n\n\t\treturn () => {\n\t\t\teditableContentElement.removeEventListener( 'click', handleClick );\n\t\t};\n\t}, [ contentRef, isActive ] );\n\n\tfunction addLink( target ) {\n\t\tconst text = getTextContent( slice( value ) );\n\n\t\tif ( ! isActive && text && isURL( text ) && isValidHref( text ) ) {\n\t\t\tonChange(\n\t\t\t\tapplyFormat( value, {\n\t\t\t\t\ttype: name,\n\t\t\t\t\tattributes: { url: text },\n\t\t\t\t} )\n\t\t\t);\n\t\t} else if ( ! isActive && text && isEmail( text ) ) {\n\t\t\tonChange(\n\t\t\t\tapplyFormat( value, {\n\t\t\t\t\ttype: name,\n\t\t\t\t\tattributes: { url: `mailto:${ text }` },\n\t\t\t\t} )\n\t\t\t);\n\t\t} else {\n\t\t\tif ( target ) {\n\t\t\t\tsetOpenedBy( target );\n\t\t\t}\n\t\t\tsetAddingLink( true );\n\t\t}\n\t}\n\n\t/**\n\t * Runs when the popover is closed via escape keypress, unlinking the selected text,\n\t * but _not_ on a click outside the popover. onFocusOutside handles that.\n\t */\n\tfunction stopAddingLink() {\n\t\t// Don't let the click handler on the toolbar button trigger again.\n\n\t\t// There are two places for us to return focus to on Escape keypress:\n\t\t// 1. The rich text field.\n\t\t// 2. The toolbar button.\n\n\t\t// The toolbar button is the only one we need to handle returning focus to.\n\t\t// Otherwise, we rely on the passed in onFocus to return focus to the rich text field.\n\n\t\t// Close the popover\n\t\tsetAddingLink( false );\n\t\t// Return focus to the toolbar button or the rich text field\n\t\tif ( openedBy?.tagName === 'BUTTON' ) {\n\t\t\topenedBy.focus();\n\t\t} else {\n\t\t\tonFocus();\n\t\t}\n\t\t// Remove the openedBy state\n\t\tsetOpenedBy( null );\n\t}\n\n\t// Test for this:\n\t// 1. Click on the link button\n\t// 2. Click the Options button in the top right of header\n\t// 3. Focus should be in the dropdown of the Options button\n\t// 4. Press Escape\n\t// 5. Focus should be on the Options button\n\tfunction onFocusOutside() {\n\t\tsetAddingLink( false );\n\t\tsetOpenedBy( null );\n\t}\n\n\tfunction onRemoveFormat() {\n\t\tonChange( removeFormat( value, name ) );\n\t\tspeak( __( 'Link removed.' ), 'assertive' );\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t<RichTextShortcut type=\"primary\" character=\"k\" onUse={ addLink } />\n\t\t\t<RichTextShortcut\n\t\t\t\ttype=\"primaryShift\"\n\t\t\t\tcharacter=\"k\"\n\t\t\t\tonUse={ onRemoveFormat }\n\t\t\t/>\n\t\t\t<RichTextToolbarButton\n\t\t\t\tname=\"link\"\n\t\t\t\ticon={ linkIcon }\n\t\t\t\ttitle={ isActive ? __( 'Link' ) : title }\n\t\t\t\tonClick={ ( event ) => {\n\t\t\t\t\taddLink( event.currentTarget );\n\t\t\t\t} }\n\t\t\t\tisActive={ isActive || addingLink }\n\t\t\t\tshortcutType=\"primary\"\n\t\t\t\tshortcutCharacter=\"k\"\n\t\t\t\taria-haspopup=\"true\"\n\t\t\t\taria-expanded={ addingLink }\n\t\t\t/>\n\t\t\t{ addingLink && (\n\t\t\t\t<InlineLinkUI\n\t\t\t\t\tstopAddingLink={ stopAddingLink }\n\t\t\t\t\tonFocusOutside={ onFocusOutside }\n\t\t\t\t\tisActive={ isActive }\n\t\t\t\t\tactiveAttributes={ activeAttributes }\n\t\t\t\t\tvalue={ value }\n\t\t\t\t\tonChange={ onChange }\n\t\t\t\t\tcontentRef={ contentRef }\n\t\t\t\t/>\n\t\t\t) }\n\t\t</>\n\t);\n}\n\nexport const link = {\n\tname,\n\ttitle,\n\ttagName: 'a',\n\tclassName: null,\n\tattributes: {\n\t\turl: 'href',\n\t\ttype: 'data-type',\n\t\tid: 'data-id',\n\t\t_id: 'id',\n\t\ttarget: 'target',\n\t\trel: 'rel',\n\t},\n\t__unstablePasteRule( value, { html, plainText } ) {\n\t\tconst pastedText = ( html || plainText )\n\t\t\t.replace( /<[^>]+>/g, '' )\n\t\t\t.trim();\n\n\t\t// A URL was pasted, turn the selection into a link.\n\t\t// For the link pasting feature, allow only http(s) protocols.\n\t\tif ( ! isURL( pastedText ) || ! /^https?:/.test( pastedText ) ) {\n\t\t\treturn value;\n\t\t}\n\n\t\t// Allows us to ask for this information when we get a report.\n\t\twindow.console.log( 'Created link:\\n\\n', pastedText );\n\n\t\tconst format = {\n\t\t\ttype: name,\n\t\t\tattributes: {\n\t\t\t\turl: decodeEntities( pastedText ),\n\t\t\t},\n\t\t};\n\n\t\tif ( isCollapsed( value ) ) {\n\t\t\treturn insert(\n\t\t\t\tvalue,\n\t\t\t\tapplyFormat(\n\t\t\t\t\tcreate( { text: plainText } ),\n\t\t\t\t\tformat,\n\t\t\t\t\t0,\n\t\t\t\t\tplainText.length\n\t\t\t\t)\n\t\t\t);\n\t\t}\n\n\t\treturn applyFormat( value, format );\n\t},\n\tedit: Edit,\n};\n"],"mappings":"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"}
1
+ {"version":3,"names":["_i18n","require","_element","_richText","_url","_blockEditor","_htmlEntities","_icons","_a11y","_inline","_interopRequireDefault","_utils","name","title","__","Edit","isActive","activeAttributes","value","onChange","onFocus","contentRef","editingLink","setEditingLink","useState","creatingLink","setCreatingLink","openedBy","setOpenedBy","shouldAutoFocus","setShouldAutoFocus","setIsEditingLink","isEditing","autoFocus","setIsCreatingLink","isCreating","useEffect","useLayoutEffect","editableContentElement","current","handleClick","event","target","closest","addEventListener","removeEventListener","addLink","text","getTextContent","slice","isURL","isValidHref","applyFormat","type","attributes","url","isEmail","stopAddingLink","tagName","focus","onFocusOutside","onRemoveFormat","removeFormat","speak","isEditingActiveLink","_react","createElement","Fragment","RichTextShortcut","character","onUse","RichTextToolbarButton","icon","linkIcon","onClick","currentTarget","shortcutType","shortcutCharacter","default","focusOnMount","link","exports","className","id","_id","rel","__unstablePasteRule","html","plainText","pastedText","replace","trim","test","window","console","log","format","decodeEntities","isCollapsed","insert","create","length","edit"],"sources":["@wordpress/format-library/src/link/index.js"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\nimport { useState, useLayoutEffect, useEffect } from '@wordpress/element';\nimport {\n\tgetTextContent,\n\tapplyFormat,\n\tremoveFormat,\n\tslice,\n\tisCollapsed,\n\tinsert,\n\tcreate,\n} from '@wordpress/rich-text';\nimport { isURL, isEmail } from '@wordpress/url';\nimport {\n\tRichTextToolbarButton,\n\tRichTextShortcut,\n} from '@wordpress/block-editor';\nimport { decodeEntities } from '@wordpress/html-entities';\nimport { link as linkIcon } from '@wordpress/icons';\nimport { speak } from '@wordpress/a11y';\n\n/**\n * Internal dependencies\n */\nimport InlineLinkUI from './inline';\nimport { isValidHref } from './utils';\n\nconst name = 'core/link';\nconst title = __( 'Link' );\n\nfunction Edit( {\n\tisActive,\n\tactiveAttributes,\n\tvalue,\n\tonChange,\n\tonFocus,\n\tcontentRef,\n} ) {\n\tconst [ editingLink, setEditingLink ] = useState( false );\n\tconst [ creatingLink, setCreatingLink ] = useState( false );\n\n\t// We only need to store the button element that opened the popover. We can ignore the other states, as they will be handled by the onFocus prop to return to the rich text field.\n\tconst [ openedBy, setOpenedBy ] = useState( null );\n\n\t// Manages whether the Link UI popover should autofocus when shown.\n\tconst [ shouldAutoFocus, setShouldAutoFocus ] = useState( true );\n\n\tfunction setIsEditingLink( isEditing, { autoFocus = true } = {} ) {\n\t\tsetEditingLink( isEditing );\n\t\tsetShouldAutoFocus( autoFocus );\n\t}\n\n\tfunction setIsCreatingLink( isCreating ) {\n\t\t// Don't add a new link if there is already an active link.\n\t\t// The two states are mutually exclusive.\n\t\tif ( isCreating === true && isActive ) {\n\t\t\treturn;\n\t\t}\n\t\tsetCreatingLink( isCreating );\n\t}\n\n\tuseEffect( () => {\n\t\t// When the link becomes inactive (i.e. isActive is false), reset the editingLink state\n\t\t// and the creatingLink state. This means that if the Link UI is displayed and the link\n\t\t// becomes inactive (e.g. used arrow keys to move cursor outside of link bounds), the UI will close.\n\t\tif ( ! isActive ) {\n\t\t\tsetEditingLink( false );\n\t\t\tsetCreatingLink( false );\n\t\t}\n\t}, [ isActive ] );\n\n\tuseLayoutEffect( () => {\n\t\tconst editableContentElement = contentRef.current;\n\t\tif ( ! editableContentElement ) {\n\t\t\treturn;\n\t\t}\n\n\t\tfunction handleClick( event ) {\n\t\t\t// There is a situation whereby there is an existing link in the rich text\n\t\t\t// and the user clicks on the leftmost edge of that link and fails to activate\n\t\t\t// the link format, but the click event still fires on the `<a>` element.\n\t\t\t// This causes the `editingLink` state to be set to `true` and the link UI\n\t\t\t// to be rendered in \"creating\" mode. We need to check isActive to see if\n\t\t\t// we have an active link format.\n\t\t\tif (\n\t\t\t\t! event.target.closest( '[contenteditable] a' ) || // other formats (e.g. bold) may be nested within the link.\n\t\t\t\t! isActive\n\t\t\t) {\n\t\t\t\tsetIsEditingLink( false );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetIsEditingLink( true, { autoFocus: false } );\n\t\t}\n\n\t\teditableContentElement.addEventListener( 'click', handleClick );\n\n\t\treturn () => {\n\t\t\teditableContentElement.removeEventListener( 'click', handleClick );\n\t\t};\n\t}, [ contentRef, isActive ] );\n\n\tfunction addLink( target ) {\n\t\tsetShouldAutoFocus( true );\n\t\tconst text = getTextContent( slice( value ) );\n\n\t\tif ( ! isActive && text && isURL( text ) && isValidHref( text ) ) {\n\t\t\tonChange(\n\t\t\t\tapplyFormat( value, {\n\t\t\t\t\ttype: name,\n\t\t\t\t\tattributes: { url: text },\n\t\t\t\t} )\n\t\t\t);\n\t\t} else if ( ! isActive && text && isEmail( text ) ) {\n\t\t\tonChange(\n\t\t\t\tapplyFormat( value, {\n\t\t\t\t\ttype: name,\n\t\t\t\t\tattributes: { url: `mailto:${ text }` },\n\t\t\t\t} )\n\t\t\t);\n\t\t} else {\n\t\t\tif ( target ) {\n\t\t\t\tsetOpenedBy( target );\n\t\t\t}\n\t\t\tif ( ! isActive ) {\n\t\t\t\tsetIsCreatingLink( true );\n\t\t\t} else {\n\t\t\t\tsetIsEditingLink( true );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Runs when the popover is closed via escape keypress, unlinking the selected text,\n\t * but _not_ on a click outside the popover. onFocusOutside handles that.\n\t */\n\tfunction stopAddingLink() {\n\t\t// Don't let the click handler on the toolbar button trigger again.\n\n\t\t// There are two places for us to return focus to on Escape keypress:\n\t\t// 1. The rich text field.\n\t\t// 2. The toolbar button.\n\n\t\t// The toolbar button is the only one we need to handle returning focus to.\n\t\t// Otherwise, we rely on the passed in onFocus to return focus to the rich text field.\n\n\t\t// Close the popover\n\t\tsetIsEditingLink( false );\n\t\tsetIsCreatingLink( false );\n\n\t\t// Return focus to the toolbar button or the rich text field\n\t\tif ( openedBy?.tagName === 'BUTTON' ) {\n\t\t\topenedBy.focus();\n\t\t} else {\n\t\t\tonFocus();\n\t\t}\n\t\t// Remove the openedBy state\n\t\tsetOpenedBy( null );\n\t}\n\n\t// Test for this:\n\t// 1. Click on the link button\n\t// 2. Click the Options button in the top right of header\n\t// 3. Focus should be in the dropdown of the Options button\n\t// 4. Press Escape\n\t// 5. Focus should be on the Options button\n\tfunction onFocusOutside() {\n\t\tsetIsEditingLink( false );\n\t\tsetIsCreatingLink( false );\n\t\tsetOpenedBy( null );\n\t}\n\n\tfunction onRemoveFormat() {\n\t\tonChange( removeFormat( value, name ) );\n\t\tspeak( __( 'Link removed.' ), 'assertive' );\n\t}\n\n\tconst isEditingActiveLink = editingLink && isActive;\n\n\treturn (\n\t\t<>\n\t\t\t<RichTextShortcut type=\"primary\" character=\"k\" onUse={ addLink } />\n\t\t\t<RichTextShortcut\n\t\t\t\ttype=\"primaryShift\"\n\t\t\t\tcharacter=\"k\"\n\t\t\t\tonUse={ onRemoveFormat }\n\t\t\t/>\n\t\t\t<RichTextToolbarButton\n\t\t\t\tname=\"link\"\n\t\t\t\ticon={ linkIcon }\n\t\t\t\ttitle={ isActive ? __( 'Link' ) : title }\n\t\t\t\tonClick={ ( event ) => {\n\t\t\t\t\taddLink( event.currentTarget );\n\t\t\t\t} }\n\t\t\t\tisActive={ isActive || editingLink }\n\t\t\t\tshortcutType=\"primary\"\n\t\t\t\tshortcutCharacter=\"k\"\n\t\t\t\taria-haspopup=\"true\"\n\t\t\t\taria-expanded={ editingLink }\n\t\t\t/>\n\t\t\t{ ( isEditingActiveLink || creatingLink ) && (\n\t\t\t\t<InlineLinkUI\n\t\t\t\t\tstopAddingLink={ stopAddingLink }\n\t\t\t\t\tonFocusOutside={ onFocusOutside }\n\t\t\t\t\tisActive={ isActive }\n\t\t\t\t\tactiveAttributes={ activeAttributes }\n\t\t\t\t\tvalue={ value }\n\t\t\t\t\tonChange={ onChange }\n\t\t\t\t\tcontentRef={ contentRef }\n\t\t\t\t\tfocusOnMount={ shouldAutoFocus ? 'firstElement' : false }\n\t\t\t\t/>\n\t\t\t) }\n\t\t</>\n\t);\n}\n\nexport const link = {\n\tname,\n\ttitle,\n\ttagName: 'a',\n\tclassName: null,\n\tattributes: {\n\t\turl: 'href',\n\t\ttype: 'data-type',\n\t\tid: 'data-id',\n\t\t_id: 'id',\n\t\ttarget: 'target',\n\t\trel: 'rel',\n\t},\n\t__unstablePasteRule( value, { html, plainText } ) {\n\t\tconst pastedText = ( html || plainText )\n\t\t\t.replace( /<[^>]+>/g, '' )\n\t\t\t.trim();\n\n\t\t// A URL was pasted, turn the selection into a link.\n\t\t// For the link pasting feature, allow only http(s) protocols.\n\t\tif ( ! isURL( pastedText ) || ! /^https?:/.test( pastedText ) ) {\n\t\t\treturn value;\n\t\t}\n\n\t\t// Allows us to ask for this information when we get a report.\n\t\twindow.console.log( 'Created link:\\n\\n', pastedText );\n\n\t\tconst format = {\n\t\t\ttype: name,\n\t\t\tattributes: {\n\t\t\t\turl: decodeEntities( pastedText ),\n\t\t\t},\n\t\t};\n\n\t\tif ( isCollapsed( value ) ) {\n\t\t\treturn insert(\n\t\t\t\tvalue,\n\t\t\t\tapplyFormat(\n\t\t\t\t\tcreate( { text: plainText } ),\n\t\t\t\t\tformat,\n\t\t\t\t\t0,\n\t\t\t\t\tplainText.length\n\t\t\t\t)\n\t\t\t);\n\t\t}\n\n\t\treturn applyFormat( value, format );\n\t},\n\tedit: Edit,\n};\n"],"mappings":"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"}
@@ -34,7 +34,8 @@ function InlineLinkUI({
34
34
  onChange,
35
35
  onFocusOutside,
36
36
  stopAddingLink,
37
- contentRef
37
+ contentRef,
38
+ focusOnMount
38
39
  }) {
39
40
  const richLinkTextValue = getRichTextValueFromSelection(value, isActive);
40
41
 
@@ -200,7 +201,9 @@ function InlineLinkUI({
200
201
  onFocusOutside: onFocusOutside,
201
202
  placement: "bottom",
202
203
  offset: 10,
203
- shift: true
204
+ shift: true,
205
+ focusOnMount: focusOnMount,
206
+ constrainTabbing: true
204
207
  }, (0, _react.createElement)(_blockEditor.__experimentalLinkControl, {
205
208
  value: linkValue,
206
209
  onChange: onChangeLink,
@@ -1 +1 @@
1
- {"version":3,"names":["_element","require","_i18n","_a11y","_components","_url","_richText","_blockEditor","_data","_utils","_index","LINK_SETTINGS","LinkControl","DEFAULT_LINK_SETTINGS","id","title","__","InlineLinkUI","isActive","activeAttributes","value","onChange","onFocusOutside","stopAddingLink","contentRef","richLinkTextValue","getRichTextValueFromSelection","richTextText","text","selectionChange","useDispatch","blockEditorStore","createPageEntity","userCanCreatePages","selectionStart","useSelect","select","getSettings","getSelectionStart","_settings","__experimentalCreatePageEntity","__experimentalUserCanCreatePages","linkValue","useMemo","url","type","opensInNewTab","target","nofollow","rel","includes","removeLink","newValue","removeFormat","speak","onChangeLink","nextValue","hasLink","isNewLink","newUrl","prependHTTP","linkFormat","createLinkFormat","undefined","String","opensInNewWindow","newText","isCollapsed","inserted","insert","applyFormat","start","length","clientId","identifier","attributeKey","create","boundary","getFormatBoundary","valBefore","valAfter","split","newValAfter","replace","concat","isValidHref","popoverAnchor","useAnchor","editableContentElement","current","settings","handleCreate","pageTitle","page","status","rendered","link","kind","createButtonText","searchTerm","createInterpolateElement","sprintf","mark","_react","createElement","Popover","anchor","onClose","placement","offset","shift","__experimentalLinkControl","onRemove","hasRichPreviews","createSuggestion","withCreateSuggestion","createSuggestionButtonText","hasTextControl","showInitialSuggestions","suggestionsQuery","initialSuggestionsSearchOptions","subtype","perPage","textStart","textEnd","end","slice","_default","exports","default"],"sources":["@wordpress/format-library/src/link/inline.js"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { useMemo, createInterpolateElement } from '@wordpress/element';\nimport { __, sprintf } from '@wordpress/i18n';\nimport { speak } from '@wordpress/a11y';\nimport { Popover } from '@wordpress/components';\nimport { prependHTTP } from '@wordpress/url';\nimport {\n\tcreate,\n\tinsert,\n\tisCollapsed,\n\tapplyFormat,\n\tremoveFormat,\n\tslice,\n\treplace,\n\tsplit,\n\tconcat,\n\tuseAnchor,\n} from '@wordpress/rich-text';\nimport {\n\t__experimentalLinkControl as LinkControl,\n\tstore as blockEditorStore,\n} from '@wordpress/block-editor';\nimport { useDispatch, useSelect } from '@wordpress/data';\n\n/**\n * Internal dependencies\n */\nimport { createLinkFormat, isValidHref, getFormatBoundary } from './utils';\nimport { link as settings } from './index';\n\nconst LINK_SETTINGS = [\n\t...LinkControl.DEFAULT_LINK_SETTINGS,\n\t{\n\t\tid: 'nofollow',\n\t\ttitle: __( 'Mark as nofollow' ),\n\t},\n];\n\nfunction InlineLinkUI( {\n\tisActive,\n\tactiveAttributes,\n\tvalue,\n\tonChange,\n\tonFocusOutside,\n\tstopAddingLink,\n\tcontentRef,\n} ) {\n\tconst richLinkTextValue = getRichTextValueFromSelection( value, isActive );\n\n\t// Get the text content minus any HTML tags.\n\tconst richTextText = richLinkTextValue.text;\n\n\tconst { selectionChange } = useDispatch( blockEditorStore );\n\n\tconst { createPageEntity, userCanCreatePages, selectionStart } = useSelect(\n\t\t( select ) => {\n\t\t\tconst { getSettings, getSelectionStart } =\n\t\t\t\tselect( blockEditorStore );\n\t\t\tconst _settings = getSettings();\n\n\t\t\treturn {\n\t\t\t\tcreatePageEntity: _settings.__experimentalCreatePageEntity,\n\t\t\t\tuserCanCreatePages: _settings.__experimentalUserCanCreatePages,\n\t\t\t\tselectionStart: getSelectionStart(),\n\t\t\t};\n\t\t},\n\t\t[]\n\t);\n\n\tconst linkValue = useMemo(\n\t\t() => ( {\n\t\t\turl: activeAttributes.url,\n\t\t\ttype: activeAttributes.type,\n\t\t\tid: activeAttributes.id,\n\t\t\topensInNewTab: activeAttributes.target === '_blank',\n\t\t\tnofollow: activeAttributes.rel?.includes( 'nofollow' ),\n\t\t\ttitle: richTextText,\n\t\t} ),\n\t\t[\n\t\t\tactiveAttributes.id,\n\t\t\tactiveAttributes.rel,\n\t\t\tactiveAttributes.target,\n\t\t\tactiveAttributes.type,\n\t\t\tactiveAttributes.url,\n\t\t\trichTextText,\n\t\t]\n\t);\n\n\tfunction removeLink() {\n\t\tconst newValue = removeFormat( value, 'core/link' );\n\t\tonChange( newValue );\n\t\tstopAddingLink();\n\t\tspeak( __( 'Link removed.' ), 'assertive' );\n\t}\n\n\tfunction onChangeLink( nextValue ) {\n\t\tconst hasLink = linkValue?.url;\n\t\tconst isNewLink = ! hasLink;\n\n\t\t// Merge the next value with the current link value.\n\t\tnextValue = {\n\t\t\t...linkValue,\n\t\t\t...nextValue,\n\t\t};\n\n\t\tconst newUrl = prependHTTP( nextValue.url );\n\t\tconst linkFormat = createLinkFormat( {\n\t\t\turl: newUrl,\n\t\t\ttype: nextValue.type,\n\t\t\tid:\n\t\t\t\tnextValue.id !== undefined && nextValue.id !== null\n\t\t\t\t\t? String( nextValue.id )\n\t\t\t\t\t: undefined,\n\t\t\topensInNewWindow: nextValue.opensInNewTab,\n\t\t\tnofollow: nextValue.nofollow,\n\t\t} );\n\n\t\tconst newText = nextValue.title || newUrl;\n\n\t\t// Scenario: we have any active text selection or an active format.\n\t\tlet newValue;\n\t\tif ( isCollapsed( value ) && ! isActive ) {\n\t\t\t// Scenario: we don't have any actively selected text or formats.\n\t\t\tconst inserted = insert( value, newText );\n\n\t\t\tnewValue = applyFormat(\n\t\t\t\tinserted,\n\t\t\t\tlinkFormat,\n\t\t\t\tvalue.start,\n\t\t\t\tvalue.start + newText.length\n\t\t\t);\n\n\t\t\tonChange( newValue );\n\n\t\t\t// Close the Link UI.\n\t\t\tstopAddingLink();\n\n\t\t\t// Move the selection to the end of the inserted link outside of the format boundary\n\t\t\t// so the user can continue typing after the link.\n\t\t\tselectionChange( {\n\t\t\t\tclientId: selectionStart.clientId,\n\t\t\t\tidentifier: selectionStart.attributeKey,\n\t\t\t\tstart: value.start + newText.length + 1,\n\t\t\t} );\n\n\t\t\treturn;\n\t\t} else if ( newText === richTextText ) {\n\t\t\tnewValue = applyFormat( value, linkFormat );\n\t\t} else {\n\t\t\t// Scenario: Editing an existing link.\n\n\t\t\t// Create new RichText value for the new text in order that we\n\t\t\t// can apply formats to it.\n\t\t\tnewValue = create( { text: newText } );\n\t\t\t// Apply the new Link format to this new text value.\n\t\t\tnewValue = applyFormat( newValue, linkFormat, 0, newText.length );\n\n\t\t\t// Get the boundaries of the active link format.\n\t\t\tconst boundary = getFormatBoundary( value, {\n\t\t\t\ttype: 'core/link',\n\t\t\t} );\n\n\t\t\t// Split the value at the start of the active link format.\n\t\t\t// Passing \"start\" as the 3rd parameter is required to ensure\n\t\t\t// the second half of the split value is split at the format's\n\t\t\t// start boundary and avoids relying on the value's \"end\" property\n\t\t\t// which may not correspond correctly.\n\t\t\tconst [ valBefore, valAfter ] = split(\n\t\t\t\tvalue,\n\t\t\t\tboundary.start,\n\t\t\t\tboundary.start\n\t\t\t);\n\n\t\t\t// Update the original (full) RichTextValue replacing the\n\t\t\t// target text with the *new* RichTextValue containing:\n\t\t\t// 1. The new text content.\n\t\t\t// 2. The new link format.\n\t\t\t// As \"replace\" will operate on the first match only, it is\n\t\t\t// run only against the second half of the value which was\n\t\t\t// split at the active format's boundary. This avoids a bug\n\t\t\t// with incorrectly targetted replacements.\n\t\t\t// See: https://github.com/WordPress/gutenberg/issues/41771.\n\t\t\t// Note original formats will be lost when applying this change.\n\t\t\t// That is expected behaviour.\n\t\t\t// See: https://github.com/WordPress/gutenberg/pull/33849#issuecomment-936134179.\n\t\t\tconst newValAfter = replace( valAfter, richTextText, newValue );\n\n\t\t\tnewValue = concat( valBefore, newValAfter );\n\t\t}\n\n\t\tonChange( newValue );\n\n\t\t// Focus should only be returned to the rich text on submit if this link is not\n\t\t// being created for the first time. If it is then focus should remain within the\n\t\t// Link UI because it should remain open for the user to modify the link they have\n\t\t// just created.\n\t\tif ( ! isNewLink ) {\n\t\t\tstopAddingLink();\n\t\t}\n\n\t\tif ( ! isValidHref( newUrl ) ) {\n\t\t\tspeak(\n\t\t\t\t__(\n\t\t\t\t\t'Warning: the link has been inserted but may have errors. Please test it.'\n\t\t\t\t),\n\t\t\t\t'assertive'\n\t\t\t);\n\t\t} else if ( isActive ) {\n\t\t\tspeak( __( 'Link edited.' ), 'assertive' );\n\t\t} else {\n\t\t\tspeak( __( 'Link inserted.' ), 'assertive' );\n\t\t}\n\t}\n\n\tconst popoverAnchor = useAnchor( {\n\t\teditableContentElement: contentRef.current,\n\t\tsettings: { ...settings, isActive },\n\t} );\n\n\tasync function handleCreate( pageTitle ) {\n\t\tconst page = await createPageEntity( {\n\t\t\ttitle: pageTitle,\n\t\t\tstatus: 'draft',\n\t\t} );\n\n\t\treturn {\n\t\t\tid: page.id,\n\t\t\ttype: page.type,\n\t\t\ttitle: page.title.rendered,\n\t\t\turl: page.link,\n\t\t\tkind: 'post-type',\n\t\t};\n\t}\n\n\tfunction createButtonText( searchTerm ) {\n\t\treturn createInterpolateElement(\n\t\t\tsprintf(\n\t\t\t\t/* translators: %s: search term. */\n\t\t\t\t__( 'Create page: <mark>%s</mark>' ),\n\t\t\t\tsearchTerm\n\t\t\t),\n\t\t\t{ mark: <mark /> }\n\t\t);\n\t}\n\n\treturn (\n\t\t<Popover\n\t\t\tanchor={ popoverAnchor }\n\t\t\tonClose={ stopAddingLink }\n\t\t\tonFocusOutside={ onFocusOutside }\n\t\t\tplacement=\"bottom\"\n\t\t\toffset={ 10 }\n\t\t\tshift\n\t\t>\n\t\t\t<LinkControl\n\t\t\t\tvalue={ linkValue }\n\t\t\t\tonChange={ onChangeLink }\n\t\t\t\tonRemove={ removeLink }\n\t\t\t\thasRichPreviews\n\t\t\t\tcreateSuggestion={ createPageEntity && handleCreate }\n\t\t\t\twithCreateSuggestion={ userCanCreatePages }\n\t\t\t\tcreateSuggestionButtonText={ createButtonText }\n\t\t\t\thasTextControl\n\t\t\t\tsettings={ LINK_SETTINGS }\n\t\t\t\tshowInitialSuggestions\n\t\t\t\tsuggestionsQuery={ {\n\t\t\t\t\t// always show Pages as initial suggestions\n\t\t\t\t\tinitialSuggestionsSearchOptions: {\n\t\t\t\t\t\ttype: 'post',\n\t\t\t\t\t\tsubtype: 'page',\n\t\t\t\t\t\tperPage: 20,\n\t\t\t\t\t},\n\t\t\t\t} }\n\t\t\t/>\n\t\t</Popover>\n\t);\n}\n\nfunction getRichTextValueFromSelection( value, isActive ) {\n\t// Default to the selection ranges on the RichTextValue object.\n\tlet textStart = value.start;\n\tlet textEnd = value.end;\n\n\t// If the format is currently active then the rich text value\n\t// should always be taken from the bounds of the active format\n\t// and not the selected text.\n\tif ( isActive ) {\n\t\tconst boundary = getFormatBoundary( value, {\n\t\t\ttype: 'core/link',\n\t\t} );\n\n\t\ttextStart = boundary.start;\n\n\t\t// Text *selection* always extends +1 beyond the edge of the format.\n\t\t// We account for that here.\n\t\ttextEnd = boundary.end + 1;\n\t}\n\n\t// Get a RichTextValue containing the selected text content.\n\treturn slice( value, textStart, textEnd );\n}\n\nexport default InlineLinkUI;\n"],"mappings":"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"}
1
+ {"version":3,"names":["_element","require","_i18n","_a11y","_components","_url","_richText","_blockEditor","_data","_utils","_index","LINK_SETTINGS","LinkControl","DEFAULT_LINK_SETTINGS","id","title","__","InlineLinkUI","isActive","activeAttributes","value","onChange","onFocusOutside","stopAddingLink","contentRef","focusOnMount","richLinkTextValue","getRichTextValueFromSelection","richTextText","text","selectionChange","useDispatch","blockEditorStore","createPageEntity","userCanCreatePages","selectionStart","useSelect","select","getSettings","getSelectionStart","_settings","__experimentalCreatePageEntity","__experimentalUserCanCreatePages","linkValue","useMemo","url","type","opensInNewTab","target","nofollow","rel","includes","removeLink","newValue","removeFormat","speak","onChangeLink","nextValue","hasLink","isNewLink","newUrl","prependHTTP","linkFormat","createLinkFormat","undefined","String","opensInNewWindow","newText","isCollapsed","inserted","insert","applyFormat","start","length","clientId","identifier","attributeKey","create","boundary","getFormatBoundary","valBefore","valAfter","split","newValAfter","replace","concat","isValidHref","popoverAnchor","useAnchor","editableContentElement","current","settings","handleCreate","pageTitle","page","status","rendered","link","kind","createButtonText","searchTerm","createInterpolateElement","sprintf","mark","_react","createElement","Popover","anchor","onClose","placement","offset","shift","constrainTabbing","__experimentalLinkControl","onRemove","hasRichPreviews","createSuggestion","withCreateSuggestion","createSuggestionButtonText","hasTextControl","showInitialSuggestions","suggestionsQuery","initialSuggestionsSearchOptions","subtype","perPage","textStart","textEnd","end","slice","_default","exports","default"],"sources":["@wordpress/format-library/src/link/inline.js"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { useMemo, createInterpolateElement } from '@wordpress/element';\nimport { __, sprintf } from '@wordpress/i18n';\nimport { speak } from '@wordpress/a11y';\nimport { Popover } from '@wordpress/components';\nimport { prependHTTP } from '@wordpress/url';\nimport {\n\tcreate,\n\tinsert,\n\tisCollapsed,\n\tapplyFormat,\n\tremoveFormat,\n\tslice,\n\treplace,\n\tsplit,\n\tconcat,\n\tuseAnchor,\n} from '@wordpress/rich-text';\nimport {\n\t__experimentalLinkControl as LinkControl,\n\tstore as blockEditorStore,\n} from '@wordpress/block-editor';\nimport { useDispatch, useSelect } from '@wordpress/data';\n\n/**\n * Internal dependencies\n */\nimport { createLinkFormat, isValidHref, getFormatBoundary } from './utils';\nimport { link as settings } from './index';\n\nconst LINK_SETTINGS = [\n\t...LinkControl.DEFAULT_LINK_SETTINGS,\n\t{\n\t\tid: 'nofollow',\n\t\ttitle: __( 'Mark as nofollow' ),\n\t},\n];\n\nfunction InlineLinkUI( {\n\tisActive,\n\tactiveAttributes,\n\tvalue,\n\tonChange,\n\tonFocusOutside,\n\tstopAddingLink,\n\tcontentRef,\n\tfocusOnMount,\n} ) {\n\tconst richLinkTextValue = getRichTextValueFromSelection( value, isActive );\n\n\t// Get the text content minus any HTML tags.\n\tconst richTextText = richLinkTextValue.text;\n\n\tconst { selectionChange } = useDispatch( blockEditorStore );\n\n\tconst { createPageEntity, userCanCreatePages, selectionStart } = useSelect(\n\t\t( select ) => {\n\t\t\tconst { getSettings, getSelectionStart } =\n\t\t\t\tselect( blockEditorStore );\n\t\t\tconst _settings = getSettings();\n\n\t\t\treturn {\n\t\t\t\tcreatePageEntity: _settings.__experimentalCreatePageEntity,\n\t\t\t\tuserCanCreatePages: _settings.__experimentalUserCanCreatePages,\n\t\t\t\tselectionStart: getSelectionStart(),\n\t\t\t};\n\t\t},\n\t\t[]\n\t);\n\n\tconst linkValue = useMemo(\n\t\t() => ( {\n\t\t\turl: activeAttributes.url,\n\t\t\ttype: activeAttributes.type,\n\t\t\tid: activeAttributes.id,\n\t\t\topensInNewTab: activeAttributes.target === '_blank',\n\t\t\tnofollow: activeAttributes.rel?.includes( 'nofollow' ),\n\t\t\ttitle: richTextText,\n\t\t} ),\n\t\t[\n\t\t\tactiveAttributes.id,\n\t\t\tactiveAttributes.rel,\n\t\t\tactiveAttributes.target,\n\t\t\tactiveAttributes.type,\n\t\t\tactiveAttributes.url,\n\t\t\trichTextText,\n\t\t]\n\t);\n\n\tfunction removeLink() {\n\t\tconst newValue = removeFormat( value, 'core/link' );\n\t\tonChange( newValue );\n\t\tstopAddingLink();\n\t\tspeak( __( 'Link removed.' ), 'assertive' );\n\t}\n\n\tfunction onChangeLink( nextValue ) {\n\t\tconst hasLink = linkValue?.url;\n\t\tconst isNewLink = ! hasLink;\n\n\t\t// Merge the next value with the current link value.\n\t\tnextValue = {\n\t\t\t...linkValue,\n\t\t\t...nextValue,\n\t\t};\n\n\t\tconst newUrl = prependHTTP( nextValue.url );\n\t\tconst linkFormat = createLinkFormat( {\n\t\t\turl: newUrl,\n\t\t\ttype: nextValue.type,\n\t\t\tid:\n\t\t\t\tnextValue.id !== undefined && nextValue.id !== null\n\t\t\t\t\t? String( nextValue.id )\n\t\t\t\t\t: undefined,\n\t\t\topensInNewWindow: nextValue.opensInNewTab,\n\t\t\tnofollow: nextValue.nofollow,\n\t\t} );\n\n\t\tconst newText = nextValue.title || newUrl;\n\n\t\t// Scenario: we have any active text selection or an active format.\n\t\tlet newValue;\n\t\tif ( isCollapsed( value ) && ! isActive ) {\n\t\t\t// Scenario: we don't have any actively selected text or formats.\n\t\t\tconst inserted = insert( value, newText );\n\n\t\t\tnewValue = applyFormat(\n\t\t\t\tinserted,\n\t\t\t\tlinkFormat,\n\t\t\t\tvalue.start,\n\t\t\t\tvalue.start + newText.length\n\t\t\t);\n\n\t\t\tonChange( newValue );\n\n\t\t\t// Close the Link UI.\n\t\t\tstopAddingLink();\n\n\t\t\t// Move the selection to the end of the inserted link outside of the format boundary\n\t\t\t// so the user can continue typing after the link.\n\t\t\tselectionChange( {\n\t\t\t\tclientId: selectionStart.clientId,\n\t\t\t\tidentifier: selectionStart.attributeKey,\n\t\t\t\tstart: value.start + newText.length + 1,\n\t\t\t} );\n\n\t\t\treturn;\n\t\t} else if ( newText === richTextText ) {\n\t\t\tnewValue = applyFormat( value, linkFormat );\n\t\t} else {\n\t\t\t// Scenario: Editing an existing link.\n\n\t\t\t// Create new RichText value for the new text in order that we\n\t\t\t// can apply formats to it.\n\t\t\tnewValue = create( { text: newText } );\n\t\t\t// Apply the new Link format to this new text value.\n\t\t\tnewValue = applyFormat( newValue, linkFormat, 0, newText.length );\n\n\t\t\t// Get the boundaries of the active link format.\n\t\t\tconst boundary = getFormatBoundary( value, {\n\t\t\t\ttype: 'core/link',\n\t\t\t} );\n\n\t\t\t// Split the value at the start of the active link format.\n\t\t\t// Passing \"start\" as the 3rd parameter is required to ensure\n\t\t\t// the second half of the split value is split at the format's\n\t\t\t// start boundary and avoids relying on the value's \"end\" property\n\t\t\t// which may not correspond correctly.\n\t\t\tconst [ valBefore, valAfter ] = split(\n\t\t\t\tvalue,\n\t\t\t\tboundary.start,\n\t\t\t\tboundary.start\n\t\t\t);\n\n\t\t\t// Update the original (full) RichTextValue replacing the\n\t\t\t// target text with the *new* RichTextValue containing:\n\t\t\t// 1. The new text content.\n\t\t\t// 2. The new link format.\n\t\t\t// As \"replace\" will operate on the first match only, it is\n\t\t\t// run only against the second half of the value which was\n\t\t\t// split at the active format's boundary. This avoids a bug\n\t\t\t// with incorrectly targetted replacements.\n\t\t\t// See: https://github.com/WordPress/gutenberg/issues/41771.\n\t\t\t// Note original formats will be lost when applying this change.\n\t\t\t// That is expected behaviour.\n\t\t\t// See: https://github.com/WordPress/gutenberg/pull/33849#issuecomment-936134179.\n\t\t\tconst newValAfter = replace( valAfter, richTextText, newValue );\n\n\t\t\tnewValue = concat( valBefore, newValAfter );\n\t\t}\n\n\t\tonChange( newValue );\n\n\t\t// Focus should only be returned to the rich text on submit if this link is not\n\t\t// being created for the first time. If it is then focus should remain within the\n\t\t// Link UI because it should remain open for the user to modify the link they have\n\t\t// just created.\n\t\tif ( ! isNewLink ) {\n\t\t\tstopAddingLink();\n\t\t}\n\n\t\tif ( ! isValidHref( newUrl ) ) {\n\t\t\tspeak(\n\t\t\t\t__(\n\t\t\t\t\t'Warning: the link has been inserted but may have errors. Please test it.'\n\t\t\t\t),\n\t\t\t\t'assertive'\n\t\t\t);\n\t\t} else if ( isActive ) {\n\t\t\tspeak( __( 'Link edited.' ), 'assertive' );\n\t\t} else {\n\t\t\tspeak( __( 'Link inserted.' ), 'assertive' );\n\t\t}\n\t}\n\n\tconst popoverAnchor = useAnchor( {\n\t\teditableContentElement: contentRef.current,\n\t\tsettings: {\n\t\t\t...settings,\n\t\t\tisActive,\n\t\t},\n\t} );\n\n\tasync function handleCreate( pageTitle ) {\n\t\tconst page = await createPageEntity( {\n\t\t\ttitle: pageTitle,\n\t\t\tstatus: 'draft',\n\t\t} );\n\n\t\treturn {\n\t\t\tid: page.id,\n\t\t\ttype: page.type,\n\t\t\ttitle: page.title.rendered,\n\t\t\turl: page.link,\n\t\t\tkind: 'post-type',\n\t\t};\n\t}\n\n\tfunction createButtonText( searchTerm ) {\n\t\treturn createInterpolateElement(\n\t\t\tsprintf(\n\t\t\t\t/* translators: %s: search term. */\n\t\t\t\t__( 'Create page: <mark>%s</mark>' ),\n\t\t\t\tsearchTerm\n\t\t\t),\n\t\t\t{ mark: <mark /> }\n\t\t);\n\t}\n\n\treturn (\n\t\t<Popover\n\t\t\tanchor={ popoverAnchor }\n\t\t\tonClose={ stopAddingLink }\n\t\t\tonFocusOutside={ onFocusOutside }\n\t\t\tplacement=\"bottom\"\n\t\t\toffset={ 10 }\n\t\t\tshift\n\t\t\tfocusOnMount={ focusOnMount }\n\t\t\tconstrainTabbing\n\t\t>\n\t\t\t<LinkControl\n\t\t\t\tvalue={ linkValue }\n\t\t\t\tonChange={ onChangeLink }\n\t\t\t\tonRemove={ removeLink }\n\t\t\t\thasRichPreviews\n\t\t\t\tcreateSuggestion={ createPageEntity && handleCreate }\n\t\t\t\twithCreateSuggestion={ userCanCreatePages }\n\t\t\t\tcreateSuggestionButtonText={ createButtonText }\n\t\t\t\thasTextControl\n\t\t\t\tsettings={ LINK_SETTINGS }\n\t\t\t\tshowInitialSuggestions\n\t\t\t\tsuggestionsQuery={ {\n\t\t\t\t\t// always show Pages as initial suggestions\n\t\t\t\t\tinitialSuggestionsSearchOptions: {\n\t\t\t\t\t\ttype: 'post',\n\t\t\t\t\t\tsubtype: 'page',\n\t\t\t\t\t\tperPage: 20,\n\t\t\t\t\t},\n\t\t\t\t} }\n\t\t\t/>\n\t\t</Popover>\n\t);\n}\n\nfunction getRichTextValueFromSelection( value, isActive ) {\n\t// Default to the selection ranges on the RichTextValue object.\n\tlet textStart = value.start;\n\tlet textEnd = value.end;\n\n\t// If the format is currently active then the rich text value\n\t// should always be taken from the bounds of the active format\n\t// and not the selected text.\n\tif ( isActive ) {\n\t\tconst boundary = getFormatBoundary( value, {\n\t\t\ttype: 'core/link',\n\t\t} );\n\n\t\ttextStart = boundary.start;\n\n\t\t// Text *selection* always extends +1 beyond the edge of the format.\n\t\t// We account for that here.\n\t\ttextEnd = boundary.end + 1;\n\t}\n\n\t// Get a RichTextValue containing the selected text content.\n\treturn slice( value, textStart, textEnd );\n}\n\nexport default InlineLinkUI;\n"],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.nonBreakingSpace = void 0;
7
+ var _react = require("react");
8
+ var _i18n = require("@wordpress/i18n");
9
+ var _richText = require("@wordpress/rich-text");
10
+ var _blockEditor = require("@wordpress/block-editor");
11
+ /**
12
+ * WordPress dependencies
13
+ */
14
+
15
+ const name = 'core/non-breaking-space';
16
+ const title = (0, _i18n.__)('Non breaking space');
17
+ const nonBreakingSpace = exports.nonBreakingSpace = {
18
+ name,
19
+ title,
20
+ tagName: 'nbsp',
21
+ className: null,
22
+ edit({
23
+ value,
24
+ onChange
25
+ }) {
26
+ function addNonBreakingSpace() {
27
+ onChange((0, _richText.insert)(value, '\u00a0'));
28
+ }
29
+ return (0, _react.createElement)(_blockEditor.RichTextShortcut, {
30
+ type: "primaryShift",
31
+ character: " ",
32
+ onUse: addNonBreakingSpace
33
+ });
34
+ }
35
+ };
36
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_i18n","require","_richText","_blockEditor","name","title","__","nonBreakingSpace","exports","tagName","className","edit","value","onChange","addNonBreakingSpace","insert","_react","createElement","RichTextShortcut","type","character","onUse"],"sources":["@wordpress/format-library/src/non-breaking-space/index.js"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\nimport { insert } from '@wordpress/rich-text';\nimport { RichTextShortcut } from '@wordpress/block-editor';\n\nconst name = 'core/non-breaking-space';\nconst title = __( 'Non breaking space' );\n\nexport const nonBreakingSpace = {\n\tname,\n\ttitle,\n\ttagName: 'nbsp',\n\tclassName: null,\n\tedit( { value, onChange } ) {\n\t\tfunction addNonBreakingSpace() {\n\t\t\tonChange( insert( value, '\\u00a0' ) );\n\t\t}\n\n\t\treturn (\n\t\t\t<RichTextShortcut\n\t\t\t\ttype=\"primaryShift\"\n\t\t\t\tcharacter=\" \"\n\t\t\t\tonUse={ addNonBreakingSpace }\n\t\t\t/>\n\t\t);\n\t},\n};\n"],"mappings":";;;;;;;AAGA,IAAAA,KAAA,GAAAC,OAAA;AACA,IAAAC,SAAA,GAAAD,OAAA;AACA,IAAAE,YAAA,GAAAF,OAAA;AALA;AACA;AACA;;AAKA,MAAMG,IAAI,GAAG,yBAAyB;AACtC,MAAMC,KAAK,GAAG,IAAAC,QAAE,EAAE,oBAAqB,CAAC;AAEjC,MAAMC,gBAAgB,GAAAC,OAAA,CAAAD,gBAAA,GAAG;EAC/BH,IAAI;EACJC,KAAK;EACLI,OAAO,EAAE,MAAM;EACfC,SAAS,EAAE,IAAI;EACfC,IAAIA,CAAE;IAAEC,KAAK;IAAEC;EAAS,CAAC,EAAG;IAC3B,SAASC,mBAAmBA,CAAA,EAAG;MAC9BD,QAAQ,CAAE,IAAAE,gBAAM,EAAEH,KAAK,EAAE,QAAS,CAAE,CAAC;IACtC;IAEA,OACC,IAAAI,MAAA,CAAAC,aAAA,EAACd,YAAA,CAAAe,gBAAgB;MAChBC,IAAI,EAAC,cAAc;MACnBC,SAAS,EAAC,GAAG;MACbC,KAAK,EAAGP;IAAqB,CAC7B,CAAC;EAEJ;AACD,CAAC"}
@@ -14,5 +14,6 @@ import { superscript } from './superscript';
14
14
  import { keyboard } from './keyboard';
15
15
  import { unknown } from './unknown';
16
16
  import { language } from './language';
17
- export default [bold, code, image, italic, link, strikethrough, underline, textColor, subscript, superscript, keyboard, unknown, language];
17
+ import { nonBreakingSpace } from './non-breaking-space';
18
+ export default [bold, code, image, italic, link, strikethrough, underline, textColor, subscript, superscript, keyboard, unknown, language, nonBreakingSpace];
18
19
  //# sourceMappingURL=default-formats.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["bold","code","image","italic","link","strikethrough","underline","textColor","subscript","superscript","keyboard","unknown","language"],"sources":["@wordpress/format-library/src/default-formats.js"],"sourcesContent":["/**\n * Internal dependencies\n */\nimport { bold } from './bold';\nimport { code } from './code';\nimport { image } from './image';\nimport { italic } from './italic';\nimport { link } from './link';\nimport { strikethrough } from './strikethrough';\nimport { underline } from './underline';\nimport { textColor } from './text-color';\nimport { subscript } from './subscript';\nimport { superscript } from './superscript';\nimport { keyboard } from './keyboard';\nimport { unknown } from './unknown';\nimport { language } from './language';\n\nexport default [\n\tbold,\n\tcode,\n\timage,\n\titalic,\n\tlink,\n\tstrikethrough,\n\tunderline,\n\ttextColor,\n\tsubscript,\n\tsuperscript,\n\tkeyboard,\n\tunknown,\n\tlanguage,\n];\n"],"mappings":"AAAA;AACA;AACA;AACA,SAASA,IAAI,QAAQ,QAAQ;AAC7B,SAASC,IAAI,QAAQ,QAAQ;AAC7B,SAASC,KAAK,QAAQ,SAAS;AAC/B,SAASC,MAAM,QAAQ,UAAU;AACjC,SAASC,IAAI,QAAQ,QAAQ;AAC7B,SAASC,aAAa,QAAQ,iBAAiB;AAC/C,SAASC,SAAS,QAAQ,aAAa;AACvC,SAASC,SAAS,QAAQ,cAAc;AACxC,SAASC,SAAS,QAAQ,aAAa;AACvC,SAASC,WAAW,QAAQ,eAAe;AAC3C,SAASC,QAAQ,QAAQ,YAAY;AACrC,SAASC,OAAO,QAAQ,WAAW;AACnC,SAASC,QAAQ,QAAQ,YAAY;AAErC,eAAe,CACdZ,IAAI,EACJC,IAAI,EACJC,KAAK,EACLC,MAAM,EACNC,IAAI,EACJC,aAAa,EACbC,SAAS,EACTC,SAAS,EACTC,SAAS,EACTC,WAAW,EACXC,QAAQ,EACRC,OAAO,EACPC,QAAQ,CACR"}
1
+ {"version":3,"names":["bold","code","image","italic","link","strikethrough","underline","textColor","subscript","superscript","keyboard","unknown","language","nonBreakingSpace"],"sources":["@wordpress/format-library/src/default-formats.js"],"sourcesContent":["/**\n * Internal dependencies\n */\nimport { bold } from './bold';\nimport { code } from './code';\nimport { image } from './image';\nimport { italic } from './italic';\nimport { link } from './link';\nimport { strikethrough } from './strikethrough';\nimport { underline } from './underline';\nimport { textColor } from './text-color';\nimport { subscript } from './subscript';\nimport { superscript } from './superscript';\nimport { keyboard } from './keyboard';\nimport { unknown } from './unknown';\nimport { language } from './language';\nimport { nonBreakingSpace } from './non-breaking-space';\n\nexport default [\n\tbold,\n\tcode,\n\timage,\n\titalic,\n\tlink,\n\tstrikethrough,\n\tunderline,\n\ttextColor,\n\tsubscript,\n\tsuperscript,\n\tkeyboard,\n\tunknown,\n\tlanguage,\n\tnonBreakingSpace,\n];\n"],"mappings":"AAAA;AACA;AACA;AACA,SAASA,IAAI,QAAQ,QAAQ;AAC7B,SAASC,IAAI,QAAQ,QAAQ;AAC7B,SAASC,KAAK,QAAQ,SAAS;AAC/B,SAASC,MAAM,QAAQ,UAAU;AACjC,SAASC,IAAI,QAAQ,QAAQ;AAC7B,SAASC,aAAa,QAAQ,iBAAiB;AAC/C,SAASC,SAAS,QAAQ,aAAa;AACvC,SAASC,SAAS,QAAQ,cAAc;AACxC,SAASC,SAAS,QAAQ,aAAa;AACvC,SAASC,WAAW,QAAQ,eAAe;AAC3C,SAASC,QAAQ,QAAQ,YAAY;AACrC,SAASC,OAAO,QAAQ,WAAW;AACnC,SAASC,QAAQ,QAAQ,YAAY;AACrC,SAASC,gBAAgB,QAAQ,sBAAsB;AAEvD,eAAe,CACdb,IAAI,EACJC,IAAI,EACJC,KAAK,EACLC,MAAM,EACNC,IAAI,EACJC,aAAa,EACbC,SAAS,EACTC,SAAS,EACTC,SAAS,EACTC,WAAW,EACXC,QAAQ,EACRC,OAAO,EACPC,QAAQ,EACRC,gBAAgB,CAChB"}
@@ -3,7 +3,7 @@ import { createElement, Fragment } from "react";
3
3
  * WordPress dependencies
4
4
  */
5
5
  import { __ } from '@wordpress/i18n';
6
- import { useState, useLayoutEffect } from '@wordpress/element';
6
+ import { useState, useLayoutEffect, useEffect } from '@wordpress/element';
7
7
  import { getTextContent, applyFormat, removeFormat, slice, isCollapsed, insert, create } from '@wordpress/rich-text';
8
8
  import { isURL, isEmail } from '@wordpress/url';
9
9
  import { RichTextToolbarButton, RichTextShortcut } from '@wordpress/block-editor';
@@ -26,9 +26,37 @@ function Edit({
26
26
  onFocus,
27
27
  contentRef
28
28
  }) {
29
- const [addingLink, setAddingLink] = useState(false);
29
+ const [editingLink, setEditingLink] = useState(false);
30
+ const [creatingLink, setCreatingLink] = useState(false);
31
+
30
32
  // We only need to store the button element that opened the popover. We can ignore the other states, as they will be handled by the onFocus prop to return to the rich text field.
31
33
  const [openedBy, setOpenedBy] = useState(null);
34
+
35
+ // Manages whether the Link UI popover should autofocus when shown.
36
+ const [shouldAutoFocus, setShouldAutoFocus] = useState(true);
37
+ function setIsEditingLink(isEditing, {
38
+ autoFocus = true
39
+ } = {}) {
40
+ setEditingLink(isEditing);
41
+ setShouldAutoFocus(autoFocus);
42
+ }
43
+ function setIsCreatingLink(isCreating) {
44
+ // Don't add a new link if there is already an active link.
45
+ // The two states are mutually exclusive.
46
+ if (isCreating === true && isActive) {
47
+ return;
48
+ }
49
+ setCreatingLink(isCreating);
50
+ }
51
+ useEffect(() => {
52
+ // When the link becomes inactive (i.e. isActive is false), reset the editingLink state
53
+ // and the creatingLink state. This means that if the Link UI is displayed and the link
54
+ // becomes inactive (e.g. used arrow keys to move cursor outside of link bounds), the UI will close.
55
+ if (!isActive) {
56
+ setEditingLink(false);
57
+ setCreatingLink(false);
58
+ }
59
+ }, [isActive]);
32
60
  useLayoutEffect(() => {
33
61
  const editableContentElement = contentRef.current;
34
62
  if (!editableContentElement) {
@@ -38,13 +66,18 @@ function Edit({
38
66
  // There is a situation whereby there is an existing link in the rich text
39
67
  // and the user clicks on the leftmost edge of that link and fails to activate
40
68
  // the link format, but the click event still fires on the `<a>` element.
41
- // This causes the `addingLink` state to be set to `true` and the link UI
69
+ // This causes the `editingLink` state to be set to `true` and the link UI
42
70
  // to be rendered in "creating" mode. We need to check isActive to see if
43
71
  // we have an active link format.
44
- if (event.target.tagName !== 'A' || !isActive) {
72
+ if (!event.target.closest('[contenteditable] a') ||
73
+ // other formats (e.g. bold) may be nested within the link.
74
+ !isActive) {
75
+ setIsEditingLink(false);
45
76
  return;
46
77
  }
47
- setAddingLink(true);
78
+ setIsEditingLink(true, {
79
+ autoFocus: false
80
+ });
48
81
  }
49
82
  editableContentElement.addEventListener('click', handleClick);
50
83
  return () => {
@@ -52,6 +85,7 @@ function Edit({
52
85
  };
53
86
  }, [contentRef, isActive]);
54
87
  function addLink(target) {
88
+ setShouldAutoFocus(true);
55
89
  const text = getTextContent(slice(value));
56
90
  if (!isActive && text && isURL(text) && isValidHref(text)) {
57
91
  onChange(applyFormat(value, {
@@ -71,7 +105,11 @@ function Edit({
71
105
  if (target) {
72
106
  setOpenedBy(target);
73
107
  }
74
- setAddingLink(true);
108
+ if (!isActive) {
109
+ setIsCreatingLink(true);
110
+ } else {
111
+ setIsEditingLink(true);
112
+ }
75
113
  }
76
114
  }
77
115
 
@@ -90,7 +128,9 @@ function Edit({
90
128
  // Otherwise, we rely on the passed in onFocus to return focus to the rich text field.
91
129
 
92
130
  // Close the popover
93
- setAddingLink(false);
131
+ setIsEditingLink(false);
132
+ setIsCreatingLink(false);
133
+
94
134
  // Return focus to the toolbar button or the rich text field
95
135
  if (openedBy?.tagName === 'BUTTON') {
96
136
  openedBy.focus();
@@ -108,13 +148,15 @@ function Edit({
108
148
  // 4. Press Escape
109
149
  // 5. Focus should be on the Options button
110
150
  function onFocusOutside() {
111
- setAddingLink(false);
151
+ setIsEditingLink(false);
152
+ setIsCreatingLink(false);
112
153
  setOpenedBy(null);
113
154
  }
114
155
  function onRemoveFormat() {
115
156
  onChange(removeFormat(value, name));
116
157
  speak(__('Link removed.'), 'assertive');
117
158
  }
159
+ const isEditingActiveLink = editingLink && isActive;
118
160
  return createElement(Fragment, null, createElement(RichTextShortcut, {
119
161
  type: "primary",
120
162
  character: "k",
@@ -130,19 +172,20 @@ function Edit({
130
172
  onClick: event => {
131
173
  addLink(event.currentTarget);
132
174
  },
133
- isActive: isActive || addingLink,
175
+ isActive: isActive || editingLink,
134
176
  shortcutType: "primary",
135
177
  shortcutCharacter: "k",
136
178
  "aria-haspopup": "true",
137
- "aria-expanded": addingLink
138
- }), addingLink && createElement(InlineLinkUI, {
179
+ "aria-expanded": editingLink
180
+ }), (isEditingActiveLink || creatingLink) && createElement(InlineLinkUI, {
139
181
  stopAddingLink: stopAddingLink,
140
182
  onFocusOutside: onFocusOutside,
141
183
  isActive: isActive,
142
184
  activeAttributes: activeAttributes,
143
185
  value: value,
144
186
  onChange: onChange,
145
- contentRef: contentRef
187
+ contentRef: contentRef,
188
+ focusOnMount: shouldAutoFocus ? 'firstElement' : false
146
189
  }));
147
190
  }
148
191
  export const link = {
@@ -1 +1 @@
1
- {"version":3,"names":["__","useState","useLayoutEffect","getTextContent","applyFormat","removeFormat","slice","isCollapsed","insert","create","isURL","isEmail","RichTextToolbarButton","RichTextShortcut","decodeEntities","link","linkIcon","speak","InlineLinkUI","isValidHref","name","title","Edit","isActive","activeAttributes","value","onChange","onFocus","contentRef","addingLink","setAddingLink","openedBy","setOpenedBy","editableContentElement","current","handleClick","event","target","tagName","addEventListener","removeEventListener","addLink","text","type","attributes","url","stopAddingLink","focus","onFocusOutside","onRemoveFormat","createElement","Fragment","character","onUse","icon","onClick","currentTarget","shortcutType","shortcutCharacter","className","id","_id","rel","__unstablePasteRule","html","plainText","pastedText","replace","trim","test","window","console","log","format","length","edit"],"sources":["@wordpress/format-library/src/link/index.js"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\nimport { useState, useLayoutEffect } from '@wordpress/element';\nimport {\n\tgetTextContent,\n\tapplyFormat,\n\tremoveFormat,\n\tslice,\n\tisCollapsed,\n\tinsert,\n\tcreate,\n} from '@wordpress/rich-text';\nimport { isURL, isEmail } from '@wordpress/url';\nimport {\n\tRichTextToolbarButton,\n\tRichTextShortcut,\n} from '@wordpress/block-editor';\nimport { decodeEntities } from '@wordpress/html-entities';\nimport { link as linkIcon } from '@wordpress/icons';\nimport { speak } from '@wordpress/a11y';\n\n/**\n * Internal dependencies\n */\nimport InlineLinkUI from './inline';\nimport { isValidHref } from './utils';\n\nconst name = 'core/link';\nconst title = __( 'Link' );\n\nfunction Edit( {\n\tisActive,\n\tactiveAttributes,\n\tvalue,\n\tonChange,\n\tonFocus,\n\tcontentRef,\n} ) {\n\tconst [ addingLink, setAddingLink ] = useState( false );\n\t// We only need to store the button element that opened the popover. We can ignore the other states, as they will be handled by the onFocus prop to return to the rich text field.\n\tconst [ openedBy, setOpenedBy ] = useState( null );\n\n\tuseLayoutEffect( () => {\n\t\tconst editableContentElement = contentRef.current;\n\t\tif ( ! editableContentElement ) {\n\t\t\treturn;\n\t\t}\n\n\t\tfunction handleClick( event ) {\n\t\t\t// There is a situation whereby there is an existing link in the rich text\n\t\t\t// and the user clicks on the leftmost edge of that link and fails to activate\n\t\t\t// the link format, but the click event still fires on the `<a>` element.\n\t\t\t// This causes the `addingLink` state to be set to `true` and the link UI\n\t\t\t// to be rendered in \"creating\" mode. We need to check isActive to see if\n\t\t\t// we have an active link format.\n\t\t\tif ( event.target.tagName !== 'A' || ! isActive ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetAddingLink( true );\n\t\t}\n\n\t\teditableContentElement.addEventListener( 'click', handleClick );\n\n\t\treturn () => {\n\t\t\teditableContentElement.removeEventListener( 'click', handleClick );\n\t\t};\n\t}, [ contentRef, isActive ] );\n\n\tfunction addLink( target ) {\n\t\tconst text = getTextContent( slice( value ) );\n\n\t\tif ( ! isActive && text && isURL( text ) && isValidHref( text ) ) {\n\t\t\tonChange(\n\t\t\t\tapplyFormat( value, {\n\t\t\t\t\ttype: name,\n\t\t\t\t\tattributes: { url: text },\n\t\t\t\t} )\n\t\t\t);\n\t\t} else if ( ! isActive && text && isEmail( text ) ) {\n\t\t\tonChange(\n\t\t\t\tapplyFormat( value, {\n\t\t\t\t\ttype: name,\n\t\t\t\t\tattributes: { url: `mailto:${ text }` },\n\t\t\t\t} )\n\t\t\t);\n\t\t} else {\n\t\t\tif ( target ) {\n\t\t\t\tsetOpenedBy( target );\n\t\t\t}\n\t\t\tsetAddingLink( true );\n\t\t}\n\t}\n\n\t/**\n\t * Runs when the popover is closed via escape keypress, unlinking the selected text,\n\t * but _not_ on a click outside the popover. onFocusOutside handles that.\n\t */\n\tfunction stopAddingLink() {\n\t\t// Don't let the click handler on the toolbar button trigger again.\n\n\t\t// There are two places for us to return focus to on Escape keypress:\n\t\t// 1. The rich text field.\n\t\t// 2. The toolbar button.\n\n\t\t// The toolbar button is the only one we need to handle returning focus to.\n\t\t// Otherwise, we rely on the passed in onFocus to return focus to the rich text field.\n\n\t\t// Close the popover\n\t\tsetAddingLink( false );\n\t\t// Return focus to the toolbar button or the rich text field\n\t\tif ( openedBy?.tagName === 'BUTTON' ) {\n\t\t\topenedBy.focus();\n\t\t} else {\n\t\t\tonFocus();\n\t\t}\n\t\t// Remove the openedBy state\n\t\tsetOpenedBy( null );\n\t}\n\n\t// Test for this:\n\t// 1. Click on the link button\n\t// 2. Click the Options button in the top right of header\n\t// 3. Focus should be in the dropdown of the Options button\n\t// 4. Press Escape\n\t// 5. Focus should be on the Options button\n\tfunction onFocusOutside() {\n\t\tsetAddingLink( false );\n\t\tsetOpenedBy( null );\n\t}\n\n\tfunction onRemoveFormat() {\n\t\tonChange( removeFormat( value, name ) );\n\t\tspeak( __( 'Link removed.' ), 'assertive' );\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t<RichTextShortcut type=\"primary\" character=\"k\" onUse={ addLink } />\n\t\t\t<RichTextShortcut\n\t\t\t\ttype=\"primaryShift\"\n\t\t\t\tcharacter=\"k\"\n\t\t\t\tonUse={ onRemoveFormat }\n\t\t\t/>\n\t\t\t<RichTextToolbarButton\n\t\t\t\tname=\"link\"\n\t\t\t\ticon={ linkIcon }\n\t\t\t\ttitle={ isActive ? __( 'Link' ) : title }\n\t\t\t\tonClick={ ( event ) => {\n\t\t\t\t\taddLink( event.currentTarget );\n\t\t\t\t} }\n\t\t\t\tisActive={ isActive || addingLink }\n\t\t\t\tshortcutType=\"primary\"\n\t\t\t\tshortcutCharacter=\"k\"\n\t\t\t\taria-haspopup=\"true\"\n\t\t\t\taria-expanded={ addingLink }\n\t\t\t/>\n\t\t\t{ addingLink && (\n\t\t\t\t<InlineLinkUI\n\t\t\t\t\tstopAddingLink={ stopAddingLink }\n\t\t\t\t\tonFocusOutside={ onFocusOutside }\n\t\t\t\t\tisActive={ isActive }\n\t\t\t\t\tactiveAttributes={ activeAttributes }\n\t\t\t\t\tvalue={ value }\n\t\t\t\t\tonChange={ onChange }\n\t\t\t\t\tcontentRef={ contentRef }\n\t\t\t\t/>\n\t\t\t) }\n\t\t</>\n\t);\n}\n\nexport const link = {\n\tname,\n\ttitle,\n\ttagName: 'a',\n\tclassName: null,\n\tattributes: {\n\t\turl: 'href',\n\t\ttype: 'data-type',\n\t\tid: 'data-id',\n\t\t_id: 'id',\n\t\ttarget: 'target',\n\t\trel: 'rel',\n\t},\n\t__unstablePasteRule( value, { html, plainText } ) {\n\t\tconst pastedText = ( html || plainText )\n\t\t\t.replace( /<[^>]+>/g, '' )\n\t\t\t.trim();\n\n\t\t// A URL was pasted, turn the selection into a link.\n\t\t// For the link pasting feature, allow only http(s) protocols.\n\t\tif ( ! isURL( pastedText ) || ! /^https?:/.test( pastedText ) ) {\n\t\t\treturn value;\n\t\t}\n\n\t\t// Allows us to ask for this information when we get a report.\n\t\twindow.console.log( 'Created link:\\n\\n', pastedText );\n\n\t\tconst format = {\n\t\t\ttype: name,\n\t\t\tattributes: {\n\t\t\t\turl: decodeEntities( pastedText ),\n\t\t\t},\n\t\t};\n\n\t\tif ( isCollapsed( value ) ) {\n\t\t\treturn insert(\n\t\t\t\tvalue,\n\t\t\t\tapplyFormat(\n\t\t\t\t\tcreate( { text: plainText } ),\n\t\t\t\t\tformat,\n\t\t\t\t\t0,\n\t\t\t\t\tplainText.length\n\t\t\t\t)\n\t\t\t);\n\t\t}\n\n\t\treturn applyFormat( value, format );\n\t},\n\tedit: Edit,\n};\n"],"mappings":"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"}
1
+ {"version":3,"names":["__","useState","useLayoutEffect","useEffect","getTextContent","applyFormat","removeFormat","slice","isCollapsed","insert","create","isURL","isEmail","RichTextToolbarButton","RichTextShortcut","decodeEntities","link","linkIcon","speak","InlineLinkUI","isValidHref","name","title","Edit","isActive","activeAttributes","value","onChange","onFocus","contentRef","editingLink","setEditingLink","creatingLink","setCreatingLink","openedBy","setOpenedBy","shouldAutoFocus","setShouldAutoFocus","setIsEditingLink","isEditing","autoFocus","setIsCreatingLink","isCreating","editableContentElement","current","handleClick","event","target","closest","addEventListener","removeEventListener","addLink","text","type","attributes","url","stopAddingLink","tagName","focus","onFocusOutside","onRemoveFormat","isEditingActiveLink","createElement","Fragment","character","onUse","icon","onClick","currentTarget","shortcutType","shortcutCharacter","focusOnMount","className","id","_id","rel","__unstablePasteRule","html","plainText","pastedText","replace","trim","test","window","console","log","format","length","edit"],"sources":["@wordpress/format-library/src/link/index.js"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\nimport { useState, useLayoutEffect, useEffect } from '@wordpress/element';\nimport {\n\tgetTextContent,\n\tapplyFormat,\n\tremoveFormat,\n\tslice,\n\tisCollapsed,\n\tinsert,\n\tcreate,\n} from '@wordpress/rich-text';\nimport { isURL, isEmail } from '@wordpress/url';\nimport {\n\tRichTextToolbarButton,\n\tRichTextShortcut,\n} from '@wordpress/block-editor';\nimport { decodeEntities } from '@wordpress/html-entities';\nimport { link as linkIcon } from '@wordpress/icons';\nimport { speak } from '@wordpress/a11y';\n\n/**\n * Internal dependencies\n */\nimport InlineLinkUI from './inline';\nimport { isValidHref } from './utils';\n\nconst name = 'core/link';\nconst title = __( 'Link' );\n\nfunction Edit( {\n\tisActive,\n\tactiveAttributes,\n\tvalue,\n\tonChange,\n\tonFocus,\n\tcontentRef,\n} ) {\n\tconst [ editingLink, setEditingLink ] = useState( false );\n\tconst [ creatingLink, setCreatingLink ] = useState( false );\n\n\t// We only need to store the button element that opened the popover. We can ignore the other states, as they will be handled by the onFocus prop to return to the rich text field.\n\tconst [ openedBy, setOpenedBy ] = useState( null );\n\n\t// Manages whether the Link UI popover should autofocus when shown.\n\tconst [ shouldAutoFocus, setShouldAutoFocus ] = useState( true );\n\n\tfunction setIsEditingLink( isEditing, { autoFocus = true } = {} ) {\n\t\tsetEditingLink( isEditing );\n\t\tsetShouldAutoFocus( autoFocus );\n\t}\n\n\tfunction setIsCreatingLink( isCreating ) {\n\t\t// Don't add a new link if there is already an active link.\n\t\t// The two states are mutually exclusive.\n\t\tif ( isCreating === true && isActive ) {\n\t\t\treturn;\n\t\t}\n\t\tsetCreatingLink( isCreating );\n\t}\n\n\tuseEffect( () => {\n\t\t// When the link becomes inactive (i.e. isActive is false), reset the editingLink state\n\t\t// and the creatingLink state. This means that if the Link UI is displayed and the link\n\t\t// becomes inactive (e.g. used arrow keys to move cursor outside of link bounds), the UI will close.\n\t\tif ( ! isActive ) {\n\t\t\tsetEditingLink( false );\n\t\t\tsetCreatingLink( false );\n\t\t}\n\t}, [ isActive ] );\n\n\tuseLayoutEffect( () => {\n\t\tconst editableContentElement = contentRef.current;\n\t\tif ( ! editableContentElement ) {\n\t\t\treturn;\n\t\t}\n\n\t\tfunction handleClick( event ) {\n\t\t\t// There is a situation whereby there is an existing link in the rich text\n\t\t\t// and the user clicks on the leftmost edge of that link and fails to activate\n\t\t\t// the link format, but the click event still fires on the `<a>` element.\n\t\t\t// This causes the `editingLink` state to be set to `true` and the link UI\n\t\t\t// to be rendered in \"creating\" mode. We need to check isActive to see if\n\t\t\t// we have an active link format.\n\t\t\tif (\n\t\t\t\t! event.target.closest( '[contenteditable] a' ) || // other formats (e.g. bold) may be nested within the link.\n\t\t\t\t! isActive\n\t\t\t) {\n\t\t\t\tsetIsEditingLink( false );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetIsEditingLink( true, { autoFocus: false } );\n\t\t}\n\n\t\teditableContentElement.addEventListener( 'click', handleClick );\n\n\t\treturn () => {\n\t\t\teditableContentElement.removeEventListener( 'click', handleClick );\n\t\t};\n\t}, [ contentRef, isActive ] );\n\n\tfunction addLink( target ) {\n\t\tsetShouldAutoFocus( true );\n\t\tconst text = getTextContent( slice( value ) );\n\n\t\tif ( ! isActive && text && isURL( text ) && isValidHref( text ) ) {\n\t\t\tonChange(\n\t\t\t\tapplyFormat( value, {\n\t\t\t\t\ttype: name,\n\t\t\t\t\tattributes: { url: text },\n\t\t\t\t} )\n\t\t\t);\n\t\t} else if ( ! isActive && text && isEmail( text ) ) {\n\t\t\tonChange(\n\t\t\t\tapplyFormat( value, {\n\t\t\t\t\ttype: name,\n\t\t\t\t\tattributes: { url: `mailto:${ text }` },\n\t\t\t\t} )\n\t\t\t);\n\t\t} else {\n\t\t\tif ( target ) {\n\t\t\t\tsetOpenedBy( target );\n\t\t\t}\n\t\t\tif ( ! isActive ) {\n\t\t\t\tsetIsCreatingLink( true );\n\t\t\t} else {\n\t\t\t\tsetIsEditingLink( true );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Runs when the popover is closed via escape keypress, unlinking the selected text,\n\t * but _not_ on a click outside the popover. onFocusOutside handles that.\n\t */\n\tfunction stopAddingLink() {\n\t\t// Don't let the click handler on the toolbar button trigger again.\n\n\t\t// There are two places for us to return focus to on Escape keypress:\n\t\t// 1. The rich text field.\n\t\t// 2. The toolbar button.\n\n\t\t// The toolbar button is the only one we need to handle returning focus to.\n\t\t// Otherwise, we rely on the passed in onFocus to return focus to the rich text field.\n\n\t\t// Close the popover\n\t\tsetIsEditingLink( false );\n\t\tsetIsCreatingLink( false );\n\n\t\t// Return focus to the toolbar button or the rich text field\n\t\tif ( openedBy?.tagName === 'BUTTON' ) {\n\t\t\topenedBy.focus();\n\t\t} else {\n\t\t\tonFocus();\n\t\t}\n\t\t// Remove the openedBy state\n\t\tsetOpenedBy( null );\n\t}\n\n\t// Test for this:\n\t// 1. Click on the link button\n\t// 2. Click the Options button in the top right of header\n\t// 3. Focus should be in the dropdown of the Options button\n\t// 4. Press Escape\n\t// 5. Focus should be on the Options button\n\tfunction onFocusOutside() {\n\t\tsetIsEditingLink( false );\n\t\tsetIsCreatingLink( false );\n\t\tsetOpenedBy( null );\n\t}\n\n\tfunction onRemoveFormat() {\n\t\tonChange( removeFormat( value, name ) );\n\t\tspeak( __( 'Link removed.' ), 'assertive' );\n\t}\n\n\tconst isEditingActiveLink = editingLink && isActive;\n\n\treturn (\n\t\t<>\n\t\t\t<RichTextShortcut type=\"primary\" character=\"k\" onUse={ addLink } />\n\t\t\t<RichTextShortcut\n\t\t\t\ttype=\"primaryShift\"\n\t\t\t\tcharacter=\"k\"\n\t\t\t\tonUse={ onRemoveFormat }\n\t\t\t/>\n\t\t\t<RichTextToolbarButton\n\t\t\t\tname=\"link\"\n\t\t\t\ticon={ linkIcon }\n\t\t\t\ttitle={ isActive ? __( 'Link' ) : title }\n\t\t\t\tonClick={ ( event ) => {\n\t\t\t\t\taddLink( event.currentTarget );\n\t\t\t\t} }\n\t\t\t\tisActive={ isActive || editingLink }\n\t\t\t\tshortcutType=\"primary\"\n\t\t\t\tshortcutCharacter=\"k\"\n\t\t\t\taria-haspopup=\"true\"\n\t\t\t\taria-expanded={ editingLink }\n\t\t\t/>\n\t\t\t{ ( isEditingActiveLink || creatingLink ) && (\n\t\t\t\t<InlineLinkUI\n\t\t\t\t\tstopAddingLink={ stopAddingLink }\n\t\t\t\t\tonFocusOutside={ onFocusOutside }\n\t\t\t\t\tisActive={ isActive }\n\t\t\t\t\tactiveAttributes={ activeAttributes }\n\t\t\t\t\tvalue={ value }\n\t\t\t\t\tonChange={ onChange }\n\t\t\t\t\tcontentRef={ contentRef }\n\t\t\t\t\tfocusOnMount={ shouldAutoFocus ? 'firstElement' : false }\n\t\t\t\t/>\n\t\t\t) }\n\t\t</>\n\t);\n}\n\nexport const link = {\n\tname,\n\ttitle,\n\ttagName: 'a',\n\tclassName: null,\n\tattributes: {\n\t\turl: 'href',\n\t\ttype: 'data-type',\n\t\tid: 'data-id',\n\t\t_id: 'id',\n\t\ttarget: 'target',\n\t\trel: 'rel',\n\t},\n\t__unstablePasteRule( value, { html, plainText } ) {\n\t\tconst pastedText = ( html || plainText )\n\t\t\t.replace( /<[^>]+>/g, '' )\n\t\t\t.trim();\n\n\t\t// A URL was pasted, turn the selection into a link.\n\t\t// For the link pasting feature, allow only http(s) protocols.\n\t\tif ( ! isURL( pastedText ) || ! /^https?:/.test( pastedText ) ) {\n\t\t\treturn value;\n\t\t}\n\n\t\t// Allows us to ask for this information when we get a report.\n\t\twindow.console.log( 'Created link:\\n\\n', pastedText );\n\n\t\tconst format = {\n\t\t\ttype: name,\n\t\t\tattributes: {\n\t\t\t\turl: decodeEntities( pastedText ),\n\t\t\t},\n\t\t};\n\n\t\tif ( isCollapsed( value ) ) {\n\t\t\treturn insert(\n\t\t\t\tvalue,\n\t\t\t\tapplyFormat(\n\t\t\t\t\tcreate( { text: plainText } ),\n\t\t\t\t\tformat,\n\t\t\t\t\t0,\n\t\t\t\t\tplainText.length\n\t\t\t\t)\n\t\t\t);\n\t\t}\n\n\t\treturn applyFormat( value, format );\n\t},\n\tedit: Edit,\n};\n"],"mappings":"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"}
@@ -27,7 +27,8 @@ function InlineLinkUI({
27
27
  onChange,
28
28
  onFocusOutside,
29
29
  stopAddingLink,
30
- contentRef
30
+ contentRef,
31
+ focusOnMount
31
32
  }) {
32
33
  const richLinkTextValue = getRichTextValueFromSelection(value, isActive);
33
34
 
@@ -193,7 +194,9 @@ function InlineLinkUI({
193
194
  onFocusOutside: onFocusOutside,
194
195
  placement: "bottom",
195
196
  offset: 10,
196
- shift: true
197
+ shift: true,
198
+ focusOnMount: focusOnMount,
199
+ constrainTabbing: true
197
200
  }, createElement(LinkControl, {
198
201
  value: linkValue,
199
202
  onChange: onChangeLink,
@@ -1 +1 @@
1
- {"version":3,"names":["useMemo","createInterpolateElement","__","sprintf","speak","Popover","prependHTTP","create","insert","isCollapsed","applyFormat","removeFormat","slice","replace","split","concat","useAnchor","__experimentalLinkControl","LinkControl","store","blockEditorStore","useDispatch","useSelect","createLinkFormat","isValidHref","getFormatBoundary","link","settings","LINK_SETTINGS","DEFAULT_LINK_SETTINGS","id","title","InlineLinkUI","isActive","activeAttributes","value","onChange","onFocusOutside","stopAddingLink","contentRef","richLinkTextValue","getRichTextValueFromSelection","richTextText","text","selectionChange","createPageEntity","userCanCreatePages","selectionStart","select","getSettings","getSelectionStart","_settings","__experimentalCreatePageEntity","__experimentalUserCanCreatePages","linkValue","url","type","opensInNewTab","target","nofollow","rel","includes","removeLink","newValue","onChangeLink","nextValue","hasLink","isNewLink","newUrl","linkFormat","undefined","String","opensInNewWindow","newText","inserted","start","length","clientId","identifier","attributeKey","boundary","valBefore","valAfter","newValAfter","popoverAnchor","editableContentElement","current","handleCreate","pageTitle","page","status","rendered","kind","createButtonText","searchTerm","mark","createElement","anchor","onClose","placement","offset","shift","onRemove","hasRichPreviews","createSuggestion","withCreateSuggestion","createSuggestionButtonText","hasTextControl","showInitialSuggestions","suggestionsQuery","initialSuggestionsSearchOptions","subtype","perPage","textStart","textEnd","end"],"sources":["@wordpress/format-library/src/link/inline.js"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { useMemo, createInterpolateElement } from '@wordpress/element';\nimport { __, sprintf } from '@wordpress/i18n';\nimport { speak } from '@wordpress/a11y';\nimport { Popover } from '@wordpress/components';\nimport { prependHTTP } from '@wordpress/url';\nimport {\n\tcreate,\n\tinsert,\n\tisCollapsed,\n\tapplyFormat,\n\tremoveFormat,\n\tslice,\n\treplace,\n\tsplit,\n\tconcat,\n\tuseAnchor,\n} from '@wordpress/rich-text';\nimport {\n\t__experimentalLinkControl as LinkControl,\n\tstore as blockEditorStore,\n} from '@wordpress/block-editor';\nimport { useDispatch, useSelect } from '@wordpress/data';\n\n/**\n * Internal dependencies\n */\nimport { createLinkFormat, isValidHref, getFormatBoundary } from './utils';\nimport { link as settings } from './index';\n\nconst LINK_SETTINGS = [\n\t...LinkControl.DEFAULT_LINK_SETTINGS,\n\t{\n\t\tid: 'nofollow',\n\t\ttitle: __( 'Mark as nofollow' ),\n\t},\n];\n\nfunction InlineLinkUI( {\n\tisActive,\n\tactiveAttributes,\n\tvalue,\n\tonChange,\n\tonFocusOutside,\n\tstopAddingLink,\n\tcontentRef,\n} ) {\n\tconst richLinkTextValue = getRichTextValueFromSelection( value, isActive );\n\n\t// Get the text content minus any HTML tags.\n\tconst richTextText = richLinkTextValue.text;\n\n\tconst { selectionChange } = useDispatch( blockEditorStore );\n\n\tconst { createPageEntity, userCanCreatePages, selectionStart } = useSelect(\n\t\t( select ) => {\n\t\t\tconst { getSettings, getSelectionStart } =\n\t\t\t\tselect( blockEditorStore );\n\t\t\tconst _settings = getSettings();\n\n\t\t\treturn {\n\t\t\t\tcreatePageEntity: _settings.__experimentalCreatePageEntity,\n\t\t\t\tuserCanCreatePages: _settings.__experimentalUserCanCreatePages,\n\t\t\t\tselectionStart: getSelectionStart(),\n\t\t\t};\n\t\t},\n\t\t[]\n\t);\n\n\tconst linkValue = useMemo(\n\t\t() => ( {\n\t\t\turl: activeAttributes.url,\n\t\t\ttype: activeAttributes.type,\n\t\t\tid: activeAttributes.id,\n\t\t\topensInNewTab: activeAttributes.target === '_blank',\n\t\t\tnofollow: activeAttributes.rel?.includes( 'nofollow' ),\n\t\t\ttitle: richTextText,\n\t\t} ),\n\t\t[\n\t\t\tactiveAttributes.id,\n\t\t\tactiveAttributes.rel,\n\t\t\tactiveAttributes.target,\n\t\t\tactiveAttributes.type,\n\t\t\tactiveAttributes.url,\n\t\t\trichTextText,\n\t\t]\n\t);\n\n\tfunction removeLink() {\n\t\tconst newValue = removeFormat( value, 'core/link' );\n\t\tonChange( newValue );\n\t\tstopAddingLink();\n\t\tspeak( __( 'Link removed.' ), 'assertive' );\n\t}\n\n\tfunction onChangeLink( nextValue ) {\n\t\tconst hasLink = linkValue?.url;\n\t\tconst isNewLink = ! hasLink;\n\n\t\t// Merge the next value with the current link value.\n\t\tnextValue = {\n\t\t\t...linkValue,\n\t\t\t...nextValue,\n\t\t};\n\n\t\tconst newUrl = prependHTTP( nextValue.url );\n\t\tconst linkFormat = createLinkFormat( {\n\t\t\turl: newUrl,\n\t\t\ttype: nextValue.type,\n\t\t\tid:\n\t\t\t\tnextValue.id !== undefined && nextValue.id !== null\n\t\t\t\t\t? String( nextValue.id )\n\t\t\t\t\t: undefined,\n\t\t\topensInNewWindow: nextValue.opensInNewTab,\n\t\t\tnofollow: nextValue.nofollow,\n\t\t} );\n\n\t\tconst newText = nextValue.title || newUrl;\n\n\t\t// Scenario: we have any active text selection or an active format.\n\t\tlet newValue;\n\t\tif ( isCollapsed( value ) && ! isActive ) {\n\t\t\t// Scenario: we don't have any actively selected text or formats.\n\t\t\tconst inserted = insert( value, newText );\n\n\t\t\tnewValue = applyFormat(\n\t\t\t\tinserted,\n\t\t\t\tlinkFormat,\n\t\t\t\tvalue.start,\n\t\t\t\tvalue.start + newText.length\n\t\t\t);\n\n\t\t\tonChange( newValue );\n\n\t\t\t// Close the Link UI.\n\t\t\tstopAddingLink();\n\n\t\t\t// Move the selection to the end of the inserted link outside of the format boundary\n\t\t\t// so the user can continue typing after the link.\n\t\t\tselectionChange( {\n\t\t\t\tclientId: selectionStart.clientId,\n\t\t\t\tidentifier: selectionStart.attributeKey,\n\t\t\t\tstart: value.start + newText.length + 1,\n\t\t\t} );\n\n\t\t\treturn;\n\t\t} else if ( newText === richTextText ) {\n\t\t\tnewValue = applyFormat( value, linkFormat );\n\t\t} else {\n\t\t\t// Scenario: Editing an existing link.\n\n\t\t\t// Create new RichText value for the new text in order that we\n\t\t\t// can apply formats to it.\n\t\t\tnewValue = create( { text: newText } );\n\t\t\t// Apply the new Link format to this new text value.\n\t\t\tnewValue = applyFormat( newValue, linkFormat, 0, newText.length );\n\n\t\t\t// Get the boundaries of the active link format.\n\t\t\tconst boundary = getFormatBoundary( value, {\n\t\t\t\ttype: 'core/link',\n\t\t\t} );\n\n\t\t\t// Split the value at the start of the active link format.\n\t\t\t// Passing \"start\" as the 3rd parameter is required to ensure\n\t\t\t// the second half of the split value is split at the format's\n\t\t\t// start boundary and avoids relying on the value's \"end\" property\n\t\t\t// which may not correspond correctly.\n\t\t\tconst [ valBefore, valAfter ] = split(\n\t\t\t\tvalue,\n\t\t\t\tboundary.start,\n\t\t\t\tboundary.start\n\t\t\t);\n\n\t\t\t// Update the original (full) RichTextValue replacing the\n\t\t\t// target text with the *new* RichTextValue containing:\n\t\t\t// 1. The new text content.\n\t\t\t// 2. The new link format.\n\t\t\t// As \"replace\" will operate on the first match only, it is\n\t\t\t// run only against the second half of the value which was\n\t\t\t// split at the active format's boundary. This avoids a bug\n\t\t\t// with incorrectly targetted replacements.\n\t\t\t// See: https://github.com/WordPress/gutenberg/issues/41771.\n\t\t\t// Note original formats will be lost when applying this change.\n\t\t\t// That is expected behaviour.\n\t\t\t// See: https://github.com/WordPress/gutenberg/pull/33849#issuecomment-936134179.\n\t\t\tconst newValAfter = replace( valAfter, richTextText, newValue );\n\n\t\t\tnewValue = concat( valBefore, newValAfter );\n\t\t}\n\n\t\tonChange( newValue );\n\n\t\t// Focus should only be returned to the rich text on submit if this link is not\n\t\t// being created for the first time. If it is then focus should remain within the\n\t\t// Link UI because it should remain open for the user to modify the link they have\n\t\t// just created.\n\t\tif ( ! isNewLink ) {\n\t\t\tstopAddingLink();\n\t\t}\n\n\t\tif ( ! isValidHref( newUrl ) ) {\n\t\t\tspeak(\n\t\t\t\t__(\n\t\t\t\t\t'Warning: the link has been inserted but may have errors. Please test it.'\n\t\t\t\t),\n\t\t\t\t'assertive'\n\t\t\t);\n\t\t} else if ( isActive ) {\n\t\t\tspeak( __( 'Link edited.' ), 'assertive' );\n\t\t} else {\n\t\t\tspeak( __( 'Link inserted.' ), 'assertive' );\n\t\t}\n\t}\n\n\tconst popoverAnchor = useAnchor( {\n\t\teditableContentElement: contentRef.current,\n\t\tsettings: { ...settings, isActive },\n\t} );\n\n\tasync function handleCreate( pageTitle ) {\n\t\tconst page = await createPageEntity( {\n\t\t\ttitle: pageTitle,\n\t\t\tstatus: 'draft',\n\t\t} );\n\n\t\treturn {\n\t\t\tid: page.id,\n\t\t\ttype: page.type,\n\t\t\ttitle: page.title.rendered,\n\t\t\turl: page.link,\n\t\t\tkind: 'post-type',\n\t\t};\n\t}\n\n\tfunction createButtonText( searchTerm ) {\n\t\treturn createInterpolateElement(\n\t\t\tsprintf(\n\t\t\t\t/* translators: %s: search term. */\n\t\t\t\t__( 'Create page: <mark>%s</mark>' ),\n\t\t\t\tsearchTerm\n\t\t\t),\n\t\t\t{ mark: <mark /> }\n\t\t);\n\t}\n\n\treturn (\n\t\t<Popover\n\t\t\tanchor={ popoverAnchor }\n\t\t\tonClose={ stopAddingLink }\n\t\t\tonFocusOutside={ onFocusOutside }\n\t\t\tplacement=\"bottom\"\n\t\t\toffset={ 10 }\n\t\t\tshift\n\t\t>\n\t\t\t<LinkControl\n\t\t\t\tvalue={ linkValue }\n\t\t\t\tonChange={ onChangeLink }\n\t\t\t\tonRemove={ removeLink }\n\t\t\t\thasRichPreviews\n\t\t\t\tcreateSuggestion={ createPageEntity && handleCreate }\n\t\t\t\twithCreateSuggestion={ userCanCreatePages }\n\t\t\t\tcreateSuggestionButtonText={ createButtonText }\n\t\t\t\thasTextControl\n\t\t\t\tsettings={ LINK_SETTINGS }\n\t\t\t\tshowInitialSuggestions\n\t\t\t\tsuggestionsQuery={ {\n\t\t\t\t\t// always show Pages as initial suggestions\n\t\t\t\t\tinitialSuggestionsSearchOptions: {\n\t\t\t\t\t\ttype: 'post',\n\t\t\t\t\t\tsubtype: 'page',\n\t\t\t\t\t\tperPage: 20,\n\t\t\t\t\t},\n\t\t\t\t} }\n\t\t\t/>\n\t\t</Popover>\n\t);\n}\n\nfunction getRichTextValueFromSelection( value, isActive ) {\n\t// Default to the selection ranges on the RichTextValue object.\n\tlet textStart = value.start;\n\tlet textEnd = value.end;\n\n\t// If the format is currently active then the rich text value\n\t// should always be taken from the bounds of the active format\n\t// and not the selected text.\n\tif ( isActive ) {\n\t\tconst boundary = getFormatBoundary( value, {\n\t\t\ttype: 'core/link',\n\t\t} );\n\n\t\ttextStart = boundary.start;\n\n\t\t// Text *selection* always extends +1 beyond the edge of the format.\n\t\t// We account for that here.\n\t\ttextEnd = boundary.end + 1;\n\t}\n\n\t// Get a RichTextValue containing the selected text content.\n\treturn slice( value, textStart, textEnd );\n}\n\nexport default InlineLinkUI;\n"],"mappings":";AAAA;AACA;AACA;AACA,SAASA,OAAO,EAAEC,wBAAwB,QAAQ,oBAAoB;AACtE,SAASC,EAAE,EAAEC,OAAO,QAAQ,iBAAiB;AAC7C,SAASC,KAAK,QAAQ,iBAAiB;AACvC,SAASC,OAAO,QAAQ,uBAAuB;AAC/C,SAASC,WAAW,QAAQ,gBAAgB;AAC5C,SACCC,MAAM,EACNC,MAAM,EACNC,WAAW,EACXC,WAAW,EACXC,YAAY,EACZC,KAAK,EACLC,OAAO,EACPC,KAAK,EACLC,MAAM,EACNC,SAAS,QACH,sBAAsB;AAC7B,SACCC,yBAAyB,IAAIC,WAAW,EACxCC,KAAK,IAAIC,gBAAgB,QACnB,yBAAyB;AAChC,SAASC,WAAW,EAAEC,SAAS,QAAQ,iBAAiB;;AAExD;AACA;AACA;AACA,SAASC,gBAAgB,EAAEC,WAAW,EAAEC,iBAAiB,QAAQ,SAAS;AAC1E,SAASC,IAAI,IAAIC,QAAQ,QAAQ,SAAS;AAE1C,MAAMC,aAAa,GAAG,CACrB,GAAGV,WAAW,CAACW,qBAAqB,EACpC;EACCC,EAAE,EAAE,UAAU;EACdC,KAAK,EAAE7B,EAAE,CAAE,kBAAmB;AAC/B,CAAC,CACD;AAED,SAAS8B,YAAYA,CAAE;EACtBC,QAAQ;EACRC,gBAAgB;EAChBC,KAAK;EACLC,QAAQ;EACRC,cAAc;EACdC,cAAc;EACdC;AACD,CAAC,EAAG;EACH,MAAMC,iBAAiB,GAAGC,6BAA6B,CAAEN,KAAK,EAAEF,QAAS,CAAC;;EAE1E;EACA,MAAMS,YAAY,GAAGF,iBAAiB,CAACG,IAAI;EAE3C,MAAM;IAAEC;EAAgB,CAAC,GAAGvB,WAAW,CAAED,gBAAiB,CAAC;EAE3D,MAAM;IAAEyB,gBAAgB;IAAEC,kBAAkB;IAAEC;EAAe,CAAC,GAAGzB,SAAS,CACvE0B,MAAM,IAAM;IACb,MAAM;MAAEC,WAAW;MAAEC;IAAkB,CAAC,GACvCF,MAAM,CAAE5B,gBAAiB,CAAC;IAC3B,MAAM+B,SAAS,GAAGF,WAAW,CAAC,CAAC;IAE/B,OAAO;MACNJ,gBAAgB,EAAEM,SAAS,CAACC,8BAA8B;MAC1DN,kBAAkB,EAAEK,SAAS,CAACE,gCAAgC;MAC9DN,cAAc,EAAEG,iBAAiB,CAAC;IACnC,CAAC;EACF,CAAC,EACD,EACD,CAAC;EAED,MAAMI,SAAS,GAAGtD,OAAO,CACxB,OAAQ;IACPuD,GAAG,EAAErB,gBAAgB,CAACqB,GAAG;IACzBC,IAAI,EAAEtB,gBAAgB,CAACsB,IAAI;IAC3B1B,EAAE,EAAEI,gBAAgB,CAACJ,EAAE;IACvB2B,aAAa,EAAEvB,gBAAgB,CAACwB,MAAM,KAAK,QAAQ;IACnDC,QAAQ,EAAEzB,gBAAgB,CAAC0B,GAAG,EAAEC,QAAQ,CAAE,UAAW,CAAC;IACtD9B,KAAK,EAAEW;EACR,CAAC,CAAE,EACH,CACCR,gBAAgB,CAACJ,EAAE,EACnBI,gBAAgB,CAAC0B,GAAG,EACpB1B,gBAAgB,CAACwB,MAAM,EACvBxB,gBAAgB,CAACsB,IAAI,EACrBtB,gBAAgB,CAACqB,GAAG,EACpBb,YAAY,CAEd,CAAC;EAED,SAASoB,UAAUA,CAAA,EAAG;IACrB,MAAMC,QAAQ,GAAGpD,YAAY,CAAEwB,KAAK,EAAE,WAAY,CAAC;IACnDC,QAAQ,CAAE2B,QAAS,CAAC;IACpBzB,cAAc,CAAC,CAAC;IAChBlC,KAAK,CAAEF,EAAE,CAAE,eAAgB,CAAC,EAAE,WAAY,CAAC;EAC5C;EAEA,SAAS8D,YAAYA,CAAEC,SAAS,EAAG;IAClC,MAAMC,OAAO,GAAGZ,SAAS,EAAEC,GAAG;IAC9B,MAAMY,SAAS,GAAG,CAAED,OAAO;;IAE3B;IACAD,SAAS,GAAG;MACX,GAAGX,SAAS;MACZ,GAAGW;IACJ,CAAC;IAED,MAAMG,MAAM,GAAG9D,WAAW,CAAE2D,SAAS,CAACV,GAAI,CAAC;IAC3C,MAAMc,UAAU,GAAG9C,gBAAgB,CAAE;MACpCgC,GAAG,EAAEa,MAAM;MACXZ,IAAI,EAAES,SAAS,CAACT,IAAI;MACpB1B,EAAE,EACDmC,SAAS,CAACnC,EAAE,KAAKwC,SAAS,IAAIL,SAAS,CAACnC,EAAE,KAAK,IAAI,GAChDyC,MAAM,CAAEN,SAAS,CAACnC,EAAG,CAAC,GACtBwC,SAAS;MACbE,gBAAgB,EAAEP,SAAS,CAACR,aAAa;MACzCE,QAAQ,EAAEM,SAAS,CAACN;IACrB,CAAE,CAAC;IAEH,MAAMc,OAAO,GAAGR,SAAS,CAAClC,KAAK,IAAIqC,MAAM;;IAEzC;IACA,IAAIL,QAAQ;IACZ,IAAKtD,WAAW,CAAE0B,KAAM,CAAC,IAAI,CAAEF,QAAQ,EAAG;MACzC;MACA,MAAMyC,QAAQ,GAAGlE,MAAM,CAAE2B,KAAK,EAAEsC,OAAQ,CAAC;MAEzCV,QAAQ,GAAGrD,WAAW,CACrBgE,QAAQ,EACRL,UAAU,EACVlC,KAAK,CAACwC,KAAK,EACXxC,KAAK,CAACwC,KAAK,GAAGF,OAAO,CAACG,MACvB,CAAC;MAEDxC,QAAQ,CAAE2B,QAAS,CAAC;;MAEpB;MACAzB,cAAc,CAAC,CAAC;;MAEhB;MACA;MACAM,eAAe,CAAE;QAChBiC,QAAQ,EAAE9B,cAAc,CAAC8B,QAAQ;QACjCC,UAAU,EAAE/B,cAAc,CAACgC,YAAY;QACvCJ,KAAK,EAAExC,KAAK,CAACwC,KAAK,GAAGF,OAAO,CAACG,MAAM,GAAG;MACvC,CAAE,CAAC;MAEH;IACD,CAAC,MAAM,IAAKH,OAAO,KAAK/B,YAAY,EAAG;MACtCqB,QAAQ,GAAGrD,WAAW,CAAEyB,KAAK,EAAEkC,UAAW,CAAC;IAC5C,CAAC,MAAM;MACN;;MAEA;MACA;MACAN,QAAQ,GAAGxD,MAAM,CAAE;QAAEoC,IAAI,EAAE8B;MAAQ,CAAE,CAAC;MACtC;MACAV,QAAQ,GAAGrD,WAAW,CAAEqD,QAAQ,EAAEM,UAAU,EAAE,CAAC,EAAEI,OAAO,CAACG,MAAO,CAAC;;MAEjE;MACA,MAAMI,QAAQ,GAAGvD,iBAAiB,CAAEU,KAAK,EAAE;QAC1CqB,IAAI,EAAE;MACP,CAAE,CAAC;;MAEH;MACA;MACA;MACA;MACA;MACA,MAAM,CAAEyB,SAAS,EAAEC,QAAQ,CAAE,GAAGpE,KAAK,CACpCqB,KAAK,EACL6C,QAAQ,CAACL,KAAK,EACdK,QAAQ,CAACL,KACV,CAAC;;MAED;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA,MAAMQ,WAAW,GAAGtE,OAAO,CAAEqE,QAAQ,EAAExC,YAAY,EAAEqB,QAAS,CAAC;MAE/DA,QAAQ,GAAGhD,MAAM,CAAEkE,SAAS,EAAEE,WAAY,CAAC;IAC5C;IAEA/C,QAAQ,CAAE2B,QAAS,CAAC;;IAEpB;IACA;IACA;IACA;IACA,IAAK,CAAEI,SAAS,EAAG;MAClB7B,cAAc,CAAC,CAAC;IACjB;IAEA,IAAK,CAAEd,WAAW,CAAE4C,MAAO,CAAC,EAAG;MAC9BhE,KAAK,CACJF,EAAE,CACD,0EACD,CAAC,EACD,WACD,CAAC;IACF,CAAC,MAAM,IAAK+B,QAAQ,EAAG;MACtB7B,KAAK,CAAEF,EAAE,CAAE,cAAe,CAAC,EAAE,WAAY,CAAC;IAC3C,CAAC,MAAM;MACNE,KAAK,CAAEF,EAAE,CAAE,gBAAiB,CAAC,EAAE,WAAY,CAAC;IAC7C;EACD;EAEA,MAAMkF,aAAa,GAAGpE,SAAS,CAAE;IAChCqE,sBAAsB,EAAE9C,UAAU,CAAC+C,OAAO;IAC1C3D,QAAQ,EAAE;MAAE,GAAGA,QAAQ;MAAEM;IAAS;EACnC,CAAE,CAAC;EAEH,eAAesD,YAAYA,CAAEC,SAAS,EAAG;IACxC,MAAMC,IAAI,GAAG,MAAM5C,gBAAgB,CAAE;MACpCd,KAAK,EAAEyD,SAAS;MAChBE,MAAM,EAAE;IACT,CAAE,CAAC;IAEH,OAAO;MACN5D,EAAE,EAAE2D,IAAI,CAAC3D,EAAE;MACX0B,IAAI,EAAEiC,IAAI,CAACjC,IAAI;MACfzB,KAAK,EAAE0D,IAAI,CAAC1D,KAAK,CAAC4D,QAAQ;MAC1BpC,GAAG,EAAEkC,IAAI,CAAC/D,IAAI;MACdkE,IAAI,EAAE;IACP,CAAC;EACF;EAEA,SAASC,gBAAgBA,CAAEC,UAAU,EAAG;IACvC,OAAO7F,wBAAwB,CAC9BE,OAAO,EACN;IACAD,EAAE,CAAE,8BAA+B,CAAC,EACpC4F,UACD,CAAC,EACD;MAAEC,IAAI,EAAEC,aAAA,aAAO;IAAE,CAClB,CAAC;EACF;EAEA,OACCA,aAAA,CAAC3F,OAAO;IACP4F,MAAM,EAAGb,aAAe;IACxBc,OAAO,EAAG5D,cAAgB;IAC1BD,cAAc,EAAGA,cAAgB;IACjC8D,SAAS,EAAC,QAAQ;IAClBC,MAAM,EAAG,EAAI;IACbC,KAAK;EAAA,GAELL,aAAA,CAAC9E,WAAW;IACXiB,KAAK,EAAGmB,SAAW;IACnBlB,QAAQ,EAAG4B,YAAc;IACzBsC,QAAQ,EAAGxC,UAAY;IACvByC,eAAe;IACfC,gBAAgB,EAAG3D,gBAAgB,IAAI0C,YAAc;IACrDkB,oBAAoB,EAAG3D,kBAAoB;IAC3C4D,0BAA0B,EAAGb,gBAAkB;IAC/Cc,cAAc;IACdhF,QAAQ,EAAGC,aAAe;IAC1BgF,sBAAsB;IACtBC,gBAAgB,EAAG;MAClB;MACAC,+BAA+B,EAAE;QAChCtD,IAAI,EAAE,MAAM;QACZuD,OAAO,EAAE,MAAM;QACfC,OAAO,EAAE;MACV;IACD;EAAG,CACH,CACO,CAAC;AAEZ;AAEA,SAASvE,6BAA6BA,CAAEN,KAAK,EAAEF,QAAQ,EAAG;EACzD;EACA,IAAIgF,SAAS,GAAG9E,KAAK,CAACwC,KAAK;EAC3B,IAAIuC,OAAO,GAAG/E,KAAK,CAACgF,GAAG;;EAEvB;EACA;EACA;EACA,IAAKlF,QAAQ,EAAG;IACf,MAAM+C,QAAQ,GAAGvD,iBAAiB,CAAEU,KAAK,EAAE;MAC1CqB,IAAI,EAAE;IACP,CAAE,CAAC;IAEHyD,SAAS,GAAGjC,QAAQ,CAACL,KAAK;;IAE1B;IACA;IACAuC,OAAO,GAAGlC,QAAQ,CAACmC,GAAG,GAAG,CAAC;EAC3B;;EAEA;EACA,OAAOvG,KAAK,CAAEuB,KAAK,EAAE8E,SAAS,EAAEC,OAAQ,CAAC;AAC1C;AAEA,eAAelF,YAAY"}
1
+ {"version":3,"names":["useMemo","createInterpolateElement","__","sprintf","speak","Popover","prependHTTP","create","insert","isCollapsed","applyFormat","removeFormat","slice","replace","split","concat","useAnchor","__experimentalLinkControl","LinkControl","store","blockEditorStore","useDispatch","useSelect","createLinkFormat","isValidHref","getFormatBoundary","link","settings","LINK_SETTINGS","DEFAULT_LINK_SETTINGS","id","title","InlineLinkUI","isActive","activeAttributes","value","onChange","onFocusOutside","stopAddingLink","contentRef","focusOnMount","richLinkTextValue","getRichTextValueFromSelection","richTextText","text","selectionChange","createPageEntity","userCanCreatePages","selectionStart","select","getSettings","getSelectionStart","_settings","__experimentalCreatePageEntity","__experimentalUserCanCreatePages","linkValue","url","type","opensInNewTab","target","nofollow","rel","includes","removeLink","newValue","onChangeLink","nextValue","hasLink","isNewLink","newUrl","linkFormat","undefined","String","opensInNewWindow","newText","inserted","start","length","clientId","identifier","attributeKey","boundary","valBefore","valAfter","newValAfter","popoverAnchor","editableContentElement","current","handleCreate","pageTitle","page","status","rendered","kind","createButtonText","searchTerm","mark","createElement","anchor","onClose","placement","offset","shift","constrainTabbing","onRemove","hasRichPreviews","createSuggestion","withCreateSuggestion","createSuggestionButtonText","hasTextControl","showInitialSuggestions","suggestionsQuery","initialSuggestionsSearchOptions","subtype","perPage","textStart","textEnd","end"],"sources":["@wordpress/format-library/src/link/inline.js"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { useMemo, createInterpolateElement } from '@wordpress/element';\nimport { __, sprintf } from '@wordpress/i18n';\nimport { speak } from '@wordpress/a11y';\nimport { Popover } from '@wordpress/components';\nimport { prependHTTP } from '@wordpress/url';\nimport {\n\tcreate,\n\tinsert,\n\tisCollapsed,\n\tapplyFormat,\n\tremoveFormat,\n\tslice,\n\treplace,\n\tsplit,\n\tconcat,\n\tuseAnchor,\n} from '@wordpress/rich-text';\nimport {\n\t__experimentalLinkControl as LinkControl,\n\tstore as blockEditorStore,\n} from '@wordpress/block-editor';\nimport { useDispatch, useSelect } from '@wordpress/data';\n\n/**\n * Internal dependencies\n */\nimport { createLinkFormat, isValidHref, getFormatBoundary } from './utils';\nimport { link as settings } from './index';\n\nconst LINK_SETTINGS = [\n\t...LinkControl.DEFAULT_LINK_SETTINGS,\n\t{\n\t\tid: 'nofollow',\n\t\ttitle: __( 'Mark as nofollow' ),\n\t},\n];\n\nfunction InlineLinkUI( {\n\tisActive,\n\tactiveAttributes,\n\tvalue,\n\tonChange,\n\tonFocusOutside,\n\tstopAddingLink,\n\tcontentRef,\n\tfocusOnMount,\n} ) {\n\tconst richLinkTextValue = getRichTextValueFromSelection( value, isActive );\n\n\t// Get the text content minus any HTML tags.\n\tconst richTextText = richLinkTextValue.text;\n\n\tconst { selectionChange } = useDispatch( blockEditorStore );\n\n\tconst { createPageEntity, userCanCreatePages, selectionStart } = useSelect(\n\t\t( select ) => {\n\t\t\tconst { getSettings, getSelectionStart } =\n\t\t\t\tselect( blockEditorStore );\n\t\t\tconst _settings = getSettings();\n\n\t\t\treturn {\n\t\t\t\tcreatePageEntity: _settings.__experimentalCreatePageEntity,\n\t\t\t\tuserCanCreatePages: _settings.__experimentalUserCanCreatePages,\n\t\t\t\tselectionStart: getSelectionStart(),\n\t\t\t};\n\t\t},\n\t\t[]\n\t);\n\n\tconst linkValue = useMemo(\n\t\t() => ( {\n\t\t\turl: activeAttributes.url,\n\t\t\ttype: activeAttributes.type,\n\t\t\tid: activeAttributes.id,\n\t\t\topensInNewTab: activeAttributes.target === '_blank',\n\t\t\tnofollow: activeAttributes.rel?.includes( 'nofollow' ),\n\t\t\ttitle: richTextText,\n\t\t} ),\n\t\t[\n\t\t\tactiveAttributes.id,\n\t\t\tactiveAttributes.rel,\n\t\t\tactiveAttributes.target,\n\t\t\tactiveAttributes.type,\n\t\t\tactiveAttributes.url,\n\t\t\trichTextText,\n\t\t]\n\t);\n\n\tfunction removeLink() {\n\t\tconst newValue = removeFormat( value, 'core/link' );\n\t\tonChange( newValue );\n\t\tstopAddingLink();\n\t\tspeak( __( 'Link removed.' ), 'assertive' );\n\t}\n\n\tfunction onChangeLink( nextValue ) {\n\t\tconst hasLink = linkValue?.url;\n\t\tconst isNewLink = ! hasLink;\n\n\t\t// Merge the next value with the current link value.\n\t\tnextValue = {\n\t\t\t...linkValue,\n\t\t\t...nextValue,\n\t\t};\n\n\t\tconst newUrl = prependHTTP( nextValue.url );\n\t\tconst linkFormat = createLinkFormat( {\n\t\t\turl: newUrl,\n\t\t\ttype: nextValue.type,\n\t\t\tid:\n\t\t\t\tnextValue.id !== undefined && nextValue.id !== null\n\t\t\t\t\t? String( nextValue.id )\n\t\t\t\t\t: undefined,\n\t\t\topensInNewWindow: nextValue.opensInNewTab,\n\t\t\tnofollow: nextValue.nofollow,\n\t\t} );\n\n\t\tconst newText = nextValue.title || newUrl;\n\n\t\t// Scenario: we have any active text selection or an active format.\n\t\tlet newValue;\n\t\tif ( isCollapsed( value ) && ! isActive ) {\n\t\t\t// Scenario: we don't have any actively selected text or formats.\n\t\t\tconst inserted = insert( value, newText );\n\n\t\t\tnewValue = applyFormat(\n\t\t\t\tinserted,\n\t\t\t\tlinkFormat,\n\t\t\t\tvalue.start,\n\t\t\t\tvalue.start + newText.length\n\t\t\t);\n\n\t\t\tonChange( newValue );\n\n\t\t\t// Close the Link UI.\n\t\t\tstopAddingLink();\n\n\t\t\t// Move the selection to the end of the inserted link outside of the format boundary\n\t\t\t// so the user can continue typing after the link.\n\t\t\tselectionChange( {\n\t\t\t\tclientId: selectionStart.clientId,\n\t\t\t\tidentifier: selectionStart.attributeKey,\n\t\t\t\tstart: value.start + newText.length + 1,\n\t\t\t} );\n\n\t\t\treturn;\n\t\t} else if ( newText === richTextText ) {\n\t\t\tnewValue = applyFormat( value, linkFormat );\n\t\t} else {\n\t\t\t// Scenario: Editing an existing link.\n\n\t\t\t// Create new RichText value for the new text in order that we\n\t\t\t// can apply formats to it.\n\t\t\tnewValue = create( { text: newText } );\n\t\t\t// Apply the new Link format to this new text value.\n\t\t\tnewValue = applyFormat( newValue, linkFormat, 0, newText.length );\n\n\t\t\t// Get the boundaries of the active link format.\n\t\t\tconst boundary = getFormatBoundary( value, {\n\t\t\t\ttype: 'core/link',\n\t\t\t} );\n\n\t\t\t// Split the value at the start of the active link format.\n\t\t\t// Passing \"start\" as the 3rd parameter is required to ensure\n\t\t\t// the second half of the split value is split at the format's\n\t\t\t// start boundary and avoids relying on the value's \"end\" property\n\t\t\t// which may not correspond correctly.\n\t\t\tconst [ valBefore, valAfter ] = split(\n\t\t\t\tvalue,\n\t\t\t\tboundary.start,\n\t\t\t\tboundary.start\n\t\t\t);\n\n\t\t\t// Update the original (full) RichTextValue replacing the\n\t\t\t// target text with the *new* RichTextValue containing:\n\t\t\t// 1. The new text content.\n\t\t\t// 2. The new link format.\n\t\t\t// As \"replace\" will operate on the first match only, it is\n\t\t\t// run only against the second half of the value which was\n\t\t\t// split at the active format's boundary. This avoids a bug\n\t\t\t// with incorrectly targetted replacements.\n\t\t\t// See: https://github.com/WordPress/gutenberg/issues/41771.\n\t\t\t// Note original formats will be lost when applying this change.\n\t\t\t// That is expected behaviour.\n\t\t\t// See: https://github.com/WordPress/gutenberg/pull/33849#issuecomment-936134179.\n\t\t\tconst newValAfter = replace( valAfter, richTextText, newValue );\n\n\t\t\tnewValue = concat( valBefore, newValAfter );\n\t\t}\n\n\t\tonChange( newValue );\n\n\t\t// Focus should only be returned to the rich text on submit if this link is not\n\t\t// being created for the first time. If it is then focus should remain within the\n\t\t// Link UI because it should remain open for the user to modify the link they have\n\t\t// just created.\n\t\tif ( ! isNewLink ) {\n\t\t\tstopAddingLink();\n\t\t}\n\n\t\tif ( ! isValidHref( newUrl ) ) {\n\t\t\tspeak(\n\t\t\t\t__(\n\t\t\t\t\t'Warning: the link has been inserted but may have errors. Please test it.'\n\t\t\t\t),\n\t\t\t\t'assertive'\n\t\t\t);\n\t\t} else if ( isActive ) {\n\t\t\tspeak( __( 'Link edited.' ), 'assertive' );\n\t\t} else {\n\t\t\tspeak( __( 'Link inserted.' ), 'assertive' );\n\t\t}\n\t}\n\n\tconst popoverAnchor = useAnchor( {\n\t\teditableContentElement: contentRef.current,\n\t\tsettings: {\n\t\t\t...settings,\n\t\t\tisActive,\n\t\t},\n\t} );\n\n\tasync function handleCreate( pageTitle ) {\n\t\tconst page = await createPageEntity( {\n\t\t\ttitle: pageTitle,\n\t\t\tstatus: 'draft',\n\t\t} );\n\n\t\treturn {\n\t\t\tid: page.id,\n\t\t\ttype: page.type,\n\t\t\ttitle: page.title.rendered,\n\t\t\turl: page.link,\n\t\t\tkind: 'post-type',\n\t\t};\n\t}\n\n\tfunction createButtonText( searchTerm ) {\n\t\treturn createInterpolateElement(\n\t\t\tsprintf(\n\t\t\t\t/* translators: %s: search term. */\n\t\t\t\t__( 'Create page: <mark>%s</mark>' ),\n\t\t\t\tsearchTerm\n\t\t\t),\n\t\t\t{ mark: <mark /> }\n\t\t);\n\t}\n\n\treturn (\n\t\t<Popover\n\t\t\tanchor={ popoverAnchor }\n\t\t\tonClose={ stopAddingLink }\n\t\t\tonFocusOutside={ onFocusOutside }\n\t\t\tplacement=\"bottom\"\n\t\t\toffset={ 10 }\n\t\t\tshift\n\t\t\tfocusOnMount={ focusOnMount }\n\t\t\tconstrainTabbing\n\t\t>\n\t\t\t<LinkControl\n\t\t\t\tvalue={ linkValue }\n\t\t\t\tonChange={ onChangeLink }\n\t\t\t\tonRemove={ removeLink }\n\t\t\t\thasRichPreviews\n\t\t\t\tcreateSuggestion={ createPageEntity && handleCreate }\n\t\t\t\twithCreateSuggestion={ userCanCreatePages }\n\t\t\t\tcreateSuggestionButtonText={ createButtonText }\n\t\t\t\thasTextControl\n\t\t\t\tsettings={ LINK_SETTINGS }\n\t\t\t\tshowInitialSuggestions\n\t\t\t\tsuggestionsQuery={ {\n\t\t\t\t\t// always show Pages as initial suggestions\n\t\t\t\t\tinitialSuggestionsSearchOptions: {\n\t\t\t\t\t\ttype: 'post',\n\t\t\t\t\t\tsubtype: 'page',\n\t\t\t\t\t\tperPage: 20,\n\t\t\t\t\t},\n\t\t\t\t} }\n\t\t\t/>\n\t\t</Popover>\n\t);\n}\n\nfunction getRichTextValueFromSelection( value, isActive ) {\n\t// Default to the selection ranges on the RichTextValue object.\n\tlet textStart = value.start;\n\tlet textEnd = value.end;\n\n\t// If the format is currently active then the rich text value\n\t// should always be taken from the bounds of the active format\n\t// and not the selected text.\n\tif ( isActive ) {\n\t\tconst boundary = getFormatBoundary( value, {\n\t\t\ttype: 'core/link',\n\t\t} );\n\n\t\ttextStart = boundary.start;\n\n\t\t// Text *selection* always extends +1 beyond the edge of the format.\n\t\t// We account for that here.\n\t\ttextEnd = boundary.end + 1;\n\t}\n\n\t// Get a RichTextValue containing the selected text content.\n\treturn slice( value, textStart, textEnd );\n}\n\nexport default InlineLinkUI;\n"],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { createElement } from "react";
2
+ /**
3
+ * WordPress dependencies
4
+ */
5
+ import { __ } from '@wordpress/i18n';
6
+ import { insert } from '@wordpress/rich-text';
7
+ import { RichTextShortcut } from '@wordpress/block-editor';
8
+ const name = 'core/non-breaking-space';
9
+ const title = __('Non breaking space');
10
+ export const nonBreakingSpace = {
11
+ name,
12
+ title,
13
+ tagName: 'nbsp',
14
+ className: null,
15
+ edit({
16
+ value,
17
+ onChange
18
+ }) {
19
+ function addNonBreakingSpace() {
20
+ onChange(insert(value, '\u00a0'));
21
+ }
22
+ return createElement(RichTextShortcut, {
23
+ type: "primaryShift",
24
+ character: " ",
25
+ onUse: addNonBreakingSpace
26
+ });
27
+ }
28
+ };
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["__","insert","RichTextShortcut","name","title","nonBreakingSpace","tagName","className","edit","value","onChange","addNonBreakingSpace","createElement","type","character","onUse"],"sources":["@wordpress/format-library/src/non-breaking-space/index.js"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\nimport { insert } from '@wordpress/rich-text';\nimport { RichTextShortcut } from '@wordpress/block-editor';\n\nconst name = 'core/non-breaking-space';\nconst title = __( 'Non breaking space' );\n\nexport const nonBreakingSpace = {\n\tname,\n\ttitle,\n\ttagName: 'nbsp',\n\tclassName: null,\n\tedit( { value, onChange } ) {\n\t\tfunction addNonBreakingSpace() {\n\t\t\tonChange( insert( value, '\\u00a0' ) );\n\t\t}\n\n\t\treturn (\n\t\t\t<RichTextShortcut\n\t\t\t\ttype=\"primaryShift\"\n\t\t\t\tcharacter=\" \"\n\t\t\t\tonUse={ addNonBreakingSpace }\n\t\t\t/>\n\t\t);\n\t},\n};\n"],"mappings":";AAAA;AACA;AACA;AACA,SAASA,EAAE,QAAQ,iBAAiB;AACpC,SAASC,MAAM,QAAQ,sBAAsB;AAC7C,SAASC,gBAAgB,QAAQ,yBAAyB;AAE1D,MAAMC,IAAI,GAAG,yBAAyB;AACtC,MAAMC,KAAK,GAAGJ,EAAE,CAAE,oBAAqB,CAAC;AAExC,OAAO,MAAMK,gBAAgB,GAAG;EAC/BF,IAAI;EACJC,KAAK;EACLE,OAAO,EAAE,MAAM;EACfC,SAAS,EAAE,IAAI;EACfC,IAAIA,CAAE;IAAEC,KAAK;IAAEC;EAAS,CAAC,EAAG;IAC3B,SAASC,mBAAmBA,CAAA,EAAG;MAC9BD,QAAQ,CAAET,MAAM,CAAEQ,KAAK,EAAE,QAAS,CAAE,CAAC;IACtC;IAEA,OACCG,aAAA,CAACV,gBAAgB;MAChBW,IAAI,EAAC,cAAc;MACnBC,SAAS,EAAC,GAAG;MACbC,KAAK,EAAGJ;IAAqB,CAC7B,CAAC;EAEJ;AACD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/format-library",
3
- "version": "4.30.0",
3
+ "version": "4.31.0",
4
4
  "description": "Format library for the WordPress editor.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -26,18 +26,18 @@
26
26
  "react-native": "src/index",
27
27
  "dependencies": {
28
28
  "@babel/runtime": "^7.16.0",
29
- "@wordpress/a11y": "^3.53.0",
30
- "@wordpress/block-editor": "^12.21.0",
31
- "@wordpress/components": "^27.1.0",
32
- "@wordpress/compose": "^6.30.0",
33
- "@wordpress/data": "^9.23.0",
34
- "@wordpress/element": "^5.30.0",
35
- "@wordpress/html-entities": "^3.53.0",
36
- "@wordpress/i18n": "^4.53.0",
37
- "@wordpress/icons": "^9.44.0",
38
- "@wordpress/private-apis": "^0.35.0",
39
- "@wordpress/rich-text": "^6.30.0",
40
- "@wordpress/url": "^3.54.0"
29
+ "@wordpress/a11y": "^3.54.0",
30
+ "@wordpress/block-editor": "^12.22.0",
31
+ "@wordpress/components": "^27.2.0",
32
+ "@wordpress/compose": "^6.31.0",
33
+ "@wordpress/data": "^9.24.0",
34
+ "@wordpress/element": "^5.31.0",
35
+ "@wordpress/html-entities": "^3.54.0",
36
+ "@wordpress/i18n": "^4.54.0",
37
+ "@wordpress/icons": "^9.45.0",
38
+ "@wordpress/private-apis": "^0.36.0",
39
+ "@wordpress/rich-text": "^6.31.0",
40
+ "@wordpress/url": "^3.55.0"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "react": "^18.0.0",
@@ -46,5 +46,5 @@
46
46
  "publishConfig": {
47
47
  "access": "public"
48
48
  },
49
- "gitHead": "ac3c3e465a083081a86a4da6ee6fb817b41e5130"
49
+ "gitHead": "ffc07735d0abfb3f69e91d48f25b7fe8d1ef92d2"
50
50
  }
@@ -14,6 +14,7 @@ import { superscript } from './superscript';
14
14
  import { keyboard } from './keyboard';
15
15
  import { unknown } from './unknown';
16
16
  import { language } from './language';
17
+ import { nonBreakingSpace } from './non-breaking-space';
17
18
 
18
19
  export default [
19
20
  bold,
@@ -29,4 +30,5 @@ export default [
29
30
  keyboard,
30
31
  unknown,
31
32
  language,
33
+ nonBreakingSpace,
32
34
  ];
package/src/link/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import { __ } from '@wordpress/i18n';
5
- import { useState, useLayoutEffect } from '@wordpress/element';
5
+ import { useState, useLayoutEffect, useEffect } from '@wordpress/element';
6
6
  import {
7
7
  getTextContent,
8
8
  applyFormat,
@@ -38,10 +38,39 @@ function Edit( {
38
38
  onFocus,
39
39
  contentRef,
40
40
  } ) {
41
- const [ addingLink, setAddingLink ] = useState( false );
41
+ const [ editingLink, setEditingLink ] = useState( false );
42
+ const [ creatingLink, setCreatingLink ] = useState( false );
43
+
42
44
  // We only need to store the button element that opened the popover. We can ignore the other states, as they will be handled by the onFocus prop to return to the rich text field.
43
45
  const [ openedBy, setOpenedBy ] = useState( null );
44
46
 
47
+ // Manages whether the Link UI popover should autofocus when shown.
48
+ const [ shouldAutoFocus, setShouldAutoFocus ] = useState( true );
49
+
50
+ function setIsEditingLink( isEditing, { autoFocus = true } = {} ) {
51
+ setEditingLink( isEditing );
52
+ setShouldAutoFocus( autoFocus );
53
+ }
54
+
55
+ function setIsCreatingLink( isCreating ) {
56
+ // Don't add a new link if there is already an active link.
57
+ // The two states are mutually exclusive.
58
+ if ( isCreating === true && isActive ) {
59
+ return;
60
+ }
61
+ setCreatingLink( isCreating );
62
+ }
63
+
64
+ useEffect( () => {
65
+ // When the link becomes inactive (i.e. isActive is false), reset the editingLink state
66
+ // and the creatingLink state. This means that if the Link UI is displayed and the link
67
+ // becomes inactive (e.g. used arrow keys to move cursor outside of link bounds), the UI will close.
68
+ if ( ! isActive ) {
69
+ setEditingLink( false );
70
+ setCreatingLink( false );
71
+ }
72
+ }, [ isActive ] );
73
+
45
74
  useLayoutEffect( () => {
46
75
  const editableContentElement = contentRef.current;
47
76
  if ( ! editableContentElement ) {
@@ -52,14 +81,18 @@ function Edit( {
52
81
  // There is a situation whereby there is an existing link in the rich text
53
82
  // and the user clicks on the leftmost edge of that link and fails to activate
54
83
  // the link format, but the click event still fires on the `<a>` element.
55
- // This causes the `addingLink` state to be set to `true` and the link UI
84
+ // This causes the `editingLink` state to be set to `true` and the link UI
56
85
  // to be rendered in "creating" mode. We need to check isActive to see if
57
86
  // we have an active link format.
58
- if ( event.target.tagName !== 'A' || ! isActive ) {
87
+ if (
88
+ ! event.target.closest( '[contenteditable] a' ) || // other formats (e.g. bold) may be nested within the link.
89
+ ! isActive
90
+ ) {
91
+ setIsEditingLink( false );
59
92
  return;
60
93
  }
61
94
 
62
- setAddingLink( true );
95
+ setIsEditingLink( true, { autoFocus: false } );
63
96
  }
64
97
 
65
98
  editableContentElement.addEventListener( 'click', handleClick );
@@ -70,6 +103,7 @@ function Edit( {
70
103
  }, [ contentRef, isActive ] );
71
104
 
72
105
  function addLink( target ) {
106
+ setShouldAutoFocus( true );
73
107
  const text = getTextContent( slice( value ) );
74
108
 
75
109
  if ( ! isActive && text && isURL( text ) && isValidHref( text ) ) {
@@ -90,7 +124,11 @@ function Edit( {
90
124
  if ( target ) {
91
125
  setOpenedBy( target );
92
126
  }
93
- setAddingLink( true );
127
+ if ( ! isActive ) {
128
+ setIsCreatingLink( true );
129
+ } else {
130
+ setIsEditingLink( true );
131
+ }
94
132
  }
95
133
  }
96
134
 
@@ -109,7 +147,9 @@ function Edit( {
109
147
  // Otherwise, we rely on the passed in onFocus to return focus to the rich text field.
110
148
 
111
149
  // Close the popover
112
- setAddingLink( false );
150
+ setIsEditingLink( false );
151
+ setIsCreatingLink( false );
152
+
113
153
  // Return focus to the toolbar button or the rich text field
114
154
  if ( openedBy?.tagName === 'BUTTON' ) {
115
155
  openedBy.focus();
@@ -127,7 +167,8 @@ function Edit( {
127
167
  // 4. Press Escape
128
168
  // 5. Focus should be on the Options button
129
169
  function onFocusOutside() {
130
- setAddingLink( false );
170
+ setIsEditingLink( false );
171
+ setIsCreatingLink( false );
131
172
  setOpenedBy( null );
132
173
  }
133
174
 
@@ -136,6 +177,8 @@ function Edit( {
136
177
  speak( __( 'Link removed.' ), 'assertive' );
137
178
  }
138
179
 
180
+ const isEditingActiveLink = editingLink && isActive;
181
+
139
182
  return (
140
183
  <>
141
184
  <RichTextShortcut type="primary" character="k" onUse={ addLink } />
@@ -151,13 +194,13 @@ function Edit( {
151
194
  onClick={ ( event ) => {
152
195
  addLink( event.currentTarget );
153
196
  } }
154
- isActive={ isActive || addingLink }
197
+ isActive={ isActive || editingLink }
155
198
  shortcutType="primary"
156
199
  shortcutCharacter="k"
157
200
  aria-haspopup="true"
158
- aria-expanded={ addingLink }
201
+ aria-expanded={ editingLink }
159
202
  />
160
- { addingLink && (
203
+ { ( isEditingActiveLink || creatingLink ) && (
161
204
  <InlineLinkUI
162
205
  stopAddingLink={ stopAddingLink }
163
206
  onFocusOutside={ onFocusOutside }
@@ -166,6 +209,7 @@ function Edit( {
166
209
  value={ value }
167
210
  onChange={ onChange }
168
211
  contentRef={ contentRef }
212
+ focusOnMount={ shouldAutoFocus ? 'firstElement' : false }
169
213
  />
170
214
  ) }
171
215
  </>
@@ -46,6 +46,7 @@ function InlineLinkUI( {
46
46
  onFocusOutside,
47
47
  stopAddingLink,
48
48
  contentRef,
49
+ focusOnMount,
49
50
  } ) {
50
51
  const richLinkTextValue = getRichTextValueFromSelection( value, isActive );
51
52
 
@@ -216,7 +217,10 @@ function InlineLinkUI( {
216
217
 
217
218
  const popoverAnchor = useAnchor( {
218
219
  editableContentElement: contentRef.current,
219
- settings: { ...settings, isActive },
220
+ settings: {
221
+ ...settings,
222
+ isActive,
223
+ },
220
224
  } );
221
225
 
222
226
  async function handleCreate( pageTitle ) {
@@ -253,6 +257,8 @@ function InlineLinkUI( {
253
257
  placement="bottom"
254
258
  offset={ 10 }
255
259
  shift
260
+ focusOnMount={ focusOnMount }
261
+ constrainTabbing
256
262
  >
257
263
  <LinkControl
258
264
  value={ linkValue }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { __ } from '@wordpress/i18n';
5
+ import { insert } from '@wordpress/rich-text';
6
+ import { RichTextShortcut } from '@wordpress/block-editor';
7
+
8
+ const name = 'core/non-breaking-space';
9
+ const title = __( 'Non breaking space' );
10
+
11
+ export const nonBreakingSpace = {
12
+ name,
13
+ title,
14
+ tagName: 'nbsp',
15
+ className: null,
16
+ edit( { value, onChange } ) {
17
+ function addNonBreakingSpace() {
18
+ onChange( insert( value, '\u00a0' ) );
19
+ }
20
+
21
+ return (
22
+ <RichTextShortcut
23
+ type="primaryShift"
24
+ character=" "
25
+ onUse={ addNonBreakingSpace }
26
+ />
27
+ );
28
+ },
29
+ };