@wordpress/block-library 10.1.1-next.v.202607070741.0 → 10.2.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 (371) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/build/accordion/block.json +1 -0
  3. package/build/button/edit.cjs +18 -8
  4. package/build/button/edit.cjs.map +2 -2
  5. package/build/cover/block.json +11 -0
  6. package/build/cover/edit/block-controls.cjs +11 -4
  7. package/build/cover/edit/block-controls.cjs.map +2 -2
  8. package/build/cover/edit/embed-video-url-input.cjs +5 -3
  9. package/build/cover/edit/embed-video-url-input.cjs.map +3 -3
  10. package/build/cover/edit/index.cjs +1 -1
  11. package/build/cover/edit/index.cjs.map +2 -2
  12. package/build/cover/embed-video-utils.cjs +17 -7
  13. package/build/cover/embed-video-utils.cjs.map +2 -2
  14. package/build/details/transforms.cjs +1 -3
  15. package/build/details/transforms.cjs.map +2 -2
  16. package/build/embed/embed-placeholder.cjs +0 -1
  17. package/build/embed/embed-placeholder.cjs.map +2 -2
  18. package/build/file/edit.cjs +4 -3
  19. package/build/file/edit.cjs.map +2 -2
  20. package/build/file/transforms.cjs +25 -60
  21. package/build/file/transforms.cjs.map +2 -2
  22. package/build/gallery/block.json +4 -2
  23. package/build/gallery/edit.cjs +1 -1
  24. package/build/gallery/edit.cjs.map +3 -3
  25. package/build/gallery/gap-styles.cjs +49 -13
  26. package/build/gallery/gap-styles.cjs.map +3 -3
  27. package/build/group/transforms.cjs +1 -1
  28. package/build/group/transforms.cjs.map +2 -2
  29. package/build/icon/components/custom-inserter/icon-grid.cjs +25 -12
  30. package/build/icon/components/custom-inserter/icon-grid.cjs.map +2 -2
  31. package/build/icon/components/custom-inserter/index.cjs +100 -31
  32. package/build/icon/components/custom-inserter/index.cjs.map +3 -3
  33. package/build/icon/edit.cjs +11 -12
  34. package/build/icon/edit.cjs.map +2 -2
  35. package/build/image/block.json +1 -1
  36. package/build/image/edit.cjs +0 -34
  37. package/build/image/edit.cjs.map +2 -2
  38. package/build/image/image.cjs +4 -23
  39. package/build/image/image.cjs.map +3 -3
  40. package/build/image/transforms.cjs +78 -0
  41. package/build/image/transforms.cjs.map +3 -3
  42. package/build/index.cjs +18 -8
  43. package/build/index.cjs.map +2 -2
  44. package/build/latest-posts/edit.cjs +5 -8
  45. package/build/latest-posts/edit.cjs.map +2 -2
  46. package/build/list-item/edit.cjs +1 -1
  47. package/build/list-item/edit.cjs.map +2 -2
  48. package/build/list-item/hooks/use-enter.cjs +14 -17
  49. package/build/list-item/hooks/use-enter.cjs.map +3 -3
  50. package/build/list-item/hooks/use-space.cjs +3 -2
  51. package/build/list-item/hooks/use-space.cjs.map +3 -3
  52. package/build/paragraph/block.json +1 -0
  53. package/build/paragraph/use-enter.cjs +3 -7
  54. package/build/paragraph/use-enter.cjs.map +3 -3
  55. package/build/playlist/block.json +29 -10
  56. package/build/playlist/edit.cjs +216 -14
  57. package/build/playlist/edit.cjs.map +3 -3
  58. package/build/playlist/index.cjs +1 -1
  59. package/build/playlist/index.cjs.map +2 -2
  60. package/build/playlist/utils.cjs +19 -5
  61. package/build/playlist/utils.cjs.map +2 -2
  62. package/build/playlist/view.cjs +83 -13
  63. package/build/playlist/view.cjs.map +2 -2
  64. package/build/playlist-track/block.json +4 -2
  65. package/build/playlist-track/edit.cjs +94 -64
  66. package/build/playlist-track/edit.cjs.map +2 -2
  67. package/build/post-content/block.json +1 -0
  68. package/build/post-template/block.json +2 -1
  69. package/build/post-template/edit.cjs +10 -1
  70. package/build/post-template/edit.cjs.map +2 -2
  71. package/build/pullquote/block.json +3 -1
  72. package/build/query/block.json +3 -2
  73. package/build/query/edit/inspector-controls/index.cjs +38 -4
  74. package/build/query/edit/inspector-controls/index.cjs.map +2 -2
  75. package/build/query/edit/inspector-controls/offset-controls.cjs +0 -1
  76. package/build/query/edit/inspector-controls/offset-controls.cjs.map +2 -2
  77. package/build/query/edit/inspector-controls/pages-control.cjs +0 -1
  78. package/build/query/edit/inspector-controls/pages-control.cjs.map +2 -2
  79. package/build/query/edit/query-content.cjs +10 -3
  80. package/build/query/edit/query-content.cjs.map +2 -2
  81. package/build/query/index.cjs +2 -1
  82. package/build/query/index.cjs.map +2 -2
  83. package/build/quote/block.json +3 -1
  84. package/build/quote/transforms.cjs +1 -3
  85. package/build/quote/transforms.cjs.map +2 -2
  86. package/build/rss/edit.cjs +0 -1
  87. package/build/rss/edit.cjs.map +2 -2
  88. package/build/tab-list/block.json +2 -2
  89. package/build/tab-list/edit.cjs +65 -11
  90. package/build/tab-list/edit.cjs.map +3 -3
  91. package/build/tab-panel/block.json +1 -6
  92. package/build/tab-panel/edit.cjs +15 -15
  93. package/build/tab-panel/edit.cjs.map +2 -2
  94. package/build/tab-panels/block.json +0 -1
  95. package/build/tabs/block.json +0 -5
  96. package/build/tabs/edit.cjs +4 -39
  97. package/build/tabs/edit.cjs.map +3 -3
  98. package/build/tabs/use-tab-list-items-sync.cjs +19 -1
  99. package/build/tabs/use-tab-list-items-sync.cjs.map +2 -2
  100. package/build/term-name/block.json +1 -3
  101. package/build/term-name/deprecated.cjs +105 -0
  102. package/build/term-name/deprecated.cjs.map +7 -0
  103. package/build/term-name/edit.cjs +11 -37
  104. package/build/term-name/edit.cjs.map +3 -3
  105. package/build/term-name/index.cjs +3 -1
  106. package/build/term-name/index.cjs.map +3 -3
  107. package/build/utils/waveform-player.cjs +138 -22
  108. package/build/utils/waveform-player.cjs.map +2 -2
  109. package/build/utils/waveform-utils.cjs +315 -17
  110. package/build/utils/waveform-utils.cjs.map +2 -2
  111. package/build/video/edit.cjs +2 -11
  112. package/build/video/edit.cjs.map +3 -3
  113. package/build-module/accordion/block.json +1 -0
  114. package/build-module/button/edit.mjs +19 -14
  115. package/build-module/button/edit.mjs.map +2 -2
  116. package/build-module/cover/block.json +11 -0
  117. package/build-module/cover/edit/block-controls.mjs +11 -4
  118. package/build-module/cover/edit/block-controls.mjs.map +2 -2
  119. package/build-module/cover/edit/embed-video-url-input.mjs +5 -4
  120. package/build-module/cover/edit/embed-video-url-input.mjs.map +2 -2
  121. package/build-module/cover/edit/index.mjs +1 -1
  122. package/build-module/cover/edit/index.mjs.map +2 -2
  123. package/build-module/cover/embed-video-utils.mjs +16 -7
  124. package/build-module/cover/embed-video-utils.mjs.map +2 -2
  125. package/build-module/details/transforms.mjs +2 -7
  126. package/build-module/details/transforms.mjs.map +2 -2
  127. package/build-module/embed/embed-placeholder.mjs +0 -1
  128. package/build-module/embed/embed-placeholder.mjs.map +2 -2
  129. package/build-module/file/edit.mjs +4 -3
  130. package/build-module/file/edit.mjs.map +2 -2
  131. package/build-module/file/transforms.mjs +25 -60
  132. package/build-module/file/transforms.mjs.map +2 -2
  133. package/build-module/gallery/block.json +4 -2
  134. package/build-module/gallery/edit.mjs +3 -3
  135. package/build-module/gallery/edit.mjs.map +2 -2
  136. package/build-module/gallery/gap-styles.mjs +53 -14
  137. package/build-module/gallery/gap-styles.mjs.map +2 -2
  138. package/build-module/group/transforms.mjs +2 -5
  139. package/build-module/group/transforms.mjs.map +2 -2
  140. package/build-module/icon/components/custom-inserter/icon-grid.mjs +25 -12
  141. package/build-module/icon/components/custom-inserter/icon-grid.mjs.map +2 -2
  142. package/build-module/icon/components/custom-inserter/index.mjs +102 -33
  143. package/build-module/icon/components/custom-inserter/index.mjs.map +2 -2
  144. package/build-module/icon/edit.mjs +11 -12
  145. package/build-module/icon/edit.mjs.map +2 -2
  146. package/build-module/image/block.json +1 -1
  147. package/build-module/image/edit.mjs +0 -34
  148. package/build-module/image/edit.mjs.map +2 -2
  149. package/build-module/image/image.mjs +4 -13
  150. package/build-module/image/image.mjs.map +2 -2
  151. package/build-module/image/transforms.mjs +78 -0
  152. package/build-module/image/transforms.mjs.map +2 -2
  153. package/build-module/index.mjs +18 -8
  154. package/build-module/index.mjs.map +2 -2
  155. package/build-module/latest-posts/edit.mjs +5 -8
  156. package/build-module/latest-posts/edit.mjs.map +2 -2
  157. package/build-module/list-item/edit.mjs +1 -1
  158. package/build-module/list-item/edit.mjs.map +2 -2
  159. package/build-module/list-item/hooks/use-enter.mjs +15 -21
  160. package/build-module/list-item/hooks/use-enter.mjs.map +2 -2
  161. package/build-module/list-item/hooks/use-space.mjs +4 -6
  162. package/build-module/list-item/hooks/use-space.mjs.map +2 -2
  163. package/build-module/paragraph/block.json +1 -0
  164. package/build-module/paragraph/use-enter.mjs +4 -11
  165. package/build-module/paragraph/use-enter.mjs.map +2 -2
  166. package/build-module/playlist/block.json +29 -10
  167. package/build-module/playlist/edit.mjs +220 -16
  168. package/build-module/playlist/edit.mjs.map +2 -2
  169. package/build-module/playlist/index.mjs +1 -1
  170. package/build-module/playlist/index.mjs.map +2 -2
  171. package/build-module/playlist/utils.mjs +17 -4
  172. package/build-module/playlist/utils.mjs.map +2 -2
  173. package/build-module/playlist/view.mjs +89 -14
  174. package/build-module/playlist/view.mjs.map +2 -2
  175. package/build-module/playlist-track/block.json +4 -2
  176. package/build-module/playlist-track/edit.mjs +96 -65
  177. package/build-module/playlist-track/edit.mjs.map +2 -2
  178. package/build-module/post-content/block.json +1 -0
  179. package/build-module/post-template/block.json +2 -1
  180. package/build-module/post-template/edit.mjs +10 -1
  181. package/build-module/post-template/edit.mjs.map +2 -2
  182. package/build-module/pullquote/block.json +3 -1
  183. package/build-module/query/block.json +3 -2
  184. package/build-module/query/edit/inspector-controls/index.mjs +40 -5
  185. package/build-module/query/edit/inspector-controls/index.mjs.map +2 -2
  186. package/build-module/query/edit/inspector-controls/offset-controls.mjs +0 -1
  187. package/build-module/query/edit/inspector-controls/offset-controls.mjs.map +2 -2
  188. package/build-module/query/edit/inspector-controls/pages-control.mjs +0 -1
  189. package/build-module/query/edit/inspector-controls/pages-control.mjs.map +2 -2
  190. package/build-module/query/edit/query-content.mjs +10 -3
  191. package/build-module/query/edit/query-content.mjs.map +2 -2
  192. package/build-module/query/index.mjs +2 -1
  193. package/build-module/query/index.mjs.map +2 -2
  194. package/build-module/quote/block.json +3 -1
  195. package/build-module/quote/transforms.mjs +2 -4
  196. package/build-module/quote/transforms.mjs.map +2 -2
  197. package/build-module/rss/edit.mjs +0 -1
  198. package/build-module/rss/edit.mjs.map +2 -2
  199. package/build-module/tab-list/block.json +2 -2
  200. package/build-module/tab-list/edit.mjs +72 -13
  201. package/build-module/tab-list/edit.mjs.map +2 -2
  202. package/build-module/tab-panel/block.json +1 -6
  203. package/build-module/tab-panel/edit.mjs +16 -16
  204. package/build-module/tab-panel/edit.mjs.map +2 -2
  205. package/build-module/tab-panels/block.json +0 -1
  206. package/build-module/tabs/block.json +0 -5
  207. package/build-module/tabs/edit.mjs +5 -45
  208. package/build-module/tabs/edit.mjs.map +2 -2
  209. package/build-module/tabs/use-tab-list-items-sync.mjs +19 -1
  210. package/build-module/tabs/use-tab-list-items-sync.mjs.map +2 -2
  211. package/build-module/term-name/block.json +1 -3
  212. package/build-module/term-name/deprecated.mjs +74 -0
  213. package/build-module/term-name/deprecated.mjs.map +7 -0
  214. package/build-module/term-name/edit.mjs +11 -28
  215. package/build-module/term-name/edit.mjs.map +2 -2
  216. package/build-module/term-name/index.mjs +3 -1
  217. package/build-module/term-name/index.mjs.map +2 -2
  218. package/build-module/utils/waveform-player.mjs +144 -23
  219. package/build-module/utils/waveform-player.mjs.map +2 -2
  220. package/build-module/utils/waveform-utils.mjs +310 -16
  221. package/build-module/utils/waveform-utils.mjs.map +2 -2
  222. package/build-module/video/edit.mjs +2 -11
  223. package/build-module/video/edit.mjs.map +2 -2
  224. package/build-style/editor-rtl.css +46 -21
  225. package/build-style/editor.css +46 -21
  226. package/build-style/icon/editor-rtl.css +80 -7
  227. package/build-style/icon/editor.css +80 -7
  228. package/build-style/more/editor-rtl.css +2 -2
  229. package/build-style/more/editor.css +2 -2
  230. package/build-style/navigation/editor-rtl.css +3 -4
  231. package/build-style/navigation/editor.css +3 -4
  232. package/build-style/navigation-link/editor-rtl.css +1 -1
  233. package/build-style/navigation-link/editor.css +1 -1
  234. package/build-style/nextpage/editor-rtl.css +2 -2
  235. package/build-style/nextpage/editor.css +2 -2
  236. package/build-style/playlist/editor-rtl.css +6 -0
  237. package/build-style/playlist/editor.css +6 -0
  238. package/build-style/playlist/style-rtl.css +37 -1
  239. package/build-style/playlist/style.css +37 -1
  240. package/build-style/playlist-track/style-rtl.css +10 -0
  241. package/build-style/playlist-track/style.css +10 -0
  242. package/build-style/style-rtl.css +47 -1
  243. package/build-style/style.css +47 -1
  244. package/build-style/video/editor-rtl.css +1 -1
  245. package/build-style/video/editor.css +1 -1
  246. package/build-types/table-of-contents/list.d.ts +1 -1
  247. package/build-types/table-of-contents/list.d.ts.map +1 -1
  248. package/package.json +46 -44
  249. package/src/accordion/README.md +1 -0
  250. package/src/accordion/block.json +1 -0
  251. package/src/button/edit.js +21 -15
  252. package/src/cover/README.md +60 -0
  253. package/src/cover/block.json +11 -0
  254. package/src/cover/edit/block-controls.js +21 -11
  255. package/src/cover/edit/embed-video-url-input.js +5 -4
  256. package/src/cover/edit/index.js +9 -11
  257. package/src/cover/embed-video-utils.js +38 -13
  258. package/src/details/transforms.js +2 -7
  259. package/src/embed/embed-placeholder.js +0 -1
  260. package/src/file/edit.js +8 -8
  261. package/src/file/transforms.js +28 -60
  262. package/src/gallery/README.md +1 -1
  263. package/src/gallery/block.json +4 -2
  264. package/src/gallery/edit.js +3 -3
  265. package/src/gallery/gap-styles.js +79 -20
  266. package/src/gallery/index.php +103 -43
  267. package/src/group/transforms.js +2 -5
  268. package/src/icon/components/custom-inserter/icon-grid.js +40 -11
  269. package/src/icon/components/custom-inserter/index.js +98 -25
  270. package/src/icon/edit.js +11 -17
  271. package/src/icon/editor.scss +33 -8
  272. package/src/image/README.md +1 -1
  273. package/src/image/block.json +1 -1
  274. package/src/image/edit.js +0 -52
  275. package/src/image/editor.scss +2 -0
  276. package/src/image/image.js +19 -24
  277. package/src/image/transforms.js +128 -0
  278. package/src/index.js +19 -7
  279. package/src/latest-posts/edit.js +5 -8
  280. package/src/latest-posts/index.php +46 -16
  281. package/src/list-item/edit.js +1 -1
  282. package/src/list-item/hooks/use-enter.js +15 -22
  283. package/src/list-item/hooks/use-space.js +4 -6
  284. package/src/media-text/editor.scss +1 -0
  285. package/src/more/editor.scss +1 -1
  286. package/src/navigation/editor.scss +1 -2
  287. package/src/navigation-link/editor.scss +1 -1
  288. package/src/navigation-link/index.php +6 -3
  289. package/src/navigation-submenu/index.php +6 -3
  290. package/src/nextpage/editor.scss +1 -1
  291. package/src/paragraph/README.md +1 -0
  292. package/src/paragraph/block.json +1 -0
  293. package/src/paragraph/use-enter.js +4 -11
  294. package/src/playlist/README.md +17 -18
  295. package/src/playlist/block.json +29 -10
  296. package/src/playlist/edit.js +247 -15
  297. package/src/playlist/editor.scss +6 -0
  298. package/src/playlist/index.js +1 -1
  299. package/src/playlist/index.php +58 -14
  300. package/src/playlist/style.scss +51 -1
  301. package/src/playlist/test/edit.js +13 -2
  302. package/src/playlist/utils.js +25 -7
  303. package/src/playlist/view.js +97 -16
  304. package/src/playlist-track/README.md +3 -3
  305. package/src/playlist-track/block.json +4 -2
  306. package/src/playlist-track/edit.js +94 -70
  307. package/src/playlist-track/index.php +20 -6
  308. package/src/playlist-track/style.scss +10 -0
  309. package/src/playlist-track/test/edit.js +169 -0
  310. package/src/post-content/README.md +1 -0
  311. package/src/post-content/block.json +1 -0
  312. package/src/post-template/README.md +1 -0
  313. package/src/post-template/block.json +2 -1
  314. package/src/post-template/edit.js +9 -0
  315. package/src/pullquote/README.md +1 -0
  316. package/src/pullquote/block.json +3 -1
  317. package/src/query/README.md +2 -1
  318. package/src/query/block.json +3 -2
  319. package/src/query/edit/inspector-controls/index.js +43 -3
  320. package/src/query/edit/inspector-controls/offset-controls.js +0 -1
  321. package/src/query/edit/inspector-controls/pages-control.js +0 -1
  322. package/src/query/edit/query-content.js +19 -3
  323. package/src/query/index.js +1 -0
  324. package/src/quote/README.md +1 -0
  325. package/src/quote/block.json +3 -1
  326. package/src/quote/transforms.js +2 -4
  327. package/src/rss/edit.js +0 -1
  328. package/src/rss/index.php +1 -1
  329. package/src/tab-list/README.md +4 -5
  330. package/src/tab-list/block.json +2 -2
  331. package/src/tab-list/edit.js +90 -28
  332. package/src/tab-list/index.php +9 -4
  333. package/src/tab-panel/README.md +4 -6
  334. package/src/tab-panel/block.json +1 -6
  335. package/src/tab-panel/edit.js +19 -24
  336. package/src/tab-panels/README.md +5 -3
  337. package/src/tab-panels/block.json +0 -1
  338. package/src/tabs/README.md +18 -9
  339. package/src/tabs/block.json +0 -5
  340. package/src/tabs/edit.js +7 -64
  341. package/src/tabs/use-tab-list-items-sync.js +24 -4
  342. package/src/template-part/index.php +1 -16
  343. package/src/term-name/README.md +1 -1
  344. package/src/term-name/block.json +1 -3
  345. package/src/term-name/deprecated.js +74 -0
  346. package/src/term-name/edit.js +2 -18
  347. package/src/term-name/index.js +2 -0
  348. package/src/utils/media-control.scss +1 -5
  349. package/src/utils/test/waveform-player.js +297 -34
  350. package/src/utils/test/waveform-utils.js +410 -5
  351. package/src/utils/waveform-player.js +189 -59
  352. package/src/utils/waveform-utils.js +443 -40
  353. package/src/video/edit.js +0 -8
  354. package/src/video/editor.scss +1 -1
  355. package/build/image/animated-gif-convert-control.cjs +0 -105
  356. package/build/image/animated-gif-convert-control.cjs.map +0 -7
  357. package/build/utils/gif-conversion-attributes.cjs +0 -40
  358. package/build/utils/gif-conversion-attributes.cjs.map +0 -7
  359. package/build/video/gif-restore-control.cjs +0 -73
  360. package/build/video/gif-restore-control.cjs.map +0 -7
  361. package/build-module/image/animated-gif-convert-control.mjs +0 -87
  362. package/build-module/image/animated-gif-convert-control.mjs.map +0 -7
  363. package/build-module/utils/gif-conversion-attributes.mjs +0 -15
  364. package/build-module/utils/gif-conversion-attributes.mjs.map +0 -7
  365. package/build-module/video/gif-restore-control.mjs +0 -55
  366. package/build-module/video/gif-restore-control.mjs.map +0 -7
  367. package/src/image/animated-gif-convert-control.js +0 -135
  368. package/src/image/test/animated-gif-convert-control.js +0 -276
  369. package/src/utils/gif-conversion-attributes.js +0 -30
  370. package/src/utils/test/gif-conversion-attributes.js +0 -60
  371. package/src/video/gif-restore-control.js +0 -92
@@ -12,15 +12,17 @@ import {
12
12
  useBlockProps,
13
13
  BlockControls,
14
14
  InspectorControls,
15
- RichText,
15
+ PlainText,
16
16
  } from '@wordpress/block-editor';
17
17
  import {
18
18
  Button,
19
19
  PanelBody,
20
20
  TextControl,
21
+ TextareaControl,
21
22
  BaseControl,
22
23
  Spinner,
23
24
  } from '@wordpress/components';
25
+ import { Link } from '@wordpress/ui';
24
26
  import { useDispatch } from '@wordpress/data';
25
27
  import { store as noticesStore } from '@wordpress/notices';
26
28
  import { __ } from '@wordpress/i18n';
@@ -31,10 +33,11 @@ import { __unstableStripHTML as stripHTML } from '@wordpress/dom';
31
33
  * Internal dependencies
32
34
  */
33
35
  import { PlaylistContext } from '../playlist/context';
36
+ import { getTrackAttributes, getTrackImageAttributes } from '../playlist/utils';
34
37
  import { useUploadMediaFromBlobURL } from '../utils/hooks';
35
38
 
36
39
  const ALLOWED_MEDIA_TYPES = [ 'audio' ];
37
- const ALBUM_COVER_ALLOWED_MEDIA_TYPES = [ 'image' ];
40
+ const TRACK_IMAGE_ALLOWED_MEDIA_TYPES = [ 'image' ];
38
41
 
39
42
  const PlaylistTrackEdit = ( {
40
43
  attributes,
@@ -43,9 +46,11 @@ const PlaylistTrackEdit = ( {
43
46
  clientId,
44
47
  isSelected,
45
48
  } ) => {
46
- const { id, src, album, artist, image, length, title } = attributes;
49
+ const { id, src, album, artist, image, imageAlt, length, title } =
50
+ attributes;
47
51
  const [ temporaryURL, setTemporaryURL ] = useState( attributes.blob );
48
52
  const showArtists = context?.showArtists;
53
+ const showImages = context?.showImages ?? true;
49
54
  const imageButton = useRef();
50
55
  const blockProps = useBlockProps();
51
56
  const { currentTrackClientId, setCurrentTrackClientId } =
@@ -54,13 +59,19 @@ const PlaylistTrackEdit = ( {
54
59
  function onUploadError( message ) {
55
60
  createErrorNotice( message, { type: 'snackbar' } );
56
61
  }
62
+ const hasTrackSource = !! src || !! temporaryURL;
57
63
 
58
64
  useEffect( () => {
59
- if ( isSelected && currentTrackClientId !== clientId ) {
65
+ if (
66
+ isSelected &&
67
+ hasTrackSource &&
68
+ currentTrackClientId !== clientId
69
+ ) {
60
70
  setCurrentTrackClientId( clientId );
61
71
  }
62
72
  }, [
63
73
  isSelected,
74
+ hasTrackSource,
64
75
  clientId,
65
76
  currentTrackClientId,
66
77
  setCurrentTrackClientId,
@@ -83,6 +94,7 @@ const PlaylistTrackEdit = ( {
83
94
  artist: undefined,
84
95
  album: undefined,
85
96
  image: undefined,
97
+ imageAlt: undefined,
86
98
  length: undefined,
87
99
  title: undefined,
88
100
  url: undefined,
@@ -98,42 +110,23 @@ const PlaylistTrackEdit = ( {
98
110
 
99
111
  setAttributes( {
100
112
  blob: undefined,
101
- id: media.id,
102
- src: media.url,
103
- artist:
104
- media.artist ||
105
- media?.meta?.artist ||
106
- media?.media_details?.artist ||
107
- __( 'Unknown artist' ),
108
- album:
109
- media.album ||
110
- media?.meta?.album ||
111
- media?.media_details?.album ||
112
- __( 'Unknown album' ),
113
- // Prevent using the default media attachment icon as the track image.
114
- image:
115
- media?.image?.src &&
116
- media?.image?.src.endsWith( '/images/media/audio.svg' )
117
- ? ''
118
- : media?.image?.src,
119
- length: media?.fileLength || media?.media_details?.length_formatted,
120
- title: media.title,
113
+ ...getTrackAttributes( media ),
121
114
  } );
122
115
  setTemporaryURL();
123
116
  }
124
117
 
125
- function onSelectAlbumCoverImage( coverImage ) {
126
- setAttributes( { image: coverImage.url } );
118
+ function onSelectTrackImage( trackImage ) {
119
+ setAttributes( getTrackImageAttributes( trackImage ) );
127
120
  }
128
121
 
129
- function onRemoveAlbumCoverImage() {
130
- setAttributes( { image: undefined } );
122
+ function onRemoveTrackImage() {
123
+ setAttributes( { image: undefined, imageAlt: undefined } );
131
124
 
132
125
  // Move focus back to the Media Upload button.
133
126
  imageButton.current.focus();
134
127
  }
135
128
 
136
- if ( ! src && ! temporaryURL ) {
129
+ if ( ! hasTrackSource ) {
137
130
  return (
138
131
  <div { ...blockProps }>
139
132
  <MediaPlaceholder
@@ -191,46 +184,74 @@ const PlaylistTrackEdit = ( {
191
184
  } }
192
185
  />
193
186
  <MediaUploadCheck>
194
- <div className="editor-video-poster-control">
187
+ <BaseControl>
195
188
  <BaseControl.VisualLabel>
196
- { __( 'Album cover image' ) }
189
+ { __( 'Track image' ) }
197
190
  </BaseControl.VisualLabel>
198
- { !! image && (
199
- <img
200
- src={ image }
201
- alt={ __(
202
- 'Preview of the album cover image'
191
+ <div className="editor-video-poster-control">
192
+ { !! image && (
193
+ <img
194
+ src={ image }
195
+ alt={ __(
196
+ 'Preview of the track image'
197
+ ) }
198
+ />
199
+ ) }
200
+ <MediaUpload
201
+ title={ __( 'Select image' ) }
202
+ onSelect={ onSelectTrackImage }
203
+ allowedTypes={
204
+ TRACK_IMAGE_ALLOWED_MEDIA_TYPES
205
+ }
206
+ render={ ( { open } ) => (
207
+ <Button
208
+ __next40pxDefaultSize
209
+ variant="primary"
210
+ onClick={ open }
211
+ ref={ imageButton }
212
+ >
213
+ { ! image
214
+ ? __( 'Select' )
215
+ : __( 'Replace' ) }
216
+ </Button>
203
217
  ) }
204
218
  />
205
- ) }
206
- <MediaUpload
207
- title={ __( 'Select image' ) }
208
- onSelect={ onSelectAlbumCoverImage }
209
- allowedTypes={ ALBUM_COVER_ALLOWED_MEDIA_TYPES }
210
- render={ ( { open } ) => (
219
+ { !! image && (
211
220
  <Button
212
221
  __next40pxDefaultSize
213
- variant="primary"
214
- onClick={ open }
215
- ref={ imageButton }
222
+ onClick={ onRemoveTrackImage }
223
+ variant="tertiary"
216
224
  >
217
- { ! image
218
- ? __( 'Select' )
219
- : __( 'Replace' ) }
225
+ { __( 'Remove' ) }
220
226
  </Button>
221
227
  ) }
222
- />
223
- { !! image && (
224
- <Button
225
- __next40pxDefaultSize
226
- onClick={ onRemoveAlbumCoverImage }
227
- variant="tertiary"
228
- >
229
- { __( 'Remove' ) }
230
- </Button>
231
- ) }
232
- </div>
228
+ </div>
229
+ </BaseControl>
233
230
  </MediaUploadCheck>
231
+ { !! image && (
232
+ <TextareaControl
233
+ label={ __( 'Alternative text' ) }
234
+ value={ imageAlt || '' }
235
+ onChange={ ( value ) =>
236
+ setAttributes( { imageAlt: value } )
237
+ }
238
+ help={
239
+ <Link
240
+ openInNewTab
241
+ href={
242
+ // translators: Localized tutorial, if one exists. W3C Web Accessibility Initiative link has list of existing translations.
243
+ __(
244
+ 'https://www.w3.org/WAI/tutorials/images/decision-tree/'
245
+ )
246
+ }
247
+ >
248
+ { __(
249
+ 'Describe the purpose of the image.'
250
+ ) }
251
+ </Link>
252
+ }
253
+ />
254
+ ) }
234
255
  </PanelBody>
235
256
  </InspectorControls>
236
257
  <li { ...blockProps }>
@@ -242,8 +263,15 @@ const PlaylistTrackEdit = ( {
242
263
  currentTrackClientId === clientId ? 'true' : 'false'
243
264
  }
244
265
  >
266
+ { showImages && !! image && (
267
+ <img
268
+ className="wp-block-playlist-track__image"
269
+ src={ image }
270
+ alt={ imageAlt || '' }
271
+ />
272
+ ) }
245
273
  <span className="wp-block-playlist-track__content">
246
- <RichText
274
+ <PlainText
247
275
  tagName="span"
248
276
  className="wp-block-playlist-track__title"
249
277
  value={ title }
@@ -251,11 +279,10 @@ const PlaylistTrackEdit = ( {
251
279
  onChange={ ( value ) => {
252
280
  setAttributes( { title: value } );
253
281
  } }
254
- allowedFormats={ [] }
255
- withoutInteractiveFormatting
282
+ __experimentalVersion={ 2 }
256
283
  />
257
284
  { showArtists && (
258
- <RichText
285
+ <PlainText
259
286
  tagName="span"
260
287
  className="wp-block-playlist-track__artist"
261
288
  value={ artist }
@@ -263,8 +290,7 @@ const PlaylistTrackEdit = ( {
263
290
  onChange={ ( value ) =>
264
291
  setAttributes( { artist: value } )
265
292
  }
266
- allowedFormats={ [] }
267
- withoutInteractiveFormatting
293
+ __experimentalVersion={ 2 }
268
294
  />
269
295
  ) }
270
296
  </span>
@@ -272,16 +298,14 @@ const PlaylistTrackEdit = ( {
272
298
  { length && (
273
299
  <span className="screen-reader-text">
274
300
  {
275
- /* translators: %s: Visually hidden label for the track length (screen reader text). */
276
- __( 'Length:' )
301
+ /* translators: Visually hidden label for the track duration (screen reader text). */
302
+ __( 'Duration:' )
277
303
  }
278
304
  </span>
279
305
  ) }
280
306
  { length }
281
307
  </span>
282
- <span className="screen-reader-text">
283
- { __( 'Select to play this track' ) }
284
- </span>
308
+ <span className="screen-reader-text">{ __( 'Play' ) }</span>
285
309
  </button>
286
310
  </li>
287
311
  </>
@@ -10,41 +10,55 @@
10
10
  *
11
11
  * @since 6.9.0
12
12
  *
13
- * @param array $attributes The block attributes.
13
+ * @param array $attributes The block attributes.
14
+ * @param string $content The block content.
15
+ * @param WP_Block|null $block The block instance.
14
16
  *
15
17
  * @return string Returns the Playlist Track.
16
18
  */
17
- function render_block_core_playlist_track( $attributes ) {
19
+ function render_block_core_playlist_track( $attributes, $content = '', $block = null ) {
18
20
  if ( empty( $attributes['id'] ) ) {
19
21
  return '';
20
22
  }
21
23
 
22
24
  $wrapper_attributes = get_block_wrapper_attributes();
25
+ $show_images = true;
26
+ if ( $block instanceof WP_Block && isset( $block->context['showImages'] ) ) {
27
+ $show_images = $block->context['showImages'];
28
+ }
23
29
 
24
30
  $artist = $attributes['artist'] ?? '';
31
+ $image = $attributes['image'] ?? '';
32
+ $alt = $attributes['imageAlt'] ?? '';
25
33
  $length = $attributes['length'] ?? '';
26
34
  $title = isset( $attributes['title'] ) && ! empty( $attributes['title'] ) ? $attributes['title'] : __( 'Unknown title' );
27
35
 
28
36
  $html = '<li ' . $wrapper_attributes . '>';
29
37
  $html .= '<button data-wp-on--click="actions.changeTrack" data-wp-bind--aria-current="state.isCurrentTrack" class="wp-block-playlist-track__button">';
30
38
 
39
+ if ( $show_images && $image ) {
40
+ $html .= '<img class="wp-block-playlist-track__image" src="' . esc_url( $image ) . '" alt="' . esc_attr( $alt ) . '" />';
41
+ }
42
+
31
43
  $html .= '<span class="wp-block-playlist-track__content">';
32
44
  if ( $title ) {
33
- $html .= '<span class="wp-block-playlist-track__title">' . wp_kses_post( $title ) . '</span>';
45
+ $html .= '<span class="wp-block-playlist-track__title">' . esc_html( $title ) . '</span>';
34
46
  }
35
47
  if ( $artist ) {
36
- $html .= '<span class="wp-block-playlist-track__artist">' . wp_kses_post( $artist ) . '</span>';
48
+ $html .= '<span class="wp-block-playlist-track__artist">' . esc_html( $artist ) . '</span>';
37
49
  }
38
50
  $html .= '</span>';
39
51
 
40
52
  if ( $length ) {
41
53
  $html .= '<span class="wp-block-playlist-track__length">';
42
- $html .= '<span class="screen-reader-text">' . esc_html__( 'Length:' ) . ' </span>';
54
+ $html .= '<span class="screen-reader-text">' . esc_html__( 'Duration:' ) . ' </span>';
43
55
  $html .= esc_html( $length );
44
56
  $html .= '</span>';
45
57
  }
46
58
 
47
- $html .= '<span class="screen-reader-text">' . esc_html__( 'Select to play this track' ) . '</span>';
59
+ $html .= '<span class="screen-reader-text" data-wp-text="state.trackButtonActionLabel">';
60
+ $html .= esc_html__( 'Play' );
61
+ $html .= '</span>';
48
62
  $html .= '</button>';
49
63
  $html .= '</li>';
50
64
 
@@ -33,6 +33,16 @@
33
33
  opacity: 0.7;
34
34
  }
35
35
 
36
+ .wp-block-playlist-track__image {
37
+ flex: 0 0 50px;
38
+ width: 50px;
39
+ height: 50px;
40
+ margin-right: var(--wp--preset--spacing--20, 0.5em);
41
+ border: 1px solid rgb(0 0 0 / 8%);
42
+ box-sizing: border-box;
43
+ object-fit: cover;
44
+ }
45
+
36
46
  .wp-block-playlist-track__content {
37
47
  flex: 1 1 0;
38
48
  min-width: 0;
@@ -0,0 +1,169 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { fireEvent, render, screen } from '@testing-library/react';
5
+
6
+ /**
7
+ * WordPress dependencies
8
+ */
9
+ import { useDispatch } from '@wordpress/data';
10
+
11
+ /**
12
+ * Internal dependencies
13
+ */
14
+ import PlaylistTrackEdit from '../edit';
15
+ import { PlaylistContext } from '../../playlist/context';
16
+
17
+ jest.mock( '@wordpress/block-editor', () => ( {
18
+ BlockControls: ( { children } ) => <div>{ children }</div>,
19
+ BlockIcon: () => <span />,
20
+ InspectorControls: ( { children } ) => <div>{ children }</div>,
21
+ MediaPlaceholder: () => <div />,
22
+ MediaReplaceFlow: () => <div />,
23
+ MediaUpload: ( { render: renderMediaUpload } ) =>
24
+ renderMediaUpload( { open: jest.fn() } ),
25
+ MediaUploadCheck: ( { children } ) => <div>{ children }</div>,
26
+ PlainText: ( {
27
+ onChange,
28
+ placeholder,
29
+ tagName: TagName = 'div',
30
+ value,
31
+ __experimentalVersion,
32
+ ...props
33
+ } ) => <TagName { ...props }>{ value || placeholder }</TagName>,
34
+ useBlockProps: jest.fn( () => ( {} ) ),
35
+ } ) );
36
+
37
+ jest.mock( '@wordpress/data', () => ( {
38
+ useDispatch: jest.fn(),
39
+ combineReducers: jest.fn( ( reducers ) => ( state = {}, action ) => {
40
+ const newState = {};
41
+ Object.keys( reducers ).forEach( ( key ) => {
42
+ newState[ key ] = reducers[ key ]( state[ key ], action );
43
+ } );
44
+ return newState;
45
+ } ),
46
+ createRegistrySelector: jest.fn( ( fn ) => fn ),
47
+ createReduxStore: jest.fn( () => ( {} ) ),
48
+ createSelector: jest.fn( ( fn ) => fn ),
49
+ register: jest.fn(),
50
+ } ) );
51
+
52
+ jest.mock( '@wordpress/notices', () => ( {
53
+ store: 'core/notices',
54
+ } ) );
55
+
56
+ jest.mock( '../../utils/hooks', () => ( {
57
+ useUploadMediaFromBlobURL: jest.fn(),
58
+ } ) );
59
+
60
+ const defaultAttributes = {
61
+ id: 1,
62
+ src: 'https://example.com/song.mp3',
63
+ album: 'Great Album',
64
+ artist: 'The Artist',
65
+ image: 'https://example.com/cover.jpg',
66
+ imageAlt: 'A bright abstract track image',
67
+ length: '3:45',
68
+ title: 'Song One',
69
+ };
70
+
71
+ function renderEdit( props = {} ) {
72
+ const setAttributes = jest.fn();
73
+ const setCurrentTrackClientId = props.setCurrentTrackClientId || jest.fn();
74
+
75
+ render(
76
+ <PlaylistContext.Provider
77
+ value={ {
78
+ currentTrackClientId: props.currentTrackClientId ?? null,
79
+ setCurrentTrackClientId,
80
+ } }
81
+ >
82
+ <PlaylistTrackEdit
83
+ attributes={ {
84
+ ...defaultAttributes,
85
+ ...props.attributes,
86
+ } }
87
+ setAttributes={ setAttributes }
88
+ context={ {
89
+ showArtists: true,
90
+ showImages: true,
91
+ ...props.context,
92
+ } }
93
+ clientId={ props.clientId || 'playlist-track-client-id' }
94
+ isSelected={ props.isSelected ?? false }
95
+ />
96
+ </PlaylistContext.Provider>
97
+ );
98
+
99
+ return { setAttributes, setCurrentTrackClientId };
100
+ }
101
+
102
+ describe( 'PlaylistTrackEdit', () => {
103
+ beforeEach( () => {
104
+ useDispatch.mockReturnValue( {
105
+ createErrorNotice: jest.fn(),
106
+ } );
107
+ } );
108
+
109
+ it( 'allows the track image alternative text to be edited', () => {
110
+ const { setAttributes } = renderEdit();
111
+
112
+ expect(
113
+ screen.getByRole( 'link', {
114
+ name: /Describe the purpose of the image\./,
115
+ } )
116
+ ).toHaveAttribute(
117
+ 'href',
118
+ 'https://www.w3.org/WAI/tutorials/images/decision-tree/'
119
+ );
120
+ expect(
121
+ screen.queryByText( 'Leave empty if decorative.' )
122
+ ).not.toBeInTheDocument();
123
+
124
+ fireEvent.change( screen.getByLabelText( 'Alternative text' ), {
125
+ target: { value: 'A silver microphone on a red background' },
126
+ } );
127
+
128
+ expect( setAttributes ).toHaveBeenCalledWith( {
129
+ imageAlt: 'A silver microphone on a red background',
130
+ } );
131
+ } );
132
+
133
+ it( 'does not show the alternative text control without a track image', () => {
134
+ renderEdit( {
135
+ attributes: {
136
+ image: undefined,
137
+ imageAlt: undefined,
138
+ },
139
+ } );
140
+
141
+ expect(
142
+ screen.queryByLabelText( 'Alternative text' )
143
+ ).not.toBeInTheDocument();
144
+ } );
145
+
146
+ it( 'sets the selected track as the current track', () => {
147
+ const { setCurrentTrackClientId } = renderEdit( {
148
+ currentTrackClientId: 'another-track-client-id',
149
+ isSelected: true,
150
+ } );
151
+
152
+ expect( setCurrentTrackClientId ).toHaveBeenCalledWith(
153
+ 'playlist-track-client-id'
154
+ );
155
+ } );
156
+
157
+ it( 'does not set a selected placeholder track as the current track', () => {
158
+ const { setCurrentTrackClientId } = renderEdit( {
159
+ attributes: {
160
+ blob: undefined,
161
+ src: undefined,
162
+ },
163
+ currentTrackClientId: 'another-track-client-id',
164
+ isSelected: true,
165
+ } );
166
+
167
+ expect( setCurrentTrackClientId ).not.toHaveBeenCalled();
168
+ } );
169
+ } );
@@ -27,6 +27,7 @@ _Defined via the [`supports`](https://developer.wordpress.org/block-editor/refer
27
27
  - [`background`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/#background):
28
28
  - `backgroundImage`: `true`
29
29
  - `backgroundSize`: `true`
30
+ - `gradient`: `true`
30
31
  - [`dimensions`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/#dimensions):
31
32
  - `minHeight`: `true`
32
33
  - [`spacing`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/#spacing):
@@ -24,6 +24,7 @@
24
24
  "background": {
25
25
  "backgroundImage": true,
26
26
  "backgroundSize": true,
27
+ "gradient": true,
27
28
  "__experimentalDefaultControls": {
28
29
  "backgroundImage": true
29
30
  }
@@ -54,6 +54,7 @@ _Defined via the [`usesContext` and `providesContext`](https://developer.wordpre
54
54
  - `previewPostType`
55
55
  - `enhancedPagination`
56
56
  - `postType`
57
+ - `postId`
57
58
 
58
59
  ## Block Markup
59
60
 
@@ -14,7 +14,8 @@
14
14
  "templateSlug",
15
15
  "previewPostType",
16
16
  "enhancedPagination",
17
- "postType"
17
+ "postType",
18
+ "postId"
18
19
  ],
19
20
  "supports": {
20
21
  "anchor": true,
@@ -103,6 +103,7 @@ export default function PostTemplateEdit( {
103
103
  parents,
104
104
  pages,
105
105
  format,
106
+ excludeCurrent,
106
107
  // We gather extra query args to pass to the REST API call.
107
108
  // This way extenders of Query Loop can add their own query args,
108
109
  // and have accurate previews in the editor.
@@ -112,6 +113,7 @@ export default function PostTemplateEdit( {
112
113
  } = {},
113
114
  templateSlug,
114
115
  previewPostType,
116
+ postId,
115
117
  },
116
118
  attributes: { layout },
117
119
  __unstableLayoutClassNames,
@@ -203,6 +205,13 @@ export default function PostTemplateEdit( {
203
205
  if ( format?.length ) {
204
206
  query.format = format;
205
207
  }
208
+ if ( excludeCurrent && postId ) {
209
+ if ( query.exclude ) {
210
+ query.exclude = [ ...query.exclude, postId ];
211
+ } else {
212
+ query.exclude = [ postId ];
213
+ }
214
+ }
206
215
 
207
216
  /*
208
217
  * Handle cases where sticky is set to `exclude` or `only`.
@@ -26,6 +26,7 @@ _Defined via the [`supports`](https://developer.wordpress.org/block-editor/refer
26
26
  - [`background`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/#background):
27
27
  - `backgroundImage`: `true`
28
28
  - `backgroundSize`: `true`
29
+ - `gradient`: `true`
29
30
  - [`color`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/#color):
30
31
  - [`gradients`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/#color-gradients): `true`
31
32
  - [`background`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/#color-background): `true`
@@ -26,8 +26,10 @@
26
26
  "background": {
27
27
  "backgroundImage": true,
28
28
  "backgroundSize": true,
29
+ "gradient": true,
29
30
  "__experimentalDefaultControls": {
30
- "backgroundImage": true
31
+ "backgroundImage": true,
32
+ "gradient": true
31
33
  }
32
34
  },
33
35
  "color": {
@@ -16,7 +16,7 @@ _Defined via the [`attributes`](https://developer.wordpress.org/block-editor/ref
16
16
  | Attribute | [Type](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/#type-validation) | [Default](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/#default-value) | Description |
17
17
  |-----------|------|---------|-------------|
18
18
  | `queryId` | `number` | — | — |
19
- | `query` | `object` | `{"perPage":null,"pages":0,"offset":0,"postType":"post","order":"desc","orderBy":"date","author":"","search":"","exclude":[],"sticky":"","inherit":true,"taxQuery":null,"parents":[],"format":[]}` | — |
19
+ | `query` | `object` | `{"perPage":null,"pages":0,"offset":0,"postType":"post","order":"desc","orderBy":"date","author":"","search":"","exclude":[],"sticky":"","inherit":true,"taxQuery":null,"parents":[],"format":[],"excludeCurrent":null}` | — |
20
20
  | `tagName` | `string` | `"div"` | — |
21
21
  | `namespace` | `string` | — | — |
22
22
  | `enhancedPagination` | `boolean` | `false` | — |
@@ -38,6 +38,7 @@ _Defined via the [`usesContext` and `providesContext`](https://developer.wordpre
38
38
  **Uses context:**
39
39
 
40
40
  - `templateSlug`
41
+ - `postType`
41
42
 
42
43
  **Provides context:**
43
44
 
@@ -27,7 +27,8 @@
27
27
  "inherit": true,
28
28
  "taxQuery": null,
29
29
  "parents": [],
30
- "format": []
30
+ "format": [],
31
+ "excludeCurrent": null
31
32
  }
32
33
  },
33
34
  "tagName": {
@@ -42,7 +43,7 @@
42
43
  "default": false
43
44
  }
44
45
  },
45
- "usesContext": [ "templateSlug" ],
46
+ "usesContext": [ "templateSlug", "postType" ],
46
47
  "providesContext": {
47
48
  "queryId": "queryId",
48
49
  "query": "query",