@wordpress/block-editor 15.16.0 → 15.17.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.
Files changed (157) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/components/autocomplete/index.cjs +1 -2
  3. package/build/components/autocomplete/index.cjs.map +3 -3
  4. package/build/components/block-list/block-crash-warning.cjs +4 -2
  5. package/build/components/block-list/block-crash-warning.cjs.map +2 -2
  6. package/build/components/block-list/block-html.cjs +6 -2
  7. package/build/components/block-list/block-html.cjs.map +2 -2
  8. package/build/components/block-mover/button.cjs +4 -3
  9. package/build/components/block-mover/button.cjs.map +2 -2
  10. package/build/components/block-mover/index.cjs +1 -8
  11. package/build/components/block-mover/index.cjs.map +2 -2
  12. package/build/components/copy-handler/index.cjs.map +2 -2
  13. package/build/components/iframe/get-compatibility-styles.cjs +1 -1
  14. package/build/components/iframe/get-compatibility-styles.cjs.map +2 -2
  15. package/build/components/inserter/media-tab/hooks.cjs +1 -1
  16. package/build/components/inserter/media-tab/hooks.cjs.map +2 -2
  17. package/build/components/link-control/link-preview.cjs +3 -1
  18. package/build/components/link-control/link-preview.cjs.map +2 -2
  19. package/build/components/link-control/search-input.cjs +1 -1
  20. package/build/components/link-control/search-input.cjs.map +2 -2
  21. package/build/components/link-picker/link-preview.cjs +2 -1
  22. package/build/components/link-picker/link-preview.cjs.map +3 -3
  23. package/build/components/preset-input-control/index.cjs +7 -4
  24. package/build/components/preset-input-control/index.cjs.map +2 -2
  25. package/build/components/rich-text/event-listeners/index.cjs.map +2 -2
  26. package/build/components/rich-text/index.cjs +1 -1
  27. package/build/components/rich-text/index.cjs.map +2 -2
  28. package/build/components/rich-text/input-event.cjs +3 -3
  29. package/build/components/rich-text/input-event.cjs.map +2 -2
  30. package/build/components/spacing-sizes-control/utils.cjs +1 -1
  31. package/build/components/spacing-sizes-control/utils.cjs.map +2 -2
  32. package/build/components/use-on-block-drop/index.cjs +1 -1
  33. package/build/components/use-on-block-drop/index.cjs.map +2 -2
  34. package/build/components/use-paste-styles/index.cjs +2 -2
  35. package/build/components/use-paste-styles/index.cjs.map +2 -2
  36. package/build/components/writing-flow/use-selection-observer.cjs +23 -1
  37. package/build/components/writing-flow/use-selection-observer.cjs.map +2 -2
  38. package/build/hooks/block-style-variation.cjs +5 -6
  39. package/build/hooks/block-style-variation.cjs.map +3 -3
  40. package/build/hooks/index.cjs +2 -2
  41. package/build/hooks/index.cjs.map +2 -2
  42. package/build/hooks/style.cjs +54 -52
  43. package/build/hooks/style.cjs.map +2 -2
  44. package/build/private-apis.cjs +1 -1
  45. package/build/private-apis.cjs.map +1 -1
  46. package/build/store/actions.cjs +0 -8
  47. package/build/store/actions.cjs.map +2 -2
  48. package/build/store/reducer.cjs +52 -53
  49. package/build/store/reducer.cjs.map +2 -2
  50. package/build/store/selectors.cjs +12 -13
  51. package/build/store/selectors.cjs.map +2 -2
  52. package/build/store/utils.cjs +1 -1
  53. package/build/store/utils.cjs.map +2 -2
  54. package/build/utils/pasting.cjs +1 -1
  55. package/build/utils/pasting.cjs.map +2 -2
  56. package/build-module/components/autocomplete/index.mjs +1 -2
  57. package/build-module/components/autocomplete/index.mjs.map +2 -2
  58. package/build-module/components/block-list/block-crash-warning.mjs +4 -2
  59. package/build-module/components/block-list/block-crash-warning.mjs.map +2 -2
  60. package/build-module/components/block-list/block-html.mjs +7 -3
  61. package/build-module/components/block-list/block-html.mjs.map +2 -2
  62. package/build-module/components/block-mover/button.mjs +4 -3
  63. package/build-module/components/block-mover/button.mjs.map +2 -2
  64. package/build-module/components/block-mover/index.mjs +1 -8
  65. package/build-module/components/block-mover/index.mjs.map +2 -2
  66. package/build-module/components/copy-handler/index.mjs.map +2 -2
  67. package/build-module/components/iframe/get-compatibility-styles.mjs +1 -1
  68. package/build-module/components/iframe/get-compatibility-styles.mjs.map +2 -2
  69. package/build-module/components/inserter/media-tab/hooks.mjs +1 -1
  70. package/build-module/components/inserter/media-tab/hooks.mjs.map +2 -2
  71. package/build-module/components/link-control/link-preview.mjs +3 -1
  72. package/build-module/components/link-control/link-preview.mjs.map +2 -2
  73. package/build-module/components/link-control/search-input.mjs +1 -1
  74. package/build-module/components/link-control/search-input.mjs.map +2 -2
  75. package/build-module/components/link-picker/link-preview.mjs +2 -1
  76. package/build-module/components/link-picker/link-preview.mjs.map +2 -2
  77. package/build-module/components/preset-input-control/index.mjs +7 -4
  78. package/build-module/components/preset-input-control/index.mjs.map +2 -2
  79. package/build-module/components/rich-text/event-listeners/index.mjs.map +2 -2
  80. package/build-module/components/rich-text/index.mjs +2 -2
  81. package/build-module/components/rich-text/index.mjs.map +2 -2
  82. package/build-module/components/rich-text/input-event.mjs +2 -2
  83. package/build-module/components/rich-text/input-event.mjs.map +2 -2
  84. package/build-module/components/spacing-sizes-control/utils.mjs +1 -1
  85. package/build-module/components/spacing-sizes-control/utils.mjs.map +2 -2
  86. package/build-module/components/use-on-block-drop/index.mjs +1 -1
  87. package/build-module/components/use-on-block-drop/index.mjs.map +2 -2
  88. package/build-module/components/use-paste-styles/index.mjs +2 -2
  89. package/build-module/components/use-paste-styles/index.mjs.map +2 -2
  90. package/build-module/components/writing-flow/use-selection-observer.mjs +23 -1
  91. package/build-module/components/writing-flow/use-selection-observer.mjs.map +2 -2
  92. package/build-module/hooks/block-style-variation.mjs +4 -5
  93. package/build-module/hooks/block-style-variation.mjs.map +2 -2
  94. package/build-module/hooks/index.mjs +2 -2
  95. package/build-module/hooks/index.mjs.map +2 -2
  96. package/build-module/hooks/style.mjs +54 -52
  97. package/build-module/hooks/style.mjs.map +2 -2
  98. package/build-module/private-apis.mjs +2 -2
  99. package/build-module/private-apis.mjs.map +1 -1
  100. package/build-module/store/actions.mjs +0 -8
  101. package/build-module/store/actions.mjs.map +2 -2
  102. package/build-module/store/reducer.mjs +52 -53
  103. package/build-module/store/reducer.mjs.map +2 -2
  104. package/build-module/store/selectors.mjs +12 -13
  105. package/build-module/store/selectors.mjs.map +2 -2
  106. package/build-module/store/utils.mjs +1 -1
  107. package/build-module/store/utils.mjs.map +2 -2
  108. package/build-module/utils/pasting.mjs +1 -1
  109. package/build-module/utils/pasting.mjs.map +2 -2
  110. package/build-style/style-rtl.css +0 -7
  111. package/build-style/style.css +0 -7
  112. package/package.json +38 -39
  113. package/src/autocompleters/style.scss +0 -8
  114. package/src/components/autocomplete/index.js +1 -2
  115. package/src/components/block-draggable/test/helpers.native.js +1 -1
  116. package/src/components/block-list/block-crash-warning.js +3 -1
  117. package/src/components/block-list/block-crash-warning.native.js +3 -1
  118. package/src/components/block-list/block-html.js +13 -3
  119. package/src/components/block-mover/button.js +7 -4
  120. package/src/components/block-mover/index.js +1 -8
  121. package/src/components/copy-handler/index.js +1 -0
  122. package/src/components/iframe/get-compatibility-styles.js +1 -1
  123. package/src/components/inserter/media-tab/hooks.js +1 -1
  124. package/src/components/link-control/README.md +2 -2
  125. package/src/components/link-control/link-preview.js +3 -1
  126. package/src/components/link-control/search-input.js +1 -1
  127. package/src/components/link-picker/link-preview.js +2 -1
  128. package/src/components/preset-input-control/index.js +10 -4
  129. package/src/components/preset-input-control/test/index.js +70 -0
  130. package/src/components/rich-text/event-listeners/index.js +1 -0
  131. package/src/components/rich-text/index.js +1 -1
  132. package/src/components/rich-text/index.native.js +1 -1
  133. package/src/components/rich-text/input-event.js +1 -1
  134. package/src/components/rich-text/input-event.native.js +1 -1
  135. package/src/components/rich-text/native/index.native.js +18 -17
  136. package/src/components/spacing-sizes-control/utils.js +1 -1
  137. package/src/components/use-on-block-drop/index.js +1 -1
  138. package/src/components/use-paste-styles/index.js +2 -2
  139. package/src/components/writing-flow/use-selection-observer.js +39 -1
  140. package/src/hooks/block-style-variation.js +3 -4
  141. package/src/hooks/index.js +1 -1
  142. package/src/hooks/style.js +75 -61
  143. package/src/private-apis.js +2 -2
  144. package/src/store/actions.js +0 -8
  145. package/src/store/reducer.js +62 -67
  146. package/src/store/selectors.js +31 -21
  147. package/src/store/test/private-selectors.js +44 -41
  148. package/src/store/test/reducer.js +159 -88
  149. package/src/store/test/registry-selectors.js +1 -1
  150. package/src/store/test/selectors.js +265 -200
  151. package/src/store/utils.js +1 -1
  152. package/src/utils/pasting.js +1 -1
  153. package/build/autocompleters/link.cjs +0 -81
  154. package/build/autocompleters/link.cjs.map +0 -7
  155. package/build-module/autocompleters/link.mjs +0 -50
  156. package/build-module/autocompleters/link.mjs.map +0 -7
  157. package/src/autocompleters/link.js +0 -63
@@ -112,7 +112,7 @@ var getAllPatternsDependants = (select) => (state) => {
112
112
  };
113
113
  var getInsertBlockTypeDependants = () => (state, rootClientId) => {
114
114
  return [
115
- state.blockListSettings[rootClientId],
115
+ state.blockListSettings.get(rootClientId),
116
116
  state.blocks.byClientId.get(rootClientId),
117
117
  state.blocks.order.get(rootClientId || ""),
118
118
  state.settings.allowedBlockTypes,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/store/utils.js"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { parse } from '@wordpress/blocks';\nimport { parse as grammarParse } from '@wordpress/block-serialization-default-parser';\n\n/**\n * Internal dependencies\n */\nimport { selectBlockPatternsKey } from './private-keys';\nimport { unlock } from '../lock-unlock';\nimport { STORE_NAME } from './constants';\nimport {\n\tgetSectionRootClientId,\n\tisSectionBlock,\n\tgetParentSectionBlock,\n} from './private-selectors';\nimport { getBlockEditingMode } from './selectors';\nimport { INSERTER_PATTERN_TYPES } from '../components/inserter/block-patterns-tab/utils';\n\nexport const isFiltered = Symbol( 'isFiltered' );\nconst parsedPatternCache = new WeakMap();\nconst grammarMapCache = new WeakMap();\n\nexport function mapUserPattern(\n\tuserPattern,\n\t__experimentalUserPatternCategories = []\n) {\n\treturn {\n\t\tname: `core/block/${ userPattern.id }`,\n\t\tid: userPattern.id,\n\t\ttype: INSERTER_PATTERN_TYPES.user,\n\t\ttitle: userPattern.title?.raw,\n\t\tcategories: userPattern.wp_pattern_category?.map( ( catId ) => {\n\t\t\tconst category = __experimentalUserPatternCategories.find(\n\t\t\t\t( { id } ) => id === catId\n\t\t\t);\n\t\t\treturn category ? category.slug : catId;\n\t\t} ),\n\t\tcontent: userPattern.content?.raw,\n\t\tsyncStatus: userPattern.wp_pattern_sync_status,\n\t};\n}\n\nfunction parsePattern( pattern ) {\n\tconst blocks = parse( pattern.content, {\n\t\t__unstableSkipMigrationLogs: true,\n\t} );\n\tif ( blocks.length === 1 ) {\n\t\tblocks[ 0 ].attributes = {\n\t\t\t...blocks[ 0 ].attributes,\n\t\t\tmetadata: {\n\t\t\t\t...( blocks[ 0 ].attributes.metadata || {} ),\n\t\t\t\tcategories: pattern.categories,\n\t\t\t\tpatternName: pattern.name,\n\t\t\t\tname: blocks[ 0 ].attributes.metadata?.name || pattern.title,\n\t\t\t},\n\t\t};\n\t}\n\treturn {\n\t\t...pattern,\n\t\tblocks,\n\t};\n}\n\nexport function getParsedPattern( pattern ) {\n\tlet parsedPattern = parsedPatternCache.get( pattern );\n\tif ( ! parsedPattern ) {\n\t\tparsedPattern = parsePattern( pattern );\n\t\tparsedPatternCache.set( pattern, parsedPattern );\n\t}\n\treturn parsedPattern;\n}\n\nexport function getGrammar( pattern ) {\n\tlet grammarMap = grammarMapCache.get( pattern );\n\tif ( ! grammarMap ) {\n\t\tgrammarMap = grammarParse( pattern.content );\n\t\t// Block names are null only at the top level for whitespace.\n\t\tgrammarMap = grammarMap.filter( ( block ) => block.blockName !== null );\n\t\tgrammarMapCache.set( pattern, grammarMap );\n\t}\n\treturn grammarMap;\n}\n\nexport const checkAllowList = ( list, item, defaultResult = null ) => {\n\tif ( typeof list === 'boolean' ) {\n\t\treturn list;\n\t}\n\tif ( Array.isArray( list ) ) {\n\t\t// TODO: when there is a canonical way to detect that we are editing a post\n\t\t// the following check should be changed to something like:\n\t\t// if ( list.includes( 'core/post-content' ) && getEditorMode() === 'post-content' && item === null )\n\t\tif ( list.includes( 'core/post-content' ) && item === null ) {\n\t\t\treturn true;\n\t\t}\n\t\treturn list.includes( item );\n\t}\n\treturn defaultResult;\n};\n\nexport const checkAllowListRecursive = ( blocks, allowedBlockTypes ) => {\n\tif ( typeof allowedBlockTypes === 'boolean' ) {\n\t\treturn allowedBlockTypes;\n\t}\n\n\tconst blocksQueue = [ ...blocks ];\n\twhile ( blocksQueue.length > 0 ) {\n\t\tconst block = blocksQueue.shift();\n\n\t\tconst isAllowed = checkAllowList(\n\t\t\tallowedBlockTypes,\n\t\t\tblock.name || block.blockName,\n\t\t\ttrue\n\t\t);\n\t\tif ( ! isAllowed ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tblock.innerBlocks?.forEach( ( innerBlock ) => {\n\t\t\tblocksQueue.push( innerBlock );\n\t\t} );\n\t}\n\n\treturn true;\n};\n\nexport const getAllPatternsDependants = ( select ) => ( state ) => {\n\treturn [\n\t\tstate.settings.__experimentalBlockPatterns,\n\t\tstate.settings.__experimentalUserPatternCategories,\n\t\tstate.settings.__experimentalReusableBlocks,\n\t\tstate.settings[ selectBlockPatternsKey ]?.( select ),\n\t\tstate.blockPatterns,\n\t\tunlock( select( STORE_NAME ) ).getReusableBlocks(),\n\t];\n};\n\nexport const getInsertBlockTypeDependants = () => ( state, rootClientId ) => {\n\treturn [\n\t\tstate.blockListSettings[ rootClientId ],\n\t\tstate.blocks.byClientId.get( rootClientId ),\n\t\tstate.blocks.order.get( rootClientId || '' ),\n\t\tstate.settings.allowedBlockTypes,\n\t\tstate.settings.templateLock,\n\t\tgetBlockEditingMode( state, rootClientId ),\n\t\tgetSectionRootClientId( state ),\n\t\tisSectionBlock( state, rootClientId ),\n\t\tgetParentSectionBlock( state, rootClientId ),\n\t];\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { parse } from '@wordpress/blocks';\nimport { parse as grammarParse } from '@wordpress/block-serialization-default-parser';\n\n/**\n * Internal dependencies\n */\nimport { selectBlockPatternsKey } from './private-keys';\nimport { unlock } from '../lock-unlock';\nimport { STORE_NAME } from './constants';\nimport {\n\tgetSectionRootClientId,\n\tisSectionBlock,\n\tgetParentSectionBlock,\n} from './private-selectors';\nimport { getBlockEditingMode } from './selectors';\nimport { INSERTER_PATTERN_TYPES } from '../components/inserter/block-patterns-tab/utils';\n\nexport const isFiltered = Symbol( 'isFiltered' );\nconst parsedPatternCache = new WeakMap();\nconst grammarMapCache = new WeakMap();\n\nexport function mapUserPattern(\n\tuserPattern,\n\t__experimentalUserPatternCategories = []\n) {\n\treturn {\n\t\tname: `core/block/${ userPattern.id }`,\n\t\tid: userPattern.id,\n\t\ttype: INSERTER_PATTERN_TYPES.user,\n\t\ttitle: userPattern.title?.raw,\n\t\tcategories: userPattern.wp_pattern_category?.map( ( catId ) => {\n\t\t\tconst category = __experimentalUserPatternCategories.find(\n\t\t\t\t( { id } ) => id === catId\n\t\t\t);\n\t\t\treturn category ? category.slug : catId;\n\t\t} ),\n\t\tcontent: userPattern.content?.raw,\n\t\tsyncStatus: userPattern.wp_pattern_sync_status,\n\t};\n}\n\nfunction parsePattern( pattern ) {\n\tconst blocks = parse( pattern.content, {\n\t\t__unstableSkipMigrationLogs: true,\n\t} );\n\tif ( blocks.length === 1 ) {\n\t\tblocks[ 0 ].attributes = {\n\t\t\t...blocks[ 0 ].attributes,\n\t\t\tmetadata: {\n\t\t\t\t...( blocks[ 0 ].attributes.metadata || {} ),\n\t\t\t\tcategories: pattern.categories,\n\t\t\t\tpatternName: pattern.name,\n\t\t\t\tname: blocks[ 0 ].attributes.metadata?.name || pattern.title,\n\t\t\t},\n\t\t};\n\t}\n\treturn {\n\t\t...pattern,\n\t\tblocks,\n\t};\n}\n\nexport function getParsedPattern( pattern ) {\n\tlet parsedPattern = parsedPatternCache.get( pattern );\n\tif ( ! parsedPattern ) {\n\t\tparsedPattern = parsePattern( pattern );\n\t\tparsedPatternCache.set( pattern, parsedPattern );\n\t}\n\treturn parsedPattern;\n}\n\nexport function getGrammar( pattern ) {\n\tlet grammarMap = grammarMapCache.get( pattern );\n\tif ( ! grammarMap ) {\n\t\tgrammarMap = grammarParse( pattern.content );\n\t\t// Block names are null only at the top level for whitespace.\n\t\tgrammarMap = grammarMap.filter( ( block ) => block.blockName !== null );\n\t\tgrammarMapCache.set( pattern, grammarMap );\n\t}\n\treturn grammarMap;\n}\n\nexport const checkAllowList = ( list, item, defaultResult = null ) => {\n\tif ( typeof list === 'boolean' ) {\n\t\treturn list;\n\t}\n\tif ( Array.isArray( list ) ) {\n\t\t// TODO: when there is a canonical way to detect that we are editing a post\n\t\t// the following check should be changed to something like:\n\t\t// if ( list.includes( 'core/post-content' ) && getEditorMode() === 'post-content' && item === null )\n\t\tif ( list.includes( 'core/post-content' ) && item === null ) {\n\t\t\treturn true;\n\t\t}\n\t\treturn list.includes( item );\n\t}\n\treturn defaultResult;\n};\n\nexport const checkAllowListRecursive = ( blocks, allowedBlockTypes ) => {\n\tif ( typeof allowedBlockTypes === 'boolean' ) {\n\t\treturn allowedBlockTypes;\n\t}\n\n\tconst blocksQueue = [ ...blocks ];\n\twhile ( blocksQueue.length > 0 ) {\n\t\tconst block = blocksQueue.shift();\n\n\t\tconst isAllowed = checkAllowList(\n\t\t\tallowedBlockTypes,\n\t\t\tblock.name || block.blockName,\n\t\t\ttrue\n\t\t);\n\t\tif ( ! isAllowed ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tblock.innerBlocks?.forEach( ( innerBlock ) => {\n\t\t\tblocksQueue.push( innerBlock );\n\t\t} );\n\t}\n\n\treturn true;\n};\n\nexport const getAllPatternsDependants = ( select ) => ( state ) => {\n\treturn [\n\t\tstate.settings.__experimentalBlockPatterns,\n\t\tstate.settings.__experimentalUserPatternCategories,\n\t\tstate.settings.__experimentalReusableBlocks,\n\t\tstate.settings[ selectBlockPatternsKey ]?.( select ),\n\t\tstate.blockPatterns,\n\t\tunlock( select( STORE_NAME ) ).getReusableBlocks(),\n\t];\n};\n\nexport const getInsertBlockTypeDependants = () => ( state, rootClientId ) => {\n\treturn [\n\t\tstate.blockListSettings.get( rootClientId ),\n\t\tstate.blocks.byClientId.get( rootClientId ),\n\t\tstate.blocks.order.get( rootClientId || '' ),\n\t\tstate.settings.allowedBlockTypes,\n\t\tstate.settings.templateLock,\n\t\tgetBlockEditingMode( state, rootClientId ),\n\t\tgetSectionRootClientId( state ),\n\t\tisSectionBlock( state, rootClientId ),\n\t\tgetParentSectionBlock( state, rootClientId ),\n\t];\n};\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -28,7 +28,7 @@ function getPasteEventData({ clipboardData }) {
28
28
  try {
29
29
  plainText = clipboardData.getData("text/plain");
30
30
  html = clipboardData.getData("text/html");
31
- } catch (error) {
31
+ } catch {
32
32
  return;
33
33
  }
34
34
  html = removeWindowsFragments(html);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/pasting.js"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { getFilesFromDataTransfer } from '@wordpress/dom';\n\n/**\n * Normalizes a given string of HTML to remove the Windows-specific \"Fragment\"\n * comments and any preceding and trailing content.\n *\n * @param {string} html the html to be normalized\n * @return {string} the normalized html\n */\nfunction removeWindowsFragments( html ) {\n\tconst startStr = '<!--StartFragment-->';\n\tconst startIdx = html.indexOf( startStr );\n\tif ( startIdx > -1 ) {\n\t\thtml = html.substring( startIdx + startStr.length );\n\t} else {\n\t\t// No point looking for EndFragment\n\t\treturn html;\n\t}\n\n\tconst endStr = '<!--EndFragment-->';\n\tconst endIdx = html.indexOf( endStr );\n\tif ( endIdx > -1 ) {\n\t\thtml = html.substring( 0, endIdx );\n\t}\n\n\treturn html;\n}\n\n/**\n * Removes the charset meta tag inserted by Chromium.\n * See:\n * - https://github.com/WordPress/gutenberg/issues/33585\n * - https://bugs.chromium.org/p/chromium/issues/detail?id=1264616#c4\n *\n * @param {string} html the html to be stripped of the meta tag.\n * @return {string} the cleaned html\n */\nfunction removeCharsetMetaTag( html ) {\n\tconst metaTag = `<meta charset='utf-8'>`;\n\n\tif ( html.startsWith( metaTag ) ) {\n\t\treturn html.slice( metaTag.length );\n\t}\n\n\treturn html;\n}\n\nexport function getPasteEventData( { clipboardData } ) {\n\tlet plainText = '';\n\tlet html = '';\n\n\ttry {\n\t\tplainText = clipboardData.getData( 'text/plain' );\n\t\thtml = clipboardData.getData( 'text/html' );\n\t} catch ( error ) {\n\t\t// Some browsers like UC Browser paste plain text by default and\n\t\t// don't support clipboardData at all, so allow default\n\t\t// behaviour.\n\t\treturn;\n\t}\n\n\t// Remove Windows-specific metadata appended within copied HTML text.\n\thtml = removeWindowsFragments( html );\n\n\t// Strip meta tag.\n\thtml = removeCharsetMetaTag( html );\n\n\tconst files = getFilesFromDataTransfer( clipboardData );\n\n\tif ( files.length && ! shouldDismissPastedFiles( files, html ) ) {\n\t\treturn { files };\n\t}\n\n\treturn { html, plainText, files: [] };\n}\n\n/**\n * Given a collection of DataTransfer files and HTML and plain text strings,\n * determine whether the files are to be dismissed in favor of the HTML.\n *\n * Certain office-type programs, like Microsoft Word or Apple Numbers,\n * will, upon copy, generate a screenshot of the content being copied and\n * attach it to the clipboard alongside the actual rich text that the user\n * sought to copy. In those cases, we should let Gutenberg handle the rich text\n * content and not the screenshot, since this allows Gutenberg to insert\n * meaningful blocks, like paragraphs, lists or even tables.\n *\n * @param {File[]} files File objects obtained from a paste event\n * @param {string} html HTML content obtained from a paste event\n * @return {boolean} True if the files should be dismissed\n */\nexport function shouldDismissPastedFiles( files, html /*, plainText */ ) {\n\t// The question is only relevant when there is actual HTML content and when\n\t// there is exactly one image file.\n\tif (\n\t\thtml &&\n\t\tfiles?.length === 1 &&\n\t\tfiles[ 0 ].type.indexOf( 'image/' ) === 0\n\t) {\n\t\t// A single <img> tag found in the HTML source suggests that the\n\t\t// content being pasted revolves around an image. Sometimes there are\n\t\t// other elements found, like <figure>, but we assume that the user's\n\t\t// intention is to paste the actual image file.\n\t\tconst IMAGE_TAG = /<\\s*img\\b/gi;\n\t\tif ( html.match( IMAGE_TAG )?.length !== 1 ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Even when there is exactly one <img> tag in the HTML payload, we\n\t\t// choose to weed out local images, i.e. those whose source starts with\n\t\t// \"file://\". These payloads occur in specific configurations, such as\n\t\t// when copying an entire document from Microsoft Word, that contains\n\t\t// text and exactly one image, and pasting that content using Google\n\t\t// Chrome.\n\t\tconst IMG_WITH_LOCAL_SRC = /<\\s*img\\b[^>]*\\bsrc=\"file:\\/\\//i;\n\t\tif ( html.match( IMG_WITH_LOCAL_SRC ) ) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n"],
5
- "mappings": ";AAGA,SAAS,gCAAgC;AASzC,SAAS,uBAAwB,MAAO;AACvC,QAAM,WAAW;AACjB,QAAM,WAAW,KAAK,QAAS,QAAS;AACxC,MAAK,WAAW,IAAK;AACpB,WAAO,KAAK,UAAW,WAAW,SAAS,MAAO;AAAA,EACnD,OAAO;AAEN,WAAO;AAAA,EACR;AAEA,QAAM,SAAS;AACf,QAAM,SAAS,KAAK,QAAS,MAAO;AACpC,MAAK,SAAS,IAAK;AAClB,WAAO,KAAK,UAAW,GAAG,MAAO;AAAA,EAClC;AAEA,SAAO;AACR;AAWA,SAAS,qBAAsB,MAAO;AACrC,QAAM,UAAU;AAEhB,MAAK,KAAK,WAAY,OAAQ,GAAI;AACjC,WAAO,KAAK,MAAO,QAAQ,MAAO;AAAA,EACnC;AAEA,SAAO;AACR;AAEO,SAAS,kBAAmB,EAAE,cAAc,GAAI;AACtD,MAAI,YAAY;AAChB,MAAI,OAAO;AAEX,MAAI;AACH,gBAAY,cAAc,QAAS,YAAa;AAChD,WAAO,cAAc,QAAS,WAAY;AAAA,EAC3C,SAAU,OAAQ;AAIjB;AAAA,EACD;AAGA,SAAO,uBAAwB,IAAK;AAGpC,SAAO,qBAAsB,IAAK;AAElC,QAAM,QAAQ,yBAA0B,aAAc;AAEtD,MAAK,MAAM,UAAU,CAAE,yBAA0B,OAAO,IAAK,GAAI;AAChE,WAAO,EAAE,MAAM;AAAA,EAChB;AAEA,SAAO,EAAE,MAAM,WAAW,OAAO,CAAC,EAAE;AACrC;AAiBO,SAAS,yBAA0B,OAAO,MAAwB;AAGxE,MACC,QACA,OAAO,WAAW,KAClB,MAAO,CAAE,EAAE,KAAK,QAAS,QAAS,MAAM,GACvC;AAKD,UAAM,YAAY;AAClB,QAAK,KAAK,MAAO,SAAU,GAAG,WAAW,GAAI;AAC5C,aAAO;AAAA,IACR;AAQA,UAAM,qBAAqB;AAC3B,QAAK,KAAK,MAAO,kBAAmB,GAAI;AACvC,aAAO;AAAA,IACR;AAAA,EACD;AAEA,SAAO;AACR;",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { getFilesFromDataTransfer } from '@wordpress/dom';\n\n/**\n * Normalizes a given string of HTML to remove the Windows-specific \"Fragment\"\n * comments and any preceding and trailing content.\n *\n * @param {string} html the html to be normalized\n * @return {string} the normalized html\n */\nfunction removeWindowsFragments( html ) {\n\tconst startStr = '<!--StartFragment-->';\n\tconst startIdx = html.indexOf( startStr );\n\tif ( startIdx > -1 ) {\n\t\thtml = html.substring( startIdx + startStr.length );\n\t} else {\n\t\t// No point looking for EndFragment\n\t\treturn html;\n\t}\n\n\tconst endStr = '<!--EndFragment-->';\n\tconst endIdx = html.indexOf( endStr );\n\tif ( endIdx > -1 ) {\n\t\thtml = html.substring( 0, endIdx );\n\t}\n\n\treturn html;\n}\n\n/**\n * Removes the charset meta tag inserted by Chromium.\n * See:\n * - https://github.com/WordPress/gutenberg/issues/33585\n * - https://bugs.chromium.org/p/chromium/issues/detail?id=1264616#c4\n *\n * @param {string} html the html to be stripped of the meta tag.\n * @return {string} the cleaned html\n */\nfunction removeCharsetMetaTag( html ) {\n\tconst metaTag = `<meta charset='utf-8'>`;\n\n\tif ( html.startsWith( metaTag ) ) {\n\t\treturn html.slice( metaTag.length );\n\t}\n\n\treturn html;\n}\n\nexport function getPasteEventData( { clipboardData } ) {\n\tlet plainText = '';\n\tlet html = '';\n\n\ttry {\n\t\tplainText = clipboardData.getData( 'text/plain' );\n\t\thtml = clipboardData.getData( 'text/html' );\n\t} catch {\n\t\t// Some browsers like UC Browser paste plain text by default and\n\t\t// don't support clipboardData at all, so allow default\n\t\t// behaviour.\n\t\treturn;\n\t}\n\n\t// Remove Windows-specific metadata appended within copied HTML text.\n\thtml = removeWindowsFragments( html );\n\n\t// Strip meta tag.\n\thtml = removeCharsetMetaTag( html );\n\n\tconst files = getFilesFromDataTransfer( clipboardData );\n\n\tif ( files.length && ! shouldDismissPastedFiles( files, html ) ) {\n\t\treturn { files };\n\t}\n\n\treturn { html, plainText, files: [] };\n}\n\n/**\n * Given a collection of DataTransfer files and HTML and plain text strings,\n * determine whether the files are to be dismissed in favor of the HTML.\n *\n * Certain office-type programs, like Microsoft Word or Apple Numbers,\n * will, upon copy, generate a screenshot of the content being copied and\n * attach it to the clipboard alongside the actual rich text that the user\n * sought to copy. In those cases, we should let Gutenberg handle the rich text\n * content and not the screenshot, since this allows Gutenberg to insert\n * meaningful blocks, like paragraphs, lists or even tables.\n *\n * @param {File[]} files File objects obtained from a paste event\n * @param {string} html HTML content obtained from a paste event\n * @return {boolean} True if the files should be dismissed\n */\nexport function shouldDismissPastedFiles( files, html /*, plainText */ ) {\n\t// The question is only relevant when there is actual HTML content and when\n\t// there is exactly one image file.\n\tif (\n\t\thtml &&\n\t\tfiles?.length === 1 &&\n\t\tfiles[ 0 ].type.indexOf( 'image/' ) === 0\n\t) {\n\t\t// A single <img> tag found in the HTML source suggests that the\n\t\t// content being pasted revolves around an image. Sometimes there are\n\t\t// other elements found, like <figure>, but we assume that the user's\n\t\t// intention is to paste the actual image file.\n\t\tconst IMAGE_TAG = /<\\s*img\\b/gi;\n\t\tif ( html.match( IMAGE_TAG )?.length !== 1 ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Even when there is exactly one <img> tag in the HTML payload, we\n\t\t// choose to weed out local images, i.e. those whose source starts with\n\t\t// \"file://\". These payloads occur in specific configurations, such as\n\t\t// when copying an entire document from Microsoft Word, that contains\n\t\t// text and exactly one image, and pasting that content using Google\n\t\t// Chrome.\n\t\tconst IMG_WITH_LOCAL_SRC = /<\\s*img\\b[^>]*\\bsrc=\"file:\\/\\//i;\n\t\tif ( html.match( IMG_WITH_LOCAL_SRC ) ) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n"],
5
+ "mappings": ";AAGA,SAAS,gCAAgC;AASzC,SAAS,uBAAwB,MAAO;AACvC,QAAM,WAAW;AACjB,QAAM,WAAW,KAAK,QAAS,QAAS;AACxC,MAAK,WAAW,IAAK;AACpB,WAAO,KAAK,UAAW,WAAW,SAAS,MAAO;AAAA,EACnD,OAAO;AAEN,WAAO;AAAA,EACR;AAEA,QAAM,SAAS;AACf,QAAM,SAAS,KAAK,QAAS,MAAO;AACpC,MAAK,SAAS,IAAK;AAClB,WAAO,KAAK,UAAW,GAAG,MAAO;AAAA,EAClC;AAEA,SAAO;AACR;AAWA,SAAS,qBAAsB,MAAO;AACrC,QAAM,UAAU;AAEhB,MAAK,KAAK,WAAY,OAAQ,GAAI;AACjC,WAAO,KAAK,MAAO,QAAQ,MAAO;AAAA,EACnC;AAEA,SAAO;AACR;AAEO,SAAS,kBAAmB,EAAE,cAAc,GAAI;AACtD,MAAI,YAAY;AAChB,MAAI,OAAO;AAEX,MAAI;AACH,gBAAY,cAAc,QAAS,YAAa;AAChD,WAAO,cAAc,QAAS,WAAY;AAAA,EAC3C,QAAQ;AAIP;AAAA,EACD;AAGA,SAAO,uBAAwB,IAAK;AAGpC,SAAO,qBAAsB,IAAK;AAElC,QAAM,QAAQ,yBAA0B,aAAc;AAEtD,MAAK,MAAM,UAAU,CAAE,yBAA0B,OAAO,IAAK,GAAI;AAChE,WAAO,EAAE,MAAM;AAAA,EAChB;AAEA,SAAO,EAAE,MAAM,WAAW,OAAO,CAAC,EAAE;AACrC;AAiBO,SAAS,yBAA0B,OAAO,MAAwB;AAGxE,MACC,QACA,OAAO,WAAW,KAClB,MAAO,CAAE,EAAE,KAAK,QAAS,QAAS,MAAM,GACvC;AAKD,UAAM,YAAY;AAClB,QAAK,KAAK,MAAO,SAAU,GAAG,WAAW,GAAI;AAC5C,aAAO;AAAA,IACR;AAQA,UAAM,qBAAqB;AAC3B,QAAK,KAAK,MAAO,kBAAmB,GAAI;AACvC,aAAO;AAAA,IACR;AAAA,EACD;AAEA,SAAO;AACR;",
6
6
  "names": []
7
7
  }
@@ -116,13 +116,6 @@
116
116
  color: inherit !important;
117
117
  }
118
118
 
119
- .block-editor-autocompleters__link {
120
- white-space: nowrap;
121
- }
122
- .block-editor-autocompleters__link .block-editor-block-icon {
123
- margin-left: 8px;
124
- }
125
-
126
119
  .block-editor-global-styles-background-panel__inspector-media-replace-container {
127
120
  position: relative;
128
121
  }
@@ -116,13 +116,6 @@
116
116
  color: inherit !important;
117
117
  }
118
118
 
119
- .block-editor-autocompleters__link {
120
- white-space: nowrap;
121
- }
122
- .block-editor-autocompleters__link .block-editor-block-icon {
123
- margin-right: 8px;
124
- }
125
-
126
119
  .block-editor-global-styles-background-panel__inspector-media-replace-container {
127
120
  position: relative;
128
121
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/block-editor",
3
- "version": "15.16.0",
3
+ "version": "15.17.0",
4
4
  "description": "Generic block editor.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -61,43 +61,42 @@
61
61
  ],
62
62
  "dependencies": {
63
63
  "@react-spring/web": "^9.4.5",
64
- "@wordpress/a11y": "^4.43.0",
65
- "@wordpress/api-fetch": "^7.43.0",
66
- "@wordpress/base-styles": "^6.19.0",
67
- "@wordpress/blob": "^4.43.0",
68
- "@wordpress/block-serialization-default-parser": "^5.43.0",
69
- "@wordpress/blocks": "^15.16.0",
70
- "@wordpress/commands": "^1.43.0",
71
- "@wordpress/components": "^32.5.0",
72
- "@wordpress/compose": "^7.43.0",
73
- "@wordpress/data": "^10.43.0",
74
- "@wordpress/dataviews": "^14.0.0",
75
- "@wordpress/date": "^5.43.0",
76
- "@wordpress/deprecated": "^4.43.0",
77
- "@wordpress/dom": "^4.43.0",
78
- "@wordpress/element": "^6.43.0",
79
- "@wordpress/escape-html": "^3.43.0",
80
- "@wordpress/global-styles-engine": "^1.10.0",
81
- "@wordpress/hooks": "^4.43.0",
82
- "@wordpress/html-entities": "^4.43.0",
83
- "@wordpress/i18n": "^6.16.0",
84
- "@wordpress/icons": "^12.1.0",
85
- "@wordpress/image-cropper": "^1.7.0",
86
- "@wordpress/interactivity": "^6.43.0",
87
- "@wordpress/is-shallow-equal": "^5.43.0",
88
- "@wordpress/keyboard-shortcuts": "^5.43.0",
89
- "@wordpress/keycodes": "^4.43.0",
90
- "@wordpress/notices": "^5.43.0",
91
- "@wordpress/preferences": "^4.43.0",
92
- "@wordpress/priority-queue": "^3.43.0",
93
- "@wordpress/private-apis": "^1.43.0",
94
- "@wordpress/rich-text": "^7.43.0",
95
- "@wordpress/style-engine": "^2.43.0",
96
- "@wordpress/token-list": "^3.43.0",
97
- "@wordpress/upload-media": "^0.28.0",
98
- "@wordpress/url": "^4.43.0",
99
- "@wordpress/warning": "^3.43.0",
100
- "@wordpress/wordcount": "^4.43.0",
64
+ "@wordpress/a11y": "^4.44.0",
65
+ "@wordpress/base-styles": "^6.20.0",
66
+ "@wordpress/blob": "^4.44.0",
67
+ "@wordpress/block-serialization-default-parser": "^5.44.0",
68
+ "@wordpress/blocks": "^15.17.0",
69
+ "@wordpress/commands": "^1.44.0",
70
+ "@wordpress/components": "^32.6.0",
71
+ "@wordpress/compose": "^7.44.0",
72
+ "@wordpress/data": "^10.44.0",
73
+ "@wordpress/dataviews": "^14.1.0",
74
+ "@wordpress/date": "^5.44.0",
75
+ "@wordpress/deprecated": "^4.44.0",
76
+ "@wordpress/dom": "^4.44.0",
77
+ "@wordpress/element": "^6.44.0",
78
+ "@wordpress/escape-html": "^3.44.0",
79
+ "@wordpress/global-styles-engine": "^1.11.0",
80
+ "@wordpress/hooks": "^4.44.0",
81
+ "@wordpress/html-entities": "^4.44.0",
82
+ "@wordpress/i18n": "^6.17.0",
83
+ "@wordpress/icons": "^12.2.0",
84
+ "@wordpress/image-cropper": "^1.8.0",
85
+ "@wordpress/interactivity": "^6.44.0",
86
+ "@wordpress/is-shallow-equal": "^5.44.0",
87
+ "@wordpress/keyboard-shortcuts": "^5.44.0",
88
+ "@wordpress/keycodes": "^4.44.0",
89
+ "@wordpress/notices": "^5.44.0",
90
+ "@wordpress/preferences": "^4.44.0",
91
+ "@wordpress/priority-queue": "^3.44.0",
92
+ "@wordpress/private-apis": "^1.44.0",
93
+ "@wordpress/rich-text": "^7.44.0",
94
+ "@wordpress/style-engine": "^2.44.0",
95
+ "@wordpress/token-list": "^3.44.0",
96
+ "@wordpress/upload-media": "^0.29.0",
97
+ "@wordpress/url": "^4.44.0",
98
+ "@wordpress/warning": "^3.44.0",
99
+ "@wordpress/wordcount": "^4.44.0",
101
100
  "change-case": "^4.1.2",
102
101
  "clsx": "^2.1.1",
103
102
  "colord": "^2.7.0",
@@ -124,5 +123,5 @@
124
123
  "publishConfig": {
125
124
  "access": "public"
126
125
  },
127
- "gitHead": "2cea90674d11aa521ec3f71652fb3a6a4c383969"
126
+ "gitHead": "b862d8c84121a47bbeff882f6c87e61681ce2e0d"
128
127
  }
@@ -11,11 +11,3 @@
11
11
  color: inherit !important;
12
12
  }
13
13
  }
14
-
15
- .block-editor-autocompleters__link {
16
- white-space: nowrap;
17
-
18
- .block-editor-block-icon {
19
- margin-right: $grid-unit-10;
20
- }
21
- }
@@ -14,7 +14,6 @@ import { getDefaultBlockName, getBlockSupport } from '@wordpress/blocks';
14
14
  */
15
15
  import { useBlockEditContext } from '../block-edit/context';
16
16
  import blockAutocompleter from '../../autocompleters/block';
17
- import linkAutocompleter from '../../autocompleters/link';
18
17
 
19
18
  /**
20
19
  * Shared reference to an empty array for cases where it is important to avoid
@@ -27,7 +26,7 @@ const EMPTY_ARRAY = [];
27
26
  function useCompleters( { completers = EMPTY_ARRAY } ) {
28
27
  const { name } = useBlockEditContext();
29
28
  return useMemo( () => {
30
- let filteredCompleters = [ ...completers, linkAutocompleter ];
29
+ let filteredCompleters = [ ...completers ];
31
30
 
32
31
  if (
33
32
  name === getDefaultBlockName() ||
@@ -175,7 +175,7 @@ export const getDraggableChip = ( { getByTestId } ) => {
175
175
  let draggableChip;
176
176
  try {
177
177
  draggableChip = getByTestId( 'draggable-chip' );
178
- } catch ( e ) {
178
+ } catch {
179
179
  // NOOP.
180
180
  }
181
181
  return draggableChip;
@@ -14,4 +14,6 @@ const warning = (
14
14
  </Warning>
15
15
  );
16
16
 
17
- export default () => warning;
17
+ export default function BlockCrashWarning() {
18
+ return warning;
19
+ }
@@ -16,4 +16,6 @@ const warning = (
16
16
  />
17
17
  );
18
18
 
19
- export default () => warning;
19
+ export default function BlockCrashWarning() {
20
+ return warning;
21
+ }
@@ -6,7 +6,7 @@ import TextareaAutosize from 'react-autosize-textarea';
6
6
  /**
7
7
  * WordPress dependencies
8
8
  */
9
- import { useEffect, useState } from '@wordpress/element';
9
+ import { useEffect, useMemo, useState } from '@wordpress/element';
10
10
  import { useSelect, useDispatch } from '@wordpress/data';
11
11
  import {
12
12
  getBlockAttributes,
@@ -28,6 +28,16 @@ function BlockHTML( { clientId } ) {
28
28
  [ clientId ]
29
29
  );
30
30
  const { updateBlock } = useDispatch( blockEditorStore );
31
+
32
+ // Derive block content as a primitive string so the effect only fires
33
+ // when the serialized content genuinely changes, not when the block
34
+ // object reference changes (which happens on every RESET_BLOCKS during
35
+ // RTC sync, even for unchanged blocks).
36
+ const blockContent = useMemo(
37
+ () => ( block ? getBlockContent( block ) : '' ),
38
+ [ block ]
39
+ );
40
+
31
41
  const onChange = () => {
32
42
  const blockType = getBlockType( block.name );
33
43
 
@@ -64,8 +74,8 @@ function BlockHTML( { clientId } ) {
64
74
  };
65
75
 
66
76
  useEffect( () => {
67
- setHtml( getBlockContent( block ) );
68
- }, [ block ] );
77
+ setHtml( blockContent );
78
+ }, [ blockContent ] );
69
79
 
70
80
  return (
71
81
  <TextareaAutosize
@@ -12,6 +12,7 @@ import { useInstanceId } from '@wordpress/compose';
12
12
  import { useSelect, useDispatch } from '@wordpress/data';
13
13
  import { forwardRef } from '@wordpress/element';
14
14
  import { __, isRTL } from '@wordpress/i18n';
15
+ import { displayShortcut } from '@wordpress/keycodes';
15
16
 
16
17
  /**
17
18
  * Internal dependencies
@@ -65,7 +66,6 @@ const BlockMoverButton = forwardRef(
65
66
  ? clientIds
66
67
  : [ clientIds ];
67
68
  const blocksCount = normalizedClientIds.length;
68
- const { disabled } = props;
69
69
 
70
70
  const {
71
71
  blockType,
@@ -99,9 +99,7 @@ const BlockMoverButton = forwardRef(
99
99
 
100
100
  return {
101
101
  blockType: block ? getBlockType( block.name ) : null,
102
- isDisabled:
103
- disabled ||
104
- ( direction === 'up' ? isFirstBlock : isLastBlock ),
102
+ isDisabled: direction === 'up' ? isFirstBlock : isLastBlock,
105
103
  rootClientId: blockRootClientId,
106
104
  firstIndex: firstBlockIndex,
107
105
  isFirst: isFirstBlock,
@@ -145,6 +143,11 @@ const BlockMoverButton = forwardRef(
145
143
  onClick={ isDisabled ? null : onClick }
146
144
  disabled={ isDisabled }
147
145
  accessibleWhenDisabled
146
+ shortcut={
147
+ direction === 'up'
148
+ ? displayShortcut.secondary( 't' )
149
+ : displayShortcut.secondary( 'y' )
150
+ }
148
151
  />
149
152
  <VisuallyHidden id={ descriptionId }>
150
153
  { getBlockMoverDescription(
@@ -19,12 +19,7 @@ import BlockDraggable from '../block-draggable';
19
19
  import { BlockMoverUpButton, BlockMoverDownButton } from './button';
20
20
  import { store as blockEditorStore } from '../../store';
21
21
 
22
- function BlockMover( {
23
- clientIds,
24
- hideDragHandle,
25
- isBlockMoverUpButtonDisabled,
26
- isBlockMoverDownButtonDisabled,
27
- } ) {
22
+ function BlockMover( { clientIds, hideDragHandle } ) {
28
23
  const {
29
24
  canMove,
30
25
  rootClientId,
@@ -104,7 +99,6 @@ function BlockMover( {
104
99
  <ToolbarItem>
105
100
  { ( itemProps ) => (
106
101
  <BlockMoverUpButton
107
- disabled={ isBlockMoverUpButtonDisabled }
108
102
  clientIds={ clientIds }
109
103
  { ...itemProps }
110
104
  />
@@ -113,7 +107,6 @@ function BlockMover( {
113
107
  <ToolbarItem>
114
108
  { ( itemProps ) => (
115
109
  <BlockMoverDownButton
116
- disabled={ isBlockMoverDownButtonDisabled }
117
110
  clientIds={ clientIds }
118
111
  { ...itemProps }
119
112
  />
@@ -17,6 +17,7 @@ export const __unstableUseClipboardHandler = () => {
17
17
  since: '6.4',
18
18
  version: '6.7',
19
19
  } );
20
+ // eslint-disable-next-line react-hooks/rules-of-hooks
20
21
  return useClipboardHandler();
21
22
  };
22
23
 
@@ -21,7 +21,7 @@ export function getCompatibilityStyles() {
21
21
  // May fail for external styles.
22
22
  // eslint-disable-next-line no-unused-expressions
23
23
  styleSheet.cssRules;
24
- } catch ( e ) {
24
+ } catch {
25
25
  return accumulator;
26
26
  }
27
27
 
@@ -100,7 +100,7 @@ export function useMediaCategories( rootClientId ) {
100
100
  results = await category.fetch( {
101
101
  per_page: 1,
102
102
  } );
103
- } catch ( e ) {
103
+ } catch {
104
104
  // If the request fails, we shallow the error and just don't show
105
105
  // the category, in order to not break the media tab.
106
106
  }
@@ -275,14 +275,14 @@ If passed, children are rendered after the input.
275
275
 
276
276
  ```jsx
277
277
  <LinkControlSearchInput>
278
- <HStack justify="right">
278
+ <Stack justify="flex-end">
279
279
  <Button
280
280
  type="submit"
281
281
  label={ __( 'Submit' ) }
282
282
  icon={ keyboardReturn }
283
283
  className="block-editor-link-control__search-submit"
284
284
  />
285
- </HStack>
285
+ </Stack>
286
286
  </LinkControlSearchInput>
287
287
  ```
288
288
 
@@ -70,7 +70,9 @@ export default function LinkPreview( {
70
70
 
71
71
  const displayTitle =
72
72
  ! isEmptyURL &&
73
- stripHTML( richData?.title || value?.title || displayURL );
73
+ stripHTML(
74
+ value?.entityTitle || richData?.title || value?.title || displayURL
75
+ );
74
76
 
75
77
  let icon;
76
78
 
@@ -99,7 +99,7 @@ const LinkControlSearchInput = forwardRef(
99
99
  if ( suggestion?.url ) {
100
100
  onSelect( suggestion );
101
101
  }
102
- } catch ( e ) {}
102
+ } catch {}
103
103
  return;
104
104
  }
105
105
 
@@ -9,6 +9,7 @@ import {
9
9
  privateApis as componentsPrivateApis,
10
10
  } from '@wordpress/components';
11
11
  import { Icon, chevronDown } from '@wordpress/icons';
12
+ import { __unstableStripHTML as stripHTML } from '@wordpress/dom';
12
13
 
13
14
  /**
14
15
  * Internal dependencies
@@ -50,7 +51,7 @@ export function LinkPreview( { title, url, image, badges } ) {
50
51
  numberOfLines={ 1 }
51
52
  className="link-preview-button__title"
52
53
  >
53
- { title }
54
+ { stripHTML( title ) }
54
55
  </Truncate>
55
56
  { url && (
56
57
  <Truncate
@@ -168,12 +168,18 @@ export default function PresetInputControl( {
168
168
  unitConfig?.max ?? customValueSettings[ computedUnit ]?.max ?? 10;
169
169
 
170
170
  const handleCustomValueChange = ( newValue ) => {
171
- const isNumeric = ! isNaN( parseFloat( newValue ) );
172
- const newCustomValue = isNumeric ? newValue : undefined;
171
+ // Treat empty or undefined as an explicit clear and propagate undefined.
172
+ if ( newValue === undefined || newValue === '' ) {
173
+ onChange( undefined );
174
+ return;
175
+ }
173
176
 
174
- if ( newCustomValue !== undefined ) {
175
- onChange( newCustomValue );
177
+ // Ignore non-numeric intermediate input (e.g. just a unit).
178
+ if ( isNaN( parseFloat( newValue ) ) ) {
179
+ return;
176
180
  }
181
+
182
+ onChange( newValue );
177
183
  };
178
184
  const handleCustomValueSliderChange = ( next ) => {
179
185
  onChange( [ next, computedUnit ].join( '' ) );
@@ -92,6 +92,76 @@ describe( 'PresetInputControl', () => {
92
92
  expect( mockOnChange ).toHaveBeenCalledWith( '25px' );
93
93
  } );
94
94
 
95
+ it( 'clears value with undefined when input is fully erased via backspace', () => {
96
+ render(
97
+ <PresetInputControl
98
+ { ...defaultProps }
99
+ presets={ presets }
100
+ value="60px"
101
+ disableCustomValues={ false }
102
+ />
103
+ );
104
+
105
+ const input = screen.getByRole( 'spinbutton' );
106
+
107
+ // Simulate the bug scenario: backspace through "60" one character
108
+ // at a time. fireEvent.change is used here (rather than userEvent
109
+ // keyboard interactions) because the controlled UnitControl input
110
+ // does not respond to synthesised key events in jsdom. The
111
+ // intermediate "6" forwarding is expected and correct; the bug
112
+ // was that the final clear silently failed to propagate, leaving
113
+ // the parent stuck on the partial value.
114
+ fireEvent.change( input, { target: { value: '6' } } );
115
+ fireEvent.change( input, { target: { value: '' } } );
116
+
117
+ // The final clear must propagate as undefined, not be swallowed,
118
+ // and never be persisted as an empty string.
119
+ expect( mockOnChange ).toHaveBeenLastCalledWith( undefined );
120
+ expect( mockOnChange ).not.toHaveBeenCalledWith( '' );
121
+ } );
122
+
123
+ it( 'clears value with undefined when input is cleared in one shot', async () => {
124
+ const user = userEvent.setup();
125
+
126
+ render(
127
+ <PresetInputControl
128
+ { ...defaultProps }
129
+ presets={ presets }
130
+ value="25px"
131
+ disableCustomValues={ false }
132
+ />
133
+ );
134
+
135
+ const input = screen.getByRole( 'spinbutton' );
136
+ await user.clear( input );
137
+
138
+ expect( mockOnChange ).toHaveBeenCalledWith( undefined );
139
+ expect( mockOnChange ).not.toHaveBeenCalledWith( '' );
140
+ } );
141
+
142
+ it( 'does not call onChange for non-numeric intermediate input', async () => {
143
+ const user = userEvent.setup();
144
+
145
+ render(
146
+ <PresetInputControl
147
+ { ...defaultProps }
148
+ presets={ presets }
149
+ value="15px"
150
+ disableCustomValues={ false }
151
+ />
152
+ );
153
+
154
+ const input = screen.getByRole( 'spinbutton' );
155
+ await user.clear( input );
156
+ mockOnChange.mockClear();
157
+
158
+ // Typing a stray non-numeric character should not propagate a change.
159
+ await user.type( input, 'a' );
160
+
161
+ expect( mockOnChange ).not.toHaveBeenCalledWith( 'a' );
162
+ expect( mockOnChange ).not.toHaveBeenCalledWith( 'apx' );
163
+ } );
164
+
95
165
  it( 'uses select dropdown for many presets', async () => {
96
166
  const manyPresets = Array.from( { length: 12 }, ( _, i ) => ( {
97
167
  name: `Preset ${ i + 1 }`,
@@ -36,6 +36,7 @@ const allEventListeners = [
36
36
  export function useEventListeners( props ) {
37
37
  const propsRef = useRef( props );
38
38
  useInsertionEffect( () => {
39
+ // eslint-disable-next-line react-compiler/react-compiler -- false positive, see https://github.com/facebook/react/issues/29196
39
40
  propsRef.current = props;
40
41
  } );
41
42
  const refEffects = useMemo(
@@ -555,4 +555,4 @@ PublicForwardedRichTextContainer.isEmpty = ( value ) => {
555
555
  export default PublicForwardedRichTextContainer;
556
556
  export { RichTextShortcut } from './shortcut';
557
557
  export { RichTextToolbarButton } from './toolbar-button';
558
- export { __unstableRichTextInputEvent } from './input-event';
558
+ export { RichTextInputEvent as __unstableRichTextInputEvent } from './input-event';
@@ -698,4 +698,4 @@ PrivateRichText.Raw = forwardRef( ( props, ref ) => (
698
698
  export default PrivateRichText;
699
699
  export { RichTextShortcut } from './shortcut';
700
700
  export { RichTextToolbarButton } from './toolbar-button';
701
- export { __unstableRichTextInputEvent } from './input-event';
701
+ export { RichTextInputEvent as __unstableRichTextInputEvent } from './input-event';
@@ -8,7 +8,7 @@ import { useEffect, useContext, useRef } from '@wordpress/element';
8
8
  */
9
9
  import { inputEventContext } from './';
10
10
 
11
- export function __unstableRichTextInputEvent( { inputType, onInput } ) {
11
+ export function RichTextInputEvent( { inputType, onInput } ) {
12
12
  const callbacks = useContext( inputEventContext );
13
13
  const onInputRef = useRef();
14
14
  onInputRef.current = onInput;
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import { Component } from '@wordpress/element';
5
5
 
6
- export class __unstableRichTextInputEvent extends Component {
6
+ export class RichTextInputEvent extends Component {
7
7
  render() {
8
8
  return null;
9
9
  }