@wordpress/media-fields 0.1.1-next.6deb34194.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/LICENSE.md +788 -0
- package/README.md +52 -0
- package/build/alt_text/index.js +51 -0
- package/build/alt_text/index.js.map +7 -0
- package/build/caption/index.js +52 -0
- package/build/caption/index.js.map +7 -0
- package/build/description/index.js +52 -0
- package/build/description/index.js.map +7 -0
- package/build/filename/index.js +50 -0
- package/build/filename/index.js.map +7 -0
- package/build/filename/view.js +43 -0
- package/build/filename/view.js.map +7 -0
- package/build/filesize/index.js +90 -0
- package/build/filesize/index.js.map +7 -0
- package/build/index.js +62 -0
- package/build/index.js.map +7 -0
- package/build/media_dimensions/index.js +45 -0
- package/build/media_dimensions/index.js.map +7 -0
- package/build/media_thumbnail/index.js +47 -0
- package/build/media_thumbnail/index.js.map +7 -0
- package/build/media_thumbnail/view.js +94 -0
- package/build/media_thumbnail/view.js.map +7 -0
- package/build/mime_type/index.js +38 -0
- package/build/mime_type/index.js.map +7 -0
- package/build/types.js +19 -0
- package/build/types.js.map +7 -0
- package/build/utils/get-media-type-from-mime-type.js +60 -0
- package/build/utils/get-media-type-from-mime-type.js.map +7 -0
- package/build/utils/get-raw-content.js +42 -0
- package/build/utils/get-raw-content.js.map +7 -0
- package/build/utils/get-rendered-content.js +42 -0
- package/build/utils/get-rendered-content.js.map +7 -0
- package/build-module/alt_text/index.js +30 -0
- package/build-module/alt_text/index.js.map +7 -0
- package/build-module/caption/index.js +31 -0
- package/build-module/caption/index.js.map +7 -0
- package/build-module/description/index.js +31 -0
- package/build-module/description/index.js.map +7 -0
- package/build-module/filename/index.js +19 -0
- package/build-module/filename/index.js.map +7 -0
- package/build-module/filename/view.js +25 -0
- package/build-module/filename/view.js.map +7 -0
- package/build-module/filesize/index.js +69 -0
- package/build-module/filesize/index.js.map +7 -0
- package/build-module/index.js +20 -0
- package/build-module/index.js.map +7 -0
- package/build-module/media_dimensions/index.js +24 -0
- package/build-module/media_dimensions/index.js.map +7 -0
- package/build-module/media_thumbnail/index.js +16 -0
- package/build-module/media_thumbnail/index.js.map +7 -0
- package/build-module/media_thumbnail/view.js +77 -0
- package/build-module/media_thumbnail/view.js.map +7 -0
- package/build-module/mime_type/index.js +17 -0
- package/build-module/mime_type/index.js.map +7 -0
- package/build-module/types.js +1 -0
- package/build-module/types.js.map +7 -0
- package/build-module/utils/get-media-type-from-mime-type.js +35 -0
- package/build-module/utils/get-media-type-from-mime-type.js.map +7 -0
- package/build-module/utils/get-raw-content.js +17 -0
- package/build-module/utils/get-raw-content.js.map +7 -0
- package/build-module/utils/get-rendered-content.js +17 -0
- package/build-module/utils/get-rendered-content.js.map +7 -0
- package/build-style/style-rtl.css +130 -0
- package/build-style/style.css +130 -0
- package/build-types/alt_text/index.d.ts +5 -0
- package/build-types/alt_text/index.d.ts.map +1 -0
- package/build-types/caption/index.d.ts +5 -0
- package/build-types/caption/index.d.ts.map +1 -0
- package/build-types/description/index.d.ts +5 -0
- package/build-types/description/index.d.ts.map +1 -0
- package/build-types/filename/index.d.ts +8 -0
- package/build-types/filename/index.d.ts.map +1 -0
- package/build-types/filename/view.d.ts +7 -0
- package/build-types/filename/view.d.ts.map +1 -0
- package/build-types/filesize/index.d.ts +8 -0
- package/build-types/filesize/index.d.ts.map +1 -0
- package/build-types/index.d.ts +10 -0
- package/build-types/index.d.ts.map +1 -0
- package/build-types/media_dimensions/index.d.ts +5 -0
- package/build-types/media_dimensions/index.d.ts.map +1 -0
- package/build-types/media_thumbnail/index.d.ts +8 -0
- package/build-types/media_thumbnail/index.d.ts.map +1 -0
- package/build-types/media_thumbnail/view.d.ts +4 -0
- package/build-types/media_thumbnail/view.d.ts.map +1 -0
- package/build-types/mime_type/index.d.ts +5 -0
- package/build-types/mime_type/index.d.ts.map +1 -0
- package/build-types/stories/index.story.d.ts +25 -0
- package/build-types/stories/index.story.d.ts.map +1 -0
- package/build-types/types.d.ts +18 -0
- package/build-types/types.d.ts.map +1 -0
- package/build-types/utils/get-media-type-from-mime-type.d.ts +18 -0
- package/build-types/utils/get-media-type-from-mime-type.d.ts.map +1 -0
- package/build-types/utils/get-raw-content.d.ts +17 -0
- package/build-types/utils/get-raw-content.d.ts.map +1 -0
- package/build-types/utils/get-rendered-content.d.ts +17 -0
- package/build-types/utils/get-rendered-content.d.ts.map +1 -0
- package/package.json +61 -0
- package/src/alt_text/index.tsx +30 -0
- package/src/caption/index.tsx +35 -0
- package/src/description/index.tsx +37 -0
- package/src/filename/index.ts +26 -0
- package/src/filename/view.tsx +39 -0
- package/src/filesize/index.tsx +96 -0
- package/src/index.ts +15 -0
- package/src/media_dimensions/index.ts +29 -0
- package/src/media_thumbnail/index.tsx +22 -0
- package/src/media_thumbnail/style.scss +49 -0
- package/src/media_thumbnail/view.tsx +104 -0
- package/src/mime_type/index.ts +19 -0
- package/src/stories/index.story.tsx +290 -0
- package/src/style.scss +1 -0
- package/src/types.ts +24 -0
- package/src/utils/get-media-type-from-mime-type.ts +54 -0
- package/src/utils/get-raw-content.ts +32 -0
- package/src/utils/get-rendered-content.ts +32 -0
- package/tsconfig.json +31 -0
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { useSelect } from '@wordpress/data';
|
|
5
|
+
import { store as coreStore } from '@wordpress/core-data';
|
|
6
|
+
import {
|
|
7
|
+
__experimentalTruncate as Truncate,
|
|
8
|
+
__experimentalVStack as VStack,
|
|
9
|
+
Icon,
|
|
10
|
+
} from '@wordpress/components';
|
|
11
|
+
import type { Attachment } from '@wordpress/core-data';
|
|
12
|
+
import { getFilename } from '@wordpress/url';
|
|
13
|
+
import type { DataViewRenderFieldProps } from '@wordpress/dataviews';
|
|
14
|
+
/**
|
|
15
|
+
* Internal dependencies
|
|
16
|
+
*/
|
|
17
|
+
import { getMediaTypeFromMimeType } from '../utils/get-media-type-from-mime-type';
|
|
18
|
+
import type { MediaItem } from '../types';
|
|
19
|
+
|
|
20
|
+
export default function MediaThumbnailView( {
|
|
21
|
+
item,
|
|
22
|
+
config,
|
|
23
|
+
}: DataViewRenderFieldProps< MediaItem > ) {
|
|
24
|
+
const _featuredMedia = useSelect(
|
|
25
|
+
( select ) => {
|
|
26
|
+
// Avoid the network request if it's not needed. `featured_media` is
|
|
27
|
+
// 0 for images and media without featured media.
|
|
28
|
+
if ( ! item.featured_media ) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
return select( coreStore ).getEntityRecord< Attachment >(
|
|
32
|
+
'postType',
|
|
33
|
+
'attachment',
|
|
34
|
+
item.featured_media
|
|
35
|
+
);
|
|
36
|
+
},
|
|
37
|
+
[ item.featured_media ]
|
|
38
|
+
);
|
|
39
|
+
const featuredMedia = item.featured_media ? _featuredMedia : item;
|
|
40
|
+
|
|
41
|
+
// Fetching.
|
|
42
|
+
if ( ! featuredMedia ) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const filename = getFilename( featuredMedia.source_url || '' );
|
|
47
|
+
|
|
48
|
+
if (
|
|
49
|
+
// Ensure the featured media is an image.
|
|
50
|
+
getMediaTypeFromMimeType( featuredMedia.mime_type ).type === 'image'
|
|
51
|
+
) {
|
|
52
|
+
return (
|
|
53
|
+
<div className="dataviews-media-field__media-thumbnail">
|
|
54
|
+
<img
|
|
55
|
+
className="dataviews-media-field__media-thumbnail--image"
|
|
56
|
+
src={ featuredMedia.source_url }
|
|
57
|
+
srcSet={
|
|
58
|
+
featuredMedia?.media_details?.sizes
|
|
59
|
+
? (
|
|
60
|
+
Object.values(
|
|
61
|
+
featuredMedia.media_details.sizes
|
|
62
|
+
) as Array< {
|
|
63
|
+
source_url: string;
|
|
64
|
+
width: number;
|
|
65
|
+
} >
|
|
66
|
+
)
|
|
67
|
+
.map(
|
|
68
|
+
( size ) =>
|
|
69
|
+
`${ size.source_url } ${ size.width }w`
|
|
70
|
+
)
|
|
71
|
+
.join( ', ' )
|
|
72
|
+
: undefined
|
|
73
|
+
}
|
|
74
|
+
sizes={ config?.sizes || '100vw' }
|
|
75
|
+
alt={ featuredMedia.alt_text || featuredMedia.title.raw }
|
|
76
|
+
/>
|
|
77
|
+
</div>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<div className="dataviews-media-field__media-thumbnail">
|
|
83
|
+
<VStack
|
|
84
|
+
justify="center"
|
|
85
|
+
alignment="center"
|
|
86
|
+
className="dataviews-media-field__media-thumbnail__stack"
|
|
87
|
+
spacing={ 0 }
|
|
88
|
+
>
|
|
89
|
+
<Icon
|
|
90
|
+
className="dataviews-media-field__media-thumbnail--icon"
|
|
91
|
+
icon={ getMediaTypeFromMimeType( item.mime_type ).icon }
|
|
92
|
+
size={ 24 }
|
|
93
|
+
/>
|
|
94
|
+
{ !! filename && (
|
|
95
|
+
<div className="dataviews-media-field__media-thumbnail__filename">
|
|
96
|
+
<Truncate className="dataviews-media-field__media-thumbnail__filename__truncate">
|
|
97
|
+
{ filename }
|
|
98
|
+
</Truncate>
|
|
99
|
+
</div>
|
|
100
|
+
) }
|
|
101
|
+
</VStack>
|
|
102
|
+
</div>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { __ } from '@wordpress/i18n';
|
|
5
|
+
import type { Attachment, Updatable } from '@wordpress/core-data';
|
|
6
|
+
import type { Field } from '@wordpress/dataviews';
|
|
7
|
+
|
|
8
|
+
const mimeTypeField: Partial< Field< Updatable< Attachment > > > = {
|
|
9
|
+
id: 'mime_type',
|
|
10
|
+
type: 'text',
|
|
11
|
+
label: __( 'File type' ),
|
|
12
|
+
getValue: ( { item } ) => item?.mime_type || '',
|
|
13
|
+
render: ( { item } ) => item?.mime_type || '-',
|
|
14
|
+
enableSorting: true,
|
|
15
|
+
filterBy: false,
|
|
16
|
+
readOnly: true,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default mimeTypeField;
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { useState } from '@wordpress/element';
|
|
5
|
+
import { DataForm, DataViews, type Form } from '@wordpress/dataviews';
|
|
6
|
+
import type { Field, View } from '@wordpress/dataviews';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Internal dependencies
|
|
10
|
+
*/
|
|
11
|
+
import {
|
|
12
|
+
altTextField,
|
|
13
|
+
captionField,
|
|
14
|
+
descriptionField,
|
|
15
|
+
filenameField,
|
|
16
|
+
filesizeField,
|
|
17
|
+
mediaDimensionsField,
|
|
18
|
+
mediaThumbnailField,
|
|
19
|
+
mimeTypeField,
|
|
20
|
+
type MediaItem,
|
|
21
|
+
} from '../index';
|
|
22
|
+
|
|
23
|
+
export default {
|
|
24
|
+
title: 'Fields/Media Fields',
|
|
25
|
+
component: DataForm,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Sample data for media fields
|
|
29
|
+
const sampleMediaItem: MediaItem = {
|
|
30
|
+
id: 123,
|
|
31
|
+
date: '2024-01-15T10:30:00',
|
|
32
|
+
date_gmt: '2024-01-15T10:30:00',
|
|
33
|
+
guid: {
|
|
34
|
+
raw: 'https://cldup.com/cXyG__fTLN.jpg',
|
|
35
|
+
rendered: 'https://cldup.com/cXyG__fTLN.jpg',
|
|
36
|
+
},
|
|
37
|
+
modified: '2024-01-15T10:30:00',
|
|
38
|
+
modified_gmt: '2024-01-15T10:30:00',
|
|
39
|
+
slug: 'sample-image',
|
|
40
|
+
status: 'publish',
|
|
41
|
+
type: 'attachment',
|
|
42
|
+
link: 'https://example.com/sample-image/',
|
|
43
|
+
title: {
|
|
44
|
+
raw: 'Sample Image',
|
|
45
|
+
rendered: 'Sample Image',
|
|
46
|
+
},
|
|
47
|
+
author: 1,
|
|
48
|
+
featured_media: 0,
|
|
49
|
+
comment_status: 'open',
|
|
50
|
+
ping_status: 'closed',
|
|
51
|
+
template: '',
|
|
52
|
+
meta: {},
|
|
53
|
+
permalink_template: 'https://example.com/?attachment_id=123',
|
|
54
|
+
generated_slug: 'sample-image',
|
|
55
|
+
class_list: [ 'post-123', 'attachment' ],
|
|
56
|
+
alt_text: 'A beautiful sample image',
|
|
57
|
+
caption: {
|
|
58
|
+
raw: 'A caption for the image',
|
|
59
|
+
rendered: '<p>A caption for the image</p>\n',
|
|
60
|
+
},
|
|
61
|
+
description: {
|
|
62
|
+
raw: 'This is a detailed description of the sample image. It contains useful information about what the image depicts and its context.',
|
|
63
|
+
rendered:
|
|
64
|
+
'<p>This is a detailed description of the sample image. It contains useful information about what the image depicts and its context.</p>',
|
|
65
|
+
},
|
|
66
|
+
mime_type: 'image/jpeg',
|
|
67
|
+
media_type: 'image',
|
|
68
|
+
post: null,
|
|
69
|
+
source_url: 'https://cldup.com/cXyG__fTLN.jpg',
|
|
70
|
+
media_details: {
|
|
71
|
+
file: 'sample-image.jpg',
|
|
72
|
+
width: 1920,
|
|
73
|
+
height: 1080,
|
|
74
|
+
filesize: 524288,
|
|
75
|
+
image_meta: {
|
|
76
|
+
aperture: '2.8',
|
|
77
|
+
credit: '',
|
|
78
|
+
camera: 'Sample Camera',
|
|
79
|
+
caption: '',
|
|
80
|
+
created_timestamp: '1705315800',
|
|
81
|
+
copyright: '',
|
|
82
|
+
focal_length: '50',
|
|
83
|
+
iso: '100',
|
|
84
|
+
shutter_speed: '0.004',
|
|
85
|
+
title: '',
|
|
86
|
+
orientation: '1',
|
|
87
|
+
keywords: [],
|
|
88
|
+
},
|
|
89
|
+
sizes: {
|
|
90
|
+
thumbnail: {
|
|
91
|
+
file: 'sample-image-150x150.jpg',
|
|
92
|
+
width: 150,
|
|
93
|
+
height: 150,
|
|
94
|
+
filesize: 8192,
|
|
95
|
+
mime_type: 'image/jpeg',
|
|
96
|
+
source_url: 'https://cldup.com/cXyG__fTLN.jpg',
|
|
97
|
+
},
|
|
98
|
+
medium: {
|
|
99
|
+
file: 'sample-image-300x169.jpg',
|
|
100
|
+
width: 300,
|
|
101
|
+
height: 169,
|
|
102
|
+
filesize: 24576,
|
|
103
|
+
mime_type: 'image/jpeg',
|
|
104
|
+
source_url: 'https://cldup.com/cXyG__fTLN.jpg',
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
missing_image_sizes: [],
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// Sample data for a non-image file (ZIP)
|
|
112
|
+
const sampleMediaItemZip: MediaItem = {
|
|
113
|
+
id: 101,
|
|
114
|
+
date: '2025-11-07T00:28:54',
|
|
115
|
+
date_gmt: '2025-11-07T00:28:54',
|
|
116
|
+
guid: {
|
|
117
|
+
raw: 'http://localhost:8888/wp-content/uploads/2025/11/gutenberg-v22-0-0.zip',
|
|
118
|
+
rendered:
|
|
119
|
+
'http://localhost:8888/wp-content/uploads/2025/11/gutenberg-v22-0-0.zip',
|
|
120
|
+
},
|
|
121
|
+
modified: '2025-11-07T00:28:54',
|
|
122
|
+
modified_gmt: '2025-11-07T00:28:54',
|
|
123
|
+
slug: 'gutenberg-v22-0-0',
|
|
124
|
+
status: 'publish',
|
|
125
|
+
type: 'attachment',
|
|
126
|
+
link: 'http://localhost:8888/gutenberg-v22-0-0/',
|
|
127
|
+
title: {
|
|
128
|
+
raw: 'gutenberg-v22-0-0',
|
|
129
|
+
rendered: 'gutenberg-v22-0-0',
|
|
130
|
+
},
|
|
131
|
+
author: 1,
|
|
132
|
+
featured_media: 0,
|
|
133
|
+
comment_status: 'open',
|
|
134
|
+
ping_status: 'closed',
|
|
135
|
+
template: '',
|
|
136
|
+
meta: {},
|
|
137
|
+
permalink_template: 'http://localhost:8888/?attachment_id=101',
|
|
138
|
+
generated_slug: 'gutenberg-v22-0-0',
|
|
139
|
+
class_list: [ 'post-101', 'attachment' ],
|
|
140
|
+
alt_text: '',
|
|
141
|
+
caption: {
|
|
142
|
+
raw: '',
|
|
143
|
+
rendered: '<p>gutenberg-v22-0-0</p>\n',
|
|
144
|
+
},
|
|
145
|
+
description: {
|
|
146
|
+
raw: '',
|
|
147
|
+
rendered: '',
|
|
148
|
+
},
|
|
149
|
+
mime_type: 'application/zip',
|
|
150
|
+
media_type: 'file',
|
|
151
|
+
post: 1,
|
|
152
|
+
source_url:
|
|
153
|
+
'http://localhost:8888/wp-content/uploads/2025/11/gutenberg-v22-0-0.zip',
|
|
154
|
+
media_details: {
|
|
155
|
+
file: 'gutenberg-v22-0-0.zip',
|
|
156
|
+
filesize: 19988723,
|
|
157
|
+
width: 0,
|
|
158
|
+
height: 0,
|
|
159
|
+
image_meta: {
|
|
160
|
+
aperture: '',
|
|
161
|
+
credit: '',
|
|
162
|
+
camera: '',
|
|
163
|
+
caption: '',
|
|
164
|
+
created_timestamp: '',
|
|
165
|
+
copyright: '',
|
|
166
|
+
focal_length: '',
|
|
167
|
+
iso: '',
|
|
168
|
+
shutter_speed: '',
|
|
169
|
+
title: '',
|
|
170
|
+
orientation: '',
|
|
171
|
+
keywords: [],
|
|
172
|
+
},
|
|
173
|
+
sizes: {},
|
|
174
|
+
},
|
|
175
|
+
missing_image_sizes: [],
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
// Create a showcase of all media fields.
|
|
179
|
+
const showcaseFields = [
|
|
180
|
+
mediaThumbnailField,
|
|
181
|
+
filenameField,
|
|
182
|
+
altTextField,
|
|
183
|
+
captionField,
|
|
184
|
+
descriptionField,
|
|
185
|
+
mimeTypeField,
|
|
186
|
+
mediaDimensionsField,
|
|
187
|
+
filesizeField,
|
|
188
|
+
] as Field< any >[];
|
|
189
|
+
|
|
190
|
+
const DataFormsComponent = ( { type }: { type: 'regular' | 'panel' } ) => {
|
|
191
|
+
const [ data, setData ] = useState< MediaItem >( sampleMediaItem );
|
|
192
|
+
|
|
193
|
+
const handleChange = ( updates: Partial< MediaItem > ) => {
|
|
194
|
+
setData( ( prev: MediaItem ) => ( { ...prev, ...updates } ) );
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
// Form configuration for the media fields showcase.
|
|
198
|
+
const showcaseForm: Form = {
|
|
199
|
+
layout: {
|
|
200
|
+
type,
|
|
201
|
+
},
|
|
202
|
+
fields: [
|
|
203
|
+
'media_thumbnail',
|
|
204
|
+
'alt_text',
|
|
205
|
+
'caption',
|
|
206
|
+
'description',
|
|
207
|
+
'filename',
|
|
208
|
+
'mime_type',
|
|
209
|
+
'media_dimensions',
|
|
210
|
+
'filesize',
|
|
211
|
+
],
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
return (
|
|
215
|
+
<div style={ { padding: '20px' } }>
|
|
216
|
+
<h2>Media Fields</h2>
|
|
217
|
+
<p>
|
|
218
|
+
This story demonstrates all the media fields from the
|
|
219
|
+
@wordpress/media-fields package within a DataForm.
|
|
220
|
+
</p>
|
|
221
|
+
|
|
222
|
+
<DataForm
|
|
223
|
+
data={ data }
|
|
224
|
+
fields={ showcaseFields }
|
|
225
|
+
form={ showcaseForm }
|
|
226
|
+
onChange={ handleChange }
|
|
227
|
+
/>
|
|
228
|
+
</div>
|
|
229
|
+
);
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
export const DataFormsPreview = {
|
|
233
|
+
render: DataFormsComponent,
|
|
234
|
+
argTypes: {
|
|
235
|
+
type: {
|
|
236
|
+
control: { type: 'select' },
|
|
237
|
+
description: 'Choose the layout type.',
|
|
238
|
+
options: [ 'regular', 'panel' ],
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
args: {
|
|
242
|
+
type: 'regular',
|
|
243
|
+
},
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
export const DataViewsPreview = () => {
|
|
247
|
+
const [ view, setView ] = useState< View >( {
|
|
248
|
+
type: 'table',
|
|
249
|
+
fields: showcaseFields
|
|
250
|
+
.map( ( f ) => f.id )
|
|
251
|
+
.filter( ( id ) => id !== 'media_thumbnail' ),
|
|
252
|
+
descriptionField: undefined,
|
|
253
|
+
mediaField: 'media_thumbnail',
|
|
254
|
+
showTitle: false,
|
|
255
|
+
} );
|
|
256
|
+
const [ data ] = useState< MediaItem[] >( [
|
|
257
|
+
sampleMediaItem,
|
|
258
|
+
sampleMediaItemZip,
|
|
259
|
+
] );
|
|
260
|
+
|
|
261
|
+
const paginationInfo = {
|
|
262
|
+
totalItems: 2,
|
|
263
|
+
totalPages: 1,
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
const defaultLayouts = {
|
|
267
|
+
table: {},
|
|
268
|
+
list: {},
|
|
269
|
+
grid: {},
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
return (
|
|
273
|
+
<div style={ { padding: '20px' } }>
|
|
274
|
+
<h2>Media Fields DataViews Preview</h2>
|
|
275
|
+
<p>
|
|
276
|
+
This story demonstrates all the media fields from the
|
|
277
|
+
@wordpress/media-fields package, rendered in a DataViews
|
|
278
|
+
component, allowing preview of view state and layout switching.
|
|
279
|
+
</p>
|
|
280
|
+
<DataViews
|
|
281
|
+
data={ data }
|
|
282
|
+
fields={ showcaseFields }
|
|
283
|
+
view={ view }
|
|
284
|
+
onChangeView={ ( nextView: View ) => setView( nextView ) }
|
|
285
|
+
paginationInfo={ paginationInfo }
|
|
286
|
+
defaultLayouts={ defaultLayouts }
|
|
287
|
+
/>
|
|
288
|
+
</div>
|
|
289
|
+
);
|
|
290
|
+
};
|
package/src/style.scss
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@use "./media_thumbnail/style.scss" as *;
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import type { Attachment, Updatable, Post } from '@wordpress/core-data';
|
|
5
|
+
|
|
6
|
+
export type MediaKind = 'image' | 'video' | 'audio' | 'application';
|
|
7
|
+
|
|
8
|
+
export interface MediaType {
|
|
9
|
+
type: MediaKind;
|
|
10
|
+
label: string;
|
|
11
|
+
icon: JSX.Element;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// TODO: Update the Attachment type separately.
|
|
15
|
+
export interface MediaItem extends Attachment< 'edit' > {
|
|
16
|
+
// featured_media is not in the Attachment type. See https://github.com/WordPress/gutenberg/blob/trunk/packages/core-data/src/entity-types/attachment.ts#L10
|
|
17
|
+
featured_media: number;
|
|
18
|
+
_embedded?: {
|
|
19
|
+
// TODO: Include wp:attached-to properly, and backport PHP changes from wordpress-develop to support this.
|
|
20
|
+
'wp:attached-to'?: Post[] | Partial< Post >[];
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type MediaItemUpdatable = Updatable< Attachment >;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { __ } from '@wordpress/i18n';
|
|
5
|
+
import { audio, video, image, file } from '@wordpress/icons';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Internal dependencies
|
|
9
|
+
*/
|
|
10
|
+
import type { MediaType } from '../types';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Get the media type from a mime type, including an icon.
|
|
14
|
+
* TODO - media types should be formalized somewhere.
|
|
15
|
+
*
|
|
16
|
+
* References:
|
|
17
|
+
* https://developer.wordpress.org/reference/functions/wp_mime_type_icon/
|
|
18
|
+
* https://developer.wordpress.org/reference/hooks/mime_types/
|
|
19
|
+
* https://developer.wordpress.org/reference/functions/wp_get_mime_types/
|
|
20
|
+
*
|
|
21
|
+
* @param mimeType - The mime type to get the media type from.
|
|
22
|
+
* @return The media type.
|
|
23
|
+
*/
|
|
24
|
+
export function getMediaTypeFromMimeType( mimeType: string ): MediaType {
|
|
25
|
+
if ( mimeType.startsWith( 'image/' ) ) {
|
|
26
|
+
return {
|
|
27
|
+
type: 'image',
|
|
28
|
+
label: __( 'Image' ),
|
|
29
|
+
icon: image,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if ( mimeType.startsWith( 'video/' ) ) {
|
|
34
|
+
return {
|
|
35
|
+
type: 'video',
|
|
36
|
+
label: __( 'Video' ),
|
|
37
|
+
icon: video,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if ( mimeType.startsWith( 'audio/' ) ) {
|
|
42
|
+
return {
|
|
43
|
+
type: 'audio',
|
|
44
|
+
label: __( 'Audio' ),
|
|
45
|
+
icon: audio,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
type: 'application',
|
|
51
|
+
label: __( 'Application' ),
|
|
52
|
+
icon: file,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility function to extract raw content from either a string or an object
|
|
3
|
+
* containing raw and rendered properties.
|
|
4
|
+
*
|
|
5
|
+
* This handles the inconsistency in WordPress REST API responses where
|
|
6
|
+
* some fields like caption and description can be either:
|
|
7
|
+
* - A simple string
|
|
8
|
+
* - An object with { raw: string, rendered: string }
|
|
9
|
+
*
|
|
10
|
+
* @param content - The content to extract raw value from
|
|
11
|
+
* @return The raw content string, or empty string if content is falsy
|
|
12
|
+
*/
|
|
13
|
+
export function getRawContent(
|
|
14
|
+
content: string | { raw: string; rendered: string } | undefined | null
|
|
15
|
+
): string {
|
|
16
|
+
if ( ! content ) {
|
|
17
|
+
return '';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// If it's a string, return it directly
|
|
21
|
+
if ( typeof content === 'string' ) {
|
|
22
|
+
return content;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// If it's an object with raw property, return the raw value
|
|
26
|
+
if ( typeof content === 'object' && 'raw' in content ) {
|
|
27
|
+
return content.raw || '';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Fallback to empty string
|
|
31
|
+
return '';
|
|
32
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility function to extract rendered content from either a string or an object
|
|
3
|
+
* containing raw and rendered properties.
|
|
4
|
+
*
|
|
5
|
+
* This handles the inconsistency in WordPress REST API responses where
|
|
6
|
+
* some fields like caption and description can be either:
|
|
7
|
+
* - A simple string
|
|
8
|
+
* - An object with { raw: string, rendered: string }
|
|
9
|
+
*
|
|
10
|
+
* @param content - The content to extract raw value from
|
|
11
|
+
* @return The rendered content string, falling back to raw or empty string if content is falsy
|
|
12
|
+
*/
|
|
13
|
+
export function getRenderedContent(
|
|
14
|
+
content: string | { raw: string; rendered: string } | undefined | null
|
|
15
|
+
): string {
|
|
16
|
+
if ( ! content ) {
|
|
17
|
+
return '';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// If it's a string, return it directly
|
|
21
|
+
if ( typeof content === 'string' ) {
|
|
22
|
+
return content;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// If it's an object with raw property, return the raw value
|
|
26
|
+
if ( typeof content === 'object' ) {
|
|
27
|
+
return content.rendered || content.raw || '';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Fallback to empty string
|
|
31
|
+
return '';
|
|
32
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig.json",
|
|
3
|
+
"extends": "../../tsconfig.base.json",
|
|
4
|
+
"compilerOptions": {
|
|
5
|
+
"types": [
|
|
6
|
+
"gutenberg-env",
|
|
7
|
+
"gutenberg-test-env",
|
|
8
|
+
"jest",
|
|
9
|
+
"@testing-library/jest-dom"
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
"references": [
|
|
13
|
+
{ "path": "../components" },
|
|
14
|
+
{ "path": "../core-data" },
|
|
15
|
+
{ "path": "../data" },
|
|
16
|
+
{ "path": "../dataviews" },
|
|
17
|
+
{ "path": "../element" },
|
|
18
|
+
{ "path": "../i18n" },
|
|
19
|
+
{ "path": "../icons" },
|
|
20
|
+
{ "path": "../primitives" },
|
|
21
|
+
{ "path": "../url" }
|
|
22
|
+
],
|
|
23
|
+
"exclude": [
|
|
24
|
+
"src/**/*.android.js",
|
|
25
|
+
"src/**/*.ios.js",
|
|
26
|
+
"src/**/*.native.js",
|
|
27
|
+
"src/**/react-native-*",
|
|
28
|
+
"src/**/stories/**/*.js", // only exclude js files, tsx files should be checked
|
|
29
|
+
"src/**/test/**/*.js" // only exclude js files, ts{x} files should be checked
|
|
30
|
+
]
|
|
31
|
+
}
|