@wordpress/block-library 9.41.1-next.v.202603102151.0 → 9.42.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 (140) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/cover/edit/cover-placeholder.cjs +7 -0
  3. package/build/cover/edit/cover-placeholder.cjs.map +2 -2
  4. package/build/html/modal.cjs +151 -229
  5. package/build/html/modal.cjs.map +2 -2
  6. package/build/image/edit.cjs +7 -0
  7. package/build/image/edit.cjs.map +2 -2
  8. package/build/media-text/media-container.cjs +6 -0
  9. package/build/media-text/media-container.cjs.map +2 -2
  10. package/build/navigation/edit/index.cjs +5 -4
  11. package/build/navigation/edit/index.cjs.map +2 -2
  12. package/build/navigation-link/shared/use-link-preview.cjs +29 -0
  13. package/build/navigation-link/shared/use-link-preview.cjs.map +2 -2
  14. package/build/nextpage/block.json +0 -1
  15. package/build/playlist-track/block.json +0 -0
  16. package/build/post-date/block.json +1 -3
  17. package/build/post-date/deprecated.cjs +82 -6
  18. package/build/post-date/deprecated.cjs.map +3 -3
  19. package/build/post-date/edit.cjs +49 -62
  20. package/build/post-date/edit.cjs.map +3 -3
  21. package/build/site-logo/edit.cjs +1 -3
  22. package/build/site-logo/edit.cjs.map +2 -2
  23. package/build/site-title/index.cjs +5 -1
  24. package/build/site-title/index.cjs.map +2 -2
  25. package/build/tab/add-tab-toolbar-control.cjs +22 -5
  26. package/build/tab/add-tab-toolbar-control.cjs.map +2 -2
  27. package/build/tab/remove-tab-toolbar-control.cjs +19 -1
  28. package/build/tab/remove-tab-toolbar-control.cjs.map +2 -2
  29. package/build/tabs/edit.cjs +85 -7
  30. package/build/tabs/edit.cjs.map +2 -2
  31. package/build/tabs/index.cjs +12 -2
  32. package/build/tabs/index.cjs.map +2 -2
  33. package/build/tabs-menu/block.json +1 -6
  34. package/build/tabs-menu/edit.cjs +11 -151
  35. package/build/tabs-menu/edit.cjs.map +3 -3
  36. package/build/tabs-menu/save.cjs.map +2 -2
  37. package/build/tabs-menu-item/block.json +14 -11
  38. package/build/tabs-menu-item/controls.cjs +2 -133
  39. package/build/tabs-menu-item/controls.cjs.map +3 -3
  40. package/build/tabs-menu-item/edit.cjs +44 -56
  41. package/build/tabs-menu-item/edit.cjs.map +3 -3
  42. package/build/tabs-menu-item/save.cjs +0 -1
  43. package/build/tabs-menu-item/save.cjs.map +2 -2
  44. package/build/utils/media-control.cjs +72 -29
  45. package/build/utils/media-control.cjs.map +3 -3
  46. package/build-module/cover/edit/cover-placeholder.mjs +7 -0
  47. package/build-module/cover/edit/cover-placeholder.mjs.map +2 -2
  48. package/build-module/html/modal.mjs +151 -229
  49. package/build-module/html/modal.mjs.map +2 -2
  50. package/build-module/image/edit.mjs +7 -0
  51. package/build-module/image/edit.mjs.map +2 -2
  52. package/build-module/media-text/media-container.mjs +7 -1
  53. package/build-module/media-text/media-container.mjs.map +2 -2
  54. package/build-module/navigation/edit/index.mjs +5 -4
  55. package/build-module/navigation/edit/index.mjs.map +2 -2
  56. package/build-module/navigation-link/shared/use-link-preview.mjs +28 -0
  57. package/build-module/navigation-link/shared/use-link-preview.mjs.map +2 -2
  58. package/build-module/nextpage/block.json +0 -1
  59. package/build-module/playlist-track/block.json +0 -0
  60. package/build-module/post-date/block.json +1 -3
  61. package/build-module/post-date/deprecated.mjs +82 -6
  62. package/build-module/post-date/deprecated.mjs.map +2 -2
  63. package/build-module/post-date/edit.mjs +49 -63
  64. package/build-module/post-date/edit.mjs.map +2 -2
  65. package/build-module/site-logo/edit.mjs +1 -3
  66. package/build-module/site-logo/edit.mjs.map +2 -2
  67. package/build-module/site-title/index.mjs +5 -1
  68. package/build-module/site-title/index.mjs.map +2 -2
  69. package/build-module/tab/add-tab-toolbar-control.mjs +22 -5
  70. package/build-module/tab/add-tab-toolbar-control.mjs.map +2 -2
  71. package/build-module/tab/remove-tab-toolbar-control.mjs +19 -1
  72. package/build-module/tab/remove-tab-toolbar-control.mjs.map +2 -2
  73. package/build-module/tabs/edit.mjs +87 -9
  74. package/build-module/tabs/edit.mjs.map +2 -2
  75. package/build-module/tabs/index.mjs +12 -2
  76. package/build-module/tabs/index.mjs.map +2 -2
  77. package/build-module/tabs-menu/block.json +1 -6
  78. package/build-module/tabs-menu/edit.mjs +13 -162
  79. package/build-module/tabs-menu/edit.mjs.map +2 -2
  80. package/build-module/tabs-menu/save.mjs.map +2 -2
  81. package/build-module/tabs-menu-item/block.json +14 -11
  82. package/build-module/tabs-menu-item/controls.mjs +4 -143
  83. package/build-module/tabs-menu-item/controls.mjs.map +2 -2
  84. package/build-module/tabs-menu-item/edit.mjs +45 -57
  85. package/build-module/tabs-menu-item/edit.mjs.map +3 -3
  86. package/build-module/tabs-menu-item/save.mjs +0 -1
  87. package/build-module/tabs-menu-item/save.mjs.map +2 -2
  88. package/build-module/utils/media-control.mjs +73 -30
  89. package/build-module/utils/media-control.mjs.map +2 -2
  90. package/build-style/editor-rtl.css +45 -11
  91. package/build-style/editor.css +45 -11
  92. package/build-style/navigation/style-rtl.css +4 -0
  93. package/build-style/navigation/style.css +4 -0
  94. package/build-style/navigation-overlay-close/style-rtl.css +3 -3
  95. package/build-style/navigation-overlay-close/style.css +3 -3
  96. package/build-style/style-rtl.css +7 -3
  97. package/build-style/style.css +7 -3
  98. package/build-style/tabs-menu/editor-rtl.css +5 -3
  99. package/build-style/tabs-menu/editor.css +5 -3
  100. package/package.json +38 -38
  101. package/src/cover/edit/cover-placeholder.js +8 -0
  102. package/src/html/modal.js +6 -77
  103. package/src/image/edit.js +8 -0
  104. package/src/media-text/media-container.js +8 -1
  105. package/src/navigation/edit/index.js +6 -4
  106. package/src/navigation/index.php +24 -17
  107. package/src/navigation/style.scss +10 -0
  108. package/src/navigation-link/index.php +9 -9
  109. package/src/navigation-link/shared/test/use-link-preview.test.js +149 -0
  110. package/src/navigation-link/shared/use-link-preview.js +43 -1
  111. package/src/navigation-overlay-close/style.scss +3 -3
  112. package/src/navigation-submenu/index.php +17 -11
  113. package/src/nextpage/block.json +0 -1
  114. package/src/playlist-track/block.json +0 -0
  115. package/src/playlist-track/edit.js +0 -0
  116. package/src/playlist-track/index.js +0 -0
  117. package/src/playlist-track/index.php +0 -0
  118. package/src/playlist-track/init.js +0 -0
  119. package/src/playlist-track/style.scss +0 -0
  120. package/src/post-date/block.json +1 -3
  121. package/src/post-date/deprecated.js +86 -6
  122. package/src/post-date/edit.js +65 -82
  123. package/src/site-logo/edit.js +1 -3
  124. package/src/site-title/index.js +5 -1
  125. package/src/tab/add-tab-toolbar-control.js +48 -23
  126. package/src/tab/remove-tab-toolbar-control.js +30 -10
  127. package/src/tabs/edit.js +133 -10
  128. package/src/tabs/index.js +12 -2
  129. package/src/tabs-menu/block.json +1 -6
  130. package/src/tabs-menu/edit.js +13 -214
  131. package/src/tabs-menu/editor.scss +7 -3
  132. package/src/tabs-menu/index.php +42 -27
  133. package/src/tabs-menu/save.js +0 -4
  134. package/src/tabs-menu-item/block.json +14 -11
  135. package/src/tabs-menu-item/controls.js +4 -167
  136. package/src/tabs-menu-item/edit.js +60 -69
  137. package/src/tabs-menu-item/index.php +11 -23
  138. package/src/tabs-menu-item/save.js +0 -1
  139. package/src/utils/media-control.js +61 -21
  140. package/src/utils/media-control.scss +54 -18
@@ -10,12 +10,13 @@ import { useDispatch, useSelect } from "@wordpress/data";
10
10
  import { jsx } from "react/jsx-runtime";
11
11
  function AddTabToolbarControl({ tabsClientId }) {
12
12
  const { insertBlock } = useDispatch(blockEditorStore);
13
- const { tabPanelClientId, nextTabIndex } = useSelect(
13
+ const { tabPanelClientId, tabsMenuClientId, tabCount, existingAnchors } = useSelect(
14
14
  (select) => {
15
15
  if (!tabsClientId) {
16
16
  return {
17
17
  tabPanelClientId: null,
18
- nextTabIndex: 0
18
+ tabsMenuClientId: null,
19
+ existingAnchors: []
19
20
  };
20
21
  }
21
22
  const { getBlocks } = select(blockEditorStore);
@@ -23,9 +24,14 @@ function AddTabToolbarControl({ tabsClientId }) {
23
24
  const tabPanel = innerBlocks.find(
24
25
  (block) => block.name === "core/tab-panel"
25
26
  );
27
+ const tabsMenu = innerBlocks.find(
28
+ (block) => block.name === "core/tabs-menu"
29
+ );
26
30
  return {
27
31
  tabPanelClientId: tabPanel?.clientId || null,
28
- nextTabIndex: (tabPanel?.innerBlocks.length || 0) + 1
32
+ tabsMenuClientId: tabsMenu?.clientId || null,
33
+ tabCount: tabPanel?.innerBlocks?.length || 0,
34
+ existingAnchors: (tabPanel?.innerBlocks || []).map((block) => block.attributes.anchor).filter(Boolean)
29
35
  };
30
36
  },
31
37
  [tabsClientId]
@@ -34,12 +40,23 @@ function AddTabToolbarControl({ tabsClientId }) {
34
40
  if (!tabPanelClientId) {
35
41
  return;
36
42
  }
43
+ const existingAnchorSet = new Set(existingAnchors);
44
+ let tabNumber = tabCount + 1;
45
+ while (existingAnchorSet.has(`tab-${tabNumber}`)) {
46
+ tabNumber++;
47
+ }
37
48
  const newTabBlock = createBlock("core/tab", {
38
- anchor: "tab-" + nextTabIndex,
49
+ anchor: `tab-${tabNumber}`,
39
50
  /* translators: %d: tab number */
40
- label: sprintf(__("Tab %d"), nextTabIndex)
51
+ label: sprintf(__("Tab %d"), tabNumber)
41
52
  });
42
53
  insertBlock(newTabBlock, void 0, tabPanelClientId);
54
+ if (tabsMenuClientId) {
55
+ const newMenuItemBlock = createBlock("core/tabs-menu-item", {
56
+ anchor: `tab-${tabNumber}-button`
57
+ });
58
+ insertBlock(newMenuItemBlock, void 0, tabsMenuClientId);
59
+ }
43
60
  };
44
61
  return /* @__PURE__ */ jsx(BlockControls, { group: "other", children: /* @__PURE__ */ jsx(ToolbarGroup, { children: /* @__PURE__ */ jsx(
45
62
  ToolbarButton,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/tab/add-tab-toolbar-control.js"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { sprintf, __ } from '@wordpress/i18n';\nimport { createBlock } from '@wordpress/blocks';\nimport {\n\tBlockControls,\n\tstore as blockEditorStore,\n} from '@wordpress/block-editor';\nimport { ToolbarGroup, ToolbarButton } from '@wordpress/components';\nimport { useDispatch, useSelect } from '@wordpress/data';\n\n/**\n * \"Add tab\" button in the block toolbar for the tab block.\n * Inserts new tabs into the tab-panel block.\n *\n * @param {Object} props\n * @param {string} props.tabsClientId The client ID of the parent tabs block.\n * @return {React.JSX.Element} The toolbar control element.\n */\nexport default function AddTabToolbarControl( { tabsClientId } ) {\n\tconst { insertBlock } = useDispatch( blockEditorStore );\n\n\t// Find the tab-panel block within the tabs block\n\tconst { tabPanelClientId, nextTabIndex } = useSelect(\n\t\t( select ) => {\n\t\t\tif ( ! tabsClientId ) {\n\t\t\t\treturn {\n\t\t\t\t\ttabPanelClientId: null,\n\t\t\t\t\tnextTabIndex: 0,\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst { getBlocks } = select( blockEditorStore );\n\t\t\tconst innerBlocks = getBlocks( tabsClientId );\n\t\t\tconst tabPanel = innerBlocks.find(\n\t\t\t\t( block ) => block.name === 'core/tab-panel'\n\t\t\t);\n\t\t\treturn {\n\t\t\t\ttabPanelClientId: tabPanel?.clientId || null,\n\t\t\t\tnextTabIndex: ( tabPanel?.innerBlocks.length || 0 ) + 1,\n\t\t\t};\n\t\t},\n\t\t[ tabsClientId ]\n\t);\n\n\tconst addTab = () => {\n\t\tif ( ! tabPanelClientId ) {\n\t\t\treturn;\n\t\t}\n\t\tconst newTabBlock = createBlock( 'core/tab', {\n\t\t\tanchor: 'tab-' + nextTabIndex,\n\t\t\t/* translators: %d: tab number */\n\t\t\tlabel: sprintf( __( 'Tab %d' ), nextTabIndex ),\n\t\t} );\n\t\tinsertBlock( newTabBlock, undefined, tabPanelClientId );\n\t\t// @TODO: Possible select and focus the tabs-menu-item active tab RichText editor?\n\t};\n\n\treturn (\n\t\t<BlockControls group=\"other\">\n\t\t\t<ToolbarGroup>\n\t\t\t\t<ToolbarButton\n\t\t\t\t\tclassName=\"components-toolbar__control\"\n\t\t\t\t\tonClick={ addTab }\n\t\t\t\t\ttext={ __( 'Add tab' ) }\n\t\t\t\t/>\n\t\t\t</ToolbarGroup>\n\t\t</BlockControls>\n\t);\n}\n"],
5
- "mappings": ";AAGA,SAAS,SAAS,UAAU;AAC5B,SAAS,mBAAmB;AAC5B;AAAA,EACC;AAAA,EACA,SAAS;AAAA,OACH;AACP,SAAS,cAAc,qBAAqB;AAC5C,SAAS,aAAa,iBAAiB;AAmDnC;AAzCW,SAAR,qBAAuC,EAAE,aAAa,GAAI;AAChE,QAAM,EAAE,YAAY,IAAI,YAAa,gBAAiB;AAGtD,QAAM,EAAE,kBAAkB,aAAa,IAAI;AAAA,IAC1C,CAAE,WAAY;AACb,UAAK,CAAE,cAAe;AACrB,eAAO;AAAA,UACN,kBAAkB;AAAA,UAClB,cAAc;AAAA,QACf;AAAA,MACD;AACA,YAAM,EAAE,UAAU,IAAI,OAAQ,gBAAiB;AAC/C,YAAM,cAAc,UAAW,YAAa;AAC5C,YAAM,WAAW,YAAY;AAAA,QAC5B,CAAE,UAAW,MAAM,SAAS;AAAA,MAC7B;AACA,aAAO;AAAA,QACN,kBAAkB,UAAU,YAAY;AAAA,QACxC,eAAgB,UAAU,YAAY,UAAU,KAAM;AAAA,MACvD;AAAA,IACD;AAAA,IACA,CAAE,YAAa;AAAA,EAChB;AAEA,QAAM,SAAS,MAAM;AACpB,QAAK,CAAE,kBAAmB;AACzB;AAAA,IACD;AACA,UAAM,cAAc,YAAa,YAAY;AAAA,MAC5C,QAAQ,SAAS;AAAA;AAAA,MAEjB,OAAO,QAAS,GAAI,QAAS,GAAG,YAAa;AAAA,IAC9C,CAAE;AACF,gBAAa,aAAa,QAAW,gBAAiB;AAAA,EAEvD;AAEA,SACC,oBAAC,iBAAc,OAAM,SACpB,8BAAC,gBACA;AAAA,IAAC;AAAA;AAAA,MACA,WAAU;AAAA,MACV,SAAU;AAAA,MACV,MAAO,GAAI,SAAU;AAAA;AAAA,EACtB,GACD,GACD;AAEF;",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { sprintf, __ } from '@wordpress/i18n';\nimport { createBlock } from '@wordpress/blocks';\nimport {\n\tBlockControls,\n\tstore as blockEditorStore,\n} from '@wordpress/block-editor';\nimport { ToolbarGroup, ToolbarButton } from '@wordpress/components';\nimport { useDispatch, useSelect } from '@wordpress/data';\n\n/**\n * \"Add tab\" button in the block toolbar for the tab block.\n * Inserts a new core/tab into the tab-panel and a new core/tabs-menu-item\n * into the tabs-menu, keeping both in sync.\n *\n * @param {Object} props\n * @param {string} props.tabsClientId The client ID of the parent tabs block.\n * @return {React.JSX.Element} The toolbar control element.\n */\nexport default function AddTabToolbarControl( { tabsClientId } ) {\n\tconst { insertBlock } = useDispatch( blockEditorStore );\n\n\tconst { tabPanelClientId, tabsMenuClientId, tabCount, existingAnchors } =\n\t\tuseSelect(\n\t\t\t( select ) => {\n\t\t\t\tif ( ! tabsClientId ) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttabPanelClientId: null,\n\t\t\t\t\t\ttabsMenuClientId: null,\n\t\t\t\t\t\texistingAnchors: [],\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tconst { getBlocks } = select( blockEditorStore );\n\t\t\t\tconst innerBlocks = getBlocks( tabsClientId );\n\t\t\t\tconst tabPanel = innerBlocks.find(\n\t\t\t\t\t( block ) => block.name === 'core/tab-panel'\n\t\t\t\t);\n\t\t\t\tconst tabsMenu = innerBlocks.find(\n\t\t\t\t\t( block ) => block.name === 'core/tabs-menu'\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\ttabPanelClientId: tabPanel?.clientId || null,\n\t\t\t\t\ttabsMenuClientId: tabsMenu?.clientId || null,\n\t\t\t\t\ttabCount: tabPanel?.innerBlocks?.length || 0,\n\t\t\t\t\texistingAnchors: ( tabPanel?.innerBlocks || [] )\n\t\t\t\t\t\t.map( ( block ) => block.attributes.anchor )\n\t\t\t\t\t\t.filter( Boolean ),\n\t\t\t\t};\n\t\t\t},\n\t\t\t[ tabsClientId ]\n\t\t);\n\n\tconst addTab = () => {\n\t\tif ( ! tabPanelClientId ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Start from count + 1 so the label stays sequential, then increment\n\t\t// until the anchor slot is free.\n\t\tconst existingAnchorSet = new Set( existingAnchors );\n\t\tlet tabNumber = tabCount + 1;\n\t\twhile ( existingAnchorSet.has( `tab-${ tabNumber }` ) ) {\n\t\t\ttabNumber++;\n\t\t}\n\n\t\tconst newTabBlock = createBlock( 'core/tab', {\n\t\t\tanchor: `tab-${ tabNumber }`,\n\t\t\t/* translators: %d: tab number */\n\t\t\tlabel: sprintf( __( 'Tab %d' ), tabNumber ),\n\t\t} );\n\t\tinsertBlock( newTabBlock, undefined, tabPanelClientId );\n\n\t\t// Insert a corresponding menu item into the tabs-menu.\n\t\tif ( tabsMenuClientId ) {\n\t\t\tconst newMenuItemBlock = createBlock( 'core/tabs-menu-item', {\n\t\t\t\tanchor: `tab-${ tabNumber }-button`,\n\t\t\t} );\n\t\t\tinsertBlock( newMenuItemBlock, undefined, tabsMenuClientId );\n\t\t}\n\t};\n\n\treturn (\n\t\t<BlockControls group=\"other\">\n\t\t\t<ToolbarGroup>\n\t\t\t\t<ToolbarButton\n\t\t\t\t\tclassName=\"components-toolbar__control\"\n\t\t\t\t\tonClick={ addTab }\n\t\t\t\t\ttext={ __( 'Add tab' ) }\n\t\t\t\t/>\n\t\t\t</ToolbarGroup>\n\t\t</BlockControls>\n\t);\n}\n"],
5
+ "mappings": ";AAGA,SAAS,SAAS,UAAU;AAC5B,SAAS,mBAAmB;AAC5B;AAAA,EACC;AAAA,EACA,SAAS;AAAA,OACH;AACP,SAAS,cAAc,qBAAqB;AAC5C,SAAS,aAAa,iBAAiB;AA4EnC;AAjEW,SAAR,qBAAuC,EAAE,aAAa,GAAI;AAChE,QAAM,EAAE,YAAY,IAAI,YAAa,gBAAiB;AAEtD,QAAM,EAAE,kBAAkB,kBAAkB,UAAU,gBAAgB,IACrE;AAAA,IACC,CAAE,WAAY;AACb,UAAK,CAAE,cAAe;AACrB,eAAO;AAAA,UACN,kBAAkB;AAAA,UAClB,kBAAkB;AAAA,UAClB,iBAAiB,CAAC;AAAA,QACnB;AAAA,MACD;AACA,YAAM,EAAE,UAAU,IAAI,OAAQ,gBAAiB;AAC/C,YAAM,cAAc,UAAW,YAAa;AAC5C,YAAM,WAAW,YAAY;AAAA,QAC5B,CAAE,UAAW,MAAM,SAAS;AAAA,MAC7B;AACA,YAAM,WAAW,YAAY;AAAA,QAC5B,CAAE,UAAW,MAAM,SAAS;AAAA,MAC7B;AACA,aAAO;AAAA,QACN,kBAAkB,UAAU,YAAY;AAAA,QACxC,kBAAkB,UAAU,YAAY;AAAA,QACxC,UAAU,UAAU,aAAa,UAAU;AAAA,QAC3C,kBAAmB,UAAU,eAAe,CAAC,GAC3C,IAAK,CAAE,UAAW,MAAM,WAAW,MAAO,EAC1C,OAAQ,OAAQ;AAAA,MACnB;AAAA,IACD;AAAA,IACA,CAAE,YAAa;AAAA,EAChB;AAED,QAAM,SAAS,MAAM;AACpB,QAAK,CAAE,kBAAmB;AACzB;AAAA,IACD;AAIA,UAAM,oBAAoB,IAAI,IAAK,eAAgB;AACnD,QAAI,YAAY,WAAW;AAC3B,WAAQ,kBAAkB,IAAK,OAAQ,SAAU,EAAG,GAAI;AACvD;AAAA,IACD;AAEA,UAAM,cAAc,YAAa,YAAY;AAAA,MAC5C,QAAQ,OAAQ,SAAU;AAAA;AAAA,MAE1B,OAAO,QAAS,GAAI,QAAS,GAAG,SAAU;AAAA,IAC3C,CAAE;AACF,gBAAa,aAAa,QAAW,gBAAiB;AAGtD,QAAK,kBAAmB;AACvB,YAAM,mBAAmB,YAAa,uBAAuB;AAAA,QAC5D,QAAQ,OAAQ,SAAU;AAAA,MAC3B,CAAE;AACF,kBAAa,kBAAkB,QAAW,gBAAiB;AAAA,IAC5D;AAAA,EACD;AAEA,SACC,oBAAC,iBAAc,OAAM,SACpB,8BAAC,gBACA;AAAA,IAAC;AAAA;AAAA,MACA,WAAU;AAAA,MACV,SAAU;AAAA,MACV,MAAO,GAAI,SAAU;AAAA;AAAA,EACtB,GACD,GACD;AAEF;",
6
6
  "names": []
7
7
  }
@@ -14,11 +14,17 @@ function RemoveTabToolbarControl({ tabsClientId }) {
14
14
  selectBlock,
15
15
  __unstableMarkNextChangeAsNotPersistent
16
16
  } = useDispatch(blockEditorStore);
17
- const { activeTabClientId, tabCount, editorActiveTabIndex } = useSelect(
17
+ const {
18
+ activeTabClientId,
19
+ activeMenuItemClientId,
20
+ tabCount,
21
+ editorActiveTabIndex
22
+ } = useSelect(
18
23
  (select) => {
19
24
  if (!tabsClientId) {
20
25
  return {
21
26
  activeTabClientId: null,
27
+ activeMenuItemClientId: null,
22
28
  tabCount: 0,
23
29
  editorActiveTabIndex: 0
24
30
  };
@@ -30,10 +36,19 @@ function RemoveTabToolbarControl({ tabsClientId }) {
30
36
  const tabPanel = innerBlocks.find(
31
37
  (block) => block.name === "core/tab-panel"
32
38
  );
39
+ const tabsMenu = innerBlocks.find(
40
+ (block) => block.name === "core/tabs-menu"
41
+ );
33
42
  const tabs = tabPanel?.innerBlocks || [];
43
+ const menuItems = tabsMenu?.innerBlocks || [];
34
44
  const activeTab = tabs[activeIndex];
45
+ const expectedMenuAnchor = activeTab?.attributes?.anchor ? `${activeTab.attributes.anchor}-button` : null;
46
+ const activeMenuItem = expectedMenuAnchor ? menuItems.find(
47
+ (m) => m.attributes?.anchor === expectedMenuAnchor
48
+ ) : menuItems[activeIndex];
35
49
  return {
36
50
  activeTabClientId: activeTab?.clientId || null,
51
+ activeMenuItemClientId: activeMenuItem?.clientId || null,
37
52
  tabCount: tabs.length,
38
53
  editorActiveTabIndex: activeIndex
39
54
  };
@@ -50,6 +65,9 @@ function RemoveTabToolbarControl({ tabsClientId }) {
50
65
  editorActiveTabIndex: newActiveIndex
51
66
  });
52
67
  removeBlock(activeTabClientId, false);
68
+ if (activeMenuItemClientId) {
69
+ removeBlock(activeMenuItemClientId, false);
70
+ }
53
71
  if (tabsClientId) {
54
72
  selectBlock(tabsClientId);
55
73
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/tab/remove-tab-toolbar-control.js"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport {\n\tBlockControls,\n\tstore as blockEditorStore,\n} from '@wordpress/block-editor';\nimport { ToolbarGroup, ToolbarButton } from '@wordpress/components';\nimport { __ } from '@wordpress/i18n';\nimport { useDispatch, useSelect } from '@wordpress/data';\n\n/**\n * \"Remove Tab\" button in the block toolbar for the tab block.\n * Removes the currently active tab from the tab-panel block.\n *\n * @param {Object} props\n * @param {string} props.tabsClientId The client ID of the parent tabs block.\n * @return {React.JSX.Element} The toolbar control element.\n */\nexport default function RemoveTabToolbarControl( { tabsClientId } ) {\n\tconst {\n\t\tremoveBlock,\n\t\tupdateBlockAttributes,\n\t\tselectBlock,\n\t\t__unstableMarkNextChangeAsNotPersistent,\n\t} = useDispatch( blockEditorStore );\n\n\t// Find the tab-panel block, active tab, and tab count within the tabs block\n\tconst { activeTabClientId, tabCount, editorActiveTabIndex } = useSelect(\n\t\t( select ) => {\n\t\t\tif ( ! tabsClientId ) {\n\t\t\t\treturn {\n\t\t\t\t\tactiveTabClientId: null,\n\t\t\t\t\ttabCount: 0,\n\t\t\t\t\teditorActiveTabIndex: 0,\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst { getBlocks, getBlockAttributes } =\n\t\t\t\tselect( blockEditorStore );\n\t\t\tconst tabsAttributes = getBlockAttributes( tabsClientId );\n\t\t\tconst activeIndex =\n\t\t\t\ttabsAttributes?.editorActiveTabIndex ??\n\t\t\t\ttabsAttributes?.activeTabIndex ??\n\t\t\t\t0;\n\t\t\tconst innerBlocks = getBlocks( tabsClientId );\n\t\t\tconst tabPanel = innerBlocks.find(\n\t\t\t\t( block ) => block.name === 'core/tab-panel'\n\t\t\t);\n\t\t\tconst tabs = tabPanel?.innerBlocks || [];\n\t\t\tconst activeTab = tabs[ activeIndex ];\n\t\t\treturn {\n\t\t\t\tactiveTabClientId: activeTab?.clientId || null,\n\t\t\t\ttabCount: tabs.length,\n\t\t\t\teditorActiveTabIndex: activeIndex,\n\t\t\t};\n\t\t},\n\t\t[ tabsClientId ]\n\t);\n\n\tconst removeTab = () => {\n\t\tif ( ! activeTabClientId || tabCount <= 1 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Calculate new active index after removal\n\t\tconst newActiveIndex =\n\t\t\teditorActiveTabIndex >= tabCount - 1\n\t\t\t\t? tabCount - 2 // If removing last tab, select the previous one\n\t\t\t\t: editorActiveTabIndex; // Otherwise keep the same index (next tab shifts into position)\n\n\t\t// Update the active tab index before removing\n\t\t__unstableMarkNextChangeAsNotPersistent();\n\t\tupdateBlockAttributes( tabsClientId, {\n\t\t\teditorActiveTabIndex: newActiveIndex,\n\t\t} );\n\n\t\t// Remove the tab\n\t\tremoveBlock( activeTabClientId, false );\n\n\t\t// Select the tabs block after removal\n\t\tif ( tabsClientId ) {\n\t\t\tselectBlock( tabsClientId );\n\t\t}\n\t};\n\n\t// Don't show the button if there's only one tab or no active tab\n\tconst isDisabled = tabCount <= 1 || ! activeTabClientId;\n\n\treturn (\n\t\t<BlockControls group=\"other\">\n\t\t\t<ToolbarGroup>\n\t\t\t\t<ToolbarButton\n\t\t\t\t\tclassName=\"components-toolbar__control\"\n\t\t\t\t\tonClick={ removeTab }\n\t\t\t\t\ttext={ __( 'Remove tab' ) }\n\t\t\t\t\tdisabled={ isDisabled }\n\t\t\t\t/>\n\t\t\t</ToolbarGroup>\n\t\t</BlockControls>\n\t);\n}\n"],
5
- "mappings": ";AAGA;AAAA,EACC;AAAA,EACA,SAAS;AAAA,OACH;AACP,SAAS,cAAc,qBAAqB;AAC5C,SAAS,UAAU;AACnB,SAAS,aAAa,iBAAiB;AAkFnC;AAxEW,SAAR,wBAA0C,EAAE,aAAa,GAAI;AACnE,QAAM;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI,YAAa,gBAAiB;AAGlC,QAAM,EAAE,mBAAmB,UAAU,qBAAqB,IAAI;AAAA,IAC7D,CAAE,WAAY;AACb,UAAK,CAAE,cAAe;AACrB,eAAO;AAAA,UACN,mBAAmB;AAAA,UACnB,UAAU;AAAA,UACV,sBAAsB;AAAA,QACvB;AAAA,MACD;AACA,YAAM,EAAE,WAAW,mBAAmB,IACrC,OAAQ,gBAAiB;AAC1B,YAAM,iBAAiB,mBAAoB,YAAa;AACxD,YAAM,cACL,gBAAgB,wBAChB,gBAAgB,kBAChB;AACD,YAAM,cAAc,UAAW,YAAa;AAC5C,YAAM,WAAW,YAAY;AAAA,QAC5B,CAAE,UAAW,MAAM,SAAS;AAAA,MAC7B;AACA,YAAM,OAAO,UAAU,eAAe,CAAC;AACvC,YAAM,YAAY,KAAM,WAAY;AACpC,aAAO;AAAA,QACN,mBAAmB,WAAW,YAAY;AAAA,QAC1C,UAAU,KAAK;AAAA,QACf,sBAAsB;AAAA,MACvB;AAAA,IACD;AAAA,IACA,CAAE,YAAa;AAAA,EAChB;AAEA,QAAM,YAAY,MAAM;AACvB,QAAK,CAAE,qBAAqB,YAAY,GAAI;AAC3C;AAAA,IACD;AAGA,UAAM,iBACL,wBAAwB,WAAW,IAChC,WAAW,IACX;AAGJ,4CAAwC;AACxC,0BAAuB,cAAc;AAAA,MACpC,sBAAsB;AAAA,IACvB,CAAE;AAGF,gBAAa,mBAAmB,KAAM;AAGtC,QAAK,cAAe;AACnB,kBAAa,YAAa;AAAA,IAC3B;AAAA,EACD;AAGA,QAAM,aAAa,YAAY,KAAK,CAAE;AAEtC,SACC,oBAAC,iBAAc,OAAM,SACpB,8BAAC,gBACA;AAAA,IAAC;AAAA;AAAA,MACA,WAAU;AAAA,MACV,SAAU;AAAA,MACV,MAAO,GAAI,YAAa;AAAA,MACxB,UAAW;AAAA;AAAA,EACZ,GACD,GACD;AAEF;",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport {\n\tBlockControls,\n\tstore as blockEditorStore,\n} from '@wordpress/block-editor';\nimport { ToolbarGroup, ToolbarButton } from '@wordpress/components';\nimport { __ } from '@wordpress/i18n';\nimport { useDispatch, useSelect } from '@wordpress/data';\n\n/**\n * \"Remove Tab\" button in the block toolbar for the tab block.\n * Removes the currently active core/tab and its corresponding\n * core/tabs-menu-item, keeping both in sync.\n *\n * @param {Object} props\n * @param {string} props.tabsClientId The client ID of the parent tabs block.\n * @return {React.JSX.Element} The toolbar control element.\n */\nexport default function RemoveTabToolbarControl( { tabsClientId } ) {\n\tconst {\n\t\tremoveBlock,\n\t\tupdateBlockAttributes,\n\t\tselectBlock,\n\t\t__unstableMarkNextChangeAsNotPersistent,\n\t} = useDispatch( blockEditorStore );\n\n\tconst {\n\t\tactiveTabClientId,\n\t\tactiveMenuItemClientId,\n\t\ttabCount,\n\t\teditorActiveTabIndex,\n\t} = useSelect(\n\t\t( select ) => {\n\t\t\tif ( ! tabsClientId ) {\n\t\t\t\treturn {\n\t\t\t\t\tactiveTabClientId: null,\n\t\t\t\t\tactiveMenuItemClientId: null,\n\t\t\t\t\ttabCount: 0,\n\t\t\t\t\teditorActiveTabIndex: 0,\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst { getBlocks, getBlockAttributes } =\n\t\t\t\tselect( blockEditorStore );\n\t\t\tconst tabsAttributes = getBlockAttributes( tabsClientId );\n\t\t\tconst activeIndex =\n\t\t\t\ttabsAttributes?.editorActiveTabIndex ??\n\t\t\t\ttabsAttributes?.activeTabIndex ??\n\t\t\t\t0;\n\t\t\tconst innerBlocks = getBlocks( tabsClientId );\n\t\t\tconst tabPanel = innerBlocks.find(\n\t\t\t\t( block ) => block.name === 'core/tab-panel'\n\t\t\t);\n\t\t\tconst tabsMenu = innerBlocks.find(\n\t\t\t\t( block ) => block.name === 'core/tabs-menu'\n\t\t\t);\n\t\t\tconst tabs = tabPanel?.innerBlocks || [];\n\t\t\tconst menuItems = tabsMenu?.innerBlocks || [];\n\t\t\tconst activeTab = tabs[ activeIndex ];\n\t\t\t// Match menu item by anchor (e.g. \"tab-1\" \u2192 \"tab-1-button\").\n\t\t\tconst expectedMenuAnchor = activeTab?.attributes?.anchor\n\t\t\t\t? `${ activeTab.attributes.anchor }-button`\n\t\t\t\t: null;\n\t\t\tconst activeMenuItem = expectedMenuAnchor\n\t\t\t\t? menuItems.find(\n\t\t\t\t\t\t( m ) => m.attributes?.anchor === expectedMenuAnchor\n\t\t\t\t )\n\t\t\t\t: menuItems[ activeIndex ];\n\t\t\treturn {\n\t\t\t\tactiveTabClientId: activeTab?.clientId || null,\n\t\t\t\tactiveMenuItemClientId: activeMenuItem?.clientId || null,\n\t\t\t\ttabCount: tabs.length,\n\t\t\t\teditorActiveTabIndex: activeIndex,\n\t\t\t};\n\t\t},\n\t\t[ tabsClientId ]\n\t);\n\n\tconst removeTab = () => {\n\t\tif ( ! activeTabClientId || tabCount <= 1 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Calculate new active index after removal.\n\t\tconst newActiveIndex =\n\t\t\teditorActiveTabIndex >= tabCount - 1\n\t\t\t\t? tabCount - 2\n\t\t\t\t: editorActiveTabIndex;\n\n\t\t__unstableMarkNextChangeAsNotPersistent();\n\t\tupdateBlockAttributes( tabsClientId, {\n\t\t\teditorActiveTabIndex: newActiveIndex,\n\t\t} );\n\n\t\t// Remove the tab content block and the corresponding menu item.\n\t\tremoveBlock( activeTabClientId, false );\n\t\tif ( activeMenuItemClientId ) {\n\t\t\tremoveBlock( activeMenuItemClientId, false );\n\t\t}\n\n\t\tif ( tabsClientId ) {\n\t\t\tselectBlock( tabsClientId );\n\t\t}\n\t};\n\n\tconst isDisabled = tabCount <= 1 || ! activeTabClientId;\n\n\treturn (\n\t\t<BlockControls group=\"other\">\n\t\t\t<ToolbarGroup>\n\t\t\t\t<ToolbarButton\n\t\t\t\t\tclassName=\"components-toolbar__control\"\n\t\t\t\t\tonClick={ removeTab }\n\t\t\t\t\ttext={ __( 'Remove tab' ) }\n\t\t\t\t\tdisabled={ isDisabled }\n\t\t\t\t/>\n\t\t\t</ToolbarGroup>\n\t\t</BlockControls>\n\t);\n}\n"],
5
+ "mappings": ";AAGA;AAAA,EACC;AAAA,EACA,SAAS;AAAA,OACH;AACP,SAAS,cAAc,qBAAqB;AAC5C,SAAS,UAAU;AACnB,SAAS,aAAa,iBAAiB;AAsGnC;AA3FW,SAAR,wBAA0C,EAAE,aAAa,GAAI;AACnE,QAAM;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI,YAAa,gBAAiB;AAElC,QAAM;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI;AAAA,IACH,CAAE,WAAY;AACb,UAAK,CAAE,cAAe;AACrB,eAAO;AAAA,UACN,mBAAmB;AAAA,UACnB,wBAAwB;AAAA,UACxB,UAAU;AAAA,UACV,sBAAsB;AAAA,QACvB;AAAA,MACD;AACA,YAAM,EAAE,WAAW,mBAAmB,IACrC,OAAQ,gBAAiB;AAC1B,YAAM,iBAAiB,mBAAoB,YAAa;AACxD,YAAM,cACL,gBAAgB,wBAChB,gBAAgB,kBAChB;AACD,YAAM,cAAc,UAAW,YAAa;AAC5C,YAAM,WAAW,YAAY;AAAA,QAC5B,CAAE,UAAW,MAAM,SAAS;AAAA,MAC7B;AACA,YAAM,WAAW,YAAY;AAAA,QAC5B,CAAE,UAAW,MAAM,SAAS;AAAA,MAC7B;AACA,YAAM,OAAO,UAAU,eAAe,CAAC;AACvC,YAAM,YAAY,UAAU,eAAe,CAAC;AAC5C,YAAM,YAAY,KAAM,WAAY;AAEpC,YAAM,qBAAqB,WAAW,YAAY,SAC/C,GAAI,UAAU,WAAW,MAAO,YAChC;AACH,YAAM,iBAAiB,qBACpB,UAAU;AAAA,QACV,CAAE,MAAO,EAAE,YAAY,WAAW;AAAA,MAClC,IACA,UAAW,WAAY;AAC1B,aAAO;AAAA,QACN,mBAAmB,WAAW,YAAY;AAAA,QAC1C,wBAAwB,gBAAgB,YAAY;AAAA,QACpD,UAAU,KAAK;AAAA,QACf,sBAAsB;AAAA,MACvB;AAAA,IACD;AAAA,IACA,CAAE,YAAa;AAAA,EAChB;AAEA,QAAM,YAAY,MAAM;AACvB,QAAK,CAAE,qBAAqB,YAAY,GAAI;AAC3C;AAAA,IACD;AAGA,UAAM,iBACL,wBAAwB,WAAW,IAChC,WAAW,IACX;AAEJ,4CAAwC;AACxC,0BAAuB,cAAc;AAAA,MACpC,sBAAsB;AAAA,IACvB,CAAE;AAGF,gBAAa,mBAAmB,KAAM;AACtC,QAAK,wBAAyB;AAC7B,kBAAa,wBAAwB,KAAM;AAAA,IAC5C;AAEA,QAAK,cAAe;AACnB,kBAAa,YAAa;AAAA,IAC3B;AAAA,EACD;AAEA,QAAM,aAAa,YAAY,KAAK,CAAE;AAEtC,SACC,oBAAC,iBAAc,OAAM,SACpB,8BAAC,gBACA;AAAA,IAAC;AAAA;AAAA,MACA,WAAU;AAAA,MACV,SAAU;AAAA,MACV,MAAO,GAAI,YAAa;AAAA,MACxB,UAAW;AAAA;AAAA,EACZ,GACD,GACD;AAEF;",
6
6
  "names": []
7
7
  }
@@ -5,8 +5,8 @@ import {
5
5
  BlockContextProvider,
6
6
  store as blockEditorStore
7
7
  } from "@wordpress/block-editor";
8
- import { useSelect } from "@wordpress/data";
9
- import { useMemo, useEffect } from "@wordpress/element";
8
+ import { useSelect, useDispatch } from "@wordpress/data";
9
+ import { useMemo, useEffect, useRef } from "@wordpress/element";
10
10
  import Controls from "./controls.mjs";
11
11
  import { jsx, jsxs } from "react/jsx-runtime";
12
12
  var TABS_TEMPLATE = [
@@ -16,7 +16,11 @@ var TABS_TEMPLATE = [
16
16
  lock: {
17
17
  remove: true
18
18
  }
19
- }
19
+ },
20
+ [
21
+ ["core/tabs-menu-item", { anchor: "tab-1-button" }],
22
+ ["core/tabs-menu-item", { anchor: "tab-2-button" }]
23
+ ]
20
24
  ],
21
25
  [
22
26
  "core/tab-panel",
@@ -33,6 +37,14 @@ var TABS_TEMPLATE = [
33
37
  label: "Tab 1"
34
38
  },
35
39
  [["core/paragraph"]]
40
+ ],
41
+ [
42
+ "core/tab",
43
+ {
44
+ anchor: "tab-2",
45
+ label: "Tab 2"
46
+ },
47
+ [["core/paragraph"]]
36
48
  ]
37
49
  ]
38
50
  ]
@@ -49,22 +61,88 @@ function Edit({
49
61
  setAttributes({ editorActiveTabIndex: activeTabIndex });
50
62
  }
51
63
  }, []);
52
- const tabs = useSelect(
64
+ const { removeBlock } = useDispatch(blockEditorStore);
65
+ const { tabs, menuItems } = useSelect(
53
66
  (select) => {
54
67
  const { getBlocks } = select(blockEditorStore);
55
68
  const innerBlocks = getBlocks(clientId);
56
69
  const tabPanel = innerBlocks.find(
57
70
  (block) => block.name === "core/tab-panel"
58
71
  );
59
- if (!tabPanel) {
60
- return [];
61
- }
62
- return tabPanel.innerBlocks.filter(
63
- (block) => block.name === "core/tab"
72
+ const tabsMenu = innerBlocks.find(
73
+ (block) => block.name === "core/tabs-menu"
64
74
  );
75
+ return {
76
+ tabs: tabPanel ? tabPanel.innerBlocks.filter(
77
+ (block) => block.name === "core/tab"
78
+ ) : [],
79
+ menuItems: tabsMenu ? getBlocks(tabsMenu.clientId).filter((b) => b.name === "core/tabs-menu-item").map((b) => ({
80
+ clientId: b.clientId,
81
+ anchor: b.attributes.anchor ?? ""
82
+ })) : []
83
+ };
65
84
  },
66
85
  [clientId]
67
86
  );
87
+ const prevSyncStateRef = useRef(null);
88
+ useEffect(() => {
89
+ const currentTabs = tabs.map((tab) => ({
90
+ clientId: tab.clientId,
91
+ anchor: tab.attributes.anchor ?? ""
92
+ }));
93
+ if (prevSyncStateRef.current === null) {
94
+ prevSyncStateRef.current = {
95
+ tabs: currentTabs,
96
+ menuItems: [...menuItems]
97
+ };
98
+ return;
99
+ }
100
+ const { tabs: prevTabs, menuItems: prevMenuItems } = prevSyncStateRef.current;
101
+ const tabsRemoved = currentTabs.length < prevTabs.length;
102
+ const menuItemsRemoved = menuItems.length < prevMenuItems.length;
103
+ prevSyncStateRef.current = {
104
+ tabs: currentTabs,
105
+ menuItems: [...menuItems]
106
+ };
107
+ if (!tabsRemoved && !menuItemsRemoved || tabsRemoved && menuItemsRemoved) {
108
+ return;
109
+ }
110
+ const currentTabIds = new Set(currentTabs.map((t) => t.clientId));
111
+ const currentMenuItemIds = new Set(
112
+ menuItems.map((m) => m.clientId)
113
+ );
114
+ if (tabsRemoved) {
115
+ prevTabs.forEach((prevTab) => {
116
+ if (currentTabIds.has(prevTab.clientId)) {
117
+ return;
118
+ }
119
+ const expectedMenuAnchor = prevTab.anchor ? `${prevTab.anchor}-button` : null;
120
+ const menuItemToRemove = expectedMenuAnchor ? menuItems.find((m) => m.anchor === expectedMenuAnchor) : null;
121
+ if (menuItemToRemove) {
122
+ removeBlock(menuItemToRemove.clientId, false);
123
+ prevSyncStateRef.current.menuItems = prevSyncStateRef.current.menuItems.filter(
124
+ (m) => m.clientId !== menuItemToRemove.clientId
125
+ );
126
+ }
127
+ });
128
+ } else {
129
+ prevMenuItems.forEach((prevItem) => {
130
+ if (currentMenuItemIds.has(prevItem.clientId)) {
131
+ return;
132
+ }
133
+ const expectedTabAnchor = prevItem.anchor?.replace(/-button$/, "") ?? "";
134
+ const tabToRemove = tabs.find(
135
+ (tab) => (tab.attributes.anchor ?? "") === expectedTabAnchor
136
+ );
137
+ if (tabToRemove) {
138
+ removeBlock(tabToRemove.clientId, false);
139
+ prevSyncStateRef.current.tabs = prevSyncStateRef.current.tabs.filter(
140
+ (t) => t.clientId !== tabToRemove.clientId
141
+ );
142
+ }
143
+ });
144
+ }
145
+ }, [tabs, menuItems, removeBlock]);
68
146
  const contextValue = useMemo(() => {
69
147
  const tabList = tabs.map((tab, index) => ({
70
148
  id: tab.attributes.anchor || `tab-${index}`,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/tabs/edit.js"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport {\n\tuseBlockProps,\n\tuseInnerBlocksProps,\n\tBlockContextProvider,\n\tstore as blockEditorStore,\n} from '@wordpress/block-editor';\nimport { useSelect } from '@wordpress/data';\nimport { useMemo, useEffect } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport Controls from './controls';\n\nconst TABS_TEMPLATE = [\n\t[\n\t\t'core/tabs-menu',\n\t\t{\n\t\t\tlock: {\n\t\t\t\tremove: true,\n\t\t\t},\n\t\t},\n\t],\n\t[\n\t\t'core/tab-panel',\n\t\t{\n\t\t\tlock: {\n\t\t\t\tremove: true,\n\t\t\t},\n\t\t},\n\t\t[\n\t\t\t[\n\t\t\t\t'core/tab',\n\t\t\t\t{\n\t\t\t\t\tanchor: 'tab-1',\n\t\t\t\t\tlabel: 'Tab 1',\n\t\t\t\t},\n\t\t\t\t[ [ 'core/paragraph' ] ],\n\t\t\t],\n\t\t],\n\t],\n];\n\nfunction Edit( {\n\tclientId,\n\tattributes,\n\tsetAttributes,\n\t__unstableLayoutClassNames: layoutClassNames,\n} ) {\n\tconst { anchor, activeTabIndex, editorActiveTabIndex } = attributes;\n\n\t/**\n\t * Initialize editorActiveTabIndex to activeTabIndex on mount.\n\t * This ensures the ephemeral editor state starts at the persisted default.\n\t */\n\tuseEffect( () => {\n\t\tif ( editorActiveTabIndex === undefined ) {\n\t\t\tsetAttributes( { editorActiveTabIndex: activeTabIndex } );\n\t\t}\n\t}, [] ); // eslint-disable-line react-hooks/exhaustive-deps\n\n\t/**\n\t * Construct a list of core/tab blocks, used to create tabs-list context.\n\t */\n\tconst tabs = useSelect(\n\t\t( select ) => {\n\t\t\tconst { getBlocks } = select( blockEditorStore );\n\t\t\tconst innerBlocks = getBlocks( clientId );\n\n\t\t\t// Find tab-panel block and extract tab data\n\t\t\tconst tabPanel = innerBlocks.find(\n\t\t\t\t( block ) => block.name === 'core/tab-panel'\n\t\t\t);\n\n\t\t\tif ( ! tabPanel ) {\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\treturn tabPanel.innerBlocks.filter(\n\t\t\t\t( block ) => block.name === 'core/tab'\n\t\t\t);\n\t\t},\n\t\t[ clientId ]\n\t);\n\n\t/**\n\t * Memoize context value to prevent unnecessary re-renders.\n\t */\n\tconst contextValue = useMemo( () => {\n\t\t/**\n\t\t * Compute tabs list from innerblocks to provide via context.\n\t\t * This traverses the tab-panel block to find all tab blocks\n\t\t * and extracts their label and anchor for the tabs-menu to consume.\n\t\t */\n\t\tconst tabList = tabs.map( ( tab, index ) => ( {\n\t\t\tid: tab.attributes.anchor || `tab-${ index }`,\n\t\t\tlabel: tab.attributes.label || '',\n\t\t\tclientId: tab.clientId,\n\t\t\tindex,\n\t\t} ) );\n\n\t\treturn {\n\t\t\t'core/tabs-list': tabList,\n\t\t\t'core/tabs-id': anchor,\n\t\t\t'core/tabs-activeTabIndex': activeTabIndex,\n\t\t\t'core/tabs-editorActiveTabIndex': editorActiveTabIndex,\n\t\t};\n\t}, [ tabs, anchor, activeTabIndex, editorActiveTabIndex ] );\n\n\t/**\n\t * Block props for the tabs container.\n\t */\n\tconst blockProps = useBlockProps( {\n\t\tclassName: layoutClassNames,\n\t} );\n\n\t/**\n\t * Innerblocks props for the tabs container.\n\t */\n\tconst innerBlockProps = useInnerBlocksProps( blockProps, {\n\t\t__experimentalCaptureToolbars: true,\n\t\ttemplate: TABS_TEMPLATE,\n\t\ttemplateLock: false,\n\t\trenderAppender: false,\n\t} );\n\n\treturn (\n\t\t<BlockContextProvider value={ contextValue }>\n\t\t\t<div { ...innerBlockProps }>\n\t\t\t\t<Controls\n\t\t\t\t\tclientId={ clientId }\n\t\t\t\t\tattributes={ attributes }\n\t\t\t\t\tsetAttributes={ setAttributes }\n\t\t\t\t/>\n\t\t\t\t{ innerBlockProps.children }\n\t\t\t</div>\n\t\t</BlockContextProvider>\n\t);\n}\n\nexport default Edit;\n"],
5
- "mappings": ";AAGA;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS;AAAA,OACH;AACP,SAAS,iBAAiB;AAC1B,SAAS,SAAS,iBAAiB;AAKnC,OAAO,cAAc;AAoHlB,SACC,KADD;AAlHH,IAAM,gBAAgB;AAAA,EACrB;AAAA,IACC;AAAA,IACA;AAAA,MACC,MAAM;AAAA,QACL,QAAQ;AAAA,MACT;AAAA,IACD;AAAA,EACD;AAAA,EACA;AAAA,IACC;AAAA,IACA;AAAA,MACC,MAAM;AAAA,QACL,QAAQ;AAAA,MACT;AAAA,IACD;AAAA,IACA;AAAA,MACC;AAAA,QACC;AAAA,QACA;AAAA,UACC,QAAQ;AAAA,UACR,OAAO;AAAA,QACR;AAAA,QACA,CAAE,CAAE,gBAAiB,CAAE;AAAA,MACxB;AAAA,IACD;AAAA,EACD;AACD;AAEA,SAAS,KAAM;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA,4BAA4B;AAC7B,GAAI;AACH,QAAM,EAAE,QAAQ,gBAAgB,qBAAqB,IAAI;AAMzD,YAAW,MAAM;AAChB,QAAK,yBAAyB,QAAY;AACzC,oBAAe,EAAE,sBAAsB,eAAe,CAAE;AAAA,IACzD;AAAA,EACD,GAAG,CAAC,CAAE;AAKN,QAAM,OAAO;AAAA,IACZ,CAAE,WAAY;AACb,YAAM,EAAE,UAAU,IAAI,OAAQ,gBAAiB;AAC/C,YAAM,cAAc,UAAW,QAAS;AAGxC,YAAM,WAAW,YAAY;AAAA,QAC5B,CAAE,UAAW,MAAM,SAAS;AAAA,MAC7B;AAEA,UAAK,CAAE,UAAW;AACjB,eAAO,CAAC;AAAA,MACT;AAEA,aAAO,SAAS,YAAY;AAAA,QAC3B,CAAE,UAAW,MAAM,SAAS;AAAA,MAC7B;AAAA,IACD;AAAA,IACA,CAAE,QAAS;AAAA,EACZ;AAKA,QAAM,eAAe,QAAS,MAAM;AAMnC,UAAM,UAAU,KAAK,IAAK,CAAE,KAAK,WAAa;AAAA,MAC7C,IAAI,IAAI,WAAW,UAAU,OAAQ,KAAM;AAAA,MAC3C,OAAO,IAAI,WAAW,SAAS;AAAA,MAC/B,UAAU,IAAI;AAAA,MACd;AAAA,IACD,EAAI;AAEJ,WAAO;AAAA,MACN,kBAAkB;AAAA,MAClB,gBAAgB;AAAA,MAChB,4BAA4B;AAAA,MAC5B,kCAAkC;AAAA,IACnC;AAAA,EACD,GAAG,CAAE,MAAM,QAAQ,gBAAgB,oBAAqB,CAAE;AAK1D,QAAM,aAAa,cAAe;AAAA,IACjC,WAAW;AAAA,EACZ,CAAE;AAKF,QAAM,kBAAkB,oBAAqB,YAAY;AAAA,IACxD,+BAA+B;AAAA,IAC/B,UAAU;AAAA,IACV,cAAc;AAAA,IACd,gBAAgB;AAAA,EACjB,CAAE;AAEF,SACC,oBAAC,wBAAqB,OAAQ,cAC7B,+BAAC,SAAM,GAAG,iBACT;AAAA;AAAA,MAAC;AAAA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,IACD;AAAA,IACE,gBAAgB;AAAA,KACnB,GACD;AAEF;AAEA,IAAO,eAAQ;",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport {\n\tuseBlockProps,\n\tuseInnerBlocksProps,\n\tBlockContextProvider,\n\tstore as blockEditorStore,\n} from '@wordpress/block-editor';\nimport { useSelect, useDispatch } from '@wordpress/data';\nimport { useMemo, useEffect, useRef } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport Controls from './controls';\n\nconst TABS_TEMPLATE = [\n\t[\n\t\t'core/tabs-menu',\n\t\t{\n\t\t\tlock: {\n\t\t\t\tremove: true,\n\t\t\t},\n\t\t},\n\t\t[\n\t\t\t[ 'core/tabs-menu-item', { anchor: 'tab-1-button' } ],\n\t\t\t[ 'core/tabs-menu-item', { anchor: 'tab-2-button' } ],\n\t\t],\n\t],\n\t[\n\t\t'core/tab-panel',\n\t\t{\n\t\t\tlock: {\n\t\t\t\tremove: true,\n\t\t\t},\n\t\t},\n\t\t[\n\t\t\t[\n\t\t\t\t'core/tab',\n\t\t\t\t{\n\t\t\t\t\tanchor: 'tab-1',\n\t\t\t\t\tlabel: 'Tab 1',\n\t\t\t\t},\n\t\t\t\t[ [ 'core/paragraph' ] ],\n\t\t\t],\n\t\t\t[\n\t\t\t\t'core/tab',\n\t\t\t\t{\n\t\t\t\t\tanchor: 'tab-2',\n\t\t\t\t\tlabel: 'Tab 2',\n\t\t\t\t},\n\t\t\t\t[ [ 'core/paragraph' ] ],\n\t\t\t],\n\t\t],\n\t],\n];\n\nfunction Edit( {\n\tclientId,\n\tattributes,\n\tsetAttributes,\n\t__unstableLayoutClassNames: layoutClassNames,\n} ) {\n\tconst { anchor, activeTabIndex, editorActiveTabIndex } = attributes;\n\n\t/**\n\t * Initialize editorActiveTabIndex to activeTabIndex on mount.\n\t * This ensures the ephemeral editor state starts at the persisted default.\n\t */\n\tuseEffect( () => {\n\t\tif ( editorActiveTabIndex === undefined ) {\n\t\t\tsetAttributes( { editorActiveTabIndex: activeTabIndex } );\n\t\t}\n\t}, [] ); // eslint-disable-line react-hooks/exhaustive-deps\n\n\tconst { removeBlock } = useDispatch( blockEditorStore );\n\n\t/**\n\t * Construct a list of core/tab blocks, used to create tabs-list context.\n\t * Also select menu items with their anchors for anchor-based deletion sync.\n\t */\n\tconst { tabs, menuItems } = useSelect(\n\t\t( select ) => {\n\t\t\tconst { getBlocks } = select( blockEditorStore );\n\t\t\tconst innerBlocks = getBlocks( clientId );\n\n\t\t\t// Find tab-panel block and extract tab data.\n\t\t\tconst tabPanel = innerBlocks.find(\n\t\t\t\t( block ) => block.name === 'core/tab-panel'\n\t\t\t);\n\n\t\t\t// Find tabs-menu block and get its children with their anchors.\n\t\t\tconst tabsMenu = innerBlocks.find(\n\t\t\t\t( block ) => block.name === 'core/tabs-menu'\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\ttabs: tabPanel\n\t\t\t\t\t? tabPanel.innerBlocks.filter(\n\t\t\t\t\t\t\t( block ) => block.name === 'core/tab'\n\t\t\t\t\t )\n\t\t\t\t\t: [],\n\t\t\t\tmenuItems: tabsMenu\n\t\t\t\t\t? getBlocks( tabsMenu.clientId )\n\t\t\t\t\t\t\t.filter( ( b ) => b.name === 'core/tabs-menu-item' )\n\t\t\t\t\t\t\t.map( ( b ) => ( {\n\t\t\t\t\t\t\t\tclientId: b.clientId,\n\t\t\t\t\t\t\t\tanchor: b.attributes.anchor ?? '',\n\t\t\t\t\t\t\t} ) )\n\t\t\t\t\t: [],\n\t\t\t};\n\t\t},\n\t\t[ clientId ]\n\t);\n\n\t/**\n\t * Keep tabs and menu items in sync when either is deleted directly (e.g.\n\t * via the Backspace key or List View).\n\t *\n\t * TODO: This effect only handles deletions. The two lists can get out of\n\t * sync in other cases: if a user pastes a core/tab block into the tab-panel\n\t * (or duplicates one), no corresponding tabs-menu-item is created; if a\n\t * user drags and drops a tabs-menu-item, the tab panel is not copied with\n\t * it. We should extend this effect to handle insertions, detecting when\n\t * tabs.length > menuItems.length and inserting the missing menu\n\t * item(s) at the correct index.\n\t */\n\tconst prevSyncStateRef = useRef( null );\n\tuseEffect( () => {\n\t\tconst currentTabs = tabs.map( ( tab ) => ( {\n\t\t\tclientId: tab.clientId,\n\t\t\tanchor: tab.attributes.anchor ?? '',\n\t\t} ) );\n\n\t\tif ( prevSyncStateRef.current === null ) {\n\t\t\tprevSyncStateRef.current = {\n\t\t\t\ttabs: currentTabs,\n\t\t\t\tmenuItems: [ ...menuItems ],\n\t\t\t};\n\t\t\treturn;\n\t\t}\n\n\t\tconst { tabs: prevTabs, menuItems: prevMenuItems } =\n\t\t\tprevSyncStateRef.current;\n\n\t\tconst tabsRemoved = currentTabs.length < prevTabs.length;\n\t\tconst menuItemsRemoved = menuItems.length < prevMenuItems.length;\n\n\t\t// Update snapshot to the current state.\n\t\t// Snapshot is updated eagerly; post-removal mutations keep it consistent\n\t\t// so the next effect invocation sees a stable baseline.\n\t\tprevSyncStateRef.current = {\n\t\t\ttabs: currentTabs,\n\t\t\tmenuItems: [ ...menuItems ],\n\t\t};\n\n\t\t// Lists are in sync, nothing changed, or toolbar already removed both.\n\t\tif (\n\t\t\t( ! tabsRemoved && ! menuItemsRemoved ) ||\n\t\t\t( tabsRemoved && menuItemsRemoved )\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentTabIds = new Set( currentTabs.map( ( t ) => t.clientId ) );\n\t\tconst currentMenuItemIds = new Set(\n\t\t\tmenuItems.map( ( m ) => m.clientId )\n\t\t);\n\n\t\tif ( tabsRemoved ) {\n\t\t\tprevTabs.forEach( ( prevTab ) => {\n\t\t\t\tif ( currentTabIds.has( prevTab.clientId ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst expectedMenuAnchor = prevTab.anchor\n\t\t\t\t\t? `${ prevTab.anchor }-button`\n\t\t\t\t\t: null;\n\t\t\t\tconst menuItemToRemove = expectedMenuAnchor\n\t\t\t\t\t? menuItems.find( ( m ) => m.anchor === expectedMenuAnchor )\n\t\t\t\t\t: null;\n\t\t\t\tif ( menuItemToRemove ) {\n\t\t\t\t\tremoveBlock( menuItemToRemove.clientId, false );\n\t\t\t\t\tprevSyncStateRef.current.menuItems =\n\t\t\t\t\t\tprevSyncStateRef.current.menuItems.filter(\n\t\t\t\t\t\t\t( m ) => m.clientId !== menuItemToRemove.clientId\n\t\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} );\n\t\t} else {\n\t\t\tprevMenuItems.forEach( ( prevItem ) => {\n\t\t\t\tif ( currentMenuItemIds.has( prevItem.clientId ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst expectedTabAnchor =\n\t\t\t\t\tprevItem.anchor?.replace( /-button$/, '' ) ?? '';\n\t\t\t\tconst tabToRemove = tabs.find(\n\t\t\t\t\t( tab ) =>\n\t\t\t\t\t\t( tab.attributes.anchor ?? '' ) === expectedTabAnchor\n\t\t\t\t);\n\t\t\t\tif ( tabToRemove ) {\n\t\t\t\t\tremoveBlock( tabToRemove.clientId, false );\n\t\t\t\t\tprevSyncStateRef.current.tabs =\n\t\t\t\t\t\tprevSyncStateRef.current.tabs.filter(\n\t\t\t\t\t\t\t( t ) => t.clientId !== tabToRemove.clientId\n\t\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t}, [ tabs, menuItems, removeBlock ] );\n\n\t/**\n\t * Memoize context value to prevent unnecessary re-renders.\n\t */\n\tconst contextValue = useMemo( () => {\n\t\t/**\n\t\t * Compute tabs list from innerblocks to provide via context.\n\t\t * This traverses the tab-panel block to find all tab blocks\n\t\t * and extracts their label and anchor for the tabs-menu to consume.\n\t\t */\n\t\tconst tabList = tabs.map( ( tab, index ) => ( {\n\t\t\tid: tab.attributes.anchor || `tab-${ index }`,\n\t\t\tlabel: tab.attributes.label || '',\n\t\t\tclientId: tab.clientId,\n\t\t\tindex,\n\t\t} ) );\n\n\t\treturn {\n\t\t\t'core/tabs-list': tabList,\n\t\t\t'core/tabs-id': anchor,\n\t\t\t'core/tabs-activeTabIndex': activeTabIndex,\n\t\t\t'core/tabs-editorActiveTabIndex': editorActiveTabIndex,\n\t\t};\n\t}, [ tabs, anchor, activeTabIndex, editorActiveTabIndex ] );\n\n\t/**\n\t * Block props for the tabs container.\n\t */\n\tconst blockProps = useBlockProps( {\n\t\tclassName: layoutClassNames,\n\t} );\n\n\t/**\n\t * Innerblocks props for the tabs container.\n\t */\n\tconst innerBlockProps = useInnerBlocksProps( blockProps, {\n\t\t__experimentalCaptureToolbars: true,\n\t\ttemplate: TABS_TEMPLATE,\n\t\ttemplateLock: false,\n\t\trenderAppender: false,\n\t} );\n\n\treturn (\n\t\t<BlockContextProvider value={ contextValue }>\n\t\t\t<div { ...innerBlockProps }>\n\t\t\t\t<Controls\n\t\t\t\t\tclientId={ clientId }\n\t\t\t\t\tattributes={ attributes }\n\t\t\t\t\tsetAttributes={ setAttributes }\n\t\t\t\t/>\n\t\t\t\t{ innerBlockProps.children }\n\t\t\t</div>\n\t\t</BlockContextProvider>\n\t);\n}\n\nexport default Edit;\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -12,13 +12,23 @@ var settings = {
12
12
  innerBlocks: [
13
13
  {
14
14
  name: "core/tabs-menu",
15
- innerBlocks: [{ name: "core/tabs-menu-item" }]
15
+ innerBlocks: [
16
+ {
17
+ name: "core/tabs-menu-item",
18
+ attributes: { anchor: "tab-1-button" }
19
+ },
20
+ {
21
+ name: "core/tabs-menu-item",
22
+ attributes: { anchor: "tab-2-button" }
23
+ }
24
+ ]
16
25
  },
17
26
  {
18
27
  name: "core/tab-panel",
19
- innerBlocks: [1, 2, 3].map((index) => ({
28
+ innerBlocks: [1, 2].map((index) => ({
20
29
  name: "core/tab",
21
30
  attributes: {
31
+ anchor: `tab-${index}`,
22
32
  label: sprintf(
23
33
  /** translators: %s: tab index number */
24
34
  __("Tab %s"),
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/tabs/index.js"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { __, sprintf } from '@wordpress/i18n';\nimport { tabs as icon } from '@wordpress/icons';\n\n/**\n * Internal dependencies\n */\nimport initBlock from '../utils/init-block';\nimport edit from './edit';\nimport save from './save';\nimport metadata from './block.json';\n\nconst { name } = metadata;\n\nexport { metadata, name };\n\nexport const settings = {\n\ticon,\n\texample: {\n\t\tinnerBlocks: [\n\t\t\t{\n\t\t\t\tname: 'core/tabs-menu',\n\t\t\t\tinnerBlocks: [ { name: 'core/tabs-menu-item' } ],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'core/tab-panel',\n\t\t\t\tinnerBlocks: [ 1, 2, 3 ].map( ( index ) => ( {\n\t\t\t\t\tname: 'core/tab',\n\t\t\t\t\tattributes: {\n\t\t\t\t\t\tlabel: sprintf(\n\t\t\t\t\t\t\t/** translators: %s: tab index number */\n\t\t\t\t\t\t\t__( 'Tab %s' ),\n\t\t\t\t\t\t\tindex\n\t\t\t\t\t\t),\n\t\t\t\t\t},\n\t\t\t\t\tinnerBlocks: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tname: 'core/paragraph',\n\t\t\t\t\t\t\tattributes: {\n\t\t\t\t\t\t\t\tcontent: __(\n\t\t\t\t\t\t\t\t\t'In a village of La Mancha, the name of which I have no desire to call to mind, there lived not long since one of those gentlemen that keep a lance in the lance-rack, an old buckler, a lean hack, and a greyhound for coursing.'\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t} ) ),\n\t\t\t},\n\t\t],\n\t},\n\tedit,\n\tsave,\n};\n\nexport const init = () => initBlock( { name, metadata, settings } );\n"],
5
- "mappings": ";AAGA,SAAS,IAAI,eAAe;AAC5B,SAAS,QAAQ,YAAY;AAK7B,OAAO,eAAe;AACtB,OAAO,UAAU;AACjB,OAAO,UAAU;AACjB,OAAO,cAAc;AAErB,IAAM,EAAE,KAAK,IAAI;AAIV,IAAM,WAAW;AAAA,EACvB;AAAA,EACA,SAAS;AAAA,IACR,aAAa;AAAA,MACZ;AAAA,QACC,MAAM;AAAA,QACN,aAAa,CAAE,EAAE,MAAM,sBAAsB,CAAE;AAAA,MAChD;AAAA,MACA;AAAA,QACC,MAAM;AAAA,QACN,aAAa,CAAE,GAAG,GAAG,CAAE,EAAE,IAAK,CAAE,WAAa;AAAA,UAC5C,MAAM;AAAA,UACN,YAAY;AAAA,YACX,OAAO;AAAA;AAAA,cAEN,GAAI,QAAS;AAAA,cACb;AAAA,YACD;AAAA,UACD;AAAA,UACA,aAAa;AAAA,YACZ;AAAA,cACC,MAAM;AAAA,cACN,YAAY;AAAA,gBACX,SAAS;AAAA,kBACR;AAAA,gBACD;AAAA,cACD;AAAA,YACD;AAAA,UACD;AAAA,QACD,EAAI;AAAA,MACL;AAAA,IACD;AAAA,EACD;AAAA,EACA;AAAA,EACA;AACD;AAEO,IAAM,OAAO,MAAM,UAAW,EAAE,MAAM,UAAU,SAAS,CAAE;",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { __, sprintf } from '@wordpress/i18n';\nimport { tabs as icon } from '@wordpress/icons';\n\n/**\n * Internal dependencies\n */\nimport initBlock from '../utils/init-block';\nimport edit from './edit';\nimport save from './save';\nimport metadata from './block.json';\n\nconst { name } = metadata;\n\nexport { metadata, name };\n\nexport const settings = {\n\ticon,\n\texample: {\n\t\tinnerBlocks: [\n\t\t\t{\n\t\t\t\tname: 'core/tabs-menu',\n\t\t\t\tinnerBlocks: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'core/tabs-menu-item',\n\t\t\t\t\t\tattributes: { anchor: 'tab-1-button' },\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'core/tabs-menu-item',\n\t\t\t\t\t\tattributes: { anchor: 'tab-2-button' },\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'core/tab-panel',\n\t\t\t\tinnerBlocks: [ 1, 2 ].map( ( index ) => ( {\n\t\t\t\t\tname: 'core/tab',\n\t\t\t\t\tattributes: {\n\t\t\t\t\t\tanchor: `tab-${ index }`,\n\t\t\t\t\t\tlabel: sprintf(\n\t\t\t\t\t\t\t/** translators: %s: tab index number */\n\t\t\t\t\t\t\t__( 'Tab %s' ),\n\t\t\t\t\t\t\tindex\n\t\t\t\t\t\t),\n\t\t\t\t\t},\n\t\t\t\t\tinnerBlocks: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tname: 'core/paragraph',\n\t\t\t\t\t\t\tattributes: {\n\t\t\t\t\t\t\t\tcontent: __(\n\t\t\t\t\t\t\t\t\t'In a village of La Mancha, the name of which I have no desire to call to mind, there lived not long since one of those gentlemen that keep a lance in the lance-rack, an old buckler, a lean hack, and a greyhound for coursing.'\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t} ) ),\n\t\t\t},\n\t\t],\n\t},\n\tedit,\n\tsave,\n};\n\nexport const init = () => initBlock( { name, metadata, settings } );\n"],
5
+ "mappings": ";AAGA,SAAS,IAAI,eAAe;AAC5B,SAAS,QAAQ,YAAY;AAK7B,OAAO,eAAe;AACtB,OAAO,UAAU;AACjB,OAAO,UAAU;AACjB,OAAO,cAAc;AAErB,IAAM,EAAE,KAAK,IAAI;AAIV,IAAM,WAAW;AAAA,EACvB;AAAA,EACA,SAAS;AAAA,IACR,aAAa;AAAA,MACZ;AAAA,QACC,MAAM;AAAA,QACN,aAAa;AAAA,UACZ;AAAA,YACC,MAAM;AAAA,YACN,YAAY,EAAE,QAAQ,eAAe;AAAA,UACtC;AAAA,UACA;AAAA,YACC,MAAM;AAAA,YACN,YAAY,EAAE,QAAQ,eAAe;AAAA,UACtC;AAAA,QACD;AAAA,MACD;AAAA,MACA;AAAA,QACC,MAAM;AAAA,QACN,aAAa,CAAE,GAAG,CAAE,EAAE,IAAK,CAAE,WAAa;AAAA,UACzC,MAAM;AAAA,UACN,YAAY;AAAA,YACX,QAAQ,OAAQ,KAAM;AAAA,YACtB,OAAO;AAAA;AAAA,cAEN,GAAI,QAAS;AAAA,cACb;AAAA,YACD;AAAA,UACD;AAAA,UACA,aAAa;AAAA,YACZ;AAAA,cACC,MAAM;AAAA,cACN,YAAY;AAAA,gBACX,SAAS;AAAA,kBACR;AAAA,gBACD;AAAA,cACD;AAAA,YACD;AAAA,UACD;AAAA,QACD,EAAI;AAAA,MACL;AAAA,IACD;AAAA,EACD;AAAA,EACA;AAAA,EACA;AACD;AAEO,IAAM,OAAO,MAAM,UAAW,EAAE,MAAM,UAAU,SAAS,CAAE;",
6
6
  "names": []
7
7
  }
@@ -10,12 +10,7 @@
10
10
  "textdomain": "default",
11
11
  "parent": [ "core/tabs" ],
12
12
  "allowedBlocks": [ "core/tabs-menu-item" ],
13
- "usesContext": [
14
- "core/tabs-list",
15
- "core/tabs-id",
16
- "core/tabs-activeTabIndex",
17
- "core/tabs-editorActiveTabIndex"
18
- ],
13
+ "usesContext": [ "core/tabs-list" ],
19
14
  "attributes": {},
20
15
  "supports": {
21
16
  "html": false,
@@ -1,183 +1,34 @@
1
1
  // packages/block-library/src/tabs-menu/edit.js
2
2
  import clsx from "clsx";
3
- import { __ } from "@wordpress/i18n";
4
3
  import {
5
4
  useBlockProps,
6
5
  useInnerBlocksProps,
7
- BlockContextProvider,
8
- __experimentalUseBlockPreview as useBlockPreview,
9
- store as blockEditorStore,
10
- useBlockEditContext
6
+ store as blockEditorStore
11
7
  } from "@wordpress/block-editor";
12
- import { useSelect, useDispatch } from "@wordpress/data";
13
- import {
14
- memo,
15
- useMemo,
16
- useState,
17
- useEffect,
18
- useCallback
19
- } from "@wordpress/element";
8
+ import { useSelect } from "@wordpress/data";
20
9
  import AddTabToolbarControl from "../tab/add-tab-toolbar-control.mjs";
21
10
  import RemoveTabToolbarControl from "../tab/remove-tab-toolbar-control.mjs";
22
11
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
23
- var TABS_MENU_ITEM_TEMPLATE = [["core/tabs-menu-item", {}]];
24
- var EMPTY_ARRAY = [];
25
- function TabsMenuItemPreview({
26
- blocks,
27
- blockContextId,
28
- isHidden,
29
- setActiveBlockContextId
30
- }) {
31
- const blockPreviewProps = useBlockPreview({ blocks });
32
- const handleOnClick = () => {
33
- setActiveBlockContextId(blockContextId);
34
- };
35
- const style = {
36
- display: isHidden ? "none" : "flex"
37
- };
38
- return /* @__PURE__ */ jsx(
39
- "div",
40
- {
41
- ...blockPreviewProps,
42
- tabIndex: 0,
43
- role: "button",
44
- onClick: handleOnClick,
45
- onKeyDown: handleOnClick,
46
- style
47
- }
48
- );
49
- }
50
- var MemoizedTabsMenuItemPreview = memo(TabsMenuItemPreview);
51
- function TabsMenuItemTemplateBlocks({ wrapperProps = {}, layout }) {
52
- const innerBlocksProps = useInnerBlocksProps(wrapperProps, {
53
- template: TABS_MENU_ITEM_TEMPLATE,
54
- templateLock: "all",
55
- renderAppender: false,
56
- layout
57
- });
58
- return innerBlocksProps.children;
59
- }
60
- function Edit({
61
- context,
62
- clientId,
63
- __unstableLayoutClassNames: layoutClassNames
64
- }) {
65
- const { layout } = useBlockEditContext();
66
- const tabsId = context["core/tabs-id"] || null;
67
- const tabsList = context["core/tabs-list"] || EMPTY_ARRAY;
68
- const activeTabIndex = context["core/tabs-activeTabIndex"] ?? 0;
69
- const editorActiveTabIndex = context["core/tabs-editorActiveTabIndex"];
70
- const effectiveActiveIndex = useMemo(() => {
71
- return editorActiveTabIndex ?? activeTabIndex;
72
- }, [editorActiveTabIndex, activeTabIndex]);
73
- const { __unstableMarkNextChangeAsNotPersistent } = useDispatch(blockEditorStore);
74
- const { updateBlockAttributes } = useDispatch(blockEditorStore);
75
- const [activeBlockContextId, setActiveBlockContextId] = useState(null);
76
- const { blocks, tabsClientId } = useSelect(
77
- (select) => {
78
- const { getBlocks, getBlockRootClientId } = select(blockEditorStore);
79
- return {
80
- blocks: getBlocks(clientId),
81
- tabsClientId: getBlockRootClientId(clientId)
82
- };
83
- },
12
+ function Edit({ clientId, __unstableLayoutClassNames: layoutClassNames }) {
13
+ const { tabsClientId } = useSelect(
14
+ (select) => ({
15
+ tabsClientId: select(blockEditorStore).getBlockRootClientId(clientId)
16
+ }),
84
17
  [clientId]
85
18
  );
86
- const blockContexts = useMemo(() => {
87
- return tabsList.map((tab, index) => ({
88
- "core/tabs-menu-item-index": index,
89
- "core/tabs-menu-item-id": tab.id || `tab-${index}`,
90
- "core/tabs-menu-item-label": tab.label || "",
91
- "core/tabs-menu-item-clientId": tab.clientId,
92
- // Pass through parent context
93
- "core/tabs-id": tabsId,
94
- "core/tabs-list": tabsList,
95
- "core/tabs-activeTabIndex": activeTabIndex,
96
- "core/tabs-editorActiveTabIndex": editorActiveTabIndex
97
- }));
98
- }, [tabsList, tabsId, activeTabIndex, editorActiveTabIndex]);
99
- const getContextId = useCallback((blockContext) => {
100
- return `tab-context-${blockContext["core/tabs-menu-item-index"]}`;
101
- }, []);
102
- useEffect(() => {
103
- if (blockContexts.length > 0 && activeBlockContextId === null) {
104
- setActiveBlockContextId(getContextId(blockContexts[0]));
105
- }
106
- }, [blockContexts, activeBlockContextId, getContextId]);
107
- useEffect(() => {
108
- if (blockContexts.length > 0 && effectiveActiveIndex < blockContexts.length) {
109
- const newContextId = getContextId(
110
- blockContexts[effectiveActiveIndex]
111
- );
112
- setActiveBlockContextId(
113
- (prevId) => prevId !== newContextId ? newContextId : prevId
114
- );
115
- }
116
- }, [effectiveActiveIndex, blockContexts, getContextId]);
117
- const handleTabContextClick = useCallback(
118
- (index) => {
119
- if (tabsClientId && index !== effectiveActiveIndex) {
120
- __unstableMarkNextChangeAsNotPersistent();
121
- updateBlockAttributes(tabsClientId, {
122
- editorActiveTabIndex: index
123
- });
124
- }
125
- },
126
- [
127
- tabsClientId,
128
- effectiveActiveIndex,
129
- updateBlockAttributes,
130
- __unstableMarkNextChangeAsNotPersistent
131
- ]
132
- );
133
19
  const blockProps = useBlockProps({
134
20
  className: clsx(layoutClassNames),
135
21
  role: "tablist"
136
22
  });
137
- if (tabsList.length === 0) {
138
- return /* @__PURE__ */ jsxs(Fragment, { children: [
139
- /* @__PURE__ */ jsx(AddTabToolbarControl, { tabsClientId }),
140
- /* @__PURE__ */ jsx(RemoveTabToolbarControl, { tabsClientId }),
141
- /* @__PURE__ */ jsx("div", { ...blockProps, children: /* @__PURE__ */ jsx("span", { className: "tabs__tab-label tabs__tab-label--placeholder", children: __("Add tabs to display menu") }) })
142
- ] });
143
- }
23
+ const innerBlocksProps = useInnerBlocksProps(blockProps, {
24
+ allowedBlocks: ["core/tabs-menu-item"],
25
+ orientation: "horizontal",
26
+ renderAppender: false
27
+ });
144
28
  return /* @__PURE__ */ jsxs(Fragment, { children: [
145
29
  /* @__PURE__ */ jsx(AddTabToolbarControl, { tabsClientId }),
146
30
  /* @__PURE__ */ jsx(RemoveTabToolbarControl, { tabsClientId }),
147
- /* @__PURE__ */ jsx("div", { ...blockProps, children: blockContexts.map((blockContext, index) => {
148
- const contextId = getContextId(blockContext);
149
- const isVisible = contextId === activeBlockContextId;
150
- return /* @__PURE__ */ jsxs(
151
- BlockContextProvider,
152
- {
153
- value: blockContext,
154
- children: [
155
- isVisible ? /* @__PURE__ */ jsx(
156
- TabsMenuItemTemplateBlocks,
157
- {
158
- wrapperProps: {
159
- onClick: () => handleTabContextClick(index)
160
- },
161
- layout
162
- }
163
- ) : null,
164
- /* @__PURE__ */ jsx(
165
- MemoizedTabsMenuItemPreview,
166
- {
167
- blocks,
168
- blockContextId: contextId,
169
- setActiveBlockContextId: (id) => {
170
- setActiveBlockContextId(id);
171
- handleTabContextClick(index);
172
- },
173
- isHidden: isVisible
174
- }
175
- )
176
- ]
177
- },
178
- contextId
179
- );
180
- }) })
31
+ /* @__PURE__ */ jsx("div", { ...innerBlocksProps })
181
32
  ] });
182
33
  }
183
34
  var edit_default = Edit;