@wordpress/block-library 9.40.2-next.v.202602271551.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.
- package/CHANGELOG.md +2 -0
- package/build/button/block.json +11 -3
- package/build/button/deprecated.cjs +246 -13
- package/build/button/deprecated.cjs.map +2 -2
- package/build/button/edit.cjs +45 -58
- package/build/button/edit.cjs.map +3 -3
- package/build/button/save.cjs +3 -7
- package/build/button/save.cjs.map +2 -2
- package/build/button/utils.cjs +59 -0
- package/build/button/utils.cjs.map +7 -0
- package/build/image/image.cjs +1 -1
- package/build/image/image.cjs.map +2 -2
- package/build/navigation-link/shared/use-link-preview.cjs +2 -2
- package/build/navigation-link/shared/use-link-preview.cjs.map +2 -2
- package/build/playlist/edit.cjs +43 -136
- package/build/playlist/edit.cjs.map +3 -3
- package/build/playlist/view.cjs +56 -38
- package/build/playlist/view.cjs.map +2 -2
- package/build/playlist-track/edit.cjs +0 -1
- package/build/playlist-track/edit.cjs.map +2 -2
- package/build/post-title/block.json +3 -0
- package/build/post-title/edit.cjs +2 -2
- package/build/post-title/edit.cjs.map +2 -2
- package/build/utils/waveform-player.cjs +68 -0
- package/build/utils/waveform-player.cjs.map +7 -0
- package/build/utils/waveform-utils.cjs +171 -0
- package/build/utils/waveform-utils.cjs.map +7 -0
- package/build-module/button/block.json +11 -3
- package/build-module/button/deprecated.mjs +246 -13
- package/build-module/button/deprecated.mjs.map +2 -2
- package/build-module/button/edit.mjs +47 -63
- package/build-module/button/edit.mjs.map +2 -2
- package/build-module/button/save.mjs +3 -7
- package/build-module/button/save.mjs.map +2 -2
- package/build-module/button/utils.mjs +33 -0
- package/build-module/button/utils.mjs.map +7 -0
- package/build-module/image/image.mjs +1 -1
- package/build-module/image/image.mjs.map +2 -2
- package/build-module/navigation-link/shared/use-link-preview.mjs +2 -2
- package/build-module/navigation-link/shared/use-link-preview.mjs.map +2 -2
- package/build-module/playlist/edit.mjs +41 -139
- package/build-module/playlist/edit.mjs.map +2 -2
- package/build-module/playlist/view.mjs +56 -38
- package/build-module/playlist/view.mjs.map +2 -2
- package/build-module/playlist-track/edit.mjs +0 -1
- package/build-module/playlist-track/edit.mjs.map +2 -2
- package/build-module/post-title/block.json +3 -0
- package/build-module/post-title/edit.mjs +2 -2
- package/build-module/post-title/edit.mjs.map +2 -2
- package/build-module/utils/waveform-player.mjs +43 -0
- package/build-module/utils/waveform-player.mjs.map +7 -0
- package/build-module/utils/waveform-utils.mjs +131 -0
- package/build-module/utils/waveform-utils.mjs.map +7 -0
- package/build-style/button/style-rtl.css +6 -0
- package/build-style/button/style.css +6 -0
- package/build-style/editor-rtl.css +3 -3
- package/build-style/editor.css +3 -3
- package/build-style/playlist/editor-rtl.css +3 -3
- package/build-style/playlist/editor.css +3 -3
- package/build-style/playlist/style-rtl.css +351 -17
- package/build-style/playlist/style.css +351 -17
- package/build-style/style-rtl.css +357 -17
- package/build-style/style.css +357 -17
- package/package.json +39 -38
- package/src/button/block.json +11 -3
- package/src/button/deprecated.js +254 -16
- package/src/button/edit.js +50 -61
- package/src/button/index.php +68 -0
- package/src/button/save.js +2 -8
- package/src/button/style.scss +49 -7
- package/src/button/test/utils.js +84 -0
- package/src/button/utils.js +42 -0
- package/src/image/image.js +14 -15
- package/src/image/index.php +3 -1
- package/src/navigation-link/shared/test/use-link-preview.test.js +9 -0
- package/src/navigation-link/shared/use-link-preview.js +6 -9
- package/src/playlist/edit.js +60 -154
- package/src/playlist/editor.scss +3 -3
- package/src/playlist/index.php +15 -40
- package/src/playlist/style.scss +34 -27
- package/src/playlist/test/edit.js +137 -0
- package/src/playlist/view.js +97 -40
- package/src/playlist-track/edit.js +0 -1
- package/src/post-title/block.json +3 -0
- package/src/post-title/edit.js +4 -2
- package/src/search/index.php +1 -1
- package/src/utils/test/waveform-utils.js +328 -0
- package/src/utils/waveform-player.js +77 -0
- package/src/utils/waveform-utils.js +232 -0
package/src/playlist/index.php
CHANGED
|
@@ -58,13 +58,16 @@ function render_block_core_playlist( $attributes, $content, $block ) {
|
|
|
58
58
|
);
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
// Data is passed to wp_interactivity_state() which JSON-encodes it,
|
|
62
|
+
// so we use wp_strip_all_tags() instead of esc_html() to prevent
|
|
63
|
+
// HTML injection without double-encoding. URLs still use esc_url().
|
|
61
64
|
$tracks_data[ $unique_id ] = array(
|
|
62
65
|
'url' => esc_url( $url ),
|
|
63
|
-
'title' =>
|
|
64
|
-
'artist' =>
|
|
65
|
-
'album' =>
|
|
66
|
+
'title' => wp_strip_all_tags( $title ),
|
|
67
|
+
'artist' => wp_strip_all_tags( $artist ),
|
|
68
|
+
'album' => wp_strip_all_tags( $album ),
|
|
66
69
|
'image' => esc_url( $image ),
|
|
67
|
-
'ariaLabel' =>
|
|
70
|
+
'ariaLabel' => wp_strip_all_tags( $aria_label ),
|
|
68
71
|
);
|
|
69
72
|
|
|
70
73
|
if ( $unique_id === $current_media_id ) {
|
|
@@ -96,41 +99,14 @@ function render_block_core_playlist( $attributes, $content, $block ) {
|
|
|
96
99
|
)
|
|
97
100
|
);
|
|
98
101
|
|
|
99
|
-
//
|
|
100
|
-
$
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
$
|
|
105
|
-
'
|
|
106
|
-
|
|
107
|
-
alt=""
|
|
108
|
-
width="70px"
|
|
109
|
-
height="70px"
|
|
110
|
-
data-wp-bind--src="state.currentTrack.image"
|
|
111
|
-
data-wp-bind--hidden="!state.currentTrack.image"
|
|
112
|
-
/>';
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
$html .= '
|
|
116
|
-
<div>
|
|
117
|
-
<span class="wp-block-playlist__item-title" data-wp-text="state.currentTrack.title"></span>
|
|
118
|
-
<div class="wp-block-playlist__current-item-artist-album">
|
|
119
|
-
<span class="wp-block-playlist__item-artist" data-wp-text="state.currentTrack.artist"></span>
|
|
120
|
-
<span class="wp-block-playlist__item-album" data-wp-text="state.currentTrack.album"></span>
|
|
121
|
-
</div>
|
|
122
|
-
</div>
|
|
123
|
-
</div>
|
|
124
|
-
<audio
|
|
125
|
-
controls="controls"
|
|
126
|
-
data-wp-on--ended="actions.nextSong"
|
|
127
|
-
data-wp-on--play="actions.isPlaying"
|
|
128
|
-
data-wp-on--pause="actions.isPaused"
|
|
129
|
-
data-wp-bind--src="state.currentTrack.url"
|
|
130
|
-
data-wp-bind--aria-label="state.currentTrack.ariaLabel"
|
|
131
|
-
data-wp-watch="callbacks.autoPlay"
|
|
132
|
-
></audio>
|
|
133
|
-
';
|
|
102
|
+
// Add waveform player container with translated button labels.
|
|
103
|
+
$label_play = esc_attr__( 'Play' );
|
|
104
|
+
$label_pause = esc_attr__( 'Pause' );
|
|
105
|
+
$html = '<div class="wp-block-playlist__waveform-player"
|
|
106
|
+
data-wp-watch="callbacks.initWaveformPlayer"
|
|
107
|
+
data-label-play="' . $label_play . '"
|
|
108
|
+
data-label-pause="' . $label_pause . '"
|
|
109
|
+
></div>';
|
|
134
110
|
|
|
135
111
|
// Add the HTML for the current track inside the figure.
|
|
136
112
|
$figure = null;
|
|
@@ -149,7 +125,6 @@ function render_block_core_playlist( $attributes, $content, $block ) {
|
|
|
149
125
|
'playlistId' => $playlist_id,
|
|
150
126
|
'currentId' => $current_unique_id,
|
|
151
127
|
'tracks' => $playlist_tracks,
|
|
152
|
-
'isPlaying' => false,
|
|
153
128
|
)
|
|
154
129
|
)
|
|
155
130
|
);
|
package/src/playlist/style.scss
CHANGED
|
@@ -1,32 +1,44 @@
|
|
|
1
|
+
@use "@arraypress/waveform-player/dist/waveform-player";
|
|
2
|
+
|
|
3
|
+
// Waveform player dimensions.
|
|
4
|
+
$waveform-player-height: 100px;
|
|
5
|
+
|
|
1
6
|
.wp-block-playlist {
|
|
2
|
-
.
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
margin-bottom: var(--wp--preset--spacing--30, 1em);
|
|
9
|
-
|
|
10
|
-
div {
|
|
11
|
-
display: flex;
|
|
12
|
-
flex-direction: column;
|
|
13
|
-
align-items: flex-start;
|
|
14
|
-
gap: var(--wp--preset--spacing--20, 0.5em);
|
|
15
|
-
}
|
|
7
|
+
// Main waveform player container.
|
|
8
|
+
.wp-block-playlist__waveform-player {
|
|
9
|
+
width: 100%;
|
|
10
|
+
margin: var(--wp--preset--spacing--20, 0.625em) 0;
|
|
11
|
+
position: relative;
|
|
12
|
+
}
|
|
16
13
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
// Set the waveform track height and remove gap between button and waveform.
|
|
15
|
+
.waveform-track {
|
|
16
|
+
height: $waveform-player-height;
|
|
17
|
+
gap: 0;
|
|
18
|
+
}
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
// WaveformPlayer button styling.
|
|
21
|
+
.waveform-btn {
|
|
22
|
+
border-radius: 0;
|
|
23
|
+
border-end-start-radius: 0.125rem;
|
|
24
|
+
border-start-start-radius: 0.125rem;
|
|
25
|
+
width: $waveform-player-height;
|
|
26
|
+
height: $waveform-player-height;
|
|
27
|
+
min-width: $waveform-player-height;
|
|
28
|
+
background: currentColor;
|
|
29
|
+
margin: 0;
|
|
30
|
+
|
|
31
|
+
&:hover:not(:disabled) {
|
|
32
|
+
transform: none;
|
|
23
33
|
}
|
|
34
|
+
}
|
|
24
35
|
|
|
36
|
+
.waveform-track.waveform-align-bottom .waveform-btn {
|
|
37
|
+
margin-bottom: 0;
|
|
25
38
|
}
|
|
26
39
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
margin-top: var(--wp--preset--spacing--20, 0.625em);
|
|
40
|
+
.waveform-subtitle {
|
|
41
|
+
opacity: 0.7;
|
|
30
42
|
}
|
|
31
43
|
|
|
32
44
|
.wp-block-playlist__tracklist {
|
|
@@ -49,9 +61,4 @@
|
|
|
49
61
|
counter-reset: playlist-track;
|
|
50
62
|
}
|
|
51
63
|
}
|
|
52
|
-
|
|
53
|
-
li.block-list-appender.block-list-appender {
|
|
54
|
-
position: initial;
|
|
55
|
-
margin-top: var(--wp--preset--spacing--30, 1em);
|
|
56
|
-
}
|
|
57
64
|
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jest-environment jsdom
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Internal dependencies
|
|
7
|
+
*/
|
|
8
|
+
import { getTrackAttributes } from '../edit';
|
|
9
|
+
|
|
10
|
+
// Mock uuid to return predictable values.
|
|
11
|
+
jest.mock( 'uuid', () => ( {
|
|
12
|
+
v4: jest.fn( () => 'mock-uuid-1234' ),
|
|
13
|
+
} ) );
|
|
14
|
+
|
|
15
|
+
describe( 'Playlist block edit utilities', () => {
|
|
16
|
+
describe( 'getTrackAttributes', () => {
|
|
17
|
+
it( 'should transform media object to track attributes', () => {
|
|
18
|
+
const media = {
|
|
19
|
+
id: 123,
|
|
20
|
+
url: 'https://example.com/song.mp3',
|
|
21
|
+
title: 'My Song',
|
|
22
|
+
artist: 'The Artist',
|
|
23
|
+
album: 'Great Album',
|
|
24
|
+
fileLength: '3:45',
|
|
25
|
+
image: { src: 'https://example.com/cover.jpg' },
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const result = getTrackAttributes( media );
|
|
29
|
+
|
|
30
|
+
expect( result ).toEqual( {
|
|
31
|
+
id: 123,
|
|
32
|
+
uniqueId: 'mock-uuid-1234',
|
|
33
|
+
src: 'https://example.com/song.mp3',
|
|
34
|
+
title: 'My Song',
|
|
35
|
+
artist: 'The Artist',
|
|
36
|
+
album: 'Great Album',
|
|
37
|
+
length: '3:45',
|
|
38
|
+
image: 'https://example.com/cover.jpg',
|
|
39
|
+
} );
|
|
40
|
+
} );
|
|
41
|
+
|
|
42
|
+
it( 'should use URL as id when attachment id is not available', () => {
|
|
43
|
+
const media = {
|
|
44
|
+
url: 'https://example.com/song.mp3',
|
|
45
|
+
title: 'My Song',
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const result = getTrackAttributes( media );
|
|
49
|
+
|
|
50
|
+
expect( result.id ).toBe( 'https://example.com/song.mp3' );
|
|
51
|
+
} );
|
|
52
|
+
|
|
53
|
+
it( 'should fall back to meta.artist when artist is not available', () => {
|
|
54
|
+
const media = {
|
|
55
|
+
url: 'https://example.com/song.mp3',
|
|
56
|
+
title: 'My Song',
|
|
57
|
+
meta: { artist: 'Meta Artist' },
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const result = getTrackAttributes( media );
|
|
61
|
+
|
|
62
|
+
expect( result.artist ).toBe( 'Meta Artist' );
|
|
63
|
+
} );
|
|
64
|
+
|
|
65
|
+
it( 'should fall back to media_details.artist when artist and meta.artist are not available', () => {
|
|
66
|
+
const media = {
|
|
67
|
+
url: 'https://example.com/song.mp3',
|
|
68
|
+
title: 'My Song',
|
|
69
|
+
media_details: { artist: 'Media Details Artist' },
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const result = getTrackAttributes( media );
|
|
73
|
+
|
|
74
|
+
expect( result.artist ).toBe( 'Media Details Artist' );
|
|
75
|
+
} );
|
|
76
|
+
|
|
77
|
+
it( 'should use "Unknown artist" when no artist is available', () => {
|
|
78
|
+
const media = {
|
|
79
|
+
url: 'https://example.com/song.mp3',
|
|
80
|
+
title: 'My Song',
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const result = getTrackAttributes( media );
|
|
84
|
+
|
|
85
|
+
expect( result.artist ).toBe( 'Unknown artist' );
|
|
86
|
+
} );
|
|
87
|
+
|
|
88
|
+
it( 'should use "Unknown album" when no album is available', () => {
|
|
89
|
+
const media = {
|
|
90
|
+
url: 'https://example.com/song.mp3',
|
|
91
|
+
title: 'My Song',
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const result = getTrackAttributes( media );
|
|
95
|
+
|
|
96
|
+
expect( result.album ).toBe( 'Unknown album' );
|
|
97
|
+
} );
|
|
98
|
+
|
|
99
|
+
it( 'should use media_details.length_formatted when fileLength is not available', () => {
|
|
100
|
+
const media = {
|
|
101
|
+
url: 'https://example.com/song.mp3',
|
|
102
|
+
title: 'My Song',
|
|
103
|
+
media_details: { length_formatted: '4:30' },
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const result = getTrackAttributes( media );
|
|
107
|
+
|
|
108
|
+
expect( result.length ).toBe( '4:30' );
|
|
109
|
+
} );
|
|
110
|
+
|
|
111
|
+
it( 'should exclude default audio icon from image', () => {
|
|
112
|
+
const media = {
|
|
113
|
+
url: 'https://example.com/song.mp3',
|
|
114
|
+
title: 'My Song',
|
|
115
|
+
image: {
|
|
116
|
+
src: 'https://example.com/wp-includes/images/media/audio.svg',
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const result = getTrackAttributes( media );
|
|
121
|
+
|
|
122
|
+
expect( result.image ).toBe( '' );
|
|
123
|
+
} );
|
|
124
|
+
|
|
125
|
+
it( 'should include image URLs', () => {
|
|
126
|
+
const media = {
|
|
127
|
+
url: 'https://example.com/song.mp3',
|
|
128
|
+
title: 'My Song',
|
|
129
|
+
image: { src: 'https://example.com/cover.jpg' },
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const result = getTrackAttributes( media );
|
|
133
|
+
|
|
134
|
+
expect( result.image ).toBe( 'https://example.com/cover.jpg' );
|
|
135
|
+
} );
|
|
136
|
+
} );
|
|
137
|
+
} );
|
package/src/playlist/view.js
CHANGED
|
@@ -3,22 +3,21 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { store, getContext, getElement } from '@wordpress/interactivity';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Internal dependencies
|
|
8
|
+
*/
|
|
9
|
+
import { initWaveformPlayer, logPlayError } from '../utils/waveform-utils';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Store player state for each element.
|
|
13
|
+
*/
|
|
14
|
+
const playerState = new WeakMap();
|
|
15
|
+
|
|
16
|
+
const { state } = store(
|
|
7
17
|
'core/playlist',
|
|
8
18
|
{
|
|
9
19
|
state: {
|
|
10
20
|
playlists: {},
|
|
11
|
-
get currentTrack() {
|
|
12
|
-
const { currentId, playlistId } = getContext();
|
|
13
|
-
if ( ! currentId || ! playlistId ) {
|
|
14
|
-
return {};
|
|
15
|
-
}
|
|
16
|
-
const playlist = this.playlists[ playlistId ];
|
|
17
|
-
if ( ! playlist ) {
|
|
18
|
-
return {};
|
|
19
|
-
}
|
|
20
|
-
return playlist.tracks[ currentId ] || {};
|
|
21
|
-
},
|
|
22
21
|
get isCurrentTrack() {
|
|
23
22
|
const { currentId, uniqueId } = getContext();
|
|
24
23
|
return currentId === uniqueId;
|
|
@@ -28,42 +27,100 @@ store(
|
|
|
28
27
|
changeTrack() {
|
|
29
28
|
const context = getContext();
|
|
30
29
|
context.currentId = context.uniqueId;
|
|
31
|
-
context.isPlaying = true;
|
|
32
|
-
},
|
|
33
|
-
isPlaying() {
|
|
34
|
-
const context = getContext();
|
|
35
|
-
context.isPlaying = true;
|
|
36
|
-
},
|
|
37
|
-
isPaused() {
|
|
38
|
-
const context = getContext();
|
|
39
|
-
context.isPlaying = false;
|
|
40
|
-
},
|
|
41
|
-
nextSong() {
|
|
42
|
-
const context = getContext();
|
|
43
|
-
const currentIndex = context.tracks.findIndex(
|
|
44
|
-
( uniqueId ) => uniqueId === context.currentId
|
|
45
|
-
);
|
|
46
|
-
const nextTrack = context.tracks[ currentIndex + 1 ];
|
|
47
|
-
if ( nextTrack ) {
|
|
48
|
-
context.currentId = nextTrack;
|
|
49
|
-
const { ref } = getElement();
|
|
50
|
-
// Waits a moment before changing the track, since
|
|
51
|
-
// immediately changing the track can be jarring.
|
|
52
|
-
setTimeout( () => {
|
|
53
|
-
ref.play();
|
|
54
|
-
}, 1000 );
|
|
55
|
-
}
|
|
56
30
|
},
|
|
57
31
|
},
|
|
58
32
|
callbacks: {
|
|
59
|
-
|
|
33
|
+
initWaveformPlayer() {
|
|
60
34
|
const context = getContext();
|
|
61
35
|
const { ref } = getElement();
|
|
62
|
-
|
|
63
|
-
|
|
36
|
+
|
|
37
|
+
if ( ! context.currentId || ! ref ) {
|
|
38
|
+
return;
|
|
64
39
|
}
|
|
40
|
+
|
|
41
|
+
const track =
|
|
42
|
+
state.playlists[ context.playlistId ]?.tracks[
|
|
43
|
+
context.currentId
|
|
44
|
+
];
|
|
45
|
+
if ( ! track?.url ) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const existing = playerState.get( ref );
|
|
50
|
+
|
|
51
|
+
// Skip if we already initialized with this exact URL.
|
|
52
|
+
if ( existing?.url === track.url ) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Autoplay if we're switching from a different track (user action),
|
|
57
|
+
// but not on initial page load (when existing has no URL).
|
|
58
|
+
const shouldAutoPlay = !! existing?.url;
|
|
59
|
+
|
|
60
|
+
initPlayer( ref, track, shouldAutoPlay, context );
|
|
65
61
|
},
|
|
66
62
|
},
|
|
67
63
|
},
|
|
68
64
|
{ lock: true }
|
|
69
65
|
);
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Initialize the waveform player for a given element.
|
|
69
|
+
*
|
|
70
|
+
* @param {Element} ref - The container element.
|
|
71
|
+
* @param {Object} track - The track data.
|
|
72
|
+
* @param {boolean} shouldAutoPlay - Whether to auto-play after initialization.
|
|
73
|
+
* @param {Object} context - The Interactivity API context.
|
|
74
|
+
*/
|
|
75
|
+
function initPlayer( ref, track, shouldAutoPlay, context ) {
|
|
76
|
+
const existing = playerState.get( ref );
|
|
77
|
+
|
|
78
|
+
// If a player already exists, load the new track without recreating.
|
|
79
|
+
if ( existing?.instance ) {
|
|
80
|
+
existing.instance
|
|
81
|
+
.loadTrack( track.url, track.title, track.artist, {
|
|
82
|
+
artwork: track.image,
|
|
83
|
+
} )
|
|
84
|
+
.then( () => {
|
|
85
|
+
existing.url = track.url;
|
|
86
|
+
if ( shouldAutoPlay ) {
|
|
87
|
+
existing.instance.play()?.catch( logPlayError );
|
|
88
|
+
}
|
|
89
|
+
} )
|
|
90
|
+
.catch( logPlayError );
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Read translated labels from server-rendered data attributes.
|
|
95
|
+
const labels = {
|
|
96
|
+
play: ref.dataset.labelPlay,
|
|
97
|
+
pause: ref.dataset.labelPause,
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
// Initialize using the shared core.
|
|
101
|
+
const player = initWaveformPlayer( ref, {
|
|
102
|
+
src: track.url,
|
|
103
|
+
title: track.title,
|
|
104
|
+
artist: track.artist,
|
|
105
|
+
image: track.image,
|
|
106
|
+
autoPlay: shouldAutoPlay,
|
|
107
|
+
labels,
|
|
108
|
+
onEnded: () => {
|
|
109
|
+
// Advance to next track (autoPlay handles playback).
|
|
110
|
+
const currentIndex = context.tracks.findIndex(
|
|
111
|
+
( uniqueId ) => uniqueId === context.currentId
|
|
112
|
+
);
|
|
113
|
+
const nextTrack = context.tracks[ currentIndex + 1 ];
|
|
114
|
+
if ( nextTrack ) {
|
|
115
|
+
context.currentId = nextTrack;
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
} );
|
|
119
|
+
|
|
120
|
+
// Store state for cleanup, including instance for loadTrack reuse.
|
|
121
|
+
playerState.set( ref, {
|
|
122
|
+
url: track.url,
|
|
123
|
+
instance: player.instance,
|
|
124
|
+
destroy: player.destroy,
|
|
125
|
+
} );
|
|
126
|
+
}
|
|
@@ -180,7 +180,6 @@ const PlaylistTrackEdit = ( { attributes, setAttributes, context } ) => {
|
|
|
180
180
|
__next40pxDefaultSize
|
|
181
181
|
label={ __( 'Title' ) }
|
|
182
182
|
value={ title ? stripHTML( title ) : '' }
|
|
183
|
-
placeholder={ title ? stripHTML( title ) : '' }
|
|
184
183
|
onChange={ ( titleValue ) => {
|
|
185
184
|
setAttributes( { title: titleValue } );
|
|
186
185
|
} }
|
package/src/post-title/edit.js
CHANGED
|
@@ -28,7 +28,7 @@ import { createInterpolateElement } from '@wordpress/element';
|
|
|
28
28
|
import { useToolsPanelDropdownMenuProps } from '../utils/hooks';
|
|
29
29
|
|
|
30
30
|
export default function PostTitleEdit( {
|
|
31
|
-
attributes: { level, levelOptions, isLink, rel, linkTarget },
|
|
31
|
+
attributes: { level, levelOptions, isLink, rel, linkTarget, placeholder },
|
|
32
32
|
setAttributes,
|
|
33
33
|
context: { postType, postId, queryId },
|
|
34
34
|
insertBlocksAfter,
|
|
@@ -70,7 +70,9 @@ export default function PostTitleEdit( {
|
|
|
70
70
|
const blockEditingMode = useBlockEditingMode();
|
|
71
71
|
const dropdownMenuProps = useToolsPanelDropdownMenuProps();
|
|
72
72
|
|
|
73
|
-
let titleElement =
|
|
73
|
+
let titleElement = (
|
|
74
|
+
<TagName { ...blockProps }>{ placeholder || __( 'Title' ) }</TagName>
|
|
75
|
+
);
|
|
74
76
|
|
|
75
77
|
if ( postType && postId ) {
|
|
76
78
|
titleElement = userCanEdit ? (
|
package/src/search/index.php
CHANGED
|
@@ -72,7 +72,7 @@ function render_block_core_search( $attributes ) {
|
|
|
72
72
|
if ( $input->next_tag() ) {
|
|
73
73
|
$input->add_class( implode( ' ', $input_classes ) );
|
|
74
74
|
$input->set_attribute( 'id', $input_id );
|
|
75
|
-
$input->set_attribute( 'value', get_search_query() );
|
|
75
|
+
$input->set_attribute( 'value', get_search_query( false ) );
|
|
76
76
|
$input->set_attribute( 'placeholder', $attributes['placeholder'] );
|
|
77
77
|
|
|
78
78
|
// If it's interactive, enqueue the script module and add the directives.
|