@wordpress/block-library 9.44.1-next.v.202604201441.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 (315) 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/categories/edit.cjs +5 -1
  6. package/build/categories/edit.cjs.map +2 -2
  7. package/build/embed/edit.cjs +38 -34
  8. package/build/embed/edit.cjs.map +3 -3
  9. package/build/embed/transforms.cjs +3 -1
  10. package/build/embed/transforms.cjs.map +2 -2
  11. package/build/embed/util.cjs +13 -2
  12. package/build/embed/util.cjs.map +2 -2
  13. package/build/form/block.json +1 -1
  14. package/build/form-input/block.json +1 -1
  15. package/build/form-submission-notification/block.json +1 -1
  16. package/build/form-submit-button/block.json +1 -1
  17. package/build/image/edit.cjs +1 -1
  18. package/build/image/edit.cjs.map +2 -2
  19. package/build/image/image.cjs +29 -10
  20. package/build/image/image.cjs.map +3 -3
  21. package/build/index.cjs +4 -4
  22. package/build/index.cjs.map +2 -2
  23. package/build/math/edit.cjs +2 -2
  24. package/build/math/edit.cjs.map +2 -2
  25. package/build/navigation/edit/accessible-description.cjs +2 -2
  26. package/build/navigation/edit/accessible-description.cjs.map +2 -2
  27. package/build/navigation/edit/overlay-template-part-selector.cjs.map +2 -2
  28. package/build/navigation-link/edit.cjs +2 -1
  29. package/build/navigation-link/edit.cjs.map +2 -2
  30. package/build/navigation-link/link-ui/dialog-wrapper.cjs +2 -1
  31. package/build/navigation-link/link-ui/dialog-wrapper.cjs.map +2 -2
  32. package/build/navigation-link/link-ui/index.cjs +2 -1
  33. package/build/navigation-link/link-ui/index.cjs.map +2 -2
  34. package/build/post-author/edit.cjs.map +3 -3
  35. package/build/post-comments-form/edit.cjs +2 -2
  36. package/build/post-comments-form/edit.cjs.map +2 -2
  37. package/build/query/edit/inspector-controls/author-control.cjs +1 -1
  38. package/build/query/edit/inspector-controls/author-control.cjs.map +2 -2
  39. package/build/query/edit/inspector-controls/format-controls.cjs +1 -1
  40. package/build/query/edit/inspector-controls/format-controls.cjs.map +2 -2
  41. package/build/query/edit/inspector-controls/parent-control.cjs +1 -1
  42. package/build/query/edit/inspector-controls/parent-control.cjs.map +2 -2
  43. package/build/query/edit/inspector-controls/taxonomy-controls.cjs +1 -1
  44. package/build/query/edit/inspector-controls/taxonomy-controls.cjs.map +2 -2
  45. package/build/site-logo/edit.cjs +32 -18
  46. package/build/site-logo/edit.cjs.map +2 -2
  47. package/build/tab/block.json +23 -23
  48. package/build/tab/controls.cjs +5 -48
  49. package/build/tab/controls.cjs.map +3 -3
  50. package/build/tab/edit.cjs +77 -75
  51. package/build/tab/edit.cjs.map +3 -3
  52. package/build/tab/save.cjs +3 -3
  53. package/build/tab/save.cjs.map +2 -2
  54. package/{src/tabs-menu → build/tab-list}/block.json +3 -3
  55. package/build/{tabs-menu → tab-list}/edit.cjs +4 -4
  56. package/build/tab-list/edit.cjs.map +7 -0
  57. package/build/{tabs-menu → tab-list}/index.cjs +5 -5
  58. package/build/tab-list/index.cjs.map +7 -0
  59. package/build/{tabs-menu → tab-list}/save.cjs +1 -1
  60. package/build/{tabs-menu → tab-list}/save.cjs.map +1 -1
  61. package/build/{tab → tab-panel}/add-tab-toolbar-control.cjs +16 -16
  62. package/build/tab-panel/add-tab-toolbar-control.cjs.map +7 -0
  63. package/build/tab-panel/block.json +27 -37
  64. package/build/tab-panel/controls.cjs +89 -0
  65. package/build/tab-panel/controls.cjs.map +7 -0
  66. package/build/tab-panel/edit.cjs +90 -17
  67. package/build/tab-panel/edit.cjs.map +3 -3
  68. package/build/tab-panel/index.cjs +1 -1
  69. package/build/tab-panel/index.cjs.map +1 -1
  70. package/build/{tab → tab-panel}/init.cjs +1 -1
  71. package/build/{tab → tab-panel}/init.cjs.map +1 -1
  72. package/build/{tab → tab-panel}/remove-tab-toolbar-control.cjs +16 -16
  73. package/build/tab-panel/remove-tab-toolbar-control.cjs.map +7 -0
  74. package/build/tab-panel/save.cjs +4 -2
  75. package/build/tab-panel/save.cjs.map +2 -2
  76. package/build/tab-panels/block.json +66 -0
  77. package/build/{tabs-menu-item/controls.cjs → tab-panels/edit.cjs} +25 -11
  78. package/build/tab-panels/edit.cjs.map +7 -0
  79. package/build/{tabs-menu-item → tab-panels}/index.cjs +5 -5
  80. package/build/{tabs-menu → tab-panels}/index.cjs.map +2 -2
  81. package/build/{tabs-menu-item → tab-panels}/save.cjs +4 -6
  82. package/build/tab-panels/save.cjs.map +7 -0
  83. package/build/tabs/block.json +1 -1
  84. package/build/tabs/controls.cjs +2 -2
  85. package/build/tabs/controls.cjs.map +1 -1
  86. package/build/tabs/edit.cjs +24 -19
  87. package/build/tabs/edit.cjs.map +3 -3
  88. package/build/tabs/index.cjs +5 -5
  89. package/build/tabs/index.cjs.map +1 -1
  90. package/build/tabs/{use-tab-menu-sync.cjs → use-tab-list-sync.cjs} +78 -80
  91. package/build/tabs/use-tab-list-sync.cjs.map +7 -0
  92. package/build/terms-query/edit/inspector-controls/include-control.cjs +1 -1
  93. package/build/terms-query/edit/inspector-controls/include-control.cjs.map +2 -2
  94. package/build/video/tracks-editor.cjs +2 -2
  95. package/build/video/tracks-editor.cjs.map +2 -2
  96. package/build-module/accordion/edit.mjs +0 -2
  97. package/build-module/accordion/edit.mjs.map +2 -2
  98. package/build-module/accordion-item/block.json +1 -0
  99. package/build-module/categories/edit.mjs +5 -2
  100. package/build-module/categories/edit.mjs.map +2 -2
  101. package/build-module/embed/edit.mjs +45 -36
  102. package/build-module/embed/edit.mjs.map +2 -2
  103. package/build-module/embed/transforms.mjs +8 -2
  104. package/build-module/embed/transforms.mjs.map +2 -2
  105. package/build-module/embed/util.mjs +11 -1
  106. package/build-module/embed/util.mjs.map +2 -2
  107. package/build-module/form/block.json +1 -1
  108. package/build-module/form-input/block.json +1 -1
  109. package/build-module/form-submission-notification/block.json +1 -1
  110. package/build-module/form-submit-button/block.json +1 -1
  111. package/build-module/image/edit.mjs +1 -1
  112. package/build-module/image/edit.mjs.map +2 -2
  113. package/build-module/image/image.mjs +29 -10
  114. package/build-module/image/image.mjs.map +3 -3
  115. package/build-module/index.mjs +4 -4
  116. package/build-module/index.mjs.map +2 -2
  117. package/build-module/math/edit.mjs +2 -2
  118. package/build-module/math/edit.mjs.map +2 -2
  119. package/build-module/navigation/edit/accessible-description.mjs +1 -1
  120. package/build-module/navigation/edit/accessible-description.mjs.map +1 -1
  121. package/build-module/navigation/edit/overlay-template-part-selector.mjs +2 -2
  122. package/build-module/navigation/edit/overlay-template-part-selector.mjs.map +1 -1
  123. package/build-module/navigation-link/edit.mjs +2 -5
  124. package/build-module/navigation-link/edit.mjs.map +2 -2
  125. package/build-module/navigation-link/link-ui/dialog-wrapper.mjs +2 -1
  126. package/build-module/navigation-link/link-ui/dialog-wrapper.mjs.map +2 -2
  127. package/build-module/navigation-link/link-ui/index.mjs +1 -1
  128. package/build-module/navigation-link/link-ui/index.mjs.map +2 -2
  129. package/build-module/post-author/edit.mjs +2 -2
  130. package/build-module/post-author/edit.mjs.map +2 -2
  131. package/build-module/post-comments-form/edit.mjs +1 -1
  132. package/build-module/post-comments-form/edit.mjs.map +2 -2
  133. package/build-module/query/edit/inspector-controls/author-control.mjs +1 -1
  134. package/build-module/query/edit/inspector-controls/author-control.mjs.map +2 -2
  135. package/build-module/query/edit/inspector-controls/format-controls.mjs +1 -1
  136. package/build-module/query/edit/inspector-controls/format-controls.mjs.map +2 -2
  137. package/build-module/query/edit/inspector-controls/parent-control.mjs +1 -1
  138. package/build-module/query/edit/inspector-controls/parent-control.mjs.map +2 -2
  139. package/build-module/query/edit/inspector-controls/taxonomy-controls.mjs +1 -1
  140. package/build-module/query/edit/inspector-controls/taxonomy-controls.mjs.map +2 -2
  141. package/build-module/site-logo/edit.mjs +32 -18
  142. package/build-module/site-logo/edit.mjs.map +2 -2
  143. package/build-module/tab/block.json +23 -23
  144. package/build-module/tab/controls.mjs +7 -57
  145. package/build-module/tab/controls.mjs.map +2 -2
  146. package/build-module/tab/edit.mjs +81 -79
  147. package/build-module/tab/edit.mjs.map +3 -3
  148. package/build-module/tab/save.mjs +4 -4
  149. package/build-module/tab/save.mjs.map +2 -2
  150. package/build-module/{tabs-menu → tab-list}/block.json +3 -3
  151. package/build-module/{tabs-menu → tab-list}/edit.mjs +4 -4
  152. package/build-module/tab-list/edit.mjs.map +7 -0
  153. package/build-module/{tabs-menu → tab-list}/index.mjs +2 -2
  154. package/build-module/tab-list/index.mjs.map +7 -0
  155. package/build-module/{tabs-menu → tab-list}/save.mjs +1 -1
  156. package/build-module/{tabs-menu → tab-list}/save.mjs.map +1 -1
  157. package/build-module/{tab → tab-panel}/add-tab-toolbar-control.mjs +16 -16
  158. package/build-module/tab-panel/add-tab-toolbar-control.mjs.map +7 -0
  159. package/build-module/tab-panel/block.json +27 -37
  160. package/build-module/tab-panel/controls.mjs +65 -0
  161. package/build-module/tab-panel/controls.mjs.map +7 -0
  162. package/build-module/tab-panel/edit.mjs +92 -19
  163. package/build-module/tab-panel/edit.mjs.map +2 -2
  164. package/build-module/tab-panel/index.mjs +1 -1
  165. package/build-module/tab-panel/index.mjs.map +1 -1
  166. package/build-module/{tab → tab-panel}/init.mjs +1 -1
  167. package/build-module/{tab → tab-panel}/init.mjs.map +1 -1
  168. package/build-module/{tab → tab-panel}/remove-tab-toolbar-control.mjs +16 -16
  169. package/build-module/tab-panel/remove-tab-toolbar-control.mjs.map +7 -0
  170. package/build-module/tab-panel/save.mjs +4 -2
  171. package/build-module/tab-panel/save.mjs.map +2 -2
  172. package/build-module/tab-panels/block.json +66 -0
  173. package/build-module/tab-panels/edit.mjs +33 -0
  174. package/build-module/tab-panels/edit.mjs.map +7 -0
  175. package/build-module/{tabs-menu-item → tab-panels}/index.mjs +2 -2
  176. package/build-module/{tabs-menu → tab-panels}/index.mjs.map +2 -2
  177. package/build-module/tab-panels/save.mjs +12 -0
  178. package/build-module/tab-panels/save.mjs.map +7 -0
  179. package/build-module/tabs/block.json +1 -1
  180. package/build-module/tabs/controls.mjs +2 -2
  181. package/build-module/tabs/controls.mjs.map +1 -1
  182. package/build-module/tabs/edit.mjs +24 -19
  183. package/build-module/tabs/edit.mjs.map +2 -2
  184. package/build-module/tabs/index.mjs +5 -5
  185. package/build-module/tabs/index.mjs.map +1 -1
  186. package/build-module/tabs/use-tab-list-sync.mjs +169 -0
  187. package/build-module/tabs/use-tab-list-sync.mjs.map +7 -0
  188. package/build-module/terms-query/edit/inspector-controls/include-control.mjs +1 -1
  189. package/build-module/terms-query/edit/inspector-controls/include-control.mjs.map +2 -2
  190. package/build-module/video/tracks-editor.mjs +2 -2
  191. package/build-module/video/tracks-editor.mjs.map +2 -2
  192. package/build-style/classic-rtl.css +14 -0
  193. package/build-style/classic.css +14 -0
  194. package/build-style/editor-rtl.css +9 -5
  195. package/build-style/editor.css +9 -5
  196. package/build-style/style-rtl.css +40 -40
  197. package/build-style/style.css +40 -40
  198. package/build-style/tab/editor-rtl.css +11 -0
  199. package/build-style/tab/editor.css +11 -0
  200. package/build-style/tab/style-rtl.css +29 -16
  201. package/build-style/tab/style.css +29 -16
  202. package/build-style/tab-list/editor-rtl.css +6 -0
  203. package/build-style/tab-list/editor.css +6 -0
  204. package/build-style/tab-panel/style-rtl.css +17 -1
  205. package/build-style/tab-panel/style.css +17 -1
  206. package/build-style/tab-panels/style-rtl.css +4 -0
  207. package/build-style/tab-panels/style.css +4 -0
  208. package/build-style/video/editor-rtl.css +4 -0
  209. package/build-style/video/editor.css +4 -0
  210. package/package.json +39 -38
  211. package/src/accordion/edit.js +0 -2
  212. package/src/accordion-item/block.json +1 -0
  213. package/src/categories/edit.js +3 -2
  214. package/src/classic.scss +25 -0
  215. package/src/editor.scss +2 -2
  216. package/src/embed/edit.js +61 -52
  217. package/src/embed/edit.native.js +71 -57
  218. package/src/embed/transforms.js +8 -2
  219. package/src/embed/util.js +17 -0
  220. package/src/form/block.json +1 -1
  221. package/src/form-input/block.json +1 -1
  222. package/src/form-submission-notification/block.json +1 -1
  223. package/src/form-submit-button/block.json +1 -1
  224. package/src/image/edit.js +5 -1
  225. package/src/image/edit.native.js +3 -3
  226. package/src/image/image.js +30 -5
  227. package/src/index.js +4 -4
  228. package/src/math/edit.js +3 -3
  229. package/src/navigation/edit/accessible-description.js +1 -1
  230. package/src/navigation/edit/overlay-template-part-selector.js +3 -3
  231. package/src/navigation-link/edit.js +2 -5
  232. package/src/navigation-link/link-ui/dialog-wrapper.js +2 -1
  233. package/src/navigation-link/link-ui/index.js +1 -1
  234. package/src/post-author/edit.js +3 -5
  235. package/src/post-comments-form/edit.js +1 -1
  236. package/src/query/edit/inspector-controls/author-control.js +1 -1
  237. package/src/query/edit/inspector-controls/format-controls.js +1 -1
  238. package/src/query/edit/inspector-controls/parent-control.js +1 -1
  239. package/src/query/edit/inspector-controls/taxonomy-controls.js +1 -1
  240. package/src/site-logo/edit.js +38 -18
  241. package/src/style.scss +1 -1
  242. package/src/tab/block.json +23 -23
  243. package/src/tab/controls.js +6 -52
  244. package/src/tab/edit.js +99 -103
  245. package/src/{tabs-menu-item → tab}/editor.scss +3 -3
  246. package/src/tab/index.php +32 -51
  247. package/src/tab/save.js +4 -4
  248. package/src/tab/style.scss +34 -17
  249. package/{build/tabs-menu → src/tab-list}/block.json +3 -3
  250. package/src/{tabs-menu → tab-list}/edit.js +3 -3
  251. package/src/{tabs-menu → tab-list}/editor.scss +2 -2
  252. package/src/{tabs-menu → tab-list}/index.js +1 -1
  253. package/src/tab-list/index.php +80 -0
  254. package/src/{tab → tab-panel}/add-tab-toolbar-control.js +19 -19
  255. package/src/tab-panel/block.json +27 -37
  256. package/src/tab-panel/controls.js +65 -0
  257. package/src/tab-panel/edit.js +123 -20
  258. package/src/tab-panel/index.js +1 -1
  259. package/src/tab-panel/index.php +88 -0
  260. package/src/{tab → tab-panel}/remove-tab-toolbar-control.js +20 -19
  261. package/src/tab-panel/save.js +4 -2
  262. package/src/tab-panel/style.scss +20 -1
  263. package/src/tab-panels/block.json +66 -0
  264. package/src/tab-panels/edit.js +42 -0
  265. package/src/{tabs-menu-item → tab-panels}/index.js +1 -1
  266. package/src/tab-panels/save.js +11 -0
  267. package/src/tab-panels/style.scss +4 -0
  268. package/src/tabs/block.json +1 -1
  269. package/src/tabs/controls.js +2 -2
  270. package/src/tabs/edit.js +25 -20
  271. package/src/tabs/index.js +5 -5
  272. package/src/tabs/index.php +5 -5
  273. package/src/tabs/use-tab-list-sync.js +237 -0
  274. package/src/terms-query/edit/inspector-controls/include-control.js +1 -1
  275. package/src/video/editor.scss +5 -0
  276. package/src/video/tracks-editor.js +2 -2
  277. package/build/tab/add-tab-toolbar-control.cjs.map +0 -7
  278. package/build/tab/remove-tab-toolbar-control.cjs.map +0 -7
  279. package/build/tabs/use-tab-menu-sync.cjs.map +0 -7
  280. package/build/tabs-menu/edit.cjs.map +0 -7
  281. package/build/tabs-menu-item/block.json +0 -56
  282. package/build/tabs-menu-item/controls.cjs.map +0 -7
  283. package/build/tabs-menu-item/edit.cjs +0 -135
  284. package/build/tabs-menu-item/edit.cjs.map +0 -7
  285. package/build/tabs-menu-item/index.cjs.map +0 -7
  286. package/build/tabs-menu-item/save.cjs.map +0 -7
  287. package/build-module/tab/add-tab-toolbar-control.mjs.map +0 -7
  288. package/build-module/tab/remove-tab-toolbar-control.mjs.map +0 -7
  289. package/build-module/tabs/use-tab-menu-sync.mjs +0 -171
  290. package/build-module/tabs/use-tab-menu-sync.mjs.map +0 -7
  291. package/build-module/tabs-menu/edit.mjs.map +0 -7
  292. package/build-module/tabs-menu-item/block.json +0 -56
  293. package/build-module/tabs-menu-item/controls.mjs +0 -15
  294. package/build-module/tabs-menu-item/controls.mjs.map +0 -7
  295. package/build-module/tabs-menu-item/edit.mjs +0 -108
  296. package/build-module/tabs-menu-item/edit.mjs.map +0 -7
  297. package/build-module/tabs-menu-item/index.mjs.map +0 -7
  298. package/build-module/tabs-menu-item/save.mjs +0 -14
  299. package/build-module/tabs-menu-item/save.mjs.map +0 -7
  300. package/build-style/tabs-menu/editor-rtl.css +0 -6
  301. package/build-style/tabs-menu/editor.css +0 -6
  302. package/build-style/tabs-menu-item/editor-rtl.css +0 -11
  303. package/build-style/tabs-menu-item/editor.css +0 -11
  304. package/build-style/tabs-menu-item/style-rtl.css +0 -33
  305. package/build-style/tabs-menu-item/style.css +0 -33
  306. package/src/tabs/use-tab-menu-sync.js +0 -239
  307. package/src/tabs-menu/index.php +0 -80
  308. package/src/tabs-menu-item/block.json +0 -56
  309. package/src/tabs-menu-item/controls.js +0 -19
  310. package/src/tabs-menu-item/edit.js +0 -141
  311. package/src/tabs-menu-item/index.php +0 -70
  312. package/src/tabs-menu-item/save.js +0 -13
  313. package/src/tabs-menu-item/style.scss +0 -40
  314. /package/src/{tabs-menu → tab-list}/save.js +0 -0
  315. /package/src/{tab → tab-panel}/init.js +0 -0
@@ -1,239 +0,0 @@
1
- /**
2
- * WordPress dependencies
3
- */
4
- import { createBlock } from '@wordpress/blocks';
5
- import { store as blockEditorStore } from '@wordpress/block-editor';
6
- import { useDispatch } from '@wordpress/data';
7
- import { useEffect, useRef } from '@wordpress/element';
8
-
9
- /**
10
- * Keep tabs and menu items in sync when the lists change due to direct
11
- * user actions (deletion, paste, duplicate, drag-and-drop).
12
- *
13
- * Deletion: when one side shrinks, remove the counterpart at the same index.
14
- * Insertion: when one side grows without the other, insert the missing
15
- * counterpart at the matching index.
16
- *
17
- * When both lists change simultaneously (e.g. the "Add Tab" toolbar button,
18
- * which inserts both at once), no action is needed and the effect exits early.
19
- *
20
- * @param {Object} props
21
- * @param {Array} props.tabs Raw core/tab block objects.
22
- * @param {Array} props.menuItems Raw core/tabs-menu-item block objects.
23
- * @param {string|null} props.tabPanelClientId Client ID of the core/tab-panel block.
24
- * @param {string|null} props.tabsMenuClientId Client ID of the core/tabs-menu block.
25
- */
26
- export default function useTabMenuSync( {
27
- tabs,
28
- menuItems,
29
- tabPanelClientId,
30
- tabsMenuClientId,
31
- } ) {
32
- const {
33
- removeBlock,
34
- insertBlocks,
35
- replaceInnerBlocks,
36
- __unstableMarkNextChangeAsNotPersistent,
37
- } = useDispatch( blockEditorStore );
38
-
39
- const prevSyncStateRef = useRef( null );
40
- useEffect( () => {
41
- if ( prevSyncStateRef.current === null ) {
42
- prevSyncStateRef.current = {
43
- tabs: [ ...tabs ],
44
- menuItems: [ ...menuItems ],
45
- };
46
- return;
47
- }
48
-
49
- const { tabs: prevTabs, menuItems: prevMenuItems } =
50
- prevSyncStateRef.current;
51
-
52
- const tabCountChange = tabs.length - prevTabs.length;
53
- const menuItemCountChange = menuItems.length - prevMenuItems.length;
54
-
55
- const tabsInserted = tabCountChange > 0;
56
- const menuItemsInserted = menuItemCountChange > 0;
57
-
58
- // Both sides changed by the same amount.
59
- // Covers: no-op re-renders, "Add Tab" toolbar, and toolbar-remove.
60
- // Also handles drag-and-drop reordering of menu items.
61
- if ( tabCountChange === menuItemCountChange ) {
62
- // When lengths are equal but order changed, the user reordered menu
63
- // items via drag-and-drop. Reorder the tab content blocks to match.
64
- if (
65
- tabCountChange === 0 &&
66
- tabPanelClientId &&
67
- menuItems.some(
68
- ( m, i ) => m.clientId !== prevMenuItems[ i ]?.clientId
69
- )
70
- ) {
71
- const reorderedTabs = menuItems
72
- .map( ( menuItem ) => {
73
- const oldIndex = prevMenuItems.findIndex(
74
- ( pm ) => pm.clientId === menuItem.clientId
75
- );
76
- return oldIndex !== -1 ? tabs[ oldIndex ] : null;
77
- } )
78
- .filter( Boolean );
79
- if ( reorderedTabs.length === tabs.length ) {
80
- __unstableMarkNextChangeAsNotPersistent();
81
- replaceInnerBlocks(
82
- tabPanelClientId,
83
- reorderedTabs,
84
- false
85
- );
86
- }
87
- }
88
- prevSyncStateRef.current = {
89
- tabs: [ ...tabs ],
90
- menuItems: [ ...menuItems ],
91
- };
92
- return;
93
- }
94
-
95
- // Both sides changed in the same direction but by different amounts.
96
- // Bail without making a partial fix.
97
- if (
98
- ( tabCountChange > 0 && menuItemCountChange > 0 ) ||
99
- ( tabCountChange < 0 && menuItemCountChange < 0 )
100
- ) {
101
- prevSyncStateRef.current = {
102
- tabs: [ ...tabs ],
103
- menuItems: [ ...menuItems ],
104
- };
105
- return;
106
- }
107
-
108
- // If the required container block isn't available yet, bail without
109
- // updating the snapshot so the next render re-evaluates the same count change.
110
- if ( tabsInserted && ! tabsMenuClientId ) {
111
- return;
112
- }
113
- if ( menuItemsInserted && ! tabPanelClientId ) {
114
- return;
115
- }
116
-
117
- // Update snapshot to the current state.
118
- prevSyncStateRef.current = {
119
- tabs: [ ...tabs ],
120
- menuItems: [ ...menuItems ],
121
- };
122
-
123
- const currentTabIds = new Set( tabs.map( ( t ) => t.clientId ) );
124
- const currentMenuItemIds = new Set(
125
- menuItems.map( ( m ) => m.clientId )
126
- );
127
-
128
- if ( tabCountChange < 0 ) {
129
- // Remove the menu item at the same position as each deleted tab.
130
- const removedIndices = prevTabs
131
- .map( ( t, i ) =>
132
- ! currentTabIds.has( t.clientId ) ? i : -1
133
- )
134
- .filter( ( i ) => i !== -1 );
135
- const removedSet = new Set( removedIndices );
136
- removedIndices.forEach( ( removedIndex ) => {
137
- if ( menuItems[ removedIndex ] ) {
138
- __unstableMarkNextChangeAsNotPersistent();
139
- removeBlock( menuItems[ removedIndex ].clientId, false );
140
- }
141
- } );
142
- prevSyncStateRef.current.menuItems =
143
- prevSyncStateRef.current.menuItems.filter(
144
- ( _, i ) => ! removedSet.has( i )
145
- );
146
- } else if ( menuItemCountChange < 0 ) {
147
- // Remove the tab at the same position as each deleted menu item.
148
- const removedIndices = prevMenuItems
149
- .map( ( m, i ) =>
150
- ! currentMenuItemIds.has( m.clientId ) ? i : -1
151
- )
152
- .filter( ( i ) => i !== -1 );
153
- const removedSet = new Set( removedIndices );
154
- removedIndices.forEach( ( removedIndex ) => {
155
- if ( tabs[ removedIndex ] ) {
156
- __unstableMarkNextChangeAsNotPersistent();
157
- removeBlock( tabs[ removedIndex ].clientId, false );
158
- }
159
- } );
160
- prevSyncStateRef.current.tabs =
161
- prevSyncStateRef.current.tabs.filter(
162
- ( _, i ) => ! removedSet.has( i )
163
- );
164
- } else if ( tabsInserted ) {
165
- // A tab was pasted or duplicated — insert matching menu items.
166
- const prevTabIds = new Set( prevTabs.map( ( t ) => t.clientId ) );
167
- const newMenuItems = tabs
168
- .map( ( tab, tabIndex ) =>
169
- ! prevTabIds.has( tab.clientId )
170
- ? {
171
- tabIndex,
172
- block: createBlock( 'core/tabs-menu-item', {} ),
173
- }
174
- : null
175
- )
176
- .filter( Boolean );
177
-
178
- if ( newMenuItems.length > 0 ) {
179
- __unstableMarkNextChangeAsNotPersistent();
180
- insertBlocks(
181
- newMenuItems.map( ( { block } ) => block ),
182
- newMenuItems[ 0 ].tabIndex,
183
- tabsMenuClientId,
184
- false
185
- );
186
- newMenuItems.forEach( ( { tabIndex, block } ) => {
187
- prevSyncStateRef.current.menuItems.splice( tabIndex, 0, {
188
- clientId: block.clientId,
189
- } );
190
- } );
191
- }
192
- } else if ( menuItemsInserted ) {
193
- // A menu item was pasted or duplicated — insert matching tabs,
194
- // copying the label from the adjacent tab.
195
- const prevMenuItemIds = new Set(
196
- prevMenuItems.map( ( m ) => m.clientId )
197
- );
198
- const newTabs = menuItems
199
- .map( ( menuItem, menuItemIndex ) => {
200
- if ( prevMenuItemIds.has( menuItem.clientId ) ) {
201
- return null;
202
- }
203
- const label =
204
- tabs[ menuItemIndex - 1 ]?.attributes?.label ??
205
- tabs[ menuItemIndex ]?.attributes?.label ??
206
- '';
207
- return {
208
- menuItemIndex,
209
- block: createBlock( 'core/tab', { label } ),
210
- };
211
- } )
212
- .filter( Boolean );
213
-
214
- if ( newTabs.length > 0 ) {
215
- __unstableMarkNextChangeAsNotPersistent();
216
- insertBlocks(
217
- newTabs.map( ( { block } ) => block ),
218
- newTabs[ 0 ].menuItemIndex,
219
- tabPanelClientId,
220
- false
221
- );
222
- newTabs.forEach( ( { menuItemIndex, block } ) => {
223
- prevSyncStateRef.current.tabs.splice( menuItemIndex, 0, {
224
- clientId: block.clientId,
225
- } );
226
- } );
227
- }
228
- }
229
- }, [
230
- tabs,
231
- menuItems,
232
- removeBlock,
233
- insertBlocks,
234
- replaceInnerBlocks,
235
- __unstableMarkNextChangeAsNotPersistent,
236
- tabsMenuClientId,
237
- tabPanelClientId,
238
- ] );
239
- }
@@ -1,80 +0,0 @@
1
- <?php
2
- /**
3
- * Tabs Menu Block
4
- *
5
- * @package WordPress
6
- */
7
-
8
- /**
9
- * Render callback for core/tabs-menu.
10
- *
11
- * Re-renders each tabs-menu-item inner block with per-item context (index, id,
12
- * label) injected from the tabs-list, so the tabs-menu-item 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_tabs_menu_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 tabs-menu-item with per-item context (index, id, label).
31
- // Match by position so items align with their corresponding tabs.
32
- $buttons_html = '';
33
- $menu_item_position = 0;
34
-
35
- foreach ( $block->parsed_block['innerBlocks'] ?? array() as $parsed_menu_item ) {
36
- if ( 'core/tabs-menu-item' !== ( $parsed_menu_item['blockName'] ?? '' ) ) {
37
- continue;
38
- }
39
-
40
- $tab = $tabs_list[ $menu_item_position ] ?? null;
41
- $tab_index = $menu_item_position;
42
- ++$menu_item_position;
43
-
44
- // Skip menu items with no matching tab.
45
- if ( null === $tab ) {
46
- continue;
47
- }
48
-
49
- $item_context = array_merge(
50
- $block->context,
51
- array(
52
- 'core/tabs-menu-item-index' => $tab_index,
53
- 'core/tabs-menu-item-id' => $tab['id'] ?? '',
54
- 'core/tabs-menu-item-label' => $tab['label'] ?? '',
55
- )
56
- );
57
-
58
- $menu_item_block = new WP_Block( $parsed_menu_item, $item_context );
59
- $buttons_html .= $menu_item_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/tabs-menu` block on the server.
69
- *
70
- * @since 7.0.0
71
- */
72
- function register_block_core_tabs_menu() {
73
- register_block_type_from_metadata(
74
- __DIR__ . '/tabs-menu',
75
- array(
76
- 'render_callback' => 'block_core_tabs_menu_render_callback',
77
- )
78
- );
79
- }
80
- add_action( 'init', 'register_block_core_tabs_menu' );
@@ -1,56 +0,0 @@
1
- {
2
- "$schema": "https://schemas.wp.org/trunk/block.json",
3
- "__experimental": true,
4
- "apiVersion": 3,
5
- "name": "core/tabs-menu-item",
6
- "title": "Tab Menu Item",
7
- "description": "A single tab button in the tabs menu.",
8
- "category": "design",
9
- "textdomain": "default",
10
- "parent": [ "core/tabs-menu" ],
11
- "usesContext": [
12
- "core/tabs-list",
13
- "core/tabs-activeTabIndex",
14
- "core/tabs-editorActiveTabIndex",
15
- "core/tabs-menu-item-index",
16
- "core/tabs-menu-item-id",
17
- "core/tabs-menu-item-label"
18
- ],
19
- "supports": {
20
- "html": false,
21
- "reusable": false,
22
- "visibility": false,
23
- "lock": false,
24
- "color": {
25
- "background": true,
26
- "text": true,
27
- "__experimentalDefaultControls": {
28
- "background": true,
29
- "text": true
30
- }
31
- },
32
- "typography": {
33
- "fontSize": true,
34
- "__experimentalFontFamily": true,
35
- "textAlign": true,
36
- "__experimentalDefaultControls": {
37
- "fontSize": true
38
- }
39
- },
40
- "spacing": {
41
- "padding": true,
42
- "__experimentalDefaultControls": {
43
- "padding": true
44
- }
45
- },
46
- "__experimentalBorder": {
47
- "radius": true,
48
- "color": true,
49
- "width": true,
50
- "style": true
51
- }
52
- },
53
- "editorScript": "file:./index.js",
54
- "editorStyle": "file:./editor.css",
55
- "style": "file:./style-index.css"
56
- }
@@ -1,19 +0,0 @@
1
- /**
2
- * WordPress dependencies
3
- */
4
- import { BlockControls } from '@wordpress/block-editor';
5
-
6
- /**
7
- * Internal dependencies
8
- */
9
- import AddTabToolbarControl from '../tab/add-tab-toolbar-control';
10
- import RemoveTabToolbarControl from '../tab/remove-tab-toolbar-control';
11
-
12
- export default function Controls( { tabsClientId } ) {
13
- return (
14
- <BlockControls>
15
- <AddTabToolbarControl tabsClientId={ tabsClientId } />
16
- <RemoveTabToolbarControl tabsClientId={ tabsClientId } />
17
- </BlockControls>
18
- );
19
- }
@@ -1,141 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import clsx from 'clsx';
5
-
6
- /**
7
- * WordPress dependencies
8
- */
9
- import { __ } from '@wordpress/i18n';
10
- import {
11
- useBlockProps,
12
- store as blockEditorStore,
13
- RichText,
14
- } from '@wordpress/block-editor';
15
- import { useSelect, useDispatch } from '@wordpress/data';
16
- import { useMemo, useCallback } from '@wordpress/element';
17
-
18
- /**
19
- * Internal dependencies
20
- */
21
- import Controls from './controls';
22
-
23
- const EMPTY_ARRAY = [];
24
-
25
- function Edit( { context, clientId } ) {
26
- const tabsList = context[ 'core/tabs-list' ] || EMPTY_ARRAY;
27
- const activeTabIndex = context[ 'core/tabs-activeTabIndex' ];
28
- const editorActiveTabIndex = context[ 'core/tabs-editorActiveTabIndex' ];
29
-
30
- const effectiveActiveIndex = useMemo( () => {
31
- return editorActiveTabIndex ?? activeTabIndex;
32
- }, [ editorActiveTabIndex, activeTabIndex ] );
33
-
34
- const { menuItemIndex, tabsClientId, selectedTabClientId } = useSelect(
35
- ( select ) => {
36
- const {
37
- getBlockOrder,
38
- getBlockRootClientId,
39
- getSelectedBlockClientIds,
40
- hasSelectedInnerBlock,
41
- } = select( blockEditorStore );
42
-
43
- const _tabsMenuClientId = getBlockRootClientId( clientId );
44
- const _tabsClientId = _tabsMenuClientId
45
- ? getBlockRootClientId( _tabsMenuClientId )
46
- : null;
47
-
48
- const siblings = getBlockOrder( _tabsMenuClientId );
49
- const _menuItemIndex = 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
- }
63
-
64
- return {
65
- menuItemIndex: _menuItemIndex,
66
- tabsClientId: _tabsClientId,
67
- selectedTabClientId: _selectedTabClientId,
68
- };
69
- },
70
- [ clientId, tabsList ]
71
- );
72
-
73
- const tab = tabsList[ menuItemIndex ] || {};
74
-
75
- // tabListIndex is the tab's position in tabsList, used for active-state
76
- // checks and click handling.
77
- const tabListIndex = tab.index ?? menuItemIndex;
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 } =
86
- useDispatch( blockEditorStore );
87
-
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
- ]
105
- );
106
-
107
- const handleLabelChange = useCallback(
108
- ( newLabel ) => {
109
- if ( tabClientId ) {
110
- updateBlockAttributes( tabClientId, { label: newLabel } );
111
- }
112
- },
113
- [ tabClientId, updateBlockAttributes ]
114
- );
115
-
116
- const blockProps = useBlockProps( {
117
- className: clsx( {
118
- 'is-active': isActive,
119
- 'is-selected': isSelected,
120
- } ),
121
- tabIndex: -1,
122
- onClick: handleTabClick,
123
- } );
124
-
125
- return (
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
- </>
138
- );
139
- }
140
-
141
- export default Edit;
@@ -1,70 +0,0 @@
1
- <?php
2
- /**
3
- * Tabs Menu Item Block
4
- *
5
- * @package WordPress
6
- */
7
-
8
- /**
9
- * Render callback for core/tabs-menu-item.
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 tabs-menu
13
- * render callback before this is called.
14
- *
15
- * @since 7.0.0
16
- *
17
- * @param array $attributes Block attributes.
18
- * @param string $content Block content (styled button from save.js).
19
- * @param \WP_Block $block WP_Block instance.
20
- *
21
- * @return string Updated HTML.
22
- */
23
- function block_core_tabs_menu_item_render_callback( array $attributes, string $content, \WP_Block $block ): string {
24
- $tab_index = $block->context['core/tabs-menu-item-index'] ?? 0;
25
- $tab_id = $block->context['core/tabs-menu-item-id'] ?? '';
26
- $tab_label = $block->context['core/tabs-menu-item-label'] ?? '';
27
-
28
- if ( empty( $tab_id ) ) {
29
- $tab_id = 'tab-' . $tab_index;
30
- }
31
-
32
- // Add Interactivity API directives and tab-specific attributes to the button.
33
- $tag_processor = new WP_HTML_Tag_Processor( $content );
34
-
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
- );
46
- }
47
-
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
54
- );
55
- }
56
-
57
- /**
58
- * Registers the `core/tabs-menu-item` block on the server.
59
- *
60
- * @since 7.0.0
61
- */
62
- function register_block_core_tabs_menu_item() {
63
- register_block_type_from_metadata(
64
- __DIR__ . '/tabs-menu-item',
65
- array(
66
- 'render_callback' => 'block_core_tabs_menu_item_render_callback',
67
- )
68
- );
69
- }
70
- add_action( 'init', 'register_block_core_tabs_menu_item' );
@@ -1,13 +0,0 @@
1
- /**
2
- * WordPress dependencies
3
- */
4
- import { useBlockProps } from '@wordpress/block-editor';
5
-
6
- export default function save() {
7
- const blockProps = useBlockProps.save( {
8
- type: 'button',
9
- role: 'tab',
10
- } );
11
-
12
- return <button { ...blockProps } />;
13
- }
@@ -1,40 +0,0 @@
1
- .wp-block-tabs-menu-item {
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;
11
-
12
- // Button reset
13
- border: none;
14
- background: none;
15
- appearance: none;
16
- -webkit-appearance: none;
17
-
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;
29
-
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
- }
40
- }
File without changes
File without changes