@wordpress/block-library 9.40.2-next.v.202602241322.0 → 9.41.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 (153) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/accordion/view.cjs +0 -34
  3. package/build/accordion/view.cjs.map +2 -2
  4. package/build/button/block.json +11 -3
  5. package/build/button/deprecated.cjs +246 -13
  6. package/build/button/deprecated.cjs.map +2 -2
  7. package/build/button/edit.cjs +45 -58
  8. package/build/button/edit.cjs.map +3 -3
  9. package/build/button/save.cjs +3 -7
  10. package/build/button/save.cjs.map +2 -2
  11. package/build/button/utils.cjs +59 -0
  12. package/build/button/utils.cjs.map +7 -0
  13. package/build/image/image.cjs +1 -1
  14. package/build/image/image.cjs.map +2 -2
  15. package/build/navigation/edit/index.cjs +4 -2
  16. package/build/navigation/edit/index.cjs.map +3 -3
  17. package/build/navigation/edit/leaf-more-menu.cjs +68 -6
  18. package/build/navigation/edit/leaf-more-menu.cjs.map +3 -3
  19. package/build/navigation/edit/menu-inspector-controls.cjs +20 -91
  20. package/build/navigation/edit/menu-inspector-controls.cjs.map +3 -3
  21. package/build/navigation/edit/navigation-link-ui.cjs +97 -0
  22. package/build/navigation/edit/navigation-link-ui.cjs.map +7 -0
  23. package/build/navigation/edit/navigation-list-view-header.cjs +86 -0
  24. package/build/navigation/edit/navigation-list-view-header.cjs.map +7 -0
  25. package/build/navigation/edit/navigation-menu-selector.cjs +4 -2
  26. package/build/navigation/edit/navigation-menu-selector.cjs.map +3 -3
  27. package/build/navigation/edit/placeholder/index.cjs +2 -2
  28. package/build/navigation/edit/placeholder/index.cjs.map +3 -3
  29. package/build/navigation-link/shared/controls.cjs +29 -52
  30. package/build/navigation-link/shared/controls.cjs.map +3 -3
  31. package/build/navigation-link/shared/use-link-preview.cjs +8 -9
  32. package/build/navigation-link/shared/use-link-preview.cjs.map +2 -2
  33. package/build/page-list-item/edit.cjs +6 -3
  34. package/build/page-list-item/edit.cjs.map +2 -2
  35. package/build/playlist/edit.cjs +43 -136
  36. package/build/playlist/edit.cjs.map +3 -3
  37. package/build/playlist/view.cjs +56 -38
  38. package/build/playlist/view.cjs.map +2 -2
  39. package/build/playlist-track/edit.cjs +0 -1
  40. package/build/playlist-track/edit.cjs.map +2 -2
  41. package/build/post-title/block.json +3 -0
  42. package/build/post-title/edit.cjs +2 -2
  43. package/build/post-title/edit.cjs.map +2 -2
  44. package/build/utils/waveform-player.cjs +68 -0
  45. package/build/utils/waveform-player.cjs.map +7 -0
  46. package/build/utils/waveform-utils.cjs +171 -0
  47. package/build/utils/waveform-utils.cjs.map +7 -0
  48. package/build-module/accordion/view.mjs +1 -35
  49. package/build-module/accordion/view.mjs.map +2 -2
  50. package/build-module/button/block.json +11 -3
  51. package/build-module/button/deprecated.mjs +246 -13
  52. package/build-module/button/deprecated.mjs.map +2 -2
  53. package/build-module/button/edit.mjs +47 -63
  54. package/build-module/button/edit.mjs.map +2 -2
  55. package/build-module/button/save.mjs +3 -7
  56. package/build-module/button/save.mjs.map +2 -2
  57. package/build-module/button/utils.mjs +33 -0
  58. package/build-module/button/utils.mjs.map +7 -0
  59. package/build-module/image/image.mjs +1 -1
  60. package/build-module/image/image.mjs.map +2 -2
  61. package/build-module/navigation/edit/index.mjs +4 -2
  62. package/build-module/navigation/edit/index.mjs.map +2 -2
  63. package/build-module/navigation/edit/leaf-more-menu.mjs +73 -7
  64. package/build-module/navigation/edit/leaf-more-menu.mjs.map +2 -2
  65. package/build-module/navigation/edit/menu-inspector-controls.mjs +21 -101
  66. package/build-module/navigation/edit/menu-inspector-controls.mjs.map +2 -2
  67. package/build-module/navigation/edit/navigation-link-ui.mjs +76 -0
  68. package/build-module/navigation/edit/navigation-link-ui.mjs.map +7 -0
  69. package/build-module/navigation/edit/navigation-list-view-header.mjs +58 -0
  70. package/build-module/navigation/edit/navigation-list-view-header.mjs.map +7 -0
  71. package/build-module/navigation/edit/navigation-menu-selector.mjs +5 -3
  72. package/build-module/navigation/edit/navigation-menu-selector.mjs.map +2 -2
  73. package/build-module/navigation/edit/placeholder/index.mjs +2 -2
  74. package/build-module/navigation/edit/placeholder/index.mjs.map +2 -2
  75. package/build-module/navigation-link/shared/controls.mjs +29 -53
  76. package/build-module/navigation-link/shared/controls.mjs.map +2 -2
  77. package/build-module/navigation-link/shared/use-link-preview.mjs +8 -9
  78. package/build-module/navigation-link/shared/use-link-preview.mjs.map +2 -2
  79. package/build-module/page-list-item/edit.mjs +6 -3
  80. package/build-module/page-list-item/edit.mjs.map +2 -2
  81. package/build-module/playlist/edit.mjs +41 -139
  82. package/build-module/playlist/edit.mjs.map +2 -2
  83. package/build-module/playlist/view.mjs +56 -38
  84. package/build-module/playlist/view.mjs.map +2 -2
  85. package/build-module/playlist-track/edit.mjs +0 -1
  86. package/build-module/playlist-track/edit.mjs.map +2 -2
  87. package/build-module/post-title/block.json +3 -0
  88. package/build-module/post-title/edit.mjs +2 -2
  89. package/build-module/post-title/edit.mjs.map +2 -2
  90. package/build-module/utils/waveform-player.mjs +43 -0
  91. package/build-module/utils/waveform-player.mjs.map +7 -0
  92. package/build-module/utils/waveform-utils.mjs +131 -0
  93. package/build-module/utils/waveform-utils.mjs.map +7 -0
  94. package/build-style/button/style-rtl.css +6 -0
  95. package/build-style/button/style.css +6 -0
  96. package/build-style/editor-rtl.css +13 -3
  97. package/build-style/editor.css +13 -3
  98. package/build-style/navigation-link/editor-rtl.css +10 -0
  99. package/build-style/navigation-link/editor.css +10 -0
  100. package/build-style/playlist/editor-rtl.css +3 -3
  101. package/build-style/playlist/editor.css +3 -3
  102. package/build-style/playlist/style-rtl.css +351 -17
  103. package/build-style/playlist/style.css +351 -17
  104. package/build-style/style-rtl.css +357 -17
  105. package/build-style/style.css +357 -17
  106. package/package.json +39 -38
  107. package/src/accordion/view.js +1 -44
  108. package/src/accordion-item/index.php +0 -1
  109. package/src/button/block.json +11 -3
  110. package/src/button/deprecated.js +254 -16
  111. package/src/button/edit.js +50 -61
  112. package/src/button/index.php +68 -0
  113. package/src/button/save.js +2 -8
  114. package/src/button/style.scss +49 -7
  115. package/src/button/test/utils.js +84 -0
  116. package/src/button/utils.js +42 -0
  117. package/src/cover/index.php +4 -4
  118. package/src/image/image.js +14 -15
  119. package/src/image/index.php +3 -1
  120. package/src/navigation/edit/index.js +4 -2
  121. package/src/navigation/edit/leaf-more-menu.js +86 -11
  122. package/src/navigation/edit/menu-inspector-controls.js +23 -142
  123. package/src/navigation/edit/navigation-link-ui.js +115 -0
  124. package/src/navigation/edit/navigation-list-view-header.js +62 -0
  125. package/src/navigation/edit/navigation-menu-selector.js +5 -3
  126. package/src/navigation/edit/placeholder/index.js +3 -2
  127. package/src/navigation/edit/test/navigation-menu-selector.js +23 -20
  128. package/src/navigation-link/editor.scss +18 -0
  129. package/src/navigation-link/shared/controls.js +35 -62
  130. package/src/navigation-link/shared/test/controls.js +5 -5
  131. package/src/navigation-link/shared/test/use-link-preview.test.js +19 -1
  132. package/src/navigation-link/shared/use-link-preview.js +14 -15
  133. package/src/page-list/index.php +1 -1
  134. package/src/page-list-item/edit.js +8 -7
  135. package/src/playlist/edit.js +60 -154
  136. package/src/playlist/editor.scss +3 -3
  137. package/src/playlist/index.php +15 -40
  138. package/src/playlist/style.scss +34 -27
  139. package/src/playlist/test/edit.js +137 -0
  140. package/src/playlist/view.js +97 -40
  141. package/src/playlist-track/edit.js +0 -1
  142. package/src/post-title/block.json +3 -0
  143. package/src/post-title/edit.js +4 -2
  144. package/src/query-title/index.php +1 -1
  145. package/src/search/index.php +1 -1
  146. package/src/utils/test/waveform-utils.js +328 -0
  147. package/src/utils/waveform-player.js +77 -0
  148. package/src/utils/waveform-utils.js +232 -0
  149. package/build/navigation/use-navigation-entities.cjs +0 -67
  150. package/build/navigation/use-navigation-entities.cjs.map +0 -7
  151. package/build-module/navigation/use-navigation-entities.mjs +0 -46
  152. package/build-module/navigation/use-navigation-entities.mjs.map +0 -7
  153. package/src/navigation/use-navigation-entities.js +0 -72
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/navigation-link/shared/use-link-preview.js"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { __, sprintf } from '@wordpress/i18n';\nimport { safeDecodeURI } from '@wordpress/url';\nimport { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor';\nimport { useSelect } from '@wordpress/data';\nimport { store as coreDataStore } from '@wordpress/core-data';\n\n/**\n * Internal dependencies\n */\nimport { unlock } from '../../lock-unlock';\n\nconst { useRemoteUrlData, isHashLink, isRelativePath } = unlock(\n\tblockEditorPrivateApis\n);\n\n/**\n * Capitalize the first letter of a string.\n *\n * @param {string} str - The string to capitalize\n * @return {string} Capitalized string\n */\nfunction capitalize( str ) {\n\treturn str.charAt( 0 ).toUpperCase() + str.slice( 1 );\n}\n\n/**\n * Compute display URL - strips site URL if internal, shows full URL if external.\n *\n * @param {Object} options - Parameters object\n * @param {string} options.linkUrl - The URL to process\n * @param {string} options.siteUrl - The WordPress site URL (falls back to window.location.origin)\n * @return {Object} Object with displayUrl and isExternal flag\n */\nexport function computeDisplayUrl( { linkUrl, siteUrl } = {} ) {\n\tif ( ! linkUrl ) {\n\t\treturn { displayUrl: '', isExternal: false };\n\t}\n\n\tlet displayUrl = safeDecodeURI( linkUrl );\n\tlet isExternal = false;\n\n\t// Check hash links and relative paths first - these are always internal\n\tif ( isRelativePath( linkUrl ) || isHashLink( linkUrl ) ) {\n\t\treturn { displayUrl, isExternal: false };\n\t}\n\n\t// Try to parse as a full URL to determine if it's actually external\n\t// This must happen before trusting the type attribute\n\ttry {\n\t\tconst parsedUrl = new URL( linkUrl );\n\t\t// Use provided siteUrl or fall back to window.location.origin\n\t\tconst siteDomain = siteUrl || window.location.origin;\n\t\tif ( parsedUrl.origin === siteDomain ) {\n\t\t\t// Show only the pathname (and search/hash if present)\n\t\t\tlet path = parsedUrl.pathname + parsedUrl.search + parsedUrl.hash;\n\t\t\t// Remove trailing slash\n\t\t\tif ( path.endsWith( '/' ) && path.length > 1 ) {\n\t\t\t\tpath = path.slice( 0, -1 );\n\t\t\t}\n\t\t\tdisplayUrl = path;\n\t\t} else {\n\t\t\t// Different origin - this is an external link\n\t\t\tisExternal = true;\n\t\t}\n\t} catch ( e ) {\n\t\t// URL parsing failed - this means it's likely a URL without a protocol (e.g., \"www.example.com\")\n\t\t// Since we already checked for relative paths and hash links above, treat as external\n\t\tisExternal = true;\n\t}\n\n\treturn { displayUrl, isExternal };\n}\n\n/**\n * Compute badges for the link preview.\n *\n * @param {Object} options - Options object\n * @param {string} options.url - Link URL\n * @param {string} options.type - Entity type (page, post, etc.)\n * @param {boolean} options.isExternal - Whether link is external\n * @param {string} options.entityStatus - Entity status (publish, draft, etc.)\n * @param {boolean} options.hasBinding - Whether link has entity binding\n * @param {boolean} options.isEntityAvailable - Whether bound entity exists\n * @return {Array} Array of badge objects with label and intent\n */\nexport function computeBadges( {\n\turl,\n\ttype,\n\tisExternal,\n\tentityStatus,\n\thasBinding,\n\tisEntityAvailable,\n} ) {\n\tconst badges = [];\n\n\t// Kind badge\n\tif ( url ) {\n\t\tif ( isExternal ) {\n\t\t\tbadges.push( {\n\t\t\t\tlabel: __( 'External link' ),\n\t\t\t\tintent: 'default',\n\t\t\t} );\n\t\t} else if ( isHashLink( url ) ) {\n\t\t\t// Hash links should be detected before type check\n\t\t\t// because they're not entity links even if type is set\n\t\t\tbadges.push( {\n\t\t\t\tlabel: __( 'Internal link' ),\n\t\t\t\tintent: 'default',\n\t\t\t} );\n\t\t} else if ( type && type !== 'custom' ) {\n\t\t\t// Show entity type badge (page, post, category, etc.)\n\t\t\t// but not 'custom' since that's just a manual link\n\t\t\tbadges.push( { label: capitalize( type ), intent: 'default' } );\n\t\t} else {\n\t\t\t// Internal link (not external, not hash, not entity)\n\t\t\tbadges.push( {\n\t\t\t\tlabel: __( 'Page' ),\n\t\t\t\tintent: 'default',\n\t\t\t} );\n\t\t}\n\t}\n\n\t// Status badge\n\tif ( hasBinding && ! isEntityAvailable ) {\n\t\tbadges.push( {\n\t\t\tlabel: sprintf(\n\t\t\t\t/* translators: %s is the entity type (e.g., \"page\", \"post\", \"category\") */\n\t\t\t\t__( 'Missing %s' ),\n\t\t\t\ttype\n\t\t\t),\n\t\t\tintent: 'error',\n\t\t} );\n\t} else if ( ! url ) {\n\t\tbadges.push( { label: __( 'No link selected' ), intent: 'error' } );\n\t} else if ( entityStatus ) {\n\t\tconst statusMap = {\n\t\t\tpublish: { label: __( 'Published' ), intent: 'success' },\n\t\t\tfuture: { label: __( 'Scheduled' ), intent: 'warning' },\n\t\t\tdraft: { label: __( 'Draft' ), intent: 'warning' },\n\t\t\tpending: { label: __( 'Pending' ), intent: 'warning' },\n\t\t\tprivate: { label: __( 'Private' ), intent: 'default' },\n\t\t\ttrash: { label: __( 'Trash' ), intent: 'error' },\n\t\t};\n\t\tconst badge = statusMap[ entityStatus ];\n\t\tif ( badge ) {\n\t\t\tbadges.push( badge );\n\t\t}\n\t}\n\n\treturn badges;\n}\n\n/**\n * Hook to compute link preview data for display.\n *\n * This hook takes raw link data and entity information and computes\n * presentation-ready preview data including formatted title, URL, and badges.\n *\n * @param {Object} options - Options object\n * @param {string} options.url - Link URL\n * @param {string} options.type - Entity type (page, post, etc.)\n * @param {Object} options.entityRecord - Entity record\n * @param {boolean} options.hasBinding - Whether link has entity binding\n * @param {boolean} options.isEntityAvailable - Whether bound entity exists\n * @return {Object} Preview data object with title, url, image, and badges\n */\nexport function useLinkPreview( {\n\turl,\n\tentityRecord,\n\ttype,\n\thasBinding,\n\tisEntityAvailable,\n} ) {\n\t// Get the WordPress site URL from settings\n\tconst siteUrl = useSelect( ( select ) => {\n\t\tconst siteEntity = select( coreDataStore ).getEntityRecord(\n\t\t\t'root',\n\t\t\t'site'\n\t\t);\n\t\treturn siteEntity?.url;\n\t}, [] );\n\n\tconst title =\n\t\tentityRecord?.title?.rendered ||\n\t\tentityRecord?.title ||\n\t\tentityRecord?.name;\n\n\t// Fetch rich URL data if we don't have a title. Internal links should have passed a title.\n\tconst { richData } = useRemoteUrlData( title ? null : url );\n\n\t// Compute display URL and external flag\n\tconst { displayUrl, isExternal } = computeDisplayUrl( {\n\t\tlinkUrl: url,\n\t\tsiteUrl,\n\t} );\n\n\tconst image = useSelect(\n\t\t( select ) => {\n\t\t\t// Only fetch for post-type entities with featured media\n\t\t\tif ( ! entityRecord?.featured_media ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst { getEntityRecord } = select( coreDataStore );\n\n\t\t\t// Get the media entity to fetch the image URL\n\t\t\tconst media = getEntityRecord(\n\t\t\t\t'postType',\n\t\t\t\t'attachment',\n\t\t\t\tentityRecord.featured_media\n\t\t\t);\n\n\t\t\t// Return the thumbnail or medium size URL, fallback to source_url\n\t\t\treturn (\n\t\t\t\tmedia?.media_details?.sizes?.thumbnail?.source_url ||\n\t\t\t\tmedia?.media_details?.sizes?.medium?.source_url ||\n\t\t\t\tmedia?.source_url ||\n\t\t\t\tnull\n\t\t\t);\n\t\t},\n\t\t[ entityRecord?.featured_media ]\n\t);\n\n\t// Compute badges\n\tconst badges = computeBadges( {\n\t\turl,\n\t\ttype,\n\t\tisExternal,\n\t\tentityStatus: entityRecord?.status,\n\t\thasBinding,\n\t\tisEntityAvailable,\n\t} );\n\n\t// Get display title - use provided title, fallback to rich data, or URL\n\tconst displayTitle = url\n\t\t? title || richData?.title || safeDecodeURI( url )\n\t\t: __( 'Add link' );\n\n\treturn {\n\t\ttitle: displayTitle,\n\t\turl: displayUrl,\n\t\timage,\n\t\tbadges,\n\t};\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { __, sprintf } from '@wordpress/i18n';\nimport { safeDecodeURI } from '@wordpress/url';\nimport { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor';\nimport { useSelect } from '@wordpress/data';\nimport { store as coreDataStore } from '@wordpress/core-data';\n\n/**\n * Internal dependencies\n */\nimport { unlock } from '../../lock-unlock';\n\nconst { useRemoteUrlData, isHashLink, isRelativePath } = unlock(\n\tblockEditorPrivateApis\n);\n\n/**\n * Capitalize the first letter of a string.\n *\n * @param {string} str - The string to capitalize\n * @return {string} Capitalized string\n */\nfunction capitalize( str ) {\n\treturn str.charAt( 0 ).toUpperCase() + str.slice( 1 );\n}\n\n/**\n * Compute display URL - strips site URL if internal, shows full URL if external.\n *\n * @param {Object} options - Parameters object\n * @param {string} options.linkUrl - The URL to process\n * @param {string} options.homeUrl - The WordPress site URL (required for internal/external detection)\n * @return {Object} Object with displayUrl and isExternal flag\n */\nexport function computeDisplayUrl( { linkUrl, homeUrl } = {} ) {\n\tif ( ! linkUrl ) {\n\t\treturn { displayUrl: '', isExternal: false };\n\t}\n\n\tlet displayUrl = safeDecodeURI( linkUrl );\n\tlet isExternal = false;\n\n\t// Check hash links and relative paths first - these are always internal\n\tif ( isRelativePath( linkUrl ) || isHashLink( linkUrl ) ) {\n\t\treturn { displayUrl, isExternal: false };\n\t}\n\n\t// Try to parse as a full URL to determine if it's actually external\n\t// This must happen before trusting the type attribute\n\ttry {\n\t\tconst parsedUrl = new URL( linkUrl );\n\t\t// Compare by host (not origin) so http/https to same site both count as internal\n\t\tconst siteHost = new URL( homeUrl ).host;\n\n\t\tif ( parsedUrl.host === siteHost ) {\n\t\t\t// Show only the pathname (and search/hash if present)\n\t\t\tlet path = parsedUrl.pathname + parsedUrl.search + parsedUrl.hash;\n\t\t\t// Remove trailing slash\n\t\t\tif ( path.endsWith( '/' ) && path.length > 1 ) {\n\t\t\t\tpath = path.slice( 0, -1 );\n\t\t\t}\n\t\t\tdisplayUrl = path;\n\t\t} else {\n\t\t\t// Different host - this is an external link\n\t\t\tisExternal = true;\n\t\t}\n\t} catch ( e ) {\n\t\t// URL parsing failed - treat as external (e.g. no homeUrl, or URL without protocol)\n\t\tisExternal = true;\n\t}\n\n\treturn { displayUrl, isExternal };\n}\n\n/**\n * Compute badges for the link preview.\n *\n * @param {Object} options - Options object\n * @param {string} options.url - Link URL\n * @param {string} options.type - Entity type (page, post, etc.)\n * @param {boolean} options.isExternal - Whether link is external\n * @param {string} options.entityStatus - Entity status (publish, draft, etc.)\n * @param {boolean} options.hasBinding - Whether link has entity binding\n * @param {boolean} options.isEntityAvailable - Whether bound entity exists\n * @return {Array} Array of badge objects with label and intent\n */\nexport function computeBadges( {\n\turl,\n\ttype,\n\tisExternal,\n\tentityStatus,\n\thasBinding,\n\tisEntityAvailable,\n} ) {\n\tconst badges = [];\n\n\t// Kind badge\n\tif ( url ) {\n\t\tif ( isExternal ) {\n\t\t\tbadges.push( {\n\t\t\t\tlabel: __( 'External link' ),\n\t\t\t\tintent: 'default',\n\t\t\t} );\n\t\t} else if ( isHashLink( url ) ) {\n\t\t\t// Hash links should be detected before type check\n\t\t\t// because they're not entity links even if type is set\n\t\t\tbadges.push( {\n\t\t\t\tlabel: __( 'Internal link' ),\n\t\t\t\tintent: 'default',\n\t\t\t} );\n\t\t} else if ( type && type !== 'custom' ) {\n\t\t\t// Show entity type badge (page, post, category, etc.)\n\t\t\t// but not 'custom' since that's just a manual link\n\t\t\tbadges.push( { label: capitalize( type ), intent: 'default' } );\n\t\t} else {\n\t\t\t// Internal link (not external, not hash, not entity)\n\t\t\tbadges.push( {\n\t\t\t\tlabel: __( 'Page' ),\n\t\t\t\tintent: 'default',\n\t\t\t} );\n\t\t}\n\t}\n\n\t// Status badge\n\tif ( hasBinding && ! isEntityAvailable ) {\n\t\tbadges.push( {\n\t\t\tlabel: sprintf(\n\t\t\t\t/* translators: %s is the entity type (e.g., \"page\", \"post\", \"category\") */\n\t\t\t\t__( 'Missing %s' ),\n\t\t\t\ttype\n\t\t\t),\n\t\t\tintent: 'error',\n\t\t} );\n\t} else if ( ! url ) {\n\t\tbadges.push( { label: __( 'No link selected' ), intent: 'error' } );\n\t} else if ( entityStatus ) {\n\t\tconst statusMap = {\n\t\t\tpublish: { label: __( 'Published' ), intent: 'success' },\n\t\t\tfuture: { label: __( 'Scheduled' ), intent: 'warning' },\n\t\t\tdraft: { label: __( 'Draft' ), intent: 'warning' },\n\t\t\tpending: { label: __( 'Pending' ), intent: 'warning' },\n\t\t\tprivate: { label: __( 'Private' ), intent: 'default' },\n\t\t\ttrash: { label: __( 'Trash' ), intent: 'error' },\n\t\t};\n\t\tconst badge = statusMap[ entityStatus ];\n\t\tif ( badge ) {\n\t\t\tbadges.push( badge );\n\t\t}\n\t}\n\n\treturn badges;\n}\n\n/**\n * Hook to compute link preview data for display.\n *\n * This hook takes raw link data and entity information and computes\n * presentation-ready preview data including formatted title, URL, and badges.\n *\n * @param {Object} options - Options object\n * @param {string} options.url - Link URL\n * @param {string} options.type - Entity type (page, post, etc.)\n * @param {Object} options.entityRecord - Entity record\n * @param {boolean} options.hasBinding - Whether link has entity binding\n * @param {boolean} options.isEntityAvailable - Whether bound entity exists\n * @return {Object} Preview data object with title, url, image, and badges\n */\nexport function useLinkPreview( {\n\turl,\n\tentityRecord,\n\ttype,\n\thasBinding,\n\tisEntityAvailable,\n} ) {\n\t// Get the WordPress homepage URL from settings\n\tconst homeUrl = useSelect( ( select ) => {\n\t\treturn select( coreDataStore ).getEntityRecord(\n\t\t\t'root',\n\t\t\t'__unstableBase'\n\t\t)?.home;\n\t}, [] );\n\n\tconst title =\n\t\tentityRecord?.title?.rendered ||\n\t\tentityRecord?.title ||\n\t\tentityRecord?.name;\n\n\t// Fetch rich URL data if we don't have a title. Internal links should have passed a title.\n\tconst { richData } = useRemoteUrlData( title ? null : url );\n\n\t// Compute display URL and external flag\n\tconst { displayUrl, isExternal } = computeDisplayUrl( {\n\t\tlinkUrl: url,\n\t\thomeUrl,\n\t} );\n\n\tconst image = useSelect(\n\t\t( select ) => {\n\t\t\t// Only fetch for post-type entities with featured media\n\t\t\tif ( ! entityRecord?.featured_media ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst { getEntityRecord } = select( coreDataStore );\n\n\t\t\t// Get the media entity to fetch the image URL\n\t\t\tconst media = getEntityRecord(\n\t\t\t\t'postType',\n\t\t\t\t'attachment',\n\t\t\t\tentityRecord.featured_media\n\t\t\t);\n\n\t\t\t// Return the thumbnail or medium size URL, fallback to source_url\n\t\t\treturn (\n\t\t\t\tmedia?.media_details?.sizes?.thumbnail?.source_url ||\n\t\t\t\tmedia?.media_details?.sizes?.medium?.source_url ||\n\t\t\t\tmedia?.source_url ||\n\t\t\t\tnull\n\t\t\t);\n\t\t},\n\t\t[ entityRecord?.featured_media ]\n\t);\n\n\t// Compute badges\n\tconst badges = computeBadges( {\n\t\turl,\n\t\ttype,\n\t\tisExternal,\n\t\tentityStatus: entityRecord?.status,\n\t\thasBinding,\n\t\tisEntityAvailable,\n\t} );\n\n\t// Get display title - use provided title, fallback to rich data, or URL\n\tconst displayTitle = url\n\t\t? title || richData?.title || safeDecodeURI( url )\n\t\t: __( 'Add link' );\n\n\treturn {\n\t\ttitle: displayTitle,\n\t\turl: displayUrl,\n\t\timage,\n\t\tbadges,\n\t};\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -3,7 +3,6 @@ import clsx from "clsx";
3
3
  import { useBlockProps, useInnerBlocksProps } from "@wordpress/block-editor";
4
4
  import { useSelect } from "@wordpress/data";
5
5
  import { store as coreStore } from "@wordpress/core-data";
6
- import { RawHTML } from "@wordpress/element";
7
6
  import { safeHTML } from "@wordpress/dom";
8
7
  import { ItemSubmenuIcon } from "../navigation-link/icons.mjs";
9
8
  import {
@@ -57,7 +56,9 @@ function PageListItemEdit({ context, attributes }) {
57
56
  type: "button",
58
57
  className: "wp-block-navigation-item__content wp-block-navigation-submenu__toggle",
59
58
  "aria-expanded": "false",
60
- children: /* @__PURE__ */ jsx(RawHTML, { children: safeHTML(label) })
59
+ dangerouslySetInnerHTML: {
60
+ __html: safeHTML(label)
61
+ }
61
62
  }
62
63
  ),
63
64
  /* @__PURE__ */ jsx("span", { className: "wp-block-page-list__submenu-icon wp-block-navigation__submenu-icon", children: /* @__PURE__ */ jsx(ItemSubmenuIcon, {}) })
@@ -68,7 +69,9 @@ function PageListItemEdit({ context, attributes }) {
68
69
  "wp-block-navigation-item__content": isNavigationChild
69
70
  }),
70
71
  href: link,
71
- children: /* @__PURE__ */ jsx(RawHTML, { children: safeHTML(title) })
72
+ dangerouslySetInnerHTML: {
73
+ __html: safeHTML(title)
74
+ }
72
75
  }
73
76
  ),
74
77
  hasChildren && /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/page-list-item/edit.js"],
4
- "sourcesContent": ["/**\n * External dependencies\n */\nimport clsx from 'clsx';\n/**\n * WordPress dependencies\n */\nimport { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';\nimport { useSelect } from '@wordpress/data';\nimport { store as coreStore } from '@wordpress/core-data';\nimport { RawHTML } from '@wordpress/element';\nimport { safeHTML } from '@wordpress/dom';\n\n/**\n * Internal dependencies\n */\nimport { ItemSubmenuIcon } from '../navigation-link/icons';\nimport {\n\tgetColors,\n\tgetNavigationChildBlockProps,\n} from '../navigation/edit/utils';\n\nfunction useFrontPageId() {\n\treturn useSelect( ( select ) => {\n\t\tconst canReadSettings = select( coreStore ).canUser( 'read', {\n\t\t\tkind: 'root',\n\t\t\tname: 'site',\n\t\t} );\n\t\tif ( ! canReadSettings ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst site = select( coreStore ).getEntityRecord( 'root', 'site' );\n\t\treturn site?.show_on_front === 'page' && site?.page_on_front;\n\t}, [] );\n}\n\nexport default function PageListItemEdit( { context, attributes } ) {\n\tconst { id, label, link, hasChildren, title } = attributes;\n\tconst isNavigationChild = 'showSubmenuIcon' in context;\n\tconst frontPageId = useFrontPageId();\n\n\t// Get submenu visibility from context. The Navigation block handles\n\t// backward compatibility by migrating openSubmenusOnClick to submenuVisibility\n\t// via its deprecation handler before this context is received.\n\tconst submenuVisibility = context.submenuVisibility;\n\n\tconst openOnClick = submenuVisibility === 'click';\n\n\tconst innerBlocksColors = getColors( context, true );\n\n\tconst navigationChildBlockProps =\n\t\tgetNavigationChildBlockProps( innerBlocksColors );\n\tconst blockProps = useBlockProps( navigationChildBlockProps, {\n\t\tclassName: 'wp-block-pages-list__item',\n\t} );\n\n\tconst innerBlocksProps = useInnerBlocksProps( blockProps );\n\n\treturn (\n\t\t<li\n\t\t\tkey={ id }\n\t\t\tclassName={ clsx( 'wp-block-pages-list__item', {\n\t\t\t\t'has-child': hasChildren,\n\t\t\t\t'wp-block-navigation-item': isNavigationChild,\n\t\t\t\t// Class assignment logic matches PHP rendering in page-list/index.php\n\t\t\t\t'open-on-click': openOnClick,\n\t\t\t\t'open-always': submenuVisibility === 'always',\n\t\t\t\t// Must check hover mode explicitly to match PHP elseif structure (index.php:212)\n\t\t\t\t'open-on-hover-click':\n\t\t\t\t\tsubmenuVisibility === 'hover' && context.showSubmenuIcon,\n\t\t\t\t'menu-item-home': id === frontPageId,\n\t\t\t} ) }\n\t\t>\n\t\t\t{ hasChildren && openOnClick ? (\n\t\t\t\t<>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"wp-block-navigation-item__content wp-block-navigation-submenu__toggle\"\n\t\t\t\t\t\taria-expanded=\"false\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<RawHTML>{ safeHTML( label ) }</RawHTML>\n\t\t\t\t\t</button>\n\t\t\t\t\t<span className=\"wp-block-page-list__submenu-icon wp-block-navigation__submenu-icon\">\n\t\t\t\t\t\t<ItemSubmenuIcon />\n\t\t\t\t\t</span>\n\t\t\t\t</>\n\t\t\t) : (\n\t\t\t\t<a\n\t\t\t\t\tclassName={ clsx( 'wp-block-pages-list__item__link', {\n\t\t\t\t\t\t'wp-block-navigation-item__content': isNavigationChild,\n\t\t\t\t\t} ) }\n\t\t\t\t\thref={ link }\n\t\t\t\t>\n\t\t\t\t\t<RawHTML>{ safeHTML( title ) }</RawHTML>\n\t\t\t\t</a>\n\t\t\t) }\n\t\t\t{ hasChildren && (\n\t\t\t\t<>\n\t\t\t\t\t{ ! openOnClick && context.showSubmenuIcon && (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tclassName=\"wp-block-navigation-item__content wp-block-navigation-submenu__toggle wp-block-page-list__submenu-icon wp-block-navigation__submenu-icon\"\n\t\t\t\t\t\t\taria-expanded=\"false\"\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<ItemSubmenuIcon />\n\t\t\t\t\t\t</button>\n\t\t\t\t\t) }\n\t\t\t\t\t<ul { ...innerBlocksProps }></ul>\n\t\t\t\t</>\n\t\t\t) }\n\t\t</li>\n\t);\n}\n"],
5
- "mappings": ";AAGA,OAAO,UAAU;AAIjB,SAAS,eAAe,2BAA2B;AACnD,SAAS,iBAAiB;AAC1B,SAAS,SAAS,iBAAiB;AACnC,SAAS,eAAe;AACxB,SAAS,gBAAgB;AAKzB,SAAS,uBAAuB;AAChC;AAAA,EACC;AAAA,EACA;AAAA,OACM;AAuDH,mBAME,KANF;AArDJ,SAAS,iBAAiB;AACzB,SAAO,UAAW,CAAE,WAAY;AAC/B,UAAM,kBAAkB,OAAQ,SAAU,EAAE,QAAS,QAAQ;AAAA,MAC5D,MAAM;AAAA,MACN,MAAM;AAAA,IACP,CAAE;AACF,QAAK,CAAE,iBAAkB;AACxB,aAAO;AAAA,IACR;AAEA,UAAM,OAAO,OAAQ,SAAU,EAAE,gBAAiB,QAAQ,MAAO;AACjE,WAAO,MAAM,kBAAkB,UAAU,MAAM;AAAA,EAChD,GAAG,CAAC,CAAE;AACP;AAEe,SAAR,iBAAmC,EAAE,SAAS,WAAW,GAAI;AACnE,QAAM,EAAE,IAAI,OAAO,MAAM,aAAa,MAAM,IAAI;AAChD,QAAM,oBAAoB,qBAAqB;AAC/C,QAAM,cAAc,eAAe;AAKnC,QAAM,oBAAoB,QAAQ;AAElC,QAAM,cAAc,sBAAsB;AAE1C,QAAM,oBAAoB,UAAW,SAAS,IAAK;AAEnD,QAAM,4BACL,6BAA8B,iBAAkB;AACjD,QAAM,aAAa,cAAe,2BAA2B;AAAA,IAC5D,WAAW;AAAA,EACZ,CAAE;AAEF,QAAM,mBAAmB,oBAAqB,UAAW;AAEzD,SACC;AAAA,IAAC;AAAA;AAAA,MAEA,WAAY,KAAM,6BAA6B;AAAA,QAC9C,aAAa;AAAA,QACb,4BAA4B;AAAA;AAAA,QAE5B,iBAAiB;AAAA,QACjB,eAAe,sBAAsB;AAAA;AAAA,QAErC,uBACC,sBAAsB,WAAW,QAAQ;AAAA,QAC1C,kBAAkB,OAAO;AAAA,MAC1B,CAAE;AAAA,MAEA;AAAA,uBAAe,cAChB,iCACC;AAAA;AAAA,YAAC;AAAA;AAAA,cACA,MAAK;AAAA,cACL,WAAU;AAAA,cACV,iBAAc;AAAA,cAEd,8BAAC,WAAU,mBAAU,KAAM,GAAG;AAAA;AAAA,UAC/B;AAAA,UACA,oBAAC,UAAK,WAAU,sEACf,8BAAC,mBAAgB,GAClB;AAAA,WACD,IAEA;AAAA,UAAC;AAAA;AAAA,YACA,WAAY,KAAM,mCAAmC;AAAA,cACpD,qCAAqC;AAAA,YACtC,CAAE;AAAA,YACF,MAAO;AAAA,YAEP,8BAAC,WAAU,mBAAU,KAAM,GAAG;AAAA;AAAA,QAC/B;AAAA,QAEC,eACD,iCACG;AAAA,WAAE,eAAe,QAAQ,mBAC1B;AAAA,YAAC;AAAA;AAAA,cACA,WAAU;AAAA,cACV,iBAAc;AAAA,cACd,MAAK;AAAA,cAEL,8BAAC,mBAAgB;AAAA;AAAA,UAClB;AAAA,UAED,oBAAC,QAAK,GAAG,kBAAmB;AAAA,WAC7B;AAAA;AAAA;AAAA,IAhDK;AAAA,EAkDP;AAEF;",
4
+ "sourcesContent": ["/**\n * External dependencies\n */\nimport clsx from 'clsx';\n/**\n * WordPress dependencies\n */\nimport { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';\nimport { useSelect } from '@wordpress/data';\nimport { store as coreStore } from '@wordpress/core-data';\nimport { safeHTML } from '@wordpress/dom';\n\n/**\n * Internal dependencies\n */\nimport { ItemSubmenuIcon } from '../navigation-link/icons';\nimport {\n\tgetColors,\n\tgetNavigationChildBlockProps,\n} from '../navigation/edit/utils';\n\nfunction useFrontPageId() {\n\treturn useSelect( ( select ) => {\n\t\tconst canReadSettings = select( coreStore ).canUser( 'read', {\n\t\t\tkind: 'root',\n\t\t\tname: 'site',\n\t\t} );\n\t\tif ( ! canReadSettings ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst site = select( coreStore ).getEntityRecord( 'root', 'site' );\n\t\treturn site?.show_on_front === 'page' && site?.page_on_front;\n\t}, [] );\n}\n\nexport default function PageListItemEdit( { context, attributes } ) {\n\tconst { id, label, link, hasChildren, title } = attributes;\n\tconst isNavigationChild = 'showSubmenuIcon' in context;\n\tconst frontPageId = useFrontPageId();\n\n\t// Get submenu visibility from context. The Navigation block handles\n\t// backward compatibility by migrating openSubmenusOnClick to submenuVisibility\n\t// via its deprecation handler before this context is received.\n\tconst submenuVisibility = context.submenuVisibility;\n\n\tconst openOnClick = submenuVisibility === 'click';\n\n\tconst innerBlocksColors = getColors( context, true );\n\n\tconst navigationChildBlockProps =\n\t\tgetNavigationChildBlockProps( innerBlocksColors );\n\tconst blockProps = useBlockProps( navigationChildBlockProps, {\n\t\tclassName: 'wp-block-pages-list__item',\n\t} );\n\n\tconst innerBlocksProps = useInnerBlocksProps( blockProps );\n\n\treturn (\n\t\t<li\n\t\t\tkey={ id }\n\t\t\tclassName={ clsx( 'wp-block-pages-list__item', {\n\t\t\t\t'has-child': hasChildren,\n\t\t\t\t'wp-block-navigation-item': isNavigationChild,\n\t\t\t\t// Class assignment logic matches PHP rendering in page-list/index.php\n\t\t\t\t'open-on-click': openOnClick,\n\t\t\t\t'open-always': submenuVisibility === 'always',\n\t\t\t\t// Must check hover mode explicitly to match PHP elseif structure (index.php:212)\n\t\t\t\t'open-on-hover-click':\n\t\t\t\t\tsubmenuVisibility === 'hover' && context.showSubmenuIcon,\n\t\t\t\t'menu-item-home': id === frontPageId,\n\t\t\t} ) }\n\t\t>\n\t\t\t{ hasChildren && openOnClick ? (\n\t\t\t\t<>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"wp-block-navigation-item__content wp-block-navigation-submenu__toggle\"\n\t\t\t\t\t\taria-expanded=\"false\"\n\t\t\t\t\t\tdangerouslySetInnerHTML={ {\n\t\t\t\t\t\t\t__html: safeHTML( label ),\n\t\t\t\t\t\t} }\n\t\t\t\t\t/>\n\t\t\t\t\t<span className=\"wp-block-page-list__submenu-icon wp-block-navigation__submenu-icon\">\n\t\t\t\t\t\t<ItemSubmenuIcon />\n\t\t\t\t\t</span>\n\t\t\t\t</>\n\t\t\t) : (\n\t\t\t\t<a\n\t\t\t\t\tclassName={ clsx( 'wp-block-pages-list__item__link', {\n\t\t\t\t\t\t'wp-block-navigation-item__content': isNavigationChild,\n\t\t\t\t\t} ) }\n\t\t\t\t\thref={ link }\n\t\t\t\t\tdangerouslySetInnerHTML={ {\n\t\t\t\t\t\t__html: safeHTML( title ),\n\t\t\t\t\t} }\n\t\t\t\t/>\n\t\t\t) }\n\t\t\t{ hasChildren && (\n\t\t\t\t<>\n\t\t\t\t\t{ ! openOnClick && context.showSubmenuIcon && (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tclassName=\"wp-block-navigation-item__content wp-block-navigation-submenu__toggle wp-block-page-list__submenu-icon wp-block-navigation__submenu-icon\"\n\t\t\t\t\t\t\taria-expanded=\"false\"\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<ItemSubmenuIcon />\n\t\t\t\t\t\t</button>\n\t\t\t\t\t) }\n\t\t\t\t\t<ul { ...innerBlocksProps }></ul>\n\t\t\t\t</>\n\t\t\t) }\n\t\t</li>\n\t);\n}\n"],
5
+ "mappings": ";AAGA,OAAO,UAAU;AAIjB,SAAS,eAAe,2BAA2B;AACnD,SAAS,iBAAiB;AAC1B,SAAS,SAAS,iBAAiB;AACnC,SAAS,gBAAgB;AAKzB,SAAS,uBAAuB;AAChC;AAAA,EACC;AAAA,EACA;AAAA,OACM;AAuDH,mBACC,KADD;AArDJ,SAAS,iBAAiB;AACzB,SAAO,UAAW,CAAE,WAAY;AAC/B,UAAM,kBAAkB,OAAQ,SAAU,EAAE,QAAS,QAAQ;AAAA,MAC5D,MAAM;AAAA,MACN,MAAM;AAAA,IACP,CAAE;AACF,QAAK,CAAE,iBAAkB;AACxB,aAAO;AAAA,IACR;AAEA,UAAM,OAAO,OAAQ,SAAU,EAAE,gBAAiB,QAAQ,MAAO;AACjE,WAAO,MAAM,kBAAkB,UAAU,MAAM;AAAA,EAChD,GAAG,CAAC,CAAE;AACP;AAEe,SAAR,iBAAmC,EAAE,SAAS,WAAW,GAAI;AACnE,QAAM,EAAE,IAAI,OAAO,MAAM,aAAa,MAAM,IAAI;AAChD,QAAM,oBAAoB,qBAAqB;AAC/C,QAAM,cAAc,eAAe;AAKnC,QAAM,oBAAoB,QAAQ;AAElC,QAAM,cAAc,sBAAsB;AAE1C,QAAM,oBAAoB,UAAW,SAAS,IAAK;AAEnD,QAAM,4BACL,6BAA8B,iBAAkB;AACjD,QAAM,aAAa,cAAe,2BAA2B;AAAA,IAC5D,WAAW;AAAA,EACZ,CAAE;AAEF,QAAM,mBAAmB,oBAAqB,UAAW;AAEzD,SACC;AAAA,IAAC;AAAA;AAAA,MAEA,WAAY,KAAM,6BAA6B;AAAA,QAC9C,aAAa;AAAA,QACb,4BAA4B;AAAA;AAAA,QAE5B,iBAAiB;AAAA,QACjB,eAAe,sBAAsB;AAAA;AAAA,QAErC,uBACC,sBAAsB,WAAW,QAAQ;AAAA,QAC1C,kBAAkB,OAAO;AAAA,MAC1B,CAAE;AAAA,MAEA;AAAA,uBAAe,cAChB,iCACC;AAAA;AAAA,YAAC;AAAA;AAAA,cACA,MAAK;AAAA,cACL,WAAU;AAAA,cACV,iBAAc;AAAA,cACd,yBAA0B;AAAA,gBACzB,QAAQ,SAAU,KAAM;AAAA,cACzB;AAAA;AAAA,UACD;AAAA,UACA,oBAAC,UAAK,WAAU,sEACf,8BAAC,mBAAgB,GAClB;AAAA,WACD,IAEA;AAAA,UAAC;AAAA;AAAA,YACA,WAAY,KAAM,mCAAmC;AAAA,cACpD,qCAAqC;AAAA,YACtC,CAAE;AAAA,YACF,MAAO;AAAA,YACP,yBAA0B;AAAA,cACzB,QAAQ,SAAU,KAAM;AAAA,YACzB;AAAA;AAAA,QACD;AAAA,QAEC,eACD,iCACG;AAAA,WAAE,eAAe,QAAQ,mBAC1B;AAAA,YAAC;AAAA;AAAA,cACA,WAAU;AAAA,cACV,iBAAc;AAAA,cACd,MAAK;AAAA,cAEL,8BAAC,mBAAgB;AAAA;AAAA,UAClB;AAAA,UAED,oBAAC,QAAK,GAAG,kBAAmB;AAAA,WAC7B;AAAA;AAAA;AAAA,IAlDK;AAAA,EAoDP;AAEF;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  // packages/block-library/src/playlist/edit.js
2
2
  import clsx from "clsx";
3
3
  import { v4 as uuid } from "uuid";
4
- import { useState, useCallback, useEffect } from "@wordpress/element";
4
+ import { useCallback, useEffect } from "@wordpress/element";
5
5
  import {
6
6
  store as blockEditorStore,
7
7
  MediaPlaceholder,
@@ -17,109 +17,35 @@ import {
17
17
  ToggleControl,
18
18
  Disabled,
19
19
  SelectControl,
20
- Spinner,
21
20
  __experimentalToolsPanel as ToolsPanel,
22
21
  __experimentalToolsPanelItem as ToolsPanelItem
23
22
  } from "@wordpress/components";
24
23
  import { useSelect, useDispatch } from "@wordpress/data";
25
24
  import { store as noticesStore } from "@wordpress/notices";
26
- import { __, _x, sprintf } from "@wordpress/i18n";
25
+ import { __ } from "@wordpress/i18n";
27
26
  import { audio as icon } from "@wordpress/icons";
28
- import { safeHTML, __unstableStripHTML as stripHTML } from "@wordpress/dom";
29
27
  import { createBlock } from "@wordpress/blocks";
30
28
  import { Caption } from "../utils/caption.mjs";
31
29
  import { useToolsPanelDropdownMenuProps } from "../utils/hooks.mjs";
30
+ import { WaveformPlayer } from "../utils/waveform-player.mjs";
32
31
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
33
32
  var ALLOWED_MEDIA_TYPES = ["audio"];
34
- var CurrentTrack = ({ track, showImages, onTrackEnd }) => {
35
- const trackTitle = {
36
- dangerouslySetInnerHTML: {
37
- __html: safeHTML(track?.title ? track.title : __("Untitled"))
38
- }
33
+ function getTrackAttributes(media) {
34
+ return {
35
+ id: media.id || media.url,
36
+ // Attachment ID or URL.
37
+ uniqueId: uuid(),
38
+ // Unique ID for the track.
39
+ src: media.url,
40
+ title: media.title,
41
+ artist: media.artist || media?.meta?.artist || media?.media_details?.artist || __("Unknown artist"),
42
+ album: media.album || media?.meta?.album || media?.media_details?.album || __("Unknown album"),
43
+ length: media?.fileLength || media?.media_details?.length_formatted,
44
+ // Prevent using the default media attachment icon as the track image.
45
+ // Note: Image is not available when a new track is uploaded.
46
+ image: media?.image?.src && media?.image?.src.endsWith("/images/media/audio.svg") ? "" : media?.image?.src
39
47
  };
40
- const trackArtist = {
41
- dangerouslySetInnerHTML: {
42
- __html: safeHTML(
43
- track?.artist ? track.artist : __("Unknown artist")
44
- )
45
- }
46
- };
47
- const trackAlbum = {
48
- dangerouslySetInnerHTML: {
49
- __html: safeHTML(
50
- track?.album ? track.album : __("Unknown album")
51
- )
52
- }
53
- };
54
- let ariaLabel;
55
- if (track?.title && track?.artist && track?.album) {
56
- ariaLabel = stripHTML(
57
- sprintf(
58
- /* translators: %1$s: track title, %2$s artist name, %3$s: album name. */
59
- _x(
60
- "%1$s by %2$s from the album %3$s",
61
- "track title, artist name, album name"
62
- ),
63
- track?.title,
64
- track?.artist,
65
- track?.album
66
- )
67
- );
68
- } else if (track?.title) {
69
- ariaLabel = stripHTML(track.title);
70
- } else {
71
- ariaLabel = stripHTML(__("Untitled"));
72
- }
73
- return /* @__PURE__ */ jsxs(Fragment, { children: [
74
- /* @__PURE__ */ jsxs("div", { className: "wp-block-playlist__current-item", children: [
75
- showImages && track?.image && /* @__PURE__ */ jsx(
76
- "img",
77
- {
78
- className: "wp-block-playlist__item-image",
79
- src: track.image,
80
- alt: "",
81
- width: "70px",
82
- height: "70px"
83
- }
84
- ),
85
- /* @__PURE__ */ jsxs("div", { children: [
86
- !track?.title ? /* @__PURE__ */ jsx("span", { className: "wp-block-playlist__item-title", children: /* @__PURE__ */ jsx(Spinner, {}) }) : /* @__PURE__ */ jsx(
87
- "span",
88
- {
89
- className: "wp-block-playlist__item-title",
90
- ...trackTitle
91
- }
92
- ),
93
- /* @__PURE__ */ jsxs("div", { className: "wp-block-playlist__current-item-artist-album", children: [
94
- /* @__PURE__ */ jsx(
95
- "span",
96
- {
97
- className: "wp-block-playlist__item-artist",
98
- ...trackArtist
99
- }
100
- ),
101
- /* @__PURE__ */ jsx(
102
- "span",
103
- {
104
- className: "wp-block-playlist__item-album",
105
- ...trackAlbum
106
- }
107
- )
108
- ] })
109
- ] })
110
- ] }),
111
- /* @__PURE__ */ jsx(
112
- "audio",
113
- {
114
- controls: "controls",
115
- src: track?.url ? track.url : "",
116
- onEnded: onTrackEnd,
117
- "aria-label": ariaLabel,
118
- tabIndex: 0
119
- }
120
- )
121
- ] });
122
- };
48
+ }
123
49
  var PlaylistEdit = ({
124
50
  attributes,
125
51
  setAttributes,
@@ -135,7 +61,6 @@ var PlaylistEdit = ({
135
61
  showArtists,
136
62
  currentTrack
137
63
  } = attributes;
138
- const [trackListIndex, setTrackListIndex] = useState(0);
139
64
  const blockProps = useBlockProps();
140
65
  const { replaceInnerBlocks, __unstableMarkNextChangeAsNotPersistent } = useDispatch(blockEditorStore);
141
66
  const { createErrorNotice } = useDispatch(noticesStore);
@@ -205,21 +130,7 @@ var PlaylistEdit = ({
205
130
  if (!Array.isArray(media)) {
206
131
  media = [media];
207
132
  }
208
- const trackAttributes = (track) => ({
209
- id: track.id || track.url,
210
- // Attachment ID or URL.
211
- uniqueId: uuid(),
212
- // Unique ID for the track.
213
- src: track.url,
214
- title: track.title,
215
- artist: track.artist || track?.meta?.artist || track?.media_details?.artist || __("Unknown artist"),
216
- album: track.album || track?.meta?.album || track?.media_details?.album || __("Unknown album"),
217
- length: track?.fileLength || track?.media_details?.length_formatted,
218
- // Prevent using the default media attachment icon as the track image.
219
- // Note: Image is not available when a new track is uploaded.
220
- image: track?.image?.src && track?.image?.src.endsWith("/images/media/audio.svg") ? "" : track?.image?.src
221
- });
222
- const trackList = media.map(trackAttributes);
133
+ const trackList = media.map(getTrackAttributes);
223
134
  __unstableMarkNextChangeAsNotPersistent();
224
135
  setAttributes({
225
136
  currentTrack: trackList.length > 0 ? trackList[0].uniqueId : null
@@ -236,28 +147,18 @@ var PlaylistEdit = ({
236
147
  clientId
237
148
  ]
238
149
  );
239
- const onTrackEnd = useCallback(() => {
240
- if (trackListIndex < tracks.length - 1) {
241
- if (tracks[trackListIndex + 1]?.uniqueId) {
242
- setTrackListIndex(trackListIndex + 1);
243
- setAttributes({
244
- currentTrack: tracks[trackListIndex + 1].uniqueId
245
- });
246
- }
247
- } else {
248
- setTrackListIndex(0);
249
- if (tracks[0].uniqueId) {
250
- setAttributes({ currentTrack: tracks[0].uniqueId });
251
- } else if (tracks.length > 0) {
252
- const validTrack = tracks.find(
253
- (track) => track.uniqueId !== void 0
254
- );
255
- if (validTrack) {
256
- setAttributes({ currentTrack: validTrack.uniqueId });
257
- }
258
- }
150
+ const currentTrackData = tracks.find(
151
+ (track) => track.uniqueId === currentTrack
152
+ );
153
+ const onTrackEnded = useCallback(() => {
154
+ const currentIndex = tracks.findIndex(
155
+ (track) => track.uniqueId === currentTrack
156
+ );
157
+ const nextTrack = tracks[currentIndex + 1] || tracks[0];
158
+ if (nextTrack?.uniqueId) {
159
+ setAttributes({ currentTrack: nextTrack.uniqueId });
259
160
  }
260
- }, [setAttributes, trackListIndex, tracks]);
161
+ }, [currentTrack, tracks, setAttributes]);
261
162
  const onChangeOrder = useCallback(
262
163
  (trackOrder) => {
263
164
  const sortedBlocks = [...innerBlockTracks].sort((a, b) => {
@@ -268,13 +169,11 @@ var PlaylistEdit = ({
268
169
  }
269
170
  return titleB.localeCompare(titleA);
270
171
  });
271
- const sortedTracks = sortedBlocks.map(
272
- (block) => block.attributes
273
- );
172
+ const firstUniqueId = sortedBlocks[0]?.attributes?.uniqueId;
274
173
  replaceInnerBlocks(clientId, sortedBlocks);
275
174
  setAttributes({
276
175
  order: trackOrder,
277
- currentTrack: sortedTracks.length > 0 && sortedTracks[0].uniqueId !== currentTrack ? sortedTracks[0].uniqueId : currentTrack
176
+ currentTrack: firstUniqueId && firstUniqueId !== currentTrack ? firstUniqueId : currentTrack
278
177
  });
279
178
  },
280
179
  [
@@ -299,7 +198,7 @@ var PlaylistEdit = ({
299
198
  __experimentalAppenderTagName: "li",
300
199
  renderAppender: hasAnySelected && InnerBlocks.ButtonBlockAppender
301
200
  });
302
- if (!tracks || Array.isArray(tracks) && tracks.length === 0) {
201
+ if (tracks.length === 0) {
303
202
  return /* @__PURE__ */ jsx(
304
203
  "div",
305
204
  {
@@ -456,11 +355,13 @@ var PlaylistEdit = ({
456
355
  ) }),
457
356
  /* @__PURE__ */ jsxs("figure", { ...blockProps, children: [
458
357
  /* @__PURE__ */ jsx(Disabled, { isDisabled: !isSelected, children: /* @__PURE__ */ jsx(
459
- CurrentTrack,
358
+ WaveformPlayer,
460
359
  {
461
- track: tracks[trackListIndex],
462
- showImages,
463
- onTrackEnd
360
+ src: currentTrackData?.src,
361
+ title: currentTrackData?.title,
362
+ artist: currentTrackData?.artist,
363
+ image: currentTrackData?.image,
364
+ onEnded: onTrackEnded
464
365
  }
465
366
  ) }),
466
367
  showTracklist && /* @__PURE__ */ jsx(
@@ -489,6 +390,7 @@ var PlaylistEdit = ({
489
390
  };
490
391
  var edit_default = PlaylistEdit;
491
392
  export {
492
- edit_default as default
393
+ edit_default as default,
394
+ getTrackAttributes
493
395
  };
494
396
  //# sourceMappingURL=edit.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/playlist/edit.js"],
4
- "sourcesContent": ["/**\n * External dependencies\n */\nimport clsx from 'clsx';\nimport { v4 as uuid } from 'uuid';\n\n/**\n * WordPress dependencies\n */\nimport { useState, useCallback, useEffect } from '@wordpress/element';\nimport {\n\tstore as blockEditorStore,\n\tMediaPlaceholder,\n\tMediaReplaceFlow,\n\tBlockIcon,\n\tuseBlockProps,\n\tuseInnerBlocksProps,\n\tBlockControls,\n\tInspectorControls,\n\tInnerBlocks,\n} from '@wordpress/block-editor';\nimport {\n\tToggleControl,\n\tDisabled,\n\tSelectControl,\n\tSpinner,\n\t__experimentalToolsPanel as ToolsPanel,\n\t__experimentalToolsPanelItem as ToolsPanelItem,\n} from '@wordpress/components';\nimport { useSelect, useDispatch } from '@wordpress/data';\nimport { store as noticesStore } from '@wordpress/notices';\nimport { __, _x, sprintf } from '@wordpress/i18n';\nimport { audio as icon } from '@wordpress/icons';\nimport { safeHTML, __unstableStripHTML as stripHTML } from '@wordpress/dom';\nimport { createBlock } from '@wordpress/blocks';\n\n/**\n * Internal dependencies\n */\nimport { Caption } from '../utils/caption';\nimport { useToolsPanelDropdownMenuProps } from '../utils/hooks';\n\nconst ALLOWED_MEDIA_TYPES = [ 'audio' ];\n\nconst CurrentTrack = ( { track, showImages, onTrackEnd } ) => {\n\t/**\n\t * dangerouslySetInnerHTML and safeHTML are used because\n\t * the media library allows using some HTML tags in the title, artist, and album fields.\n\t */\n\tconst trackTitle = {\n\t\tdangerouslySetInnerHTML: {\n\t\t\t__html: safeHTML( track?.title ? track.title : __( 'Untitled' ) ),\n\t\t},\n\t};\n\tconst trackArtist = {\n\t\tdangerouslySetInnerHTML: {\n\t\t\t__html: safeHTML(\n\t\t\t\ttrack?.artist ? track.artist : __( 'Unknown artist' )\n\t\t\t),\n\t\t},\n\t};\n\tconst trackAlbum = {\n\t\tdangerouslySetInnerHTML: {\n\t\t\t__html: safeHTML(\n\t\t\t\ttrack?.album ? track.album : __( 'Unknown album' )\n\t\t\t),\n\t\t},\n\t};\n\n\tlet ariaLabel;\n\tif ( track?.title && track?.artist && track?.album ) {\n\t\tariaLabel = stripHTML(\n\t\t\tsprintf(\n\t\t\t\t/* translators: %1$s: track title, %2$s artist name, %3$s: album name. */\n\t\t\t\t_x(\n\t\t\t\t\t'%1$s by %2$s from the album %3$s',\n\t\t\t\t\t'track title, artist name, album name'\n\t\t\t\t),\n\t\t\t\ttrack?.title,\n\t\t\t\ttrack?.artist,\n\t\t\t\ttrack?.album\n\t\t\t)\n\t\t);\n\t} else if ( track?.title ) {\n\t\tariaLabel = stripHTML( track.title );\n\t} else {\n\t\tariaLabel = stripHTML( __( 'Untitled' ) );\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t<div className=\"wp-block-playlist__current-item\">\n\t\t\t\t{ showImages && track?.image && (\n\t\t\t\t\t<img\n\t\t\t\t\t\tclassName=\"wp-block-playlist__item-image\"\n\t\t\t\t\t\tsrc={ track.image }\n\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\twidth=\"70px\"\n\t\t\t\t\t\theight=\"70px\"\n\t\t\t\t\t/>\n\t\t\t\t) }\n\t\t\t\t<div>\n\t\t\t\t\t{ ! track?.title ? (\n\t\t\t\t\t\t<span className=\"wp-block-playlist__item-title\">\n\t\t\t\t\t\t\t<Spinner />\n\t\t\t\t\t\t</span>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tclassName=\"wp-block-playlist__item-title\"\n\t\t\t\t\t\t\t{ ...trackTitle }\n\t\t\t\t\t\t/>\n\t\t\t\t\t) }\n\t\t\t\t\t<div className=\"wp-block-playlist__current-item-artist-album\">\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tclassName=\"wp-block-playlist__item-artist\"\n\t\t\t\t\t\t\t{ ...trackArtist }\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tclassName=\"wp-block-playlist__item-album\"\n\t\t\t\t\t\t\t{ ...trackAlbum }\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<audio\n\t\t\t\tcontrols=\"controls\"\n\t\t\t\tsrc={ track?.url ? track.url : '' }\n\t\t\t\tonEnded={ onTrackEnd }\n\t\t\t\taria-label={ ariaLabel }\n\t\t\t\ttabIndex={ 0 }\n\t\t\t/>\n\t\t</>\n\t);\n};\n\nconst PlaylistEdit = ( {\n\tattributes,\n\tsetAttributes,\n\tisSelected,\n\tinsertBlocksAfter,\n\tclientId,\n} ) => {\n\tconst {\n\t\torder,\n\t\tshowTracklist,\n\t\tshowNumbers,\n\t\tshowImages,\n\t\tshowArtists,\n\t\tcurrentTrack,\n\t} = attributes;\n\tconst [ trackListIndex, setTrackListIndex ] = useState( 0 );\n\tconst blockProps = useBlockProps();\n\tconst { replaceInnerBlocks, __unstableMarkNextChangeAsNotPersistent } =\n\t\tuseDispatch( blockEditorStore );\n\tconst { createErrorNotice } = useDispatch( noticesStore );\n\tconst dropdownMenuProps = useToolsPanelDropdownMenuProps();\n\tfunction onUploadError( message ) {\n\t\tcreateErrorNotice( message, { type: 'snackbar' } );\n\t}\n\tconst { updateBlockAttributes } = useDispatch( blockEditorStore );\n\n\tconst { innerBlockTracks } = useSelect(\n\t\t( select ) => {\n\t\t\tconst { getBlock: _getBlock } = select( blockEditorStore );\n\t\t\treturn {\n\t\t\t\tinnerBlockTracks: _getBlock( clientId )?.innerBlocks ?? [],\n\t\t\t};\n\t\t},\n\t\t[ clientId ]\n\t);\n\n\t// Ensure that each inner block has a unique ID,\n\t// even if a track is duplicated.\n\tuseEffect( () => {\n\t\tconst seen = new Set();\n\t\tlet hasDuplicates = false;\n\t\tconst updatedBlocks = innerBlockTracks.map( ( block ) => {\n\t\t\tif ( seen.has( block.attributes.uniqueId ) ) {\n\t\t\t\thasDuplicates = true;\n\t\t\t\treturn {\n\t\t\t\t\t...block,\n\t\t\t\t\tattributes: {\n\t\t\t\t\t\t...block.attributes,\n\t\t\t\t\t\tuniqueId: uuid(),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\tseen.add( block.attributes.uniqueId );\n\t\t\treturn block;\n\t\t} );\n\t\tif ( hasDuplicates ) {\n\t\t\treplaceInnerBlocks( clientId, updatedBlocks );\n\t\t}\n\t}, [ innerBlockTracks, clientId, replaceInnerBlocks ] );\n\n\t// Create a list of tracks from the inner blocks,\n\t// but skip blocks that do not have a uniqueId attribute, such as the media placeholder.\n\tconst validTracks = innerBlockTracks.filter(\n\t\t( block ) => !! block.attributes.uniqueId\n\t);\n\tconst tracks = validTracks.map( ( block ) => block.attributes );\n\tconst firstTrackId = validTracks[ 0 ]?.attributes?.uniqueId;\n\n\t// updateBlockAttributes is used to force updating the parent playlist block\n\t// when the currentTrack changes. Using setAttributes directly does not update\n\t// the currentTrack when multiple tracks are moved at the same time.\n\tuseEffect( () => {\n\t\tif ( tracks.length === 0 ) {\n\t\t\t// If there are no tracks but currentTrack is set, set it to null.\n\t\t\tif ( currentTrack !== null ) {\n\t\t\t\tupdateBlockAttributes( clientId, { currentTrack: null } );\n\t\t\t}\n\t\t} else if (\n\t\t\t// If the currentTrack is not the first track, update it to the first track.\n\t\t\tfirstTrackId &&\n\t\t\tfirstTrackId !== currentTrack\n\t\t) {\n\t\t\tupdateBlockAttributes( clientId, { currentTrack: firstTrackId } );\n\t\t}\n\t}, [\n\t\ttracks,\n\t\tcurrentTrack,\n\t\tfirstTrackId,\n\t\tclientId,\n\t\tupdateBlockAttributes,\n\t] );\n\n\tconst onSelectTracks = useCallback(\n\t\t( media ) => {\n\t\t\tif ( ! media ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( ! Array.isArray( media ) ) {\n\t\t\t\tmedia = [ media ];\n\t\t\t}\n\n\t\t\tconst trackAttributes = ( track ) => ( {\n\t\t\t\tid: track.id || track.url, // Attachment ID or URL.\n\t\t\t\tuniqueId: uuid(), // Unique ID for the track.\n\t\t\t\tsrc: track.url,\n\t\t\t\ttitle: track.title,\n\t\t\t\tartist:\n\t\t\t\t\ttrack.artist ||\n\t\t\t\t\ttrack?.meta?.artist ||\n\t\t\t\t\ttrack?.media_details?.artist ||\n\t\t\t\t\t__( 'Unknown artist' ),\n\t\t\t\talbum:\n\t\t\t\t\ttrack.album ||\n\t\t\t\t\ttrack?.meta?.album ||\n\t\t\t\t\ttrack?.media_details?.album ||\n\t\t\t\t\t__( 'Unknown album' ),\n\t\t\t\tlength:\n\t\t\t\t\ttrack?.fileLength || track?.media_details?.length_formatted,\n\t\t\t\t// Prevent using the default media attachment icon as the track image.\n\t\t\t\t// Note: Image is not available when a new track is uploaded.\n\t\t\t\timage:\n\t\t\t\t\ttrack?.image?.src &&\n\t\t\t\t\ttrack?.image?.src.endsWith( '/images/media/audio.svg' )\n\t\t\t\t\t\t? ''\n\t\t\t\t\t\t: track?.image?.src,\n\t\t\t} );\n\n\t\t\tconst trackList = media.map( trackAttributes );\n\t\t\t__unstableMarkNextChangeAsNotPersistent();\n\t\t\tsetAttributes( {\n\t\t\t\tcurrentTrack:\n\t\t\t\t\ttrackList.length > 0 ? trackList[ 0 ].uniqueId : null,\n\t\t\t} );\n\n\t\t\tconst newBlocks = trackList.map( ( track ) =>\n\t\t\t\tcreateBlock( 'core/playlist-track', track )\n\t\t\t);\n\t\t\t// Replace the inner blocks with the new tracks.\n\t\t\treplaceInnerBlocks( clientId, newBlocks );\n\t\t},\n\t\t[\n\t\t\t__unstableMarkNextChangeAsNotPersistent,\n\t\t\tsetAttributes,\n\t\t\treplaceInnerBlocks,\n\t\t\tclientId,\n\t\t]\n\t);\n\n\tconst onTrackEnd = useCallback( () => {\n\t\t/* If there are tracks left, play the next track */\n\t\tif ( trackListIndex < tracks.length - 1 ) {\n\t\t\tif ( tracks[ trackListIndex + 1 ]?.uniqueId ) {\n\t\t\t\tsetTrackListIndex( trackListIndex + 1 );\n\t\t\t\tsetAttributes( {\n\t\t\t\t\tcurrentTrack: tracks[ trackListIndex + 1 ].uniqueId,\n\t\t\t\t} );\n\t\t\t}\n\t\t} else {\n\t\t\tsetTrackListIndex( 0 );\n\t\t\tif ( tracks[ 0 ].uniqueId ) {\n\t\t\t\tsetAttributes( { currentTrack: tracks[ 0 ].uniqueId } );\n\t\t\t} else if ( tracks.length > 0 ) {\n\t\t\t\tconst validTrack = tracks.find(\n\t\t\t\t\t( track ) => track.uniqueId !== undefined\n\t\t\t\t);\n\t\t\t\tif ( validTrack ) {\n\t\t\t\t\tsetAttributes( { currentTrack: validTrack.uniqueId } );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}, [ setAttributes, trackListIndex, tracks ] );\n\n\tconst onChangeOrder = useCallback(\n\t\t( trackOrder ) => {\n\t\t\tconst sortedBlocks = [ ...innerBlockTracks ].sort( ( a, b ) => {\n\t\t\t\tconst titleA = a.attributes.title || '';\n\t\t\t\tconst titleB = b.attributes.title || '';\n\n\t\t\t\tif ( trackOrder === 'asc' ) {\n\t\t\t\t\treturn titleA.localeCompare( titleB );\n\t\t\t\t}\n\t\t\t\treturn titleB.localeCompare( titleA );\n\t\t\t} );\n\t\t\tconst sortedTracks = sortedBlocks.map(\n\t\t\t\t( block ) => block.attributes\n\t\t\t);\n\t\t\treplaceInnerBlocks( clientId, sortedBlocks );\n\t\t\tsetAttributes( {\n\t\t\t\torder: trackOrder,\n\t\t\t\tcurrentTrack:\n\t\t\t\t\tsortedTracks.length > 0 &&\n\t\t\t\t\tsortedTracks[ 0 ].uniqueId !== currentTrack\n\t\t\t\t\t\t? sortedTracks[ 0 ].uniqueId\n\t\t\t\t\t\t: currentTrack,\n\t\t\t} );\n\t\t},\n\t\t[\n\t\t\tclientId,\n\t\t\tcurrentTrack,\n\t\t\tinnerBlockTracks,\n\t\t\treplaceInnerBlocks,\n\t\t\tsetAttributes,\n\t\t]\n\t);\n\n\tfunction toggleAttribute( attribute ) {\n\t\treturn ( newValue ) => {\n\t\t\tsetAttributes( { [ attribute ]: newValue } );\n\t\t};\n\t}\n\n\tconst hasSelectedChild = useSelect(\n\t\t( select ) =>\n\t\t\tselect( blockEditorStore ).hasSelectedInnerBlock( clientId ),\n\t\t[ clientId ]\n\t);\n\n\tconst hasAnySelected = isSelected || hasSelectedChild;\n\n\tconst innerBlocksProps = useInnerBlocksProps( blockProps, {\n\t\t__experimentalAppenderTagName: 'li',\n\t\trenderAppender: hasAnySelected && InnerBlocks.ButtonBlockAppender,\n\t} );\n\n\tif ( ! tracks || ( Array.isArray( tracks ) && tracks.length === 0 ) ) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\t{ ...blockProps }\n\t\t\t\tclassName={ clsx( 'is-placeholder', blockProps.className ) }\n\t\t\t>\n\t\t\t\t<MediaPlaceholder\n\t\t\t\t\ticon={ <BlockIcon icon={ icon } /> }\n\t\t\t\t\tlabels={ {\n\t\t\t\t\t\ttitle: __( 'Playlist' ),\n\t\t\t\t\t\tinstructions: __(\n\t\t\t\t\t\t\t'Upload an audio file or pick one from your media library.'\n\t\t\t\t\t\t),\n\t\t\t\t\t} }\n\t\t\t\t\tonSelect={ onSelectTracks }\n\t\t\t\t\taccept=\"audio/*\"\n\t\t\t\t\tmultiple\n\t\t\t\t\tallowedTypes={ ALLOWED_MEDIA_TYPES }\n\t\t\t\t\tonError={ onUploadError }\n\t\t\t\t/>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t<BlockControls group=\"other\">\n\t\t\t\t<MediaReplaceFlow\n\t\t\t\t\tname={ __( 'Edit' ) }\n\t\t\t\t\tonSelect={ onSelectTracks }\n\t\t\t\t\taccept=\"audio/*\"\n\t\t\t\t\tmultiple\n\t\t\t\t\tmediaIds={ tracks\n\t\t\t\t\t\t.filter( ( track ) => track.id )\n\t\t\t\t\t\t.map( ( track ) => track.id ) }\n\t\t\t\t\tallowedTypes={ ALLOWED_MEDIA_TYPES }\n\t\t\t\t\tonError={ onUploadError }\n\t\t\t\t/>\n\t\t\t</BlockControls>\n\t\t\t<InspectorControls>\n\t\t\t\t<ToolsPanel\n\t\t\t\t\tlabel={ __( 'Settings' ) }\n\t\t\t\t\tresetAll={ () => {\n\t\t\t\t\t\tsetAttributes( {\n\t\t\t\t\t\t\tshowTracklist: true,\n\t\t\t\t\t\t\tshowArtists: true,\n\t\t\t\t\t\t\tshowNumbers: true,\n\t\t\t\t\t\t\tshowImages: true,\n\t\t\t\t\t\t\torder: 'asc',\n\t\t\t\t\t\t} );\n\t\t\t\t\t} }\n\t\t\t\t\tdropdownMenuProps={ dropdownMenuProps }\n\t\t\t\t>\n\t\t\t\t\t<ToolsPanelItem\n\t\t\t\t\t\tlabel={ __( 'Show Tracklist' ) }\n\t\t\t\t\t\tisShownByDefault\n\t\t\t\t\t\thasValue={ () => showTracklist !== true }\n\t\t\t\t\t\tonDeselect={ () =>\n\t\t\t\t\t\t\tsetAttributes( { showTracklist: true } )\n\t\t\t\t\t\t}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ToggleControl\n\t\t\t\t\t\t\tlabel={ __( 'Show Tracklist' ) }\n\t\t\t\t\t\t\tonChange={ toggleAttribute( 'showTracklist' ) }\n\t\t\t\t\t\t\tchecked={ showTracklist }\n\t\t\t\t\t\t/>\n\t\t\t\t\t</ToolsPanelItem>\n\t\t\t\t\t{ showTracklist && (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<ToolsPanelItem\n\t\t\t\t\t\t\t\tlabel={ __( 'Show artist name in Tracklist' ) }\n\t\t\t\t\t\t\t\tisShownByDefault\n\t\t\t\t\t\t\t\thasValue={ () => showArtists !== true }\n\t\t\t\t\t\t\t\tonDeselect={ () =>\n\t\t\t\t\t\t\t\t\tsetAttributes( { showArtists: true } )\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<ToggleControl\n\t\t\t\t\t\t\t\t\tlabel={ __(\n\t\t\t\t\t\t\t\t\t\t'Show artist name in Tracklist'\n\t\t\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t\t\tonChange={ toggleAttribute(\n\t\t\t\t\t\t\t\t\t\t'showArtists'\n\t\t\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t\t\tchecked={ showArtists }\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</ToolsPanelItem>\n\t\t\t\t\t\t\t<ToolsPanelItem\n\t\t\t\t\t\t\t\tlabel={ __( 'Show number in Tracklist' ) }\n\t\t\t\t\t\t\t\tisShownByDefault\n\t\t\t\t\t\t\t\thasValue={ () => showNumbers !== true }\n\t\t\t\t\t\t\t\tonDeselect={ () =>\n\t\t\t\t\t\t\t\t\tsetAttributes( { showNumbers: true } )\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<ToggleControl\n\t\t\t\t\t\t\t\t\tlabel={ __( 'Show number in Tracklist' ) }\n\t\t\t\t\t\t\t\t\tonChange={ toggleAttribute(\n\t\t\t\t\t\t\t\t\t\t'showNumbers'\n\t\t\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t\t\tchecked={ showNumbers }\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</ToolsPanelItem>\n\t\t\t\t\t\t</>\n\t\t\t\t\t) }\n\t\t\t\t\t<ToolsPanelItem\n\t\t\t\t\t\tlabel={ __( 'Show images' ) }\n\t\t\t\t\t\tisShownByDefault\n\t\t\t\t\t\thasValue={ () => showImages !== true }\n\t\t\t\t\t\tonDeselect={ () =>\n\t\t\t\t\t\t\tsetAttributes( { showImages: true } )\n\t\t\t\t\t\t}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ToggleControl\n\t\t\t\t\t\t\tlabel={ __( 'Show images' ) }\n\t\t\t\t\t\t\tonChange={ toggleAttribute( 'showImages' ) }\n\t\t\t\t\t\t\tchecked={ showImages }\n\t\t\t\t\t\t/>\n\t\t\t\t\t</ToolsPanelItem>\n\t\t\t\t\t<ToolsPanelItem\n\t\t\t\t\t\tlabel={ __( 'Order' ) }\n\t\t\t\t\t\tisShownByDefault\n\t\t\t\t\t\thasValue={ () => order !== 'asc' }\n\t\t\t\t\t\tonDeselect={ () => setAttributes( { order: 'asc' } ) }\n\t\t\t\t\t>\n\t\t\t\t\t\t<SelectControl\n\t\t\t\t\t\t\t__next40pxDefaultSize\n\t\t\t\t\t\t\tlabel={ __( 'Order' ) }\n\t\t\t\t\t\t\tvalue={ order }\n\t\t\t\t\t\t\toptions={ [\n\t\t\t\t\t\t\t\t{ label: __( 'Descending' ), value: 'desc' },\n\t\t\t\t\t\t\t\t{ label: __( 'Ascending' ), value: 'asc' },\n\t\t\t\t\t\t\t] }\n\t\t\t\t\t\t\tonChange={ ( value ) => onChangeOrder( value ) }\n\t\t\t\t\t\t/>\n\t\t\t\t\t</ToolsPanelItem>\n\t\t\t\t</ToolsPanel>\n\t\t\t</InspectorControls>\n\t\t\t<figure { ...blockProps }>\n\t\t\t\t<Disabled isDisabled={ ! isSelected }>\n\t\t\t\t\t<CurrentTrack\n\t\t\t\t\t\ttrack={ tracks[ trackListIndex ] }\n\t\t\t\t\t\tshowImages={ showImages }\n\t\t\t\t\t\tonTrackEnd={ onTrackEnd }\n\t\t\t\t\t/>\n\t\t\t\t</Disabled>\n\t\t\t\t{ showTracklist && (\n\t\t\t\t\t<ol\n\t\t\t\t\t\tclassName={ clsx( 'wp-block-playlist__tracklist', {\n\t\t\t\t\t\t\t'wp-block-playlist__tracklist-show-numbers':\n\t\t\t\t\t\t\t\tshowNumbers,\n\t\t\t\t\t\t} ) }\n\t\t\t\t\t>\n\t\t\t\t\t\t{ innerBlocksProps.children }\n\t\t\t\t\t</ol>\n\t\t\t\t) }\n\t\t\t\t<Caption\n\t\t\t\t\tattributes={ attributes }\n\t\t\t\t\tsetAttributes={ setAttributes }\n\t\t\t\t\tisSelected={ isSelected }\n\t\t\t\t\tinsertBlocksAfter={ insertBlocksAfter }\n\t\t\t\t\tlabel={ __( 'Playlist caption text' ) }\n\t\t\t\t\tshowToolbarButton={ isSelected }\n\t\t\t\t\tstyle={ { marginTop: 16 } }\n\t\t\t\t/>\n\t\t\t</figure>\n\t\t</>\n\t);\n};\n\nexport default PlaylistEdit;\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * External dependencies\n */\nimport clsx from 'clsx';\nimport { v4 as uuid } from 'uuid';\n\n/**\n * WordPress dependencies\n */\nimport { useCallback, useEffect } from '@wordpress/element';\nimport {\n\tstore as blockEditorStore,\n\tMediaPlaceholder,\n\tMediaReplaceFlow,\n\tBlockIcon,\n\tuseBlockProps,\n\tuseInnerBlocksProps,\n\tBlockControls,\n\tInspectorControls,\n\tInnerBlocks,\n} from '@wordpress/block-editor';\nimport {\n\tToggleControl,\n\tDisabled,\n\tSelectControl,\n\t__experimentalToolsPanel as ToolsPanel,\n\t__experimentalToolsPanelItem as ToolsPanelItem,\n} from '@wordpress/components';\nimport { useSelect, useDispatch } from '@wordpress/data';\nimport { store as noticesStore } from '@wordpress/notices';\nimport { __ } from '@wordpress/i18n';\nimport { audio as icon } from '@wordpress/icons';\nimport { createBlock } from '@wordpress/blocks';\n\n/**\n * Internal dependencies\n */\nimport { Caption } from '../utils/caption';\nimport { useToolsPanelDropdownMenuProps } from '../utils/hooks';\nimport { WaveformPlayer } from '../utils/waveform-player';\n\nconst ALLOWED_MEDIA_TYPES = [ 'audio' ];\n\n/**\n * Transform media library data into track block attributes.\n *\n * @param {Object} media - Media object from the media library.\n * @return {Object} Track attributes for the playlist-track block.\n */\nfunction getTrackAttributes( media ) {\n\treturn {\n\t\tid: media.id || media.url, // Attachment ID or URL.\n\t\tuniqueId: uuid(), // Unique ID for the track.\n\t\tsrc: media.url,\n\t\ttitle: media.title,\n\t\tartist:\n\t\t\tmedia.artist ||\n\t\t\tmedia?.meta?.artist ||\n\t\t\tmedia?.media_details?.artist ||\n\t\t\t__( 'Unknown artist' ),\n\t\talbum:\n\t\t\tmedia.album ||\n\t\t\tmedia?.meta?.album ||\n\t\t\tmedia?.media_details?.album ||\n\t\t\t__( 'Unknown album' ),\n\t\tlength: media?.fileLength || media?.media_details?.length_formatted,\n\t\t// Prevent using the default media attachment icon as the track image.\n\t\t// Note: Image is not available when a new track is uploaded.\n\t\timage:\n\t\t\tmedia?.image?.src &&\n\t\t\tmedia?.image?.src.endsWith( '/images/media/audio.svg' )\n\t\t\t\t? ''\n\t\t\t\t: media?.image?.src,\n\t};\n}\n\nconst PlaylistEdit = ( {\n\tattributes,\n\tsetAttributes,\n\tisSelected,\n\tinsertBlocksAfter,\n\tclientId,\n} ) => {\n\tconst {\n\t\torder,\n\t\tshowTracklist,\n\t\tshowNumbers,\n\t\tshowImages,\n\t\tshowArtists,\n\t\tcurrentTrack,\n\t} = attributes;\n\tconst blockProps = useBlockProps();\n\tconst { replaceInnerBlocks, __unstableMarkNextChangeAsNotPersistent } =\n\t\tuseDispatch( blockEditorStore );\n\tconst { createErrorNotice } = useDispatch( noticesStore );\n\tconst dropdownMenuProps = useToolsPanelDropdownMenuProps();\n\tfunction onUploadError( message ) {\n\t\tcreateErrorNotice( message, { type: 'snackbar' } );\n\t}\n\tconst { updateBlockAttributes } = useDispatch( blockEditorStore );\n\n\tconst { innerBlockTracks } = useSelect(\n\t\t( select ) => {\n\t\t\tconst { getBlock: _getBlock } = select( blockEditorStore );\n\t\t\treturn {\n\t\t\t\tinnerBlockTracks: _getBlock( clientId )?.innerBlocks ?? [],\n\t\t\t};\n\t\t},\n\t\t[ clientId ]\n\t);\n\n\t// Ensure that each inner block has a unique ID,\n\t// even if a track is duplicated.\n\tuseEffect( () => {\n\t\tconst seen = new Set();\n\t\tlet hasDuplicates = false;\n\t\tconst updatedBlocks = innerBlockTracks.map( ( block ) => {\n\t\t\tif ( seen.has( block.attributes.uniqueId ) ) {\n\t\t\t\thasDuplicates = true;\n\t\t\t\treturn {\n\t\t\t\t\t...block,\n\t\t\t\t\tattributes: {\n\t\t\t\t\t\t...block.attributes,\n\t\t\t\t\t\tuniqueId: uuid(),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\tseen.add( block.attributes.uniqueId );\n\t\t\treturn block;\n\t\t} );\n\t\tif ( hasDuplicates ) {\n\t\t\treplaceInnerBlocks( clientId, updatedBlocks );\n\t\t}\n\t}, [ innerBlockTracks, clientId, replaceInnerBlocks ] );\n\n\t// Create a list of tracks from the inner blocks,\n\t// but skip blocks that do not have a uniqueId attribute, such as the media placeholder.\n\tconst validTracks = innerBlockTracks.filter(\n\t\t( block ) => !! block.attributes.uniqueId\n\t);\n\tconst tracks = validTracks.map( ( block ) => block.attributes );\n\tconst firstTrackId = validTracks[ 0 ]?.attributes?.uniqueId;\n\n\t// updateBlockAttributes is used to force updating the parent playlist block\n\t// when the currentTrack changes. Using setAttributes directly does not update\n\t// the currentTrack when multiple tracks are moved at the same time.\n\tuseEffect( () => {\n\t\tif ( tracks.length === 0 ) {\n\t\t\t// If there are no tracks but currentTrack is set, set it to null.\n\t\t\tif ( currentTrack !== null ) {\n\t\t\t\tupdateBlockAttributes( clientId, { currentTrack: null } );\n\t\t\t}\n\t\t} else if (\n\t\t\t// If the currentTrack is not the first track, update it to the first track.\n\t\t\tfirstTrackId &&\n\t\t\tfirstTrackId !== currentTrack\n\t\t) {\n\t\t\tupdateBlockAttributes( clientId, { currentTrack: firstTrackId } );\n\t\t}\n\t}, [\n\t\ttracks,\n\t\tcurrentTrack,\n\t\tfirstTrackId,\n\t\tclientId,\n\t\tupdateBlockAttributes,\n\t] );\n\n\tconst onSelectTracks = useCallback(\n\t\t( media ) => {\n\t\t\tif ( ! media ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( ! Array.isArray( media ) ) {\n\t\t\t\tmedia = [ media ];\n\t\t\t}\n\n\t\t\tconst trackList = media.map( getTrackAttributes );\n\t\t\t__unstableMarkNextChangeAsNotPersistent();\n\t\t\tsetAttributes( {\n\t\t\t\tcurrentTrack:\n\t\t\t\t\ttrackList.length > 0 ? trackList[ 0 ].uniqueId : null,\n\t\t\t} );\n\n\t\t\tconst newBlocks = trackList.map( ( track ) =>\n\t\t\t\tcreateBlock( 'core/playlist-track', track )\n\t\t\t);\n\t\t\t// Replace the inner blocks with the new tracks.\n\t\t\treplaceInnerBlocks( clientId, newBlocks );\n\t\t},\n\t\t[\n\t\t\t__unstableMarkNextChangeAsNotPersistent,\n\t\t\tsetAttributes,\n\t\t\treplaceInnerBlocks,\n\t\t\tclientId,\n\t\t]\n\t);\n\n\t// Get current track data by finding the track with matching uniqueId.\n\tconst currentTrackData = tracks.find(\n\t\t( track ) => track.uniqueId === currentTrack\n\t);\n\n\t// Handle track end - advance to next track or loop to first.\n\tconst onTrackEnded = useCallback( () => {\n\t\tconst currentIndex = tracks.findIndex(\n\t\t\t( track ) => track.uniqueId === currentTrack\n\t\t);\n\t\tconst nextTrack = tracks[ currentIndex + 1 ] || tracks[ 0 ];\n\t\tif ( nextTrack?.uniqueId ) {\n\t\t\tsetAttributes( { currentTrack: nextTrack.uniqueId } );\n\t\t}\n\t}, [ currentTrack, tracks, setAttributes ] );\n\n\tconst onChangeOrder = useCallback(\n\t\t( trackOrder ) => {\n\t\t\tconst sortedBlocks = [ ...innerBlockTracks ].sort( ( a, b ) => {\n\t\t\t\tconst titleA = a.attributes.title || '';\n\t\t\t\tconst titleB = b.attributes.title || '';\n\n\t\t\t\tif ( trackOrder === 'asc' ) {\n\t\t\t\t\treturn titleA.localeCompare( titleB );\n\t\t\t\t}\n\t\t\t\treturn titleB.localeCompare( titleA );\n\t\t\t} );\n\t\t\tconst firstUniqueId = sortedBlocks[ 0 ]?.attributes?.uniqueId;\n\t\t\treplaceInnerBlocks( clientId, sortedBlocks );\n\t\t\tsetAttributes( {\n\t\t\t\torder: trackOrder,\n\t\t\t\tcurrentTrack:\n\t\t\t\t\tfirstUniqueId && firstUniqueId !== currentTrack\n\t\t\t\t\t\t? firstUniqueId\n\t\t\t\t\t\t: currentTrack,\n\t\t\t} );\n\t\t},\n\t\t[\n\t\t\tclientId,\n\t\t\tcurrentTrack,\n\t\t\tinnerBlockTracks,\n\t\t\treplaceInnerBlocks,\n\t\t\tsetAttributes,\n\t\t]\n\t);\n\n\tfunction toggleAttribute( attribute ) {\n\t\treturn ( newValue ) => {\n\t\t\tsetAttributes( { [ attribute ]: newValue } );\n\t\t};\n\t}\n\n\tconst hasSelectedChild = useSelect(\n\t\t( select ) =>\n\t\t\tselect( blockEditorStore ).hasSelectedInnerBlock( clientId ),\n\t\t[ clientId ]\n\t);\n\n\tconst hasAnySelected = isSelected || hasSelectedChild;\n\n\tconst innerBlocksProps = useInnerBlocksProps( blockProps, {\n\t\t__experimentalAppenderTagName: 'li',\n\t\trenderAppender: hasAnySelected && InnerBlocks.ButtonBlockAppender,\n\t} );\n\n\tif ( tracks.length === 0 ) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\t{ ...blockProps }\n\t\t\t\tclassName={ clsx( 'is-placeholder', blockProps.className ) }\n\t\t\t>\n\t\t\t\t<MediaPlaceholder\n\t\t\t\t\ticon={ <BlockIcon icon={ icon } /> }\n\t\t\t\t\tlabels={ {\n\t\t\t\t\t\ttitle: __( 'Playlist' ),\n\t\t\t\t\t\tinstructions: __(\n\t\t\t\t\t\t\t'Upload an audio file or pick one from your media library.'\n\t\t\t\t\t\t),\n\t\t\t\t\t} }\n\t\t\t\t\tonSelect={ onSelectTracks }\n\t\t\t\t\taccept=\"audio/*\"\n\t\t\t\t\tmultiple\n\t\t\t\t\tallowedTypes={ ALLOWED_MEDIA_TYPES }\n\t\t\t\t\tonError={ onUploadError }\n\t\t\t\t/>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t<BlockControls group=\"other\">\n\t\t\t\t<MediaReplaceFlow\n\t\t\t\t\tname={ __( 'Edit' ) }\n\t\t\t\t\tonSelect={ onSelectTracks }\n\t\t\t\t\taccept=\"audio/*\"\n\t\t\t\t\tmultiple\n\t\t\t\t\tmediaIds={ tracks\n\t\t\t\t\t\t.filter( ( track ) => track.id )\n\t\t\t\t\t\t.map( ( track ) => track.id ) }\n\t\t\t\t\tallowedTypes={ ALLOWED_MEDIA_TYPES }\n\t\t\t\t\tonError={ onUploadError }\n\t\t\t\t/>\n\t\t\t</BlockControls>\n\t\t\t<InspectorControls>\n\t\t\t\t<ToolsPanel\n\t\t\t\t\tlabel={ __( 'Settings' ) }\n\t\t\t\t\tresetAll={ () => {\n\t\t\t\t\t\tsetAttributes( {\n\t\t\t\t\t\t\tshowTracklist: true,\n\t\t\t\t\t\t\tshowArtists: true,\n\t\t\t\t\t\t\tshowNumbers: true,\n\t\t\t\t\t\t\tshowImages: true,\n\t\t\t\t\t\t\torder: 'asc',\n\t\t\t\t\t\t} );\n\t\t\t\t\t} }\n\t\t\t\t\tdropdownMenuProps={ dropdownMenuProps }\n\t\t\t\t>\n\t\t\t\t\t<ToolsPanelItem\n\t\t\t\t\t\tlabel={ __( 'Show Tracklist' ) }\n\t\t\t\t\t\tisShownByDefault\n\t\t\t\t\t\thasValue={ () => showTracklist !== true }\n\t\t\t\t\t\tonDeselect={ () =>\n\t\t\t\t\t\t\tsetAttributes( { showTracklist: true } )\n\t\t\t\t\t\t}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ToggleControl\n\t\t\t\t\t\t\tlabel={ __( 'Show Tracklist' ) }\n\t\t\t\t\t\t\tonChange={ toggleAttribute( 'showTracklist' ) }\n\t\t\t\t\t\t\tchecked={ showTracklist }\n\t\t\t\t\t\t/>\n\t\t\t\t\t</ToolsPanelItem>\n\t\t\t\t\t{ showTracklist && (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<ToolsPanelItem\n\t\t\t\t\t\t\t\tlabel={ __( 'Show artist name in Tracklist' ) }\n\t\t\t\t\t\t\t\tisShownByDefault\n\t\t\t\t\t\t\t\thasValue={ () => showArtists !== true }\n\t\t\t\t\t\t\t\tonDeselect={ () =>\n\t\t\t\t\t\t\t\t\tsetAttributes( { showArtists: true } )\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<ToggleControl\n\t\t\t\t\t\t\t\t\tlabel={ __(\n\t\t\t\t\t\t\t\t\t\t'Show artist name in Tracklist'\n\t\t\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t\t\tonChange={ toggleAttribute(\n\t\t\t\t\t\t\t\t\t\t'showArtists'\n\t\t\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t\t\tchecked={ showArtists }\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</ToolsPanelItem>\n\t\t\t\t\t\t\t<ToolsPanelItem\n\t\t\t\t\t\t\t\tlabel={ __( 'Show number in Tracklist' ) }\n\t\t\t\t\t\t\t\tisShownByDefault\n\t\t\t\t\t\t\t\thasValue={ () => showNumbers !== true }\n\t\t\t\t\t\t\t\tonDeselect={ () =>\n\t\t\t\t\t\t\t\t\tsetAttributes( { showNumbers: true } )\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<ToggleControl\n\t\t\t\t\t\t\t\t\tlabel={ __( 'Show number in Tracklist' ) }\n\t\t\t\t\t\t\t\t\tonChange={ toggleAttribute(\n\t\t\t\t\t\t\t\t\t\t'showNumbers'\n\t\t\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t\t\tchecked={ showNumbers }\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</ToolsPanelItem>\n\t\t\t\t\t\t</>\n\t\t\t\t\t) }\n\t\t\t\t\t<ToolsPanelItem\n\t\t\t\t\t\tlabel={ __( 'Show images' ) }\n\t\t\t\t\t\tisShownByDefault\n\t\t\t\t\t\thasValue={ () => showImages !== true }\n\t\t\t\t\t\tonDeselect={ () =>\n\t\t\t\t\t\t\tsetAttributes( { showImages: true } )\n\t\t\t\t\t\t}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ToggleControl\n\t\t\t\t\t\t\tlabel={ __( 'Show images' ) }\n\t\t\t\t\t\t\tonChange={ toggleAttribute( 'showImages' ) }\n\t\t\t\t\t\t\tchecked={ showImages }\n\t\t\t\t\t\t/>\n\t\t\t\t\t</ToolsPanelItem>\n\t\t\t\t\t<ToolsPanelItem\n\t\t\t\t\t\tlabel={ __( 'Order' ) }\n\t\t\t\t\t\tisShownByDefault\n\t\t\t\t\t\thasValue={ () => order !== 'asc' }\n\t\t\t\t\t\tonDeselect={ () => setAttributes( { order: 'asc' } ) }\n\t\t\t\t\t>\n\t\t\t\t\t\t<SelectControl\n\t\t\t\t\t\t\t__next40pxDefaultSize\n\t\t\t\t\t\t\tlabel={ __( 'Order' ) }\n\t\t\t\t\t\t\tvalue={ order }\n\t\t\t\t\t\t\toptions={ [\n\t\t\t\t\t\t\t\t{ label: __( 'Descending' ), value: 'desc' },\n\t\t\t\t\t\t\t\t{ label: __( 'Ascending' ), value: 'asc' },\n\t\t\t\t\t\t\t] }\n\t\t\t\t\t\t\tonChange={ ( value ) => onChangeOrder( value ) }\n\t\t\t\t\t\t/>\n\t\t\t\t\t</ToolsPanelItem>\n\t\t\t\t</ToolsPanel>\n\t\t\t</InspectorControls>\n\t\t\t<figure { ...blockProps }>\n\t\t\t\t<Disabled isDisabled={ ! isSelected }>\n\t\t\t\t\t<WaveformPlayer\n\t\t\t\t\t\tsrc={ currentTrackData?.src }\n\t\t\t\t\t\ttitle={ currentTrackData?.title }\n\t\t\t\t\t\tartist={ currentTrackData?.artist }\n\t\t\t\t\t\timage={ currentTrackData?.image }\n\t\t\t\t\t\tonEnded={ onTrackEnded }\n\t\t\t\t\t/>\n\t\t\t\t</Disabled>\n\t\t\t\t{ showTracklist && (\n\t\t\t\t\t<ol\n\t\t\t\t\t\tclassName={ clsx( 'wp-block-playlist__tracklist', {\n\t\t\t\t\t\t\t'wp-block-playlist__tracklist-show-numbers':\n\t\t\t\t\t\t\t\tshowNumbers,\n\t\t\t\t\t\t} ) }\n\t\t\t\t\t>\n\t\t\t\t\t\t{ innerBlocksProps.children }\n\t\t\t\t\t</ol>\n\t\t\t\t) }\n\t\t\t\t<Caption\n\t\t\t\t\tattributes={ attributes }\n\t\t\t\t\tsetAttributes={ setAttributes }\n\t\t\t\t\tisSelected={ isSelected }\n\t\t\t\t\tinsertBlocksAfter={ insertBlocksAfter }\n\t\t\t\t\tlabel={ __( 'Playlist caption text' ) }\n\t\t\t\t\tshowToolbarButton={ isSelected }\n\t\t\t\t\tstyle={ { marginTop: 16 } }\n\t\t\t\t/>\n\t\t\t</figure>\n\t\t</>\n\t);\n};\n\nexport default PlaylistEdit;\nexport { getTrackAttributes };\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,21 +1,12 @@
1
1
  // packages/block-library/src/playlist/view.js
2
2
  import { store, getContext, getElement } from "@wordpress/interactivity";
3
- store(
3
+ import { initWaveformPlayer, logPlayError } from "../utils/waveform-utils.mjs";
4
+ var playerState = /* @__PURE__ */ new WeakMap();
5
+ var { state } = store(
4
6
  "core/playlist",
5
7
  {
6
8
  state: {
7
9
  playlists: {},
8
- get currentTrack() {
9
- const { currentId, playlistId } = getContext();
10
- if (!currentId || !playlistId) {
11
- return {};
12
- }
13
- const playlist = this.playlists[playlistId];
14
- if (!playlist) {
15
- return {};
16
- }
17
- return playlist.tracks[currentId] || {};
18
- },
19
10
  get isCurrentTrack() {
20
11
  const { currentId, uniqueId } = getContext();
21
12
  return currentId === uniqueId;
@@ -25,41 +16,68 @@ store(
25
16
  changeTrack() {
26
17
  const context = getContext();
27
18
  context.currentId = context.uniqueId;
28
- context.isPlaying = true;
29
- },
30
- isPlaying() {
31
- const context = getContext();
32
- context.isPlaying = true;
33
- },
34
- isPaused() {
35
- const context = getContext();
36
- context.isPlaying = false;
37
- },
38
- nextSong() {
39
- const context = getContext();
40
- const currentIndex = context.tracks.findIndex(
41
- (uniqueId) => uniqueId === context.currentId
42
- );
43
- const nextTrack = context.tracks[currentIndex + 1];
44
- if (nextTrack) {
45
- context.currentId = nextTrack;
46
- const { ref } = getElement();
47
- setTimeout(() => {
48
- ref.play();
49
- }, 1e3);
50
- }
51
19
  }
52
20
  },
53
21
  callbacks: {
54
- autoPlay() {
22
+ initWaveformPlayer() {
55
23
  const context = getContext();
56
24
  const { ref } = getElement();
57
- if (context.currentId && context.isPlaying) {
58
- ref.play();
25
+ if (!context.currentId || !ref) {
26
+ return;
59
27
  }
28
+ const track = state.playlists[context.playlistId]?.tracks[context.currentId];
29
+ if (!track?.url) {
30
+ return;
31
+ }
32
+ const existing = playerState.get(ref);
33
+ if (existing?.url === track.url) {
34
+ return;
35
+ }
36
+ const shouldAutoPlay = !!existing?.url;
37
+ initPlayer(ref, track, shouldAutoPlay, context);
60
38
  }
61
39
  }
62
40
  },
63
41
  { lock: true }
64
42
  );
43
+ function initPlayer(ref, track, shouldAutoPlay, context) {
44
+ const existing = playerState.get(ref);
45
+ if (existing?.instance) {
46
+ existing.instance.loadTrack(track.url, track.title, track.artist, {
47
+ artwork: track.image
48
+ }).then(() => {
49
+ existing.url = track.url;
50
+ if (shouldAutoPlay) {
51
+ existing.instance.play()?.catch(logPlayError);
52
+ }
53
+ }).catch(logPlayError);
54
+ return;
55
+ }
56
+ const labels = {
57
+ play: ref.dataset.labelPlay,
58
+ pause: ref.dataset.labelPause
59
+ };
60
+ const player = initWaveformPlayer(ref, {
61
+ src: track.url,
62
+ title: track.title,
63
+ artist: track.artist,
64
+ image: track.image,
65
+ autoPlay: shouldAutoPlay,
66
+ labels,
67
+ onEnded: () => {
68
+ const currentIndex = context.tracks.findIndex(
69
+ (uniqueId) => uniqueId === context.currentId
70
+ );
71
+ const nextTrack = context.tracks[currentIndex + 1];
72
+ if (nextTrack) {
73
+ context.currentId = nextTrack;
74
+ }
75
+ }
76
+ });
77
+ playerState.set(ref, {
78
+ url: track.url,
79
+ instance: player.instance,
80
+ destroy: player.destroy
81
+ });
82
+ }
65
83
  //# sourceMappingURL=view.mjs.map