@wordpress/block-library 9.44.0 → 9.45.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 (367) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/accordion/edit.cjs +0 -2
  3. package/build/accordion/edit.cjs.map +2 -2
  4. package/build/accordion-item/block.json +1 -0
  5. package/build/button/constants.cjs +1 -1
  6. package/build/button/constants.cjs.map +1 -1
  7. package/build/categories/edit.cjs +5 -1
  8. package/build/categories/edit.cjs.map +2 -2
  9. package/build/embed/edit.cjs +38 -34
  10. package/build/embed/edit.cjs.map +3 -3
  11. package/build/embed/transforms.cjs +3 -1
  12. package/build/embed/transforms.cjs.map +2 -2
  13. package/build/embed/util.cjs +13 -2
  14. package/build/embed/util.cjs.map +2 -2
  15. package/build/form/block.json +1 -1
  16. package/build/form-input/block.json +1 -1
  17. package/build/form-submission-notification/block.json +1 -1
  18. package/build/form-submit-button/block.json +1 -1
  19. package/build/group/block.json +2 -1
  20. package/build/image/constants.cjs +1 -1
  21. package/build/image/constants.cjs.map +2 -2
  22. package/build/image/edit.cjs +2 -4
  23. package/build/image/edit.cjs.map +2 -2
  24. package/build/image/image.cjs +49 -19
  25. package/build/image/image.cjs.map +3 -3
  26. package/build/index.cjs +4 -4
  27. package/build/index.cjs.map +2 -2
  28. package/build/latest-posts/edit.cjs +1 -1
  29. package/build/latest-posts/edit.cjs.map +1 -1
  30. package/build/math/edit.cjs +2 -2
  31. package/build/math/edit.cjs.map +2 -2
  32. package/build/navigation/edit/accessible-description.cjs +2 -2
  33. package/build/navigation/edit/accessible-description.cjs.map +2 -2
  34. package/build/navigation/edit/overlay-template-part-selector.cjs.map +2 -2
  35. package/build/navigation-link/edit.cjs +2 -1
  36. package/build/navigation-link/edit.cjs.map +2 -2
  37. package/build/navigation-link/link-ui/dialog-wrapper.cjs +2 -1
  38. package/build/navigation-link/link-ui/dialog-wrapper.cjs.map +2 -2
  39. package/build/navigation-link/link-ui/index.cjs +2 -1
  40. package/build/navigation-link/link-ui/index.cjs.map +2 -2
  41. package/build/paragraph/use-enter.cjs +12 -23
  42. package/build/paragraph/use-enter.cjs.map +2 -2
  43. package/build/post-author/edit.cjs.map +3 -3
  44. package/build/post-comments-form/edit.cjs +2 -2
  45. package/build/post-comments-form/edit.cjs.map +2 -2
  46. package/build/post-featured-image/edit.cjs +2 -5
  47. package/build/post-featured-image/edit.cjs.map +2 -2
  48. package/build/post-template/edit.cjs +8 -2
  49. package/build/post-template/edit.cjs.map +2 -2
  50. package/build/pullquote/block.json +1 -4
  51. package/build/query/edit/inspector-controls/author-control.cjs +1 -1
  52. package/build/query/edit/inspector-controls/author-control.cjs.map +2 -2
  53. package/build/query/edit/inspector-controls/format-controls.cjs +1 -1
  54. package/build/query/edit/inspector-controls/format-controls.cjs.map +2 -2
  55. package/build/query/edit/inspector-controls/parent-control.cjs +1 -1
  56. package/build/query/edit/inspector-controls/parent-control.cjs.map +2 -2
  57. package/build/query/edit/inspector-controls/taxonomy-controls.cjs +1 -1
  58. package/build/query/edit/inspector-controls/taxonomy-controls.cjs.map +2 -2
  59. package/build/site-logo/edit.cjs +34 -20
  60. package/build/site-logo/edit.cjs.map +2 -2
  61. package/build/tab/block.json +23 -23
  62. package/build/tab/controls.cjs +5 -48
  63. package/build/tab/controls.cjs.map +3 -3
  64. package/build/tab/edit.cjs +76 -92
  65. package/build/tab/edit.cjs.map +3 -3
  66. package/build/tab/save.cjs +3 -3
  67. package/build/tab/save.cjs.map +2 -2
  68. package/{src/tabs-menu → build/tab-list}/block.json +4 -4
  69. package/build/{tabs-menu → tab-list}/edit.cjs +9 -14
  70. package/build/tab-list/edit.cjs.map +7 -0
  71. package/build/{tabs-menu → tab-list}/index.cjs +5 -5
  72. package/build/tab-list/index.cjs.map +7 -0
  73. package/build/{tabs-menu → tab-list}/save.cjs +1 -1
  74. package/build/{tabs-menu → tab-list}/save.cjs.map +1 -1
  75. package/build/{tab → tab-panel}/add-tab-toolbar-control.cjs +16 -16
  76. package/build/tab-panel/add-tab-toolbar-control.cjs.map +7 -0
  77. package/build/tab-panel/block.json +27 -37
  78. package/build/tab-panel/controls.cjs +89 -0
  79. package/build/tab-panel/controls.cjs.map +7 -0
  80. package/build/tab-panel/edit.cjs +88 -18
  81. package/build/tab-panel/edit.cjs.map +3 -3
  82. package/build/tab-panel/index.cjs +1 -1
  83. package/build/tab-panel/index.cjs.map +1 -1
  84. package/build/{tab → tab-panel}/init.cjs +1 -1
  85. package/build/{tab → tab-panel}/init.cjs.map +1 -1
  86. package/build/{tab → tab-panel}/remove-tab-toolbar-control.cjs +16 -16
  87. package/build/tab-panel/remove-tab-toolbar-control.cjs.map +7 -0
  88. package/build/tab-panel/save.cjs +4 -2
  89. package/build/tab-panel/save.cjs.map +2 -2
  90. package/build/tab-panels/block.json +66 -0
  91. package/build/{tabs-menu-item/controls.cjs → tab-panels/edit.cjs} +25 -11
  92. package/build/tab-panels/edit.cjs.map +7 -0
  93. package/build/{tabs-menu-item → tab-panels}/index.cjs +5 -5
  94. package/build/{tabs-menu → tab-panels}/index.cjs.map +2 -2
  95. package/build/{tabs-menu-item → tab-panels}/save.cjs +4 -6
  96. package/build/tab-panels/save.cjs.map +7 -0
  97. package/build/tabs/block.json +1 -2
  98. package/build/tabs/controls.cjs +2 -2
  99. package/build/tabs/controls.cjs.map +1 -1
  100. package/build/tabs/edit.cjs +29 -100
  101. package/build/tabs/edit.cjs.map +3 -3
  102. package/build/tabs/index.cjs +5 -5
  103. package/build/tabs/index.cjs.map +1 -1
  104. package/build/tabs/use-tab-list-sync.cjs +190 -0
  105. package/build/tabs/use-tab-list-sync.cjs.map +7 -0
  106. package/build/terms-query/edit/inspector-controls/include-control.cjs +1 -1
  107. package/build/terms-query/edit/inspector-controls/include-control.cjs.map +2 -2
  108. package/build/video/tracks-editor.cjs +2 -2
  109. package/build/video/tracks-editor.cjs.map +2 -2
  110. package/build-module/accordion/edit.mjs +0 -2
  111. package/build-module/accordion/edit.mjs.map +2 -2
  112. package/build-module/accordion-item/block.json +1 -0
  113. package/build-module/button/constants.mjs +1 -1
  114. package/build-module/button/constants.mjs.map +1 -1
  115. package/build-module/categories/edit.mjs +5 -2
  116. package/build-module/categories/edit.mjs.map +2 -2
  117. package/build-module/embed/edit.mjs +45 -36
  118. package/build-module/embed/edit.mjs.map +2 -2
  119. package/build-module/embed/transforms.mjs +8 -2
  120. package/build-module/embed/transforms.mjs.map +2 -2
  121. package/build-module/embed/util.mjs +11 -1
  122. package/build-module/embed/util.mjs.map +2 -2
  123. package/build-module/form/block.json +1 -1
  124. package/build-module/form-input/block.json +1 -1
  125. package/build-module/form-submission-notification/block.json +1 -1
  126. package/build-module/form-submit-button/block.json +1 -1
  127. package/build-module/group/block.json +2 -1
  128. package/build-module/image/constants.mjs +1 -1
  129. package/build-module/image/constants.mjs.map +2 -2
  130. package/build-module/image/edit.mjs +2 -4
  131. package/build-module/image/edit.mjs.map +2 -2
  132. package/build-module/image/image.mjs +49 -19
  133. package/build-module/image/image.mjs.map +3 -3
  134. package/build-module/index.mjs +4 -4
  135. package/build-module/index.mjs.map +2 -2
  136. package/build-module/latest-posts/edit.mjs +1 -1
  137. package/build-module/latest-posts/edit.mjs.map +1 -1
  138. package/build-module/math/edit.mjs +2 -2
  139. package/build-module/math/edit.mjs.map +2 -2
  140. package/build-module/navigation/edit/accessible-description.mjs +1 -1
  141. package/build-module/navigation/edit/accessible-description.mjs.map +1 -1
  142. package/build-module/navigation/edit/overlay-template-part-selector.mjs +2 -2
  143. package/build-module/navigation/edit/overlay-template-part-selector.mjs.map +1 -1
  144. package/build-module/navigation-link/edit.mjs +2 -5
  145. package/build-module/navigation-link/edit.mjs.map +2 -2
  146. package/build-module/navigation-link/link-ui/dialog-wrapper.mjs +2 -1
  147. package/build-module/navigation-link/link-ui/dialog-wrapper.mjs.map +2 -2
  148. package/build-module/navigation-link/link-ui/index.mjs +1 -1
  149. package/build-module/navigation-link/link-ui/index.mjs.map +2 -2
  150. package/build-module/paragraph/use-enter.mjs +13 -23
  151. package/build-module/paragraph/use-enter.mjs.map +2 -2
  152. package/build-module/post-author/edit.mjs +2 -2
  153. package/build-module/post-author/edit.mjs.map +2 -2
  154. package/build-module/post-comments-form/edit.mjs +1 -1
  155. package/build-module/post-comments-form/edit.mjs.map +2 -2
  156. package/build-module/post-featured-image/edit.mjs +2 -5
  157. package/build-module/post-featured-image/edit.mjs.map +2 -2
  158. package/build-module/post-template/edit.mjs +8 -2
  159. package/build-module/post-template/edit.mjs.map +2 -2
  160. package/build-module/pullquote/block.json +1 -4
  161. package/build-module/query/edit/inspector-controls/author-control.mjs +1 -1
  162. package/build-module/query/edit/inspector-controls/author-control.mjs.map +2 -2
  163. package/build-module/query/edit/inspector-controls/format-controls.mjs +1 -1
  164. package/build-module/query/edit/inspector-controls/format-controls.mjs.map +2 -2
  165. package/build-module/query/edit/inspector-controls/parent-control.mjs +1 -1
  166. package/build-module/query/edit/inspector-controls/parent-control.mjs.map +2 -2
  167. package/build-module/query/edit/inspector-controls/taxonomy-controls.mjs +1 -1
  168. package/build-module/query/edit/inspector-controls/taxonomy-controls.mjs.map +2 -2
  169. package/build-module/site-logo/edit.mjs +34 -20
  170. package/build-module/site-logo/edit.mjs.map +2 -2
  171. package/build-module/tab/block.json +23 -23
  172. package/build-module/tab/controls.mjs +7 -57
  173. package/build-module/tab/controls.mjs.map +2 -2
  174. package/build-module/tab/edit.mjs +80 -96
  175. package/build-module/tab/edit.mjs.map +3 -3
  176. package/build-module/tab/save.mjs +4 -4
  177. package/build-module/tab/save.mjs.map +2 -2
  178. package/build-module/{tabs-menu → tab-list}/block.json +4 -4
  179. package/build-module/{tabs-menu → tab-list}/edit.mjs +9 -14
  180. package/build-module/tab-list/edit.mjs.map +7 -0
  181. package/build-module/{tabs-menu → tab-list}/index.mjs +2 -2
  182. package/build-module/tab-list/index.mjs.map +7 -0
  183. package/build-module/{tabs-menu → tab-list}/save.mjs +1 -1
  184. package/build-module/{tabs-menu → tab-list}/save.mjs.map +1 -1
  185. package/build-module/{tab → tab-panel}/add-tab-toolbar-control.mjs +16 -16
  186. package/build-module/tab-panel/add-tab-toolbar-control.mjs.map +7 -0
  187. package/build-module/tab-panel/block.json +27 -37
  188. package/build-module/tab-panel/controls.mjs +65 -0
  189. package/build-module/tab-panel/controls.mjs.map +7 -0
  190. package/build-module/tab-panel/edit.mjs +90 -20
  191. package/build-module/tab-panel/edit.mjs.map +2 -2
  192. package/build-module/tab-panel/index.mjs +1 -1
  193. package/build-module/tab-panel/index.mjs.map +1 -1
  194. package/build-module/{tab → tab-panel}/init.mjs +1 -1
  195. package/build-module/{tab → tab-panel}/init.mjs.map +1 -1
  196. package/build-module/{tab → tab-panel}/remove-tab-toolbar-control.mjs +16 -16
  197. package/build-module/tab-panel/remove-tab-toolbar-control.mjs.map +7 -0
  198. package/build-module/tab-panel/save.mjs +4 -2
  199. package/build-module/tab-panel/save.mjs.map +2 -2
  200. package/build-module/tab-panels/block.json +66 -0
  201. package/build-module/tab-panels/edit.mjs +33 -0
  202. package/build-module/tab-panels/edit.mjs.map +7 -0
  203. package/build-module/{tabs-menu-item → tab-panels}/index.mjs +2 -2
  204. package/build-module/{tabs-menu → tab-panels}/index.mjs.map +2 -2
  205. package/build-module/tab-panels/save.mjs +12 -0
  206. package/build-module/tab-panels/save.mjs.map +7 -0
  207. package/build-module/tabs/block.json +1 -2
  208. package/build-module/tabs/controls.mjs +2 -2
  209. package/build-module/tabs/controls.mjs.map +1 -1
  210. package/build-module/tabs/edit.mjs +31 -102
  211. package/build-module/tabs/edit.mjs.map +2 -2
  212. package/build-module/tabs/index.mjs +5 -5
  213. package/build-module/tabs/index.mjs.map +1 -1
  214. package/build-module/tabs/use-tab-list-sync.mjs +169 -0
  215. package/build-module/tabs/use-tab-list-sync.mjs.map +7 -0
  216. package/build-module/terms-query/edit/inspector-controls/include-control.mjs +1 -1
  217. package/build-module/terms-query/edit/inspector-controls/include-control.mjs.map +2 -2
  218. package/build-module/video/tracks-editor.mjs +2 -2
  219. package/build-module/video/tracks-editor.mjs.map +2 -2
  220. package/build-style/classic-rtl.css +14 -0
  221. package/build-style/classic.css +14 -0
  222. package/build-style/editor-rtl.css +9 -5
  223. package/build-style/editor.css +9 -5
  224. package/build-style/latest-comments/style-rtl.css +4 -4
  225. package/build-style/latest-comments/style.css +4 -4
  226. package/build-style/post-template/style-rtl.css +1 -1
  227. package/build-style/post-template/style.css +1 -1
  228. package/build-style/style-rtl.css +45 -48
  229. package/build-style/style.css +45 -48
  230. package/build-style/tab/editor-rtl.css +11 -0
  231. package/build-style/tab/editor.css +11 -0
  232. package/build-style/tab/style-rtl.css +29 -16
  233. package/build-style/tab/style.css +29 -16
  234. package/build-style/tab-list/editor-rtl.css +6 -0
  235. package/build-style/tab-list/editor.css +6 -0
  236. package/build-style/tab-panel/style-rtl.css +17 -1
  237. package/build-style/tab-panel/style.css +17 -1
  238. package/build-style/tab-panels/style-rtl.css +4 -0
  239. package/build-style/tab-panels/style.css +4 -0
  240. package/build-style/tabs/style-rtl.css +0 -3
  241. package/build-style/tabs/style.css +0 -3
  242. package/build-style/video/editor-rtl.css +4 -0
  243. package/build-style/video/editor.css +4 -0
  244. package/package.json +39 -38
  245. package/src/accordion/edit.js +0 -2
  246. package/src/accordion-item/block.json +1 -0
  247. package/src/block/test/edit.native.js +1 -1
  248. package/src/button/constants.js +1 -1
  249. package/src/button/test/get-updated-link-attributes.js +6 -10
  250. package/src/categories/edit.js +3 -2
  251. package/src/classic.scss +25 -0
  252. package/src/editor.scss +2 -2
  253. package/src/embed/edit.js +61 -52
  254. package/src/embed/edit.native.js +71 -57
  255. package/src/embed/transforms.js +8 -2
  256. package/src/embed/util.js +17 -0
  257. package/src/form/block.json +1 -1
  258. package/src/form-input/block.json +1 -1
  259. package/src/form-submission-notification/block.json +1 -1
  260. package/src/form-submit-button/block.json +1 -1
  261. package/src/group/block.json +2 -1
  262. package/src/image/constants.js +1 -1
  263. package/src/image/edit.js +5 -3
  264. package/src/image/edit.native.js +3 -3
  265. package/src/image/image.js +63 -27
  266. package/src/image/test/edit.native.js +2 -2
  267. package/src/index.js +4 -4
  268. package/src/latest-comments/style.scss +7 -7
  269. package/src/latest-posts/edit.js +1 -1
  270. package/src/latest-posts/index.php +1 -1
  271. package/src/math/edit.js +3 -3
  272. package/src/navigation/edit/accessible-description.js +1 -1
  273. package/src/navigation/edit/overlay-template-part-selector.js +3 -3
  274. package/src/navigation/edit/test/overlay-template-part-selector.js +1 -0
  275. package/src/navigation-link/edit.js +2 -5
  276. package/src/navigation-link/link-ui/dialog-wrapper.js +2 -1
  277. package/src/navigation-link/link-ui/index.js +1 -1
  278. package/src/paragraph/use-enter.js +18 -24
  279. package/src/post-author/edit.js +3 -5
  280. package/src/post-comments-form/edit.js +1 -1
  281. package/src/post-featured-image/edit.js +2 -9
  282. package/src/post-template/edit.js +7 -1
  283. package/src/post-template/index.php +3 -0
  284. package/src/post-template/style.scss +2 -2
  285. package/src/pullquote/block.json +1 -4
  286. package/src/query/edit/inspector-controls/author-control.js +1 -1
  287. package/src/query/edit/inspector-controls/format-controls.js +1 -1
  288. package/src/query/edit/inspector-controls/parent-control.js +1 -1
  289. package/src/query/edit/inspector-controls/taxonomy-controls.js +1 -1
  290. package/src/site-logo/edit.js +40 -20
  291. package/src/style.scss +1 -1
  292. package/src/tab/block.json +23 -23
  293. package/src/tab/controls.js +6 -52
  294. package/src/tab/edit.js +94 -123
  295. package/src/{tabs-menu-item → tab}/editor.scss +3 -3
  296. package/src/tab/index.php +32 -51
  297. package/src/tab/save.js +4 -4
  298. package/src/tab/style.scss +34 -17
  299. package/{build/tabs-menu → src/tab-list}/block.json +4 -4
  300. package/src/{tabs-menu → tab-list}/edit.js +9 -18
  301. package/src/{tabs-menu → tab-list}/editor.scss +2 -2
  302. package/src/{tabs-menu → tab-list}/index.js +1 -1
  303. package/src/tab-list/index.php +80 -0
  304. package/src/{tab → tab-panel}/add-tab-toolbar-control.js +19 -19
  305. package/src/tab-panel/block.json +27 -37
  306. package/src/tab-panel/controls.js +65 -0
  307. package/src/tab-panel/edit.js +121 -20
  308. package/src/tab-panel/index.js +1 -1
  309. package/src/tab-panel/index.php +88 -0
  310. package/src/{tab → tab-panel}/remove-tab-toolbar-control.js +20 -19
  311. package/src/tab-panel/save.js +4 -2
  312. package/src/tab-panel/style.scss +20 -1
  313. package/src/tab-panels/block.json +66 -0
  314. package/src/tab-panels/edit.js +42 -0
  315. package/src/{tabs-menu-item → tab-panels}/index.js +1 -1
  316. package/src/tab-panels/save.js +11 -0
  317. package/src/tab-panels/style.scss +4 -0
  318. package/src/tabs/block.json +1 -2
  319. package/src/tabs/controls.js +2 -2
  320. package/src/tabs/edit.js +32 -150
  321. package/src/tabs/index.js +5 -5
  322. package/src/tabs/index.php +5 -5
  323. package/src/tabs/style.scss +0 -3
  324. package/src/tabs/use-tab-list-sync.js +237 -0
  325. package/src/terms-query/edit/inspector-controls/include-control.js +1 -1
  326. package/src/video/editor.scss +5 -0
  327. package/src/video/tracks-editor.js +2 -2
  328. package/build/tab/add-tab-toolbar-control.cjs.map +0 -7
  329. package/build/tab/remove-tab-toolbar-control.cjs.map +0 -7
  330. package/build/tab/slug-from-label.cjs +0 -37
  331. package/build/tab/slug-from-label.cjs.map +0 -7
  332. package/build/tabs-menu/edit.cjs.map +0 -7
  333. package/build/tabs-menu-item/block.json +0 -59
  334. package/build/tabs-menu-item/controls.cjs.map +0 -7
  335. package/build/tabs-menu-item/edit.cjs +0 -144
  336. package/build/tabs-menu-item/edit.cjs.map +0 -7
  337. package/build/tabs-menu-item/index.cjs.map +0 -7
  338. package/build/tabs-menu-item/save.cjs.map +0 -7
  339. package/build-module/tab/add-tab-toolbar-control.mjs.map +0 -7
  340. package/build-module/tab/remove-tab-toolbar-control.mjs.map +0 -7
  341. package/build-module/tab/slug-from-label.mjs +0 -16
  342. package/build-module/tab/slug-from-label.mjs.map +0 -7
  343. package/build-module/tabs-menu/edit.mjs.map +0 -7
  344. package/build-module/tabs-menu-item/block.json +0 -59
  345. package/build-module/tabs-menu-item/controls.mjs +0 -15
  346. package/build-module/tabs-menu-item/controls.mjs.map +0 -7
  347. package/build-module/tabs-menu-item/edit.mjs +0 -117
  348. package/build-module/tabs-menu-item/edit.mjs.map +0 -7
  349. package/build-module/tabs-menu-item/index.mjs.map +0 -7
  350. package/build-module/tabs-menu-item/save.mjs +0 -14
  351. package/build-module/tabs-menu-item/save.mjs.map +0 -7
  352. package/build-style/tabs-menu/editor-rtl.css +0 -6
  353. package/build-style/tabs-menu/editor.css +0 -6
  354. package/build-style/tabs-menu-item/editor-rtl.css +0 -11
  355. package/build-style/tabs-menu-item/editor.css +0 -11
  356. package/build-style/tabs-menu-item/style-rtl.css +0 -33
  357. package/build-style/tabs-menu-item/style.css +0 -33
  358. package/src/tab/slug-from-label.js +0 -26
  359. package/src/tabs-menu/index.php +0 -80
  360. package/src/tabs-menu-item/block.json +0 -59
  361. package/src/tabs-menu-item/controls.js +0 -19
  362. package/src/tabs-menu-item/edit.js +0 -150
  363. package/src/tabs-menu-item/index.php +0 -70
  364. package/src/tabs-menu-item/save.js +0 -13
  365. package/src/tabs-menu-item/style.scss +0 -40
  366. /package/src/{tabs-menu → tab-list}/save.js +0 -0
  367. /package/src/{tab → tab-panel}/init.js +0 -0
package/src/tab/edit.js CHANGED
@@ -9,162 +9,133 @@ import clsx from 'clsx';
9
9
  import { __ } from '@wordpress/i18n';
10
10
  import {
11
11
  useBlockProps,
12
- useInnerBlocksProps,
13
12
  store as blockEditorStore,
13
+ RichText,
14
14
  } from '@wordpress/block-editor';
15
15
  import { useSelect, useDispatch } from '@wordpress/data';
16
- import { useMemo, useRef, useEffect } from '@wordpress/element';
16
+ import { useMemo, useCallback } from '@wordpress/element';
17
17
 
18
18
  /**
19
19
  * Internal dependencies
20
20
  */
21
21
  import Controls from './controls';
22
- import slugFromLabel from './slug-from-label';
23
22
 
24
- const TEMPLATE = [
25
- [
26
- 'core/paragraph',
27
- {
28
- placeholder: __( 'Type / to choose a block' ),
29
- },
30
- ],
31
- ];
32
-
33
- const { cancelAnimationFrame } = window;
34
-
35
- export default function Edit( {
36
- attributes,
37
- clientId,
38
- context,
39
- isSelected,
40
- __unstableLayoutClassNames: layoutClassNames,
41
- } ) {
42
- const focusRef = useRef();
23
+ const EMPTY_ARRAY = [];
43
24
 
44
- const { anchor, label } = attributes;
45
-
46
- // Consume tab indices from context
47
- const activeTabIndex = context[ 'core/tabs-activeTabIndex' ] ?? 0;
25
+ function Edit( { context, clientId } ) {
26
+ const tabsList = context[ 'core/tabs-list' ] || EMPTY_ARRAY;
27
+ const activeTabIndex = context[ 'core/tabs-activeTabIndex' ];
48
28
  const editorActiveTabIndex = context[ 'core/tabs-editorActiveTabIndex' ];
49
- const effectiveActiveIndex = editorActiveTabIndex ?? activeTabIndex;
50
29
 
51
- // Clean up animation frames on unmount.
52
- useEffect( () => {
53
- return () => {
54
- if ( focusRef.current ) {
55
- cancelAnimationFrame( focusRef.current );
56
- }
57
- };
58
- }, [] );
30
+ const effectiveActiveIndex = useMemo( () => {
31
+ return editorActiveTabIndex ?? activeTabIndex;
32
+ }, [ editorActiveTabIndex, activeTabIndex ] );
59
33
 
60
- const { blockIndex, hasInnerBlocksSelected, tabsClientId } = useSelect(
34
+ const { tabIndex, tabsClientId, selectedTabClientId } = useSelect(
61
35
  ( select ) => {
62
36
  const {
37
+ getBlockOrder,
63
38
  getBlockRootClientId,
64
- getBlockIndex,
39
+ getSelectedBlockClientIds,
65
40
  hasSelectedInnerBlock,
66
41
  } = select( blockEditorStore );
67
42
 
68
- // Get the tab-panel parent first
69
- const tabPanelClientId = getBlockRootClientId( clientId );
70
- // Then get the tabs parent
71
- const _tabsClientId = getBlockRootClientId( tabPanelClientId );
72
-
73
- // Get data about this instance of core/tab.
74
- const _blockIndex = getBlockIndex( clientId );
75
- const _hasInnerBlocksSelected = hasSelectedInnerBlock(
76
- clientId,
77
- true
78
- );
43
+ const _tabsListClientId = getBlockRootClientId( clientId );
44
+ const _tabsClientId = _tabsListClientId
45
+ ? getBlockRootClientId( _tabsListClientId )
46
+ : null;
47
+
48
+ const siblings = getBlockOrder( _tabsListClientId );
49
+ const _tabIndex = siblings.indexOf( clientId );
50
+
51
+ // Find which tab panel block is currently selected.
52
+ const selectedIds = getSelectedBlockClientIds();
53
+ let _selectedTabClientId = null;
54
+ for ( const tab of tabsList ) {
55
+ if (
56
+ selectedIds.includes( tab.clientId ) ||
57
+ hasSelectedInnerBlock( tab.clientId, true )
58
+ ) {
59
+ _selectedTabClientId = tab.clientId;
60
+ break;
61
+ }
62
+ }
79
63
 
80
64
  return {
81
- blockIndex: _blockIndex,
82
- hasInnerBlocksSelected: _hasInnerBlocksSelected,
65
+ tabIndex: _tabIndex,
83
66
  tabsClientId: _tabsClientId,
67
+ selectedTabClientId: _selectedTabClientId,
84
68
  };
85
69
  },
86
- [ clientId ]
70
+ [ clientId, tabsList ]
87
71
  );
88
72
 
89
- const { updateBlockAttributes, __unstableMarkNextChangeAsNotPersistent } =
73
+ const tab = tabsList[ tabIndex ] || {};
74
+
75
+ // tabListIndex is the tab's position in tabsList, used for active-state
76
+ // checks and click handling.
77
+ const tabListIndex = tab.index ?? tabIndex;
78
+
79
+ const tabClientId = tab.clientId || '';
80
+ const label = tab.label || '';
81
+
82
+ const isActive = tabListIndex === effectiveActiveIndex;
83
+ const isSelected = tabClientId === selectedTabClientId;
84
+
85
+ const { __unstableMarkNextChangeAsNotPersistent, updateBlockAttributes } =
90
86
  useDispatch( blockEditorStore );
91
87
 
92
- // Sync editorActiveTabIndex when this tab is selected directly
93
- useEffect( () => {
94
- // Only update if this tab is selected and not already the active index
95
- const isTabSelected = isSelected || hasInnerBlocksSelected;
96
- if (
97
- isTabSelected &&
98
- tabsClientId &&
99
- effectiveActiveIndex !== blockIndex
100
- ) {
101
- // Mark as non-persistent so it doesn't add to undo history
102
- __unstableMarkNextChangeAsNotPersistent();
103
- updateBlockAttributes( tabsClientId, {
104
- editorActiveTabIndex: blockIndex,
105
- } );
106
- }
107
- }, [
108
- isSelected,
109
- hasInnerBlocksSelected,
110
- tabsClientId,
111
- effectiveActiveIndex,
112
- blockIndex,
113
- updateBlockAttributes,
114
- __unstableMarkNextChangeAsNotPersistent,
115
- ] );
116
-
117
- // Determine if this is the currently active tab (for editor visibility)
118
- const isActiveTab = effectiveActiveIndex === blockIndex;
119
-
120
- // Determine if this is the default tab (for the "Default Tab" toggle in controls)
121
- const isDefaultTab = activeTabIndex === blockIndex;
122
-
123
- /**
124
- * This hook determines if the current tab panel should be visible.
125
- * This is true if it is the editor active tab, or if it is selected directly.
126
- */
127
- const isSelectedTab = useMemo( () => {
128
- // Show if this tab is directly selected or has selected inner blocks
129
- if ( isSelected || hasInnerBlocksSelected ) {
130
- return true;
131
- }
132
- // Always show the active tab (at effectiveActiveIndex) regardless of other selection state.
133
- // This ensures the tab panel remains visible when editing labels in tabs-menu.
134
- if ( isActiveTab ) {
135
- return true;
136
- }
137
- return false;
138
- }, [ isSelected, hasInnerBlocksSelected, isActiveTab ] );
139
-
140
- // Use a custom anchor, if set. Otherwise fall back to the slug generated from the label text.
141
- const tabPanelId = useMemo(
142
- () => anchor || slugFromLabel( label, blockIndex ),
143
- [ anchor, label, blockIndex ]
88
+ const handleTabClick = useCallback(
89
+ ( event ) => {
90
+ event.preventDefault();
91
+ if ( tabsClientId && tabListIndex !== effectiveActiveIndex ) {
92
+ __unstableMarkNextChangeAsNotPersistent();
93
+ updateBlockAttributes( tabsClientId, {
94
+ editorActiveTabIndex: tabListIndex,
95
+ } );
96
+ }
97
+ },
98
+ [
99
+ tabsClientId,
100
+ tabListIndex,
101
+ effectiveActiveIndex,
102
+ updateBlockAttributes,
103
+ __unstableMarkNextChangeAsNotPersistent,
104
+ ]
144
105
  );
145
- const tabLabelId = useMemo( () => `${ tabPanelId }--tab`, [ tabPanelId ] );
146
106
 
147
- const blockProps = useBlockProps( {
148
- hidden: ! isSelectedTab,
149
- 'aria-labelledby': tabLabelId,
150
- id: tabPanelId,
151
- role: 'tabpanel',
152
- tabIndex: isSelectedTab ? 0 : -1,
153
- className: clsx( 'wp-block-tab__editor-content', layoutClassNames ),
154
- } );
107
+ const handleLabelChange = useCallback(
108
+ ( newLabel ) => {
109
+ if ( tabClientId ) {
110
+ updateBlockAttributes( tabClientId, { label: newLabel } );
111
+ }
112
+ },
113
+ [ tabClientId, updateBlockAttributes ]
114
+ );
155
115
 
156
- const innerBlocksProps = useInnerBlocksProps( blockProps, {
157
- template: TEMPLATE,
116
+ const blockProps = useBlockProps( {
117
+ className: clsx( {
118
+ 'is-active': isActive,
119
+ 'is-selected': isSelected,
120
+ } ),
121
+ tabIndex: -1,
122
+ onClick: handleTabClick,
158
123
  } );
159
124
 
160
125
  return (
161
- <section { ...innerBlocksProps }>
162
- <Controls
163
- tabsClientId={ tabsClientId }
164
- blockIndex={ blockIndex }
165
- isDefaultTab={ isDefaultTab }
166
- />
167
- { isSelectedTab && innerBlocksProps.children }
168
- </section>
126
+ <>
127
+ <Controls tabsClientId={ tabsClientId } />
128
+ <button { ...blockProps } type="button">
129
+ <RichText
130
+ tagName="span"
131
+ withoutInteractiveFormatting
132
+ placeholder={ __( 'Tab title' ) }
133
+ value={ label }
134
+ onChange={ handleLabelChange }
135
+ />
136
+ </button>
137
+ </>
169
138
  );
170
139
  }
140
+
141
+ export default Edit;
@@ -1,14 +1,14 @@
1
- .wp-block-tabs-menu-item {
1
+ .wp-block-tab {
2
2
  &.is-selected {
3
3
  outline-offset: 2px;
4
4
  }
5
5
  }
6
6
 
7
- .block-editor-block-preview__live-content:has(.wp-block-tabs-menu-item) {
7
+ .block-editor-block-preview__live-content:has(.wp-block-tab) {
8
8
  flex-basis: inherit !important;
9
9
  flex-grow: inherit !important;
10
10
 
11
- .wp-block-tabs-menu-item {
11
+ .wp-block-tab {
12
12
  flex-basis: 100% !important;
13
13
  }
14
14
  }
package/src/tab/index.php CHANGED
@@ -1,6 +1,6 @@
1
1
  <?php
2
2
  /**
3
- * Tabs Block
3
+ * Tab Block
4
4
  *
5
5
  * @package WordPress
6
6
  */
@@ -8,81 +8,62 @@
8
8
  /**
9
9
  * Render callback for core/tab.
10
10
  *
11
+ * Injects the tab label and IAPI directives into the saved button HTML.
12
+ * Per-item context (index, id, label) is provided by the parent tab-list
13
+ * render callback before this is called.
14
+ *
11
15
  * @since 7.0.0
12
16
  *
13
17
  * @param array $attributes Block attributes.
14
- * @param array $attributes Block attributes.
15
- * @param string $content Block content.
16
- * @param \WP_Block $block Block instance.
18
+ * @param string $content Block content (styled button from save.js).
19
+ * @param \WP_Block $block WP_Block instance.
17
20
  *
18
21
  * @return string Updated HTML.
19
22
  */
20
- function block_core_tab_render( array $attributes, string $content, \WP_Block $block ): string {
21
- $tabs_id = $block->context['core/tabs-id'] ?? '';
22
-
23
- static $tab_counters = array();
23
+ function block_core_tab_render_callback( array $attributes, string $content, \WP_Block $block ): string {
24
+ $tab_index = $block->context['core/tab-index'] ?? 0;
25
+ $tab_id = $block->context['core/tab-id'] ?? '';
26
+ $tab_label = $block->context['core/tab-label'] ?? '';
24
27
 
25
- if ( ! isset( $tab_counters[ $tabs_id ] ) ) {
26
- $tab_counters[ $tabs_id ] = 0;
28
+ if ( empty( $tab_id ) ) {
29
+ $tab_id = 'tab-' . $tab_index;
27
30
  }
28
31
 
29
- $tab_index = $tab_counters[ $tabs_id ];
30
- ++$tab_counters[ $tabs_id ];
31
-
32
+ // Add Interactivity API directives and tab-specific attributes to the button.
32
33
  $tag_processor = new WP_HTML_Tag_Processor( $content );
33
- $tag_processor->next_tag( array( 'class_name' => 'wp-block-tab' ) );
34
34
 
35
- // Use the user's custom anchor if present, otherwise fall back to
36
- // the generated position-based ID.
37
- $tab_id = (string) $tag_processor->get_attribute( 'id' );
38
- if ( empty( $tab_id ) ) {
39
- $tab_id = ! empty( $tabs_id )
40
- ? $tabs_id . '-tab-' . $tab_index
41
- : 'tab-' . $tab_index;
42
- $tag_processor->set_attribute( 'id', $tab_id );
35
+ if ( $tag_processor->next_tag() ) {
36
+ $tag_processor->set_attribute( 'id', 'tab__' . $tab_id );
37
+ $tag_processor->set_attribute( 'aria-controls', $tab_id );
38
+ $tag_processor->set_attribute( 'data-wp-on--click', 'actions.handleTabClick' );
39
+ $tag_processor->set_attribute( 'data-wp-on--keydown', 'actions.handleTabKeyDown' );
40
+ $tag_processor->set_attribute( 'data-wp-bind--aria-selected', 'state.isActiveTab' );
41
+ $tag_processor->set_attribute( 'data-wp-bind--tabindex', 'state.tabIndexAttribute' );
42
+ $tag_processor->set_attribute(
43
+ 'data-wp-context',
44
+ wp_json_encode( array( 'tabIndex' => $tab_index ) )
45
+ );
43
46
  }
44
47
 
45
- /**
46
- * Add interactivity to the tab element.
47
- */
48
- $tag_processor->set_attribute(
49
- 'data-wp-interactive',
50
- 'core/tabs/private'
48
+ // Inject the tab label into the button.
49
+ return preg_replace(
50
+ '/(<button\b[^>]*>).*?(<\/button>)/s',
51
+ '$1<span>' . wp_kses_post( $tab_label ) . '</span>$2',
52
+ $tag_processor->get_updated_html(),
53
+ 1
51
54
  );
52
- $tag_processor->set_attribute(
53
- 'data-wp-context',
54
- wp_json_encode(
55
- array(
56
- 'tab' => array(
57
- 'id' => $tab_id,
58
- ),
59
- )
60
- )
61
- );
62
-
63
- /**
64
- * Process accessibility and interactivity attributes.
65
- */
66
- $tag_processor->set_attribute( 'role', 'tabpanel' );
67
- $tag_processor->set_attribute( 'aria-labelledby', 'tab__' . $tab_id );
68
- $tag_processor->set_attribute( 'data-wp-bind--hidden', '!state.isActiveTab' );
69
- $tag_processor->set_attribute( 'tabindex', 0 );
70
-
71
- return (string) $tag_processor->get_updated_html();
72
55
  }
73
56
 
74
57
  /**
75
58
  * Registers the `core/tab` block on the server.
76
59
  *
77
- * @hook init
78
- *
79
60
  * @since 7.0.0
80
61
  */
81
62
  function register_block_core_tab() {
82
63
  register_block_type_from_metadata(
83
64
  __DIR__ . '/tab',
84
65
  array(
85
- 'render_callback' => 'block_core_tab_render',
66
+ 'render_callback' => 'block_core_tab_render_callback',
86
67
  )
87
68
  );
88
69
  }
package/src/tab/save.js CHANGED
@@ -1,13 +1,13 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';
4
+ import { useBlockProps } from '@wordpress/block-editor';
5
5
 
6
6
  export default function save() {
7
7
  const blockProps = useBlockProps.save( {
8
- role: 'tabpanel',
8
+ type: 'button',
9
+ role: 'tab',
9
10
  } );
10
- const innerBlocksProps = useInnerBlocksProps.save( blockProps );
11
11
 
12
- return <section { ...innerBlocksProps } />;
12
+ return <button { ...blockProps } />;
13
13
  }
@@ -1,23 +1,40 @@
1
1
  .wp-block-tab {
2
- max-width: 100%;
3
- flex-basis: 100%;
4
- flex-grow: 1;
5
2
  box-sizing: border-box;
3
+ color: inherit;
4
+ display: block;
5
+ width: max-content;
6
+ text-decoration: none;
7
+ cursor: pointer;
8
+ flex-basis: inherit !important;
9
+ flex-grow: inherit !important;
10
+ position: relative;
6
11
 
7
- & > *:first-child {
8
- margin-top: 0;
9
- }
10
- & > *:last-child {
11
- margin-bottom: 0;
12
- }
12
+ // Button reset
13
+ border: none;
14
+ background: none;
15
+ appearance: none;
16
+ -webkit-appearance: none;
13
17
 
14
- &[hidden],
15
- &:empty {
16
- display: none !important;
17
- }
18
- }
18
+ margin: 0;
19
+ padding: var(--wp--preset--spacing--20, 0.5em) var(--wp--preset--spacing--30, 1em);
20
+
21
+ // Inherit typography from parent
22
+ font-size: inherit;
23
+ font-family: inherit;
24
+ font-weight: inherit;
25
+ line-height: inherit;
26
+ letter-spacing: inherit;
27
+ text-transform: inherit;
28
+ text-align: inherit;
19
29
 
20
- .wp-block-tab.wp-block.has-background,
21
- .wp-block-tab:not(.wp-block).has-background {
22
- padding: var(--wp--preset--spacing--30);
30
+ &[aria-selected="true"]::before,
31
+ &.is-active::before {
32
+ content: "";
33
+ position: absolute;
34
+ border-bottom: 2px solid currentColor;
35
+ pointer-events: none;
36
+ left: 0;
37
+ width: 100%;
38
+ bottom: 0;
39
+ }
23
40
  }
@@ -2,19 +2,19 @@
2
2
  "$schema": "https://schemas.wp.org/trunk/block.json",
3
3
  "__experimental": true,
4
4
  "apiVersion": 3,
5
- "name": "core/tabs-menu",
6
- "title": "Tabs Menu",
5
+ "name": "core/tab-list",
6
+ "title": "Tab List",
7
7
  "description": "Display the tab buttons for a tabbed interface.",
8
- "version": "1.0.0",
9
8
  "category": "design",
10
9
  "textdomain": "default",
11
10
  "parent": [ "core/tabs" ],
12
- "allowedBlocks": [ "core/tabs-menu-item" ],
11
+ "allowedBlocks": [ "core/tab" ],
13
12
  "usesContext": [ "core/tabs-list" ],
14
13
  "attributes": {},
15
14
  "supports": {
16
15
  "html": false,
17
16
  "reusable": false,
17
+ "visibility": false,
18
18
  "lock": false,
19
19
  "dimensions": {
20
20
  "aspectRatio": false,
@@ -1,8 +1,3 @@
1
- /**
2
- * External dependencies
3
- */
4
- import clsx from 'clsx';
5
-
6
1
  /**
7
2
  * WordPress dependencies
8
3
  */
@@ -16,26 +11,22 @@ import { useSelect } from '@wordpress/data';
16
11
  /**
17
12
  * Internal dependencies
18
13
  */
19
- import AddTabToolbarControl from '../tab/add-tab-toolbar-control';
20
- import RemoveTabToolbarControl from '../tab/remove-tab-toolbar-control';
14
+ import AddTabToolbarControl from '../tab-panel/add-tab-toolbar-control';
15
+ import RemoveTabToolbarControl from '../tab-panel/remove-tab-toolbar-control';
21
16
 
22
- function Edit( { clientId, __unstableLayoutClassNames: layoutClassNames } ) {
23
- const { tabsClientId } = useSelect(
24
- ( select ) => ( {
25
- tabsClientId:
26
- select( blockEditorStore ).getBlockRootClientId( clientId ),
27
- } ),
17
+ function Edit( { clientId } ) {
18
+ const tabsClientId = useSelect(
19
+ ( select ) =>
20
+ select( blockEditorStore ).getBlockRootClientId( clientId ),
28
21
  [ clientId ]
29
22
  );
30
23
 
31
- const blockProps = useBlockProps( {
32
- className: clsx( layoutClassNames ),
33
- role: 'tablist',
34
- } );
24
+ const blockProps = useBlockProps();
35
25
 
36
26
  const innerBlocksProps = useInnerBlocksProps( blockProps, {
37
- allowedBlocks: [ 'core/tabs-menu-item' ],
27
+ allowedBlocks: [ 'core/tab' ],
38
28
  orientation: 'horizontal',
29
+ templateLock: false,
39
30
  renderAppender: false,
40
31
  } );
41
32
 
@@ -1,10 +1,10 @@
1
- .wp-block-tabs-menu {
1
+ .wp-block-tab-list {
2
2
  // Allow the inner block list to be displayed in the flex layout, so the tab buttons appear as direct flex children in the editor.
3
3
  > .block-editor-block-list__layout {
4
4
  display: contents;
5
5
  }
6
6
 
7
- .block-editor-block-list__block:has(> .wp-block-tabs-menu-item) {
7
+ .block-editor-block-list__block:has(> .wp-block-tab) {
8
8
  display: contents;
9
9
  }
10
10
  }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { tabsMenu as icon } from '@wordpress/icons';
4
+ import { tabList as icon } from '@wordpress/icons';
5
5
 
6
6
  /**
7
7
  * Internal dependencies
@@ -0,0 +1,80 @@
1
+ <?php
2
+ /**
3
+ * Tab List Block
4
+ *
5
+ * @package WordPress
6
+ */
7
+
8
+ /**
9
+ * Render callback for core/tab-list.
10
+ *
11
+ * Re-renders each tab inner block with per-item context (index, id,
12
+ * label) injected from the tabs-list, so the tab render callback
13
+ * can add the correct IAPI directives for each button.
14
+ *
15
+ * @since 7.0.0
16
+ *
17
+ * @param array $attributes Block attributes.
18
+ * @param string $content Block content (rendered inner blocks from save.js).
19
+ * @param \WP_Block $block WP_Block instance.
20
+ *
21
+ * @return string Updated HTML.
22
+ */
23
+ function block_core_tab_list_render_callback( array $attributes, string $content, \WP_Block $block ): string {
24
+ $tabs_list = $block->context['core/tabs-list'] ?? array();
25
+
26
+ if ( empty( $tabs_list ) ) {
27
+ return $content;
28
+ }
29
+
30
+ // Re-render each tab with per-item context (index, id, label).
31
+ // Match by position so items align with their corresponding tabs.
32
+ $buttons_html = '';
33
+ $tab_position = 0;
34
+
35
+ foreach ( $block->parsed_block['innerBlocks'] ?? array() as $parsed_tab ) {
36
+ if ( 'core/tab' !== ( $parsed_tab['blockName'] ?? '' ) ) {
37
+ continue;
38
+ }
39
+
40
+ $tab = $tabs_list[ $tab_position ] ?? null;
41
+ $tab_index = $tab_position;
42
+ ++$tab_position;
43
+
44
+ // Skip tabs with no matching tab panel.
45
+ if ( null === $tab ) {
46
+ continue;
47
+ }
48
+
49
+ $item_context = array_merge(
50
+ $block->context,
51
+ array(
52
+ 'core/tab-index' => $tab_index,
53
+ 'core/tab-id' => $tab['id'] ?? '',
54
+ 'core/tab-label' => $tab['label'] ?? '',
55
+ )
56
+ );
57
+
58
+ $tab_block = new WP_Block( $parsed_tab, $item_context );
59
+ $buttons_html .= $tab_block->render();
60
+ }
61
+
62
+ // Rebuild the wrapper using get_block_wrapper_attributes().
63
+ $wrapper_attributes = get_block_wrapper_attributes( array( 'role' => 'tablist' ) );
64
+ return sprintf( '<div %s>%s</div>', $wrapper_attributes, $buttons_html );
65
+ }
66
+
67
+ /**
68
+ * Registers the `core/tab-list` block on the server.
69
+ *
70
+ * @since 7.0.0
71
+ */
72
+ function register_block_core_tab_list() {
73
+ register_block_type_from_metadata(
74
+ __DIR__ . '/tab-list',
75
+ array(
76
+ 'render_callback' => 'block_core_tab_list_render_callback',
77
+ )
78
+ );
79
+ }
80
+ add_action( 'init', 'register_block_core_tab_list' );