@wordpress/media-fields 0.13.1 → 0.14.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 CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.14.0 (2026-06-24)
6
+
5
7
  ## 0.13.1 (2026-06-16)
6
8
 
7
9
  ## 0.13.0 (2026-06-10)
@@ -60,6 +60,7 @@ function MediaAttachedToEdit({
60
60
  post: 0,
61
61
  _embedded: { ...data?._embedded, "wp:attached-to": void 0 }
62
62
  });
63
+ setValue(null);
63
64
  setOptions([]);
64
65
  };
65
66
  const onValueChange = async (filterValue) => {
@@ -74,13 +75,14 @@ function MediaAttachedToEdit({
74
75
  {}
75
76
  );
76
77
  setSearchResults(results);
77
- const mappedSuggestions = results.map((result) => {
78
+ const suggestions = results.map((result) => {
78
79
  return {
79
80
  label: result.title,
80
81
  value: result.id.toString()
81
82
  };
82
83
  });
83
- setOptions(mappedSuggestions);
84
+ const includeCurrent = !filterValue && suggestions.findIndex((s) => s.value === value) === -1;
85
+ setOptions(suggestions.concat(includeCurrent ? defaultPost : []));
84
86
  setIsLoading(false);
85
87
  };
86
88
  const handleSelectOption = (selectedPostId) => {
@@ -115,7 +117,7 @@ function MediaAttachedToEdit({
115
117
  }
116
118
  }
117
119
  };
118
- const help = !!data.post ? (0, import_element.createInterpolateElement)(
120
+ const help = (0, import_element.createInterpolateElement)(
119
121
  (0, import_i18n.__)(
120
122
  "Search for a post or page to attach this media to or <button>detach current</button>."
121
123
  ),
@@ -126,11 +128,12 @@ function MediaAttachedToEdit({
126
128
  __next40pxDefaultSize: true,
127
129
  onClick: handleDetach,
128
130
  variant: "link",
129
- accessibleWhenDisabled: true
131
+ accessibleWhenDisabled: true,
132
+ disabled: !value
130
133
  }
131
134
  )
132
135
  }
133
- ) : (0, import_i18n.__)("Search for a post or page to attach this media to.");
136
+ );
134
137
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
135
138
  import_components.ComboboxControl,
136
139
  {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/attached_to/edit.tsx"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport {\n\t__experimentalFetchLinkSuggestions as fetchLinkSuggestions,\n\tstore as coreStore,\n} from '@wordpress/core-data';\nimport { Button, ComboboxControl } from '@wordpress/components';\nimport { __ } from '@wordpress/i18n';\nimport { useState, createInterpolateElement } from '@wordpress/element';\nimport { debounce } from '@wordpress/compose';\nimport { useSelect } from '@wordpress/data';\nimport type { DataFormControlProps } from '@wordpress/dataviews';\n\n/**\n * Internal dependencies\n */\nimport type { MediaItem } from '../types';\nimport { getRenderedContent } from '../utils/get-rendered-content';\n\nexport type SearchResult = {\n\t/**\n\t * Post or term id.\n\t */\n\tid: number;\n\t/**\n\t * Link url.\n\t */\n\turl: string;\n\t/**\n\t * Title of the link.\n\t */\n\ttitle: string;\n\t/**\n\t * The taxonomy or post type slug or type URL.\n\t */\n\ttype: string;\n\t/**\n\t * Link kind of post-type or taxonomy\n\t */\n\tkind?: string;\n};\n\nexport default function MediaAttachedToEdit( {\n\tdata,\n\tonChange,\n}: DataFormControlProps< MediaItem > ) {\n\tconst defaultPost =\n\t\t!! data.post && !! data?._embedded?.[ 'wp:attached-to' ]?.[ 0 ]\n\t\t\t? [\n\t\t\t\t\t{\n\t\t\t\t\t\tlabel: getRenderedContent(\n\t\t\t\t\t\t\tdata._embedded?.[ 'wp:attached-to' ]?.[ 0 ]?.title\n\t\t\t\t\t\t),\n\t\t\t\t\t\tvalue: data.post.toString(),\n\t\t\t\t\t},\n\t\t\t ]\n\t\t\t: [];\n\tconst [ options, setOptions ] =\n\t\tuseState< { label: string; value: string }[] >( defaultPost );\n\tconst [ searchResults, setSearchResults ] = useState< SearchResult[] >(\n\t\t[]\n\t);\n\tconst [ isLoading, setIsLoading ] = useState( false );\n\tconst [ value, setValue ] = useState< string | null >(\n\t\tdata?.post?.toString() ?? null\n\t);\n\n\tconst postTypes = useSelect(\n\t\t( select ) => select( coreStore ).getPostTypes(),\n\t\t[]\n\t);\n\tconst handleDetach = () => {\n\t\tonChange( {\n\t\t\tpost: 0,\n\t\t\t_embedded: { ...data?._embedded, 'wp:attached-to': undefined },\n\t\t} );\n\t\tsetOptions( [] );\n\t};\n\n\tconst onValueChange = async ( filterValue: string ) => {\n\t\tsetIsLoading( true );\n\t\tconst results = await fetchLinkSuggestions(\n\t\t\tfilterValue,\n\t\t\t/*\n\t\t\t * @TODO `fetchLinkSuggestions()` should accept `perPage` as an option argument.\n\t\t\t * `isInitialSuggestions` limits the result to 3, otherwise it's hardcoded to 20.\n\t\t\t */\n\t\t\t{ type: 'post', isInitialSuggestions: true },\n\t\t\t{}\n\t\t);\n\t\tsetSearchResults( results );\n\t\tconst mappedSuggestions = results.map( ( result ) => {\n\t\t\treturn {\n\t\t\t\tlabel: result.title,\n\t\t\t\tvalue: result.id.toString(),\n\t\t\t};\n\t\t} );\n\t\tsetOptions( mappedSuggestions );\n\t\tsetIsLoading( false );\n\t};\n\n\t/**\n\t * Handle selection.\n\t *\n\t * @param {Object} selectedPostId The selected post id.\n\t */\n\tconst handleSelectOption = (\n\t\tselectedPostId: string | null | undefined\n\t) => {\n\t\tif ( ! selectedPostId ) {\n\t\t\thandleDetach();\n\t\t\treturn;\n\t\t}\n\t\tsetValue( selectedPostId );\n\t\tif ( selectedPostId ) {\n\t\t\tconst selectedPost = searchResults.find(\n\t\t\t\t( result ) => result.id === Number( selectedPostId )\n\t\t\t);\n\t\t\t// Although unlikely, it's technically possible for selectedPost to not be found.\n\t\t\t// E.g. if the user selects an option just as new search results are loaded.\n\t\t\t// TODO: Add error handling for when selectedPost is not found.\n\t\t\tif ( selectedPost && postTypes ) {\n\t\t\t\tconst postType = postTypes.find(\n\t\t\t\t\t( _postType: { slug: string } ) =>\n\t\t\t\t\t\t_postType.slug === selectedPost?.type\n\t\t\t\t);\n\n\t\t\t\tconst attachedTo = {\n\t\t\t\t\t...( postType && { type: postType.slug } ),\n\t\t\t\t\tid: Number( selectedPostId ),\n\t\t\t\t\ttitle: {\n\t\t\t\t\t\traw: selectedPost.title,\n\t\t\t\t\t\trendered: selectedPost.title,\n\t\t\t\t\t},\n\t\t\t\t};\n\n\t\t\t\tonChange( {\n\t\t\t\t\tpost: Number( selectedPostId ),\n\t\t\t\t\t_embedded: {\n\t\t\t\t\t\t...data?._embedded,\n\t\t\t\t\t\t'wp:attached-to': [ attachedTo ],\n\t\t\t\t\t},\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t};\n\n\tconst help = !! data.post\n\t\t? createInterpolateElement(\n\t\t\t\t__(\n\t\t\t\t\t'Search for a post or page to attach this media to or <button>detach current</button>.'\n\t\t\t\t),\n\t\t\t\t{\n\t\t\t\t\tbutton: (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t__next40pxDefaultSize\n\t\t\t\t\t\t\tonClick={ handleDetach }\n\t\t\t\t\t\t\tvariant=\"link\"\n\t\t\t\t\t\t\taccessibleWhenDisabled\n\t\t\t\t\t\t/>\n\t\t\t\t\t),\n\t\t\t\t}\n\t\t )\n\t\t: __( 'Search for a post or page to attach this media to.' );\n\n\treturn (\n\t\t<ComboboxControl\n\t\t\tclassName=\"dataviews-media-field__attached-to\"\n\t\t\t__next40pxDefaultSize\n\t\t\tisLoading={ isLoading }\n\t\t\tlabel={ __( 'Attached to' ) }\n\t\t\thelp={ help }\n\t\t\tvalue={ value }\n\t\t\toptions={ options }\n\t\t\tonFilterValueChange={ debounce(\n\t\t\t\t( filterValue: unknown ) =>\n\t\t\t\t\tonValueChange( filterValue as string ),\n\t\t\t\t300\n\t\t\t) }\n\t\t\tonChange={ handleSelectOption }\n\t\t\thideLabelFromVision\n\t\t/>\n\t);\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport {\n\t__experimentalFetchLinkSuggestions as fetchLinkSuggestions,\n\tstore as coreStore,\n} from '@wordpress/core-data';\nimport { Button, ComboboxControl } from '@wordpress/components';\nimport { __ } from '@wordpress/i18n';\nimport { useState, createInterpolateElement } from '@wordpress/element';\nimport { debounce } from '@wordpress/compose';\nimport { useSelect } from '@wordpress/data';\nimport type { DataFormControlProps } from '@wordpress/dataviews';\n\n/**\n * Internal dependencies\n */\nimport type { MediaItem } from '../types';\nimport { getRenderedContent } from '../utils/get-rendered-content';\n\nexport type SearchResult = {\n\t/**\n\t * Post or term id.\n\t */\n\tid: number;\n\t/**\n\t * Link url.\n\t */\n\turl: string;\n\t/**\n\t * Title of the link.\n\t */\n\ttitle: string;\n\t/**\n\t * The taxonomy or post type slug or type URL.\n\t */\n\ttype: string;\n\t/**\n\t * Link kind of post-type or taxonomy\n\t */\n\tkind?: string;\n};\n\nexport default function MediaAttachedToEdit( {\n\tdata,\n\tonChange,\n}: DataFormControlProps< MediaItem > ) {\n\tconst defaultPost =\n\t\t!! data.post && !! data?._embedded?.[ 'wp:attached-to' ]?.[ 0 ]\n\t\t\t? [\n\t\t\t\t\t{\n\t\t\t\t\t\tlabel: getRenderedContent(\n\t\t\t\t\t\t\tdata._embedded?.[ 'wp:attached-to' ]?.[ 0 ]?.title\n\t\t\t\t\t\t),\n\t\t\t\t\t\tvalue: data.post.toString(),\n\t\t\t\t\t},\n\t\t\t ]\n\t\t\t: [];\n\tconst [ options, setOptions ] =\n\t\tuseState< { label: string; value: string }[] >( defaultPost );\n\tconst [ searchResults, setSearchResults ] = useState< SearchResult[] >(\n\t\t[]\n\t);\n\tconst [ isLoading, setIsLoading ] = useState( false );\n\tconst [ value, setValue ] = useState< string | null >(\n\t\tdata?.post?.toString() ?? null\n\t);\n\n\tconst postTypes = useSelect(\n\t\t( select ) => select( coreStore ).getPostTypes(),\n\t\t[]\n\t);\n\tconst handleDetach = () => {\n\t\tonChange( {\n\t\t\tpost: 0,\n\t\t\t_embedded: { ...data?._embedded, 'wp:attached-to': undefined },\n\t\t} );\n\t\tsetValue( null );\n\t\tsetOptions( [] );\n\t};\n\n\tconst onValueChange = async ( filterValue: string ) => {\n\t\tsetIsLoading( true );\n\t\tconst results = await fetchLinkSuggestions(\n\t\t\tfilterValue,\n\t\t\t/*\n\t\t\t * @TODO `fetchLinkSuggestions()` should accept `perPage` as an option argument.\n\t\t\t * `isInitialSuggestions` limits the result to 3, otherwise it's hardcoded to 20.\n\t\t\t */\n\t\t\t{ type: 'post', isInitialSuggestions: true },\n\t\t\t{}\n\t\t);\n\t\tsetSearchResults( results );\n\t\tconst suggestions = results.map( ( result ) => {\n\t\t\treturn {\n\t\t\t\tlabel: result.title,\n\t\t\t\tvalue: result.id.toString(),\n\t\t\t};\n\t\t} );\n\t\tconst includeCurrent =\n\t\t\t! filterValue &&\n\t\t\tsuggestions.findIndex( ( s ) => s.value === value ) === -1;\n\t\tsetOptions( suggestions.concat( includeCurrent ? defaultPost : [] ) );\n\t\tsetIsLoading( false );\n\t};\n\n\t/**\n\t * Handle selection.\n\t *\n\t * @param {Object} selectedPostId The selected post id.\n\t */\n\tconst handleSelectOption = (\n\t\tselectedPostId: string | null | undefined\n\t) => {\n\t\tif ( ! selectedPostId ) {\n\t\t\thandleDetach();\n\t\t\treturn;\n\t\t}\n\t\tsetValue( selectedPostId );\n\t\tif ( selectedPostId ) {\n\t\t\tconst selectedPost = searchResults.find(\n\t\t\t\t( result ) => result.id === Number( selectedPostId )\n\t\t\t);\n\t\t\t// Although unlikely, it's technically possible for selectedPost to not be found.\n\t\t\t// E.g. if the user selects an option just as new search results are loaded.\n\t\t\t// TODO: Add error handling for when selectedPost is not found.\n\t\t\tif ( selectedPost && postTypes ) {\n\t\t\t\tconst postType = postTypes.find(\n\t\t\t\t\t( _postType: { slug: string } ) =>\n\t\t\t\t\t\t_postType.slug === selectedPost?.type\n\t\t\t\t);\n\n\t\t\t\tconst attachedTo = {\n\t\t\t\t\t...( postType && { type: postType.slug } ),\n\t\t\t\t\tid: Number( selectedPostId ),\n\t\t\t\t\ttitle: {\n\t\t\t\t\t\traw: selectedPost.title,\n\t\t\t\t\t\trendered: selectedPost.title,\n\t\t\t\t\t},\n\t\t\t\t};\n\n\t\t\t\tonChange( {\n\t\t\t\t\tpost: Number( selectedPostId ),\n\t\t\t\t\t_embedded: {\n\t\t\t\t\t\t...data?._embedded,\n\t\t\t\t\t\t'wp:attached-to': [ attachedTo ],\n\t\t\t\t\t},\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t};\n\n\tconst help = createInterpolateElement(\n\t\t__(\n\t\t\t'Search for a post or page to attach this media to or <button>detach current</button>.'\n\t\t),\n\t\t{\n\t\t\tbutton: (\n\t\t\t\t<Button\n\t\t\t\t\t__next40pxDefaultSize\n\t\t\t\t\tonClick={ handleDetach }\n\t\t\t\t\tvariant=\"link\"\n\t\t\t\t\taccessibleWhenDisabled\n\t\t\t\t\tdisabled={ ! value }\n\t\t\t\t/>\n\t\t\t),\n\t\t}\n\t);\n\n\treturn (\n\t\t<ComboboxControl\n\t\t\tclassName=\"dataviews-media-field__attached-to\"\n\t\t\t__next40pxDefaultSize\n\t\t\tisLoading={ isLoading }\n\t\t\tlabel={ __( 'Attached to' ) }\n\t\t\thelp={ help }\n\t\t\tvalue={ value }\n\t\t\toptions={ options }\n\t\t\tonFilterValueChange={ debounce(\n\t\t\t\t( filterValue: unknown ) =>\n\t\t\t\t\tonValueChange( filterValue as string ),\n\t\t\t\t300\n\t\t\t) }\n\t\t\tonChange={ handleSelectOption }\n\t\t\thideLabelFromVision\n\t\t/>\n\t);\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["coreStore", "fetchLinkSuggestions"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/filename/view.tsx"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useMemo } from '@wordpress/element';\nimport { getFilename } from '@wordpress/url';\nimport type { DataViewRenderFieldProps } from '@wordpress/dataviews';\n// eslint-disable-next-line @wordpress/use-recommended-components -- `Tooltip` is not yet on the recommended `@wordpress/ui` allow-list; landing as a migration step ahead of the wider rollout.\nimport { Tooltip } from '@wordpress/ui';\n\n/**\n * Internal dependencies\n */\nimport type { MediaItem } from '../types';\n\n// Proxy threshold for \"long enough that the cell will visually truncate\" \u2014\n// used to decide whether to wrap the filename in a Tooltip showing the full\n// name on hover. Visual truncation itself is handled in CSS.\nconst TRUNCATE_LENGTH = 15;\n\nexport default function FileNameView( {\n\titem,\n}: DataViewRenderFieldProps< MediaItem > ) {\n\tconst fileName = useMemo(\n\t\t() => ( item?.source_url ? getFilename( item.source_url ) : null ),\n\t\t[ item?.source_url ]\n\t);\n\n\tif ( ! fileName ) {\n\t\treturn '';\n\t}\n\n\tif ( fileName.length <= TRUNCATE_LENGTH ) {\n\t\treturn (\n\t\t\t<span className=\"dataviews-media-field__filename\">\n\t\t\t\t{ fileName }\n\t\t\t</span>\n\t\t);\n\t}\n\n\t// The full filename is always in the DOM, so assistive tech gets it\n\t// regardless. The Tooltip aids mouse users where the cell visually clips\n\t// (DataViews layouts); in a non-truncating context like the DataForm the\n\t// name wraps in full, making it redundant but harmless.\n\treturn (\n\t\t<Tooltip.Root>\n\t\t\t<Tooltip.Trigger\n\t\t\t\trender={\n\t\t\t\t\t<span className=\"dataviews-media-field__filename\">\n\t\t\t\t\t\t{ fileName }\n\t\t\t\t\t</span>\n\t\t\t\t}\n\t\t\t/>\n\t\t\t<Tooltip.Popup>{ fileName }</Tooltip.Popup>\n\t\t</Tooltip.Root>\n\t);\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,qBAAwB;AACxB,iBAA4B;AAG5B,gBAAwB;AA0BrB;AAhBH,IAAM,kBAAkB;AAET,SAAR,aAA+B;AAAA,EACrC;AACD,GAA2C;AAC1C,QAAM,eAAW;AAAA,IAChB,MAAQ,MAAM,iBAAa,wBAAa,KAAK,UAAW,IAAI;AAAA,IAC5D,CAAE,MAAM,UAAW;AAAA,EACpB;AAEA,MAAK,CAAE,UAAW;AACjB,WAAO;AAAA,EACR;AAEA,MAAK,SAAS,UAAU,iBAAkB;AACzC,WACC,4CAAC,UAAK,WAAU,mCACb,oBACH;AAAA,EAEF;AAMA,SACC,6CAAC,kBAAQ,MAAR,EACA;AAAA;AAAA,MAAC,kBAAQ;AAAA,MAAR;AAAA,QACA,QACC,4CAAC,UAAK,WAAU,mCACb,oBACH;AAAA;AAAA,IAEF;AAAA,IACA,4CAAC,kBAAQ,OAAR,EAAgB,oBAAU;AAAA,KAC5B;AAEF;",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useMemo } from '@wordpress/element';\nimport { getFilename } from '@wordpress/url';\nimport type { DataViewRenderFieldProps } from '@wordpress/dataviews';\nimport { Tooltip } from '@wordpress/ui';\n\n/**\n * Internal dependencies\n */\nimport type { MediaItem } from '../types';\n\n// Proxy threshold for \"long enough that the cell will visually truncate\" —\n// used to decide whether to wrap the filename in a Tooltip showing the full\n// name on hover. Visual truncation itself is handled in CSS.\nconst TRUNCATE_LENGTH = 15;\n\nexport default function FileNameView( {\n\titem,\n}: DataViewRenderFieldProps< MediaItem > ) {\n\tconst fileName = useMemo(\n\t\t() => ( item?.source_url ? getFilename( item.source_url ) : null ),\n\t\t[ item?.source_url ]\n\t);\n\n\tif ( ! fileName ) {\n\t\treturn '';\n\t}\n\n\tif ( fileName.length <= TRUNCATE_LENGTH ) {\n\t\treturn (\n\t\t\t<span className=\"dataviews-media-field__filename\">\n\t\t\t\t{ fileName }\n\t\t\t</span>\n\t\t);\n\t}\n\n\t// The full filename is always in the DOM, so assistive tech gets it\n\t// regardless. The Tooltip aids mouse users where the cell visually clips\n\t// (DataViews layouts); in a non-truncating context like the DataForm the\n\t// name wraps in full, making it redundant but harmless.\n\treturn (\n\t\t<Tooltip.Root>\n\t\t\t<Tooltip.Trigger\n\t\t\t\trender={\n\t\t\t\t\t<span className=\"dataviews-media-field__filename\">\n\t\t\t\t\t\t{ fileName }\n\t\t\t\t\t</span>\n\t\t\t\t}\n\t\t\t/>\n\t\t\t<Tooltip.Popup>{ fileName }</Tooltip.Popup>\n\t\t</Tooltip.Root>\n\t);\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,qBAAwB;AACxB,iBAA4B;AAE5B,gBAAwB;AA0BrB;AAhBH,IAAM,kBAAkB;AAET,SAAR,aAA+B;AAAA,EACrC;AACD,GAA2C;AAC1C,QAAM,eAAW;AAAA,IAChB,MAAQ,MAAM,iBAAa,wBAAa,KAAK,UAAW,IAAI;AAAA,IAC5D,CAAE,MAAM,UAAW;AAAA,EACpB;AAEA,MAAK,CAAE,UAAW;AACjB,WAAO;AAAA,EACR;AAEA,MAAK,SAAS,UAAU,iBAAkB;AACzC,WACC,4CAAC,UAAK,WAAU,mCACb,oBACH;AAAA,EAEF;AAMA,SACC,6CAAC,kBAAQ,MAAR,EACA;AAAA;AAAA,MAAC,kBAAQ;AAAA,MAAR;AAAA,QACA,QACC,4CAAC,UAAK,WAAU,mCACb,oBACH;AAAA;AAAA,IAEF;AAAA,IACA,4CAAC,kBAAQ,OAAR,EAAgB,oBAAU;AAAA,KAC5B;AAEF;",
6
6
  "names": []
7
7
  }
@@ -30,7 +30,7 @@ var mediaDimensionsField = {
30
30
  label: (0, import_i18n.__)("Dimensions"),
31
31
  getValue: ({ item }) => item?.media_details?.width && item?.media_details?.height ? (0, import_i18n.sprintf)(
32
32
  // translators: 1: Width. 2: Height.
33
- (0, import_i18n._x)("%1$s \xD7 %2$s", "image dimensions"),
33
+ (0, import_i18n._x)("%1$s × %2$s", "image dimensions"),
34
34
  item?.media_details?.width?.toString(),
35
35
  item?.media_details?.height?.toString()
36
36
  ) : "",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/media_dimensions/index.ts"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { __, _x, sprintf } from '@wordpress/i18n';\nimport type { Attachment, Updatable } from '@wordpress/core-data';\nimport type { Field } from '@wordpress/dataviews';\n\nconst mediaDimensionsField: Partial< Field< Updatable< Attachment > > > = {\n\tid: 'media_dimensions',\n\ttype: 'text',\n\tlabel: __( 'Dimensions' ),\n\tgetValue: ( { item } ) =>\n\t\titem?.media_details?.width && item?.media_details?.height\n\t\t\t? sprintf(\n\t\t\t\t\t// translators: 1: Width. 2: Height.\n\t\t\t\t\t_x( '%1$s \u00D7 %2$s', 'image dimensions' ),\n\t\t\t\t\titem?.media_details?.width?.toString(),\n\t\t\t\t\titem?.media_details?.height?.toString()\n\t\t\t )\n\t\t\t: '',\n\tisVisible: ( item ) => {\n\t\treturn !! ( item?.media_details?.width && item?.media_details?.height );\n\t},\n\tenableSorting: false,\n\tfilterBy: false,\n\treadOnly: true,\n};\n\nexport default mediaDimensionsField;\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,kBAAgC;AAIhC,IAAM,uBAAoE;AAAA,EACzE,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,WAAO,gBAAI,YAAa;AAAA,EACxB,UAAU,CAAE,EAAE,KAAK,MAClB,MAAM,eAAe,SAAS,MAAM,eAAe,aAChD;AAAA;AAAA,QAEA,gBAAI,kBAAe,kBAAmB;AAAA,IACtC,MAAM,eAAe,OAAO,SAAS;AAAA,IACrC,MAAM,eAAe,QAAQ,SAAS;AAAA,EACtC,IACA;AAAA,EACJ,WAAW,CAAE,SAAU;AACtB,WAAO,CAAC,EAAI,MAAM,eAAe,SAAS,MAAM,eAAe;AAAA,EAChE;AAAA,EACA,eAAe;AAAA,EACf,UAAU;AAAA,EACV,UAAU;AACX;AAEA,IAAO,2BAAQ;",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { __, _x, sprintf } from '@wordpress/i18n';\nimport type { Attachment, Updatable } from '@wordpress/core-data';\nimport type { Field } from '@wordpress/dataviews';\n\nconst mediaDimensionsField: Partial< Field< Updatable< Attachment > > > = {\n\tid: 'media_dimensions',\n\ttype: 'text',\n\tlabel: __( 'Dimensions' ),\n\tgetValue: ( { item } ) =>\n\t\titem?.media_details?.width && item?.media_details?.height\n\t\t\t? sprintf(\n\t\t\t\t\t// translators: 1: Width. 2: Height.\n\t\t\t\t\t_x( '%1$s × %2$s', 'image dimensions' ),\n\t\t\t\t\titem?.media_details?.width?.toString(),\n\t\t\t\t\titem?.media_details?.height?.toString()\n\t\t\t )\n\t\t\t: '',\n\tisVisible: ( item ) => {\n\t\treturn !! ( item?.media_details?.width && item?.media_details?.height );\n\t},\n\tenableSorting: false,\n\tfilterBy: false,\n\treadOnly: true,\n};\n\nexport default mediaDimensionsField;\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,kBAAgC;AAIhC,IAAM,uBAAoE;AAAA,EACzE,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,WAAO,gBAAI,YAAa;AAAA,EACxB,UAAU,CAAE,EAAE,KAAK,MAClB,MAAM,eAAe,SAAS,MAAM,eAAe,aAChD;AAAA;AAAA,QAEA,gBAAI,eAAe,kBAAmB;AAAA,IACtC,MAAM,eAAe,OAAO,SAAS;AAAA,IACrC,MAAM,eAAe,QAAQ,SAAS;AAAA,EACtC,IACA;AAAA,EACJ,WAAW,CAAE,SAAU;AACtB,WAAO,CAAC,EAAI,MAAM,eAAe,SAAS,MAAM,eAAe;AAAA,EAChE;AAAA,EACA,eAAe;AAAA,EACf,UAAU;AAAA,EACV,UAAU;AACX;AAEA,IAAO,2BAAQ;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/media_thumbnail/view.tsx"],
4
- "sourcesContent": ["/**\n * External dependencies\n */\nimport clsx from 'clsx';\n\n/**\n * WordPress dependencies\n */\nimport { useSelect } from '@wordpress/data';\nimport { store as coreStore } from '@wordpress/core-data';\nimport {\n\t__experimentalTruncate as Truncate,\n\t__experimentalVStack as VStack,\n\tIcon as WCIcon,\n} from '@wordpress/components';\nimport { useState, useRef, useLayoutEffect } from '@wordpress/element';\nimport type { Attachment } from '@wordpress/core-data';\nimport { getFilename } from '@wordpress/url';\nimport type { DataViewRenderFieldProps } from '@wordpress/dataviews';\n/**\n * Internal dependencies\n */\nimport { getMediaTypeFromMimeType } from '../utils/get-media-type-from-mime-type';\nimport type { MediaItem } from '../types';\n\n/**\n * Given the available image sizes and a target display width, returns the URL\n * of the smallest size whose width is >= the target. Falls back to the largest\n * available size, or the original source_url.\n *\n * @param featuredMedia The media item with size details.\n * @param configSizes The target display size string (e.g. '900px').\n */\nexport function getBestImageUrl(\n\tfeaturedMedia: Attachment | MediaItem,\n\tconfigSizes?: string\n): string {\n\tconst sizes = featuredMedia?.media_details?.sizes;\n\tif ( ! sizes ) {\n\t\treturn featuredMedia.source_url;\n\t}\n\n\tconst sizeEntries = Object.values( sizes );\n\n\tif ( ! sizeEntries.length ) {\n\t\treturn featuredMedia.source_url;\n\t}\n\n\t// Parse target width from config.sizes (e.g. '900px' \u2192 900).\n\tconst targetWidth = configSizes ? parseInt( configSizes, 10 ) : NaN;\n\n\tif ( ! Number.isNaN( targetWidth ) ) {\n\t\t// Filter to entries that have a valid numeric width.\n\t\tconst validEntries = sizeEntries.filter(\n\t\t\t( s ) => typeof s.width === 'number' && ! Number.isNaN( s.width )\n\t\t);\n\n\t\tif ( ! validEntries.length ) {\n\t\t\treturn featuredMedia.source_url;\n\t\t}\n\n\t\t// Sort ascending by width.\n\t\tconst sorted = [ ...validEntries ].sort(\n\t\t\t( a, b ) => a.width - b.width\n\t\t);\n\t\t// Pick the smallest size that is >= target width.\n\t\tconst match = sorted.find( ( s ) => s.width >= targetWidth );\n\t\tif ( match ) {\n\t\t\treturn match.source_url;\n\t\t}\n\t\t// No size large enough \u2014 use the largest available.\n\t\treturn sorted[ sorted.length - 1 ].source_url;\n\t}\n\n\t// If we can't parse the target, fall back to source_url.\n\treturn featuredMedia.source_url;\n}\n\nfunction FallbackView( {\n\titem,\n\tfilename,\n}: {\n\titem: MediaItem;\n\tfilename: string;\n} ) {\n\treturn (\n\t\t<div className=\"dataviews-media-field__media-thumbnail\">\n\t\t\t<VStack\n\t\t\t\tjustify=\"center\"\n\t\t\t\talignment=\"center\"\n\t\t\t\tclassName=\"dataviews-media-field__media-thumbnail__stack\"\n\t\t\t\tspacing={ 0 }\n\t\t\t>\n\t\t\t\t<WCIcon\n\t\t\t\t\tclassName=\"dataviews-media-field__media-thumbnail--icon\"\n\t\t\t\t\ticon={ getMediaTypeFromMimeType( item.mime_type ).icon }\n\t\t\t\t\tsize={ 24 }\n\t\t\t\t/>\n\t\t\t\t{ !! filename && (\n\t\t\t\t\t<div className=\"dataviews-media-field__media-thumbnail__filename\">\n\t\t\t\t\t\t<Truncate className=\"dataviews-media-field__media-thumbnail__filename__truncate\">\n\t\t\t\t\t\t\t{ filename }\n\t\t\t\t\t\t</Truncate>\n\t\t\t\t\t</div>\n\t\t\t\t) }\n\t\t\t</VStack>\n\t\t</div>\n\t);\n}\n\nfunction ImageView( {\n\titem,\n\tconfigSizes,\n\tonError,\n}: {\n\titem: Attachment | MediaItem;\n\tconfigSizes?: string;\n\tonError: () => void;\n} ) {\n\tconst imageUrl = getBestImageUrl( item, configSizes );\n\n\t/*\n\t * Use three states to avoid fade-in animation for cached images:\n\t * 'instant' = image already cached, 'loading' = waiting, 'loaded' = just finished.\n\t *\n\t * useLayoutEffect runs synchronously after DOM mutations but before paint,\n\t * so we can check img.complete to detect disk-cached images and skip the\n\t * fade-in animation entirely.\n\t */\n\tconst imgRef = useRef< HTMLImageElement >( null );\n\tconst [ loadingState, setLoadingState ] = useState<\n\t\t'instant' | 'loading' | 'loaded'\n\t>( 'loading' );\n\n\tuseLayoutEffect( () => {\n\t\tif ( imgRef.current?.complete ) {\n\t\t\tsetLoadingState( 'instant' );\n\t\t} else {\n\t\t\tsetLoadingState( 'loading' );\n\t\t}\n\t}, [ imageUrl ] );\n\n\tconst handleLoad = () => {\n\t\tif ( loadingState === 'loading' ) {\n\t\t\tsetLoadingState( 'loaded' );\n\t\t}\n\t};\n\n\treturn (\n\t\t<div\n\t\t\tclassName={ clsx( 'dataviews-media-field__media-thumbnail', {\n\t\t\t\t'is-loading': loadingState === 'loading',\n\t\t\t\t'is-loaded': loadingState === 'loaded',\n\t\t\t} ) }\n\t\t>\n\t\t\t<img\n\t\t\t\tref={ imgRef }\n\t\t\t\tclassName=\"dataviews-media-field__media-thumbnail--image\"\n\t\t\t\tsrc={ imageUrl }\n\t\t\t\talt={ item.alt_text || item.title.raw }\n\t\t\t\tonLoad={ handleLoad }\n\t\t\t\tonError={ onError }\n\t\t\t\tloading=\"lazy\"\n\t\t\t/>\n\t\t</div>\n\t);\n}\n\nexport default function MediaThumbnailView( {\n\titem,\n\tconfig,\n}: DataViewRenderFieldProps< MediaItem > ) {\n\tconst [ imageError, setImageError ] = useState( false );\n\n\tconst _featuredMedia = useSelect(\n\t\t( select ) => {\n\t\t\t// Avoid the network request if it's not needed. `featured_media` is\n\t\t\t// 0 for images and media without featured media.\n\t\t\tif ( ! item.featured_media ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\treturn select( coreStore ).getEntityRecord< Attachment >(\n\t\t\t\t'postType',\n\t\t\t\t'attachment',\n\t\t\t\titem.featured_media\n\t\t\t);\n\t\t},\n\t\t[ item.featured_media ]\n\t);\n\tconst featuredMedia = item.featured_media ? _featuredMedia : item;\n\n\t// Fetching.\n\tif ( ! featuredMedia ) {\n\t\treturn null;\n\t}\n\n\tconst filename = getFilename( featuredMedia.source_url || '' );\n\n\t// Show fallback if image failed to load or if not an image type.\n\tif (\n\t\timageError ||\n\t\tgetMediaTypeFromMimeType( featuredMedia.mime_type ).type !== 'image'\n\t) {\n\t\treturn (\n\t\t\t<FallbackView item={ featuredMedia } filename={ filename || '' } />\n\t\t);\n\t}\n\n\treturn (\n\t\t<ImageView\n\t\t\titem={ featuredMedia }\n\t\t\tconfigSizes={ config?.sizes }\n\t\t\tonError={ () => setImageError( true ) }\n\t\t/>\n\t);\n}\n"],
4
+ "sourcesContent": ["/**\n * External dependencies\n */\nimport clsx from 'clsx';\n\n/**\n * WordPress dependencies\n */\nimport { useSelect } from '@wordpress/data';\nimport { store as coreStore } from '@wordpress/core-data';\nimport {\n\t__experimentalTruncate as Truncate,\n\t__experimentalVStack as VStack,\n\tIcon as WCIcon,\n} from '@wordpress/components';\nimport { useState, useRef, useLayoutEffect } from '@wordpress/element';\nimport type { Attachment } from '@wordpress/core-data';\nimport { getFilename } from '@wordpress/url';\nimport type { DataViewRenderFieldProps } from '@wordpress/dataviews';\n/**\n * Internal dependencies\n */\nimport { getMediaTypeFromMimeType } from '../utils/get-media-type-from-mime-type';\nimport type { MediaItem } from '../types';\n\n/**\n * Given the available image sizes and a target display width, returns the URL\n * of the smallest size whose width is >= the target. Falls back to the largest\n * available size, or the original source_url.\n *\n * @param featuredMedia The media item with size details.\n * @param configSizes The target display size string (e.g. '900px').\n */\nexport function getBestImageUrl(\n\tfeaturedMedia: Attachment | MediaItem,\n\tconfigSizes?: string\n): string {\n\tconst sizes = featuredMedia?.media_details?.sizes;\n\tif ( ! sizes ) {\n\t\treturn featuredMedia.source_url;\n\t}\n\n\tconst sizeEntries = Object.values( sizes );\n\n\tif ( ! sizeEntries.length ) {\n\t\treturn featuredMedia.source_url;\n\t}\n\n\t// Parse target width from config.sizes (e.g. '900px' 900).\n\tconst targetWidth = configSizes ? parseInt( configSizes, 10 ) : NaN;\n\n\tif ( ! Number.isNaN( targetWidth ) ) {\n\t\t// Filter to entries that have a valid numeric width.\n\t\tconst validEntries = sizeEntries.filter(\n\t\t\t( s ) => typeof s.width === 'number' && ! Number.isNaN( s.width )\n\t\t);\n\n\t\tif ( ! validEntries.length ) {\n\t\t\treturn featuredMedia.source_url;\n\t\t}\n\n\t\t// Sort ascending by width.\n\t\tconst sorted = [ ...validEntries ].sort(\n\t\t\t( a, b ) => a.width - b.width\n\t\t);\n\t\t// Pick the smallest size that is >= target width.\n\t\tconst match = sorted.find( ( s ) => s.width >= targetWidth );\n\t\tif ( match ) {\n\t\t\treturn match.source_url;\n\t\t}\n\t\t// No size large enough use the largest available.\n\t\treturn sorted[ sorted.length - 1 ].source_url;\n\t}\n\n\t// If we can't parse the target, fall back to source_url.\n\treturn featuredMedia.source_url;\n}\n\nfunction FallbackView( {\n\titem,\n\tfilename,\n}: {\n\titem: MediaItem;\n\tfilename: string;\n} ) {\n\treturn (\n\t\t<div className=\"dataviews-media-field__media-thumbnail\">\n\t\t\t<VStack\n\t\t\t\tjustify=\"center\"\n\t\t\t\talignment=\"center\"\n\t\t\t\tclassName=\"dataviews-media-field__media-thumbnail__stack\"\n\t\t\t\tspacing={ 0 }\n\t\t\t>\n\t\t\t\t<WCIcon\n\t\t\t\t\tclassName=\"dataviews-media-field__media-thumbnail--icon\"\n\t\t\t\t\ticon={ getMediaTypeFromMimeType( item.mime_type ).icon }\n\t\t\t\t\tsize={ 24 }\n\t\t\t\t/>\n\t\t\t\t{ !! filename && (\n\t\t\t\t\t<div className=\"dataviews-media-field__media-thumbnail__filename\">\n\t\t\t\t\t\t<Truncate className=\"dataviews-media-field__media-thumbnail__filename__truncate\">\n\t\t\t\t\t\t\t{ filename }\n\t\t\t\t\t\t</Truncate>\n\t\t\t\t\t</div>\n\t\t\t\t) }\n\t\t\t</VStack>\n\t\t</div>\n\t);\n}\n\nfunction ImageView( {\n\titem,\n\tconfigSizes,\n\tonError,\n}: {\n\titem: Attachment | MediaItem;\n\tconfigSizes?: string;\n\tonError: () => void;\n} ) {\n\tconst imageUrl = getBestImageUrl( item, configSizes );\n\n\t/*\n\t * Use three states to avoid fade-in animation for cached images:\n\t * 'instant' = image already cached, 'loading' = waiting, 'loaded' = just finished.\n\t *\n\t * useLayoutEffect runs synchronously after DOM mutations but before paint,\n\t * so we can check img.complete to detect disk-cached images and skip the\n\t * fade-in animation entirely.\n\t */\n\tconst imgRef = useRef< HTMLImageElement >( null );\n\tconst [ loadingState, setLoadingState ] = useState<\n\t\t'instant' | 'loading' | 'loaded'\n\t>( 'loading' );\n\n\tuseLayoutEffect( () => {\n\t\tif ( imgRef.current?.complete ) {\n\t\t\tsetLoadingState( 'instant' );\n\t\t} else {\n\t\t\tsetLoadingState( 'loading' );\n\t\t}\n\t}, [ imageUrl ] );\n\n\tconst handleLoad = () => {\n\t\tif ( loadingState === 'loading' ) {\n\t\t\tsetLoadingState( 'loaded' );\n\t\t}\n\t};\n\n\treturn (\n\t\t<div\n\t\t\tclassName={ clsx( 'dataviews-media-field__media-thumbnail', {\n\t\t\t\t'is-loading': loadingState === 'loading',\n\t\t\t\t'is-loaded': loadingState === 'loaded',\n\t\t\t} ) }\n\t\t>\n\t\t\t<img\n\t\t\t\tref={ imgRef }\n\t\t\t\tclassName=\"dataviews-media-field__media-thumbnail--image\"\n\t\t\t\tsrc={ imageUrl }\n\t\t\t\talt={ item.alt_text || item.title.raw }\n\t\t\t\tonLoad={ handleLoad }\n\t\t\t\tonError={ onError }\n\t\t\t\tloading=\"lazy\"\n\t\t\t/>\n\t\t</div>\n\t);\n}\n\nexport default function MediaThumbnailView( {\n\titem,\n\tconfig,\n}: DataViewRenderFieldProps< MediaItem > ) {\n\tconst [ imageError, setImageError ] = useState( false );\n\n\tconst _featuredMedia = useSelect(\n\t\t( select ) => {\n\t\t\t// Avoid the network request if it's not needed. `featured_media` is\n\t\t\t// 0 for images and media without featured media.\n\t\t\tif ( ! item.featured_media ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\treturn select( coreStore ).getEntityRecord< Attachment >(\n\t\t\t\t'postType',\n\t\t\t\t'attachment',\n\t\t\t\titem.featured_media\n\t\t\t);\n\t\t},\n\t\t[ item.featured_media ]\n\t);\n\tconst featuredMedia = item.featured_media ? _featuredMedia : item;\n\n\t// Fetching.\n\tif ( ! featuredMedia ) {\n\t\treturn null;\n\t}\n\n\tconst filename = getFilename( featuredMedia.source_url || '' );\n\n\t// Show fallback if image failed to load or if not an image type.\n\tif (\n\t\timageError ||\n\t\tgetMediaTypeFromMimeType( featuredMedia.mime_type ).type !== 'image'\n\t) {\n\t\treturn (\n\t\t\t<FallbackView item={ featuredMedia } filename={ filename || '' } />\n\t\t);\n\t}\n\n\treturn (\n\t\t<ImageView\n\t\t\titem={ featuredMedia }\n\t\t\tconfigSizes={ config?.sizes }\n\t\t\tonError={ () => setImageError( true ) }\n\t\t/>\n\t);\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": ["VStack", "WCIcon", "Truncate", "clsx", "coreStore"]
7
7
  }
@@ -39,6 +39,7 @@ function MediaAttachedToEdit({
39
39
  post: 0,
40
40
  _embedded: { ...data?._embedded, "wp:attached-to": void 0 }
41
41
  });
42
+ setValue(null);
42
43
  setOptions([]);
43
44
  };
44
45
  const onValueChange = async (filterValue) => {
@@ -53,13 +54,14 @@ function MediaAttachedToEdit({
53
54
  {}
54
55
  );
55
56
  setSearchResults(results);
56
- const mappedSuggestions = results.map((result) => {
57
+ const suggestions = results.map((result) => {
57
58
  return {
58
59
  label: result.title,
59
60
  value: result.id.toString()
60
61
  };
61
62
  });
62
- setOptions(mappedSuggestions);
63
+ const includeCurrent = !filterValue && suggestions.findIndex((s) => s.value === value) === -1;
64
+ setOptions(suggestions.concat(includeCurrent ? defaultPost : []));
63
65
  setIsLoading(false);
64
66
  };
65
67
  const handleSelectOption = (selectedPostId) => {
@@ -94,7 +96,7 @@ function MediaAttachedToEdit({
94
96
  }
95
97
  }
96
98
  };
97
- const help = !!data.post ? createInterpolateElement(
99
+ const help = createInterpolateElement(
98
100
  __(
99
101
  "Search for a post or page to attach this media to or <button>detach current</button>."
100
102
  ),
@@ -105,11 +107,12 @@ function MediaAttachedToEdit({
105
107
  __next40pxDefaultSize: true,
106
108
  onClick: handleDetach,
107
109
  variant: "link",
108
- accessibleWhenDisabled: true
110
+ accessibleWhenDisabled: true,
111
+ disabled: !value
109
112
  }
110
113
  )
111
114
  }
112
- ) : __("Search for a post or page to attach this media to.");
115
+ );
113
116
  return /* @__PURE__ */ jsx(
114
117
  ComboboxControl,
115
118
  {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/attached_to/edit.tsx"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport {\n\t__experimentalFetchLinkSuggestions as fetchLinkSuggestions,\n\tstore as coreStore,\n} from '@wordpress/core-data';\nimport { Button, ComboboxControl } from '@wordpress/components';\nimport { __ } from '@wordpress/i18n';\nimport { useState, createInterpolateElement } from '@wordpress/element';\nimport { debounce } from '@wordpress/compose';\nimport { useSelect } from '@wordpress/data';\nimport type { DataFormControlProps } from '@wordpress/dataviews';\n\n/**\n * Internal dependencies\n */\nimport type { MediaItem } from '../types';\nimport { getRenderedContent } from '../utils/get-rendered-content';\n\nexport type SearchResult = {\n\t/**\n\t * Post or term id.\n\t */\n\tid: number;\n\t/**\n\t * Link url.\n\t */\n\turl: string;\n\t/**\n\t * Title of the link.\n\t */\n\ttitle: string;\n\t/**\n\t * The taxonomy or post type slug or type URL.\n\t */\n\ttype: string;\n\t/**\n\t * Link kind of post-type or taxonomy\n\t */\n\tkind?: string;\n};\n\nexport default function MediaAttachedToEdit( {\n\tdata,\n\tonChange,\n}: DataFormControlProps< MediaItem > ) {\n\tconst defaultPost =\n\t\t!! data.post && !! data?._embedded?.[ 'wp:attached-to' ]?.[ 0 ]\n\t\t\t? [\n\t\t\t\t\t{\n\t\t\t\t\t\tlabel: getRenderedContent(\n\t\t\t\t\t\t\tdata._embedded?.[ 'wp:attached-to' ]?.[ 0 ]?.title\n\t\t\t\t\t\t),\n\t\t\t\t\t\tvalue: data.post.toString(),\n\t\t\t\t\t},\n\t\t\t ]\n\t\t\t: [];\n\tconst [ options, setOptions ] =\n\t\tuseState< { label: string; value: string }[] >( defaultPost );\n\tconst [ searchResults, setSearchResults ] = useState< SearchResult[] >(\n\t\t[]\n\t);\n\tconst [ isLoading, setIsLoading ] = useState( false );\n\tconst [ value, setValue ] = useState< string | null >(\n\t\tdata?.post?.toString() ?? null\n\t);\n\n\tconst postTypes = useSelect(\n\t\t( select ) => select( coreStore ).getPostTypes(),\n\t\t[]\n\t);\n\tconst handleDetach = () => {\n\t\tonChange( {\n\t\t\tpost: 0,\n\t\t\t_embedded: { ...data?._embedded, 'wp:attached-to': undefined },\n\t\t} );\n\t\tsetOptions( [] );\n\t};\n\n\tconst onValueChange = async ( filterValue: string ) => {\n\t\tsetIsLoading( true );\n\t\tconst results = await fetchLinkSuggestions(\n\t\t\tfilterValue,\n\t\t\t/*\n\t\t\t * @TODO `fetchLinkSuggestions()` should accept `perPage` as an option argument.\n\t\t\t * `isInitialSuggestions` limits the result to 3, otherwise it's hardcoded to 20.\n\t\t\t */\n\t\t\t{ type: 'post', isInitialSuggestions: true },\n\t\t\t{}\n\t\t);\n\t\tsetSearchResults( results );\n\t\tconst mappedSuggestions = results.map( ( result ) => {\n\t\t\treturn {\n\t\t\t\tlabel: result.title,\n\t\t\t\tvalue: result.id.toString(),\n\t\t\t};\n\t\t} );\n\t\tsetOptions( mappedSuggestions );\n\t\tsetIsLoading( false );\n\t};\n\n\t/**\n\t * Handle selection.\n\t *\n\t * @param {Object} selectedPostId The selected post id.\n\t */\n\tconst handleSelectOption = (\n\t\tselectedPostId: string | null | undefined\n\t) => {\n\t\tif ( ! selectedPostId ) {\n\t\t\thandleDetach();\n\t\t\treturn;\n\t\t}\n\t\tsetValue( selectedPostId );\n\t\tif ( selectedPostId ) {\n\t\t\tconst selectedPost = searchResults.find(\n\t\t\t\t( result ) => result.id === Number( selectedPostId )\n\t\t\t);\n\t\t\t// Although unlikely, it's technically possible for selectedPost to not be found.\n\t\t\t// E.g. if the user selects an option just as new search results are loaded.\n\t\t\t// TODO: Add error handling for when selectedPost is not found.\n\t\t\tif ( selectedPost && postTypes ) {\n\t\t\t\tconst postType = postTypes.find(\n\t\t\t\t\t( _postType: { slug: string } ) =>\n\t\t\t\t\t\t_postType.slug === selectedPost?.type\n\t\t\t\t);\n\n\t\t\t\tconst attachedTo = {\n\t\t\t\t\t...( postType && { type: postType.slug } ),\n\t\t\t\t\tid: Number( selectedPostId ),\n\t\t\t\t\ttitle: {\n\t\t\t\t\t\traw: selectedPost.title,\n\t\t\t\t\t\trendered: selectedPost.title,\n\t\t\t\t\t},\n\t\t\t\t};\n\n\t\t\t\tonChange( {\n\t\t\t\t\tpost: Number( selectedPostId ),\n\t\t\t\t\t_embedded: {\n\t\t\t\t\t\t...data?._embedded,\n\t\t\t\t\t\t'wp:attached-to': [ attachedTo ],\n\t\t\t\t\t},\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t};\n\n\tconst help = !! data.post\n\t\t? createInterpolateElement(\n\t\t\t\t__(\n\t\t\t\t\t'Search for a post or page to attach this media to or <button>detach current</button>.'\n\t\t\t\t),\n\t\t\t\t{\n\t\t\t\t\tbutton: (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t__next40pxDefaultSize\n\t\t\t\t\t\t\tonClick={ handleDetach }\n\t\t\t\t\t\t\tvariant=\"link\"\n\t\t\t\t\t\t\taccessibleWhenDisabled\n\t\t\t\t\t\t/>\n\t\t\t\t\t),\n\t\t\t\t}\n\t\t )\n\t\t: __( 'Search for a post or page to attach this media to.' );\n\n\treturn (\n\t\t<ComboboxControl\n\t\t\tclassName=\"dataviews-media-field__attached-to\"\n\t\t\t__next40pxDefaultSize\n\t\t\tisLoading={ isLoading }\n\t\t\tlabel={ __( 'Attached to' ) }\n\t\t\thelp={ help }\n\t\t\tvalue={ value }\n\t\t\toptions={ options }\n\t\t\tonFilterValueChange={ debounce(\n\t\t\t\t( filterValue: unknown ) =>\n\t\t\t\t\tonValueChange( filterValue as string ),\n\t\t\t\t300\n\t\t\t) }\n\t\t\tonChange={ handleSelectOption }\n\t\t\thideLabelFromVision\n\t\t/>\n\t);\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport {\n\t__experimentalFetchLinkSuggestions as fetchLinkSuggestions,\n\tstore as coreStore,\n} from '@wordpress/core-data';\nimport { Button, ComboboxControl } from '@wordpress/components';\nimport { __ } from '@wordpress/i18n';\nimport { useState, createInterpolateElement } from '@wordpress/element';\nimport { debounce } from '@wordpress/compose';\nimport { useSelect } from '@wordpress/data';\nimport type { DataFormControlProps } from '@wordpress/dataviews';\n\n/**\n * Internal dependencies\n */\nimport type { MediaItem } from '../types';\nimport { getRenderedContent } from '../utils/get-rendered-content';\n\nexport type SearchResult = {\n\t/**\n\t * Post or term id.\n\t */\n\tid: number;\n\t/**\n\t * Link url.\n\t */\n\turl: string;\n\t/**\n\t * Title of the link.\n\t */\n\ttitle: string;\n\t/**\n\t * The taxonomy or post type slug or type URL.\n\t */\n\ttype: string;\n\t/**\n\t * Link kind of post-type or taxonomy\n\t */\n\tkind?: string;\n};\n\nexport default function MediaAttachedToEdit( {\n\tdata,\n\tonChange,\n}: DataFormControlProps< MediaItem > ) {\n\tconst defaultPost =\n\t\t!! data.post && !! data?._embedded?.[ 'wp:attached-to' ]?.[ 0 ]\n\t\t\t? [\n\t\t\t\t\t{\n\t\t\t\t\t\tlabel: getRenderedContent(\n\t\t\t\t\t\t\tdata._embedded?.[ 'wp:attached-to' ]?.[ 0 ]?.title\n\t\t\t\t\t\t),\n\t\t\t\t\t\tvalue: data.post.toString(),\n\t\t\t\t\t},\n\t\t\t ]\n\t\t\t: [];\n\tconst [ options, setOptions ] =\n\t\tuseState< { label: string; value: string }[] >( defaultPost );\n\tconst [ searchResults, setSearchResults ] = useState< SearchResult[] >(\n\t\t[]\n\t);\n\tconst [ isLoading, setIsLoading ] = useState( false );\n\tconst [ value, setValue ] = useState< string | null >(\n\t\tdata?.post?.toString() ?? null\n\t);\n\n\tconst postTypes = useSelect(\n\t\t( select ) => select( coreStore ).getPostTypes(),\n\t\t[]\n\t);\n\tconst handleDetach = () => {\n\t\tonChange( {\n\t\t\tpost: 0,\n\t\t\t_embedded: { ...data?._embedded, 'wp:attached-to': undefined },\n\t\t} );\n\t\tsetValue( null );\n\t\tsetOptions( [] );\n\t};\n\n\tconst onValueChange = async ( filterValue: string ) => {\n\t\tsetIsLoading( true );\n\t\tconst results = await fetchLinkSuggestions(\n\t\t\tfilterValue,\n\t\t\t/*\n\t\t\t * @TODO `fetchLinkSuggestions()` should accept `perPage` as an option argument.\n\t\t\t * `isInitialSuggestions` limits the result to 3, otherwise it's hardcoded to 20.\n\t\t\t */\n\t\t\t{ type: 'post', isInitialSuggestions: true },\n\t\t\t{}\n\t\t);\n\t\tsetSearchResults( results );\n\t\tconst suggestions = results.map( ( result ) => {\n\t\t\treturn {\n\t\t\t\tlabel: result.title,\n\t\t\t\tvalue: result.id.toString(),\n\t\t\t};\n\t\t} );\n\t\tconst includeCurrent =\n\t\t\t! filterValue &&\n\t\t\tsuggestions.findIndex( ( s ) => s.value === value ) === -1;\n\t\tsetOptions( suggestions.concat( includeCurrent ? defaultPost : [] ) );\n\t\tsetIsLoading( false );\n\t};\n\n\t/**\n\t * Handle selection.\n\t *\n\t * @param {Object} selectedPostId The selected post id.\n\t */\n\tconst handleSelectOption = (\n\t\tselectedPostId: string | null | undefined\n\t) => {\n\t\tif ( ! selectedPostId ) {\n\t\t\thandleDetach();\n\t\t\treturn;\n\t\t}\n\t\tsetValue( selectedPostId );\n\t\tif ( selectedPostId ) {\n\t\t\tconst selectedPost = searchResults.find(\n\t\t\t\t( result ) => result.id === Number( selectedPostId )\n\t\t\t);\n\t\t\t// Although unlikely, it's technically possible for selectedPost to not be found.\n\t\t\t// E.g. if the user selects an option just as new search results are loaded.\n\t\t\t// TODO: Add error handling for when selectedPost is not found.\n\t\t\tif ( selectedPost && postTypes ) {\n\t\t\t\tconst postType = postTypes.find(\n\t\t\t\t\t( _postType: { slug: string } ) =>\n\t\t\t\t\t\t_postType.slug === selectedPost?.type\n\t\t\t\t);\n\n\t\t\t\tconst attachedTo = {\n\t\t\t\t\t...( postType && { type: postType.slug } ),\n\t\t\t\t\tid: Number( selectedPostId ),\n\t\t\t\t\ttitle: {\n\t\t\t\t\t\traw: selectedPost.title,\n\t\t\t\t\t\trendered: selectedPost.title,\n\t\t\t\t\t},\n\t\t\t\t};\n\n\t\t\t\tonChange( {\n\t\t\t\t\tpost: Number( selectedPostId ),\n\t\t\t\t\t_embedded: {\n\t\t\t\t\t\t...data?._embedded,\n\t\t\t\t\t\t'wp:attached-to': [ attachedTo ],\n\t\t\t\t\t},\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t};\n\n\tconst help = createInterpolateElement(\n\t\t__(\n\t\t\t'Search for a post or page to attach this media to or <button>detach current</button>.'\n\t\t),\n\t\t{\n\t\t\tbutton: (\n\t\t\t\t<Button\n\t\t\t\t\t__next40pxDefaultSize\n\t\t\t\t\tonClick={ handleDetach }\n\t\t\t\t\tvariant=\"link\"\n\t\t\t\t\taccessibleWhenDisabled\n\t\t\t\t\tdisabled={ ! value }\n\t\t\t\t/>\n\t\t\t),\n\t\t}\n\t);\n\n\treturn (\n\t\t<ComboboxControl\n\t\t\tclassName=\"dataviews-media-field__attached-to\"\n\t\t\t__next40pxDefaultSize\n\t\t\tisLoading={ isLoading }\n\t\t\tlabel={ __( 'Attached to' ) }\n\t\t\thelp={ help }\n\t\t\tvalue={ value }\n\t\t\toptions={ options }\n\t\t\tonFilterValueChange={ debounce(\n\t\t\t\t( filterValue: unknown ) =>\n\t\t\t\t\tonValueChange( filterValue as string ),\n\t\t\t\t300\n\t\t\t) }\n\t\t\tonChange={ handleSelectOption }\n\t\t\thideLabelFromVision\n\t\t/>\n\t);\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/filename/view.tsx"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useMemo } from '@wordpress/element';\nimport { getFilename } from '@wordpress/url';\nimport type { DataViewRenderFieldProps } from '@wordpress/dataviews';\n// eslint-disable-next-line @wordpress/use-recommended-components -- `Tooltip` is not yet on the recommended `@wordpress/ui` allow-list; landing as a migration step ahead of the wider rollout.\nimport { Tooltip } from '@wordpress/ui';\n\n/**\n * Internal dependencies\n */\nimport type { MediaItem } from '../types';\n\n// Proxy threshold for \"long enough that the cell will visually truncate\" \u2014\n// used to decide whether to wrap the filename in a Tooltip showing the full\n// name on hover. Visual truncation itself is handled in CSS.\nconst TRUNCATE_LENGTH = 15;\n\nexport default function FileNameView( {\n\titem,\n}: DataViewRenderFieldProps< MediaItem > ) {\n\tconst fileName = useMemo(\n\t\t() => ( item?.source_url ? getFilename( item.source_url ) : null ),\n\t\t[ item?.source_url ]\n\t);\n\n\tif ( ! fileName ) {\n\t\treturn '';\n\t}\n\n\tif ( fileName.length <= TRUNCATE_LENGTH ) {\n\t\treturn (\n\t\t\t<span className=\"dataviews-media-field__filename\">\n\t\t\t\t{ fileName }\n\t\t\t</span>\n\t\t);\n\t}\n\n\t// The full filename is always in the DOM, so assistive tech gets it\n\t// regardless. The Tooltip aids mouse users where the cell visually clips\n\t// (DataViews layouts); in a non-truncating context like the DataForm the\n\t// name wraps in full, making it redundant but harmless.\n\treturn (\n\t\t<Tooltip.Root>\n\t\t\t<Tooltip.Trigger\n\t\t\t\trender={\n\t\t\t\t\t<span className=\"dataviews-media-field__filename\">\n\t\t\t\t\t\t{ fileName }\n\t\t\t\t\t</span>\n\t\t\t\t}\n\t\t\t/>\n\t\t\t<Tooltip.Popup>{ fileName }</Tooltip.Popup>\n\t\t</Tooltip.Root>\n\t);\n}\n"],
5
- "mappings": ";AAGA,SAAS,eAAe;AACxB,SAAS,mBAAmB;AAG5B,SAAS,eAAe;AA0BrB,cAWD,YAXC;AAhBH,IAAM,kBAAkB;AAET,SAAR,aAA+B;AAAA,EACrC;AACD,GAA2C;AAC1C,QAAM,WAAW;AAAA,IAChB,MAAQ,MAAM,aAAa,YAAa,KAAK,UAAW,IAAI;AAAA,IAC5D,CAAE,MAAM,UAAW;AAAA,EACpB;AAEA,MAAK,CAAE,UAAW;AACjB,WAAO;AAAA,EACR;AAEA,MAAK,SAAS,UAAU,iBAAkB;AACzC,WACC,oBAAC,UAAK,WAAU,mCACb,oBACH;AAAA,EAEF;AAMA,SACC,qBAAC,QAAQ,MAAR,EACA;AAAA;AAAA,MAAC,QAAQ;AAAA,MAAR;AAAA,QACA,QACC,oBAAC,UAAK,WAAU,mCACb,oBACH;AAAA;AAAA,IAEF;AAAA,IACA,oBAAC,QAAQ,OAAR,EAAgB,oBAAU;AAAA,KAC5B;AAEF;",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { useMemo } from '@wordpress/element';\nimport { getFilename } from '@wordpress/url';\nimport type { DataViewRenderFieldProps } from '@wordpress/dataviews';\nimport { Tooltip } from '@wordpress/ui';\n\n/**\n * Internal dependencies\n */\nimport type { MediaItem } from '../types';\n\n// Proxy threshold for \"long enough that the cell will visually truncate\" —\n// used to decide whether to wrap the filename in a Tooltip showing the full\n// name on hover. Visual truncation itself is handled in CSS.\nconst TRUNCATE_LENGTH = 15;\n\nexport default function FileNameView( {\n\titem,\n}: DataViewRenderFieldProps< MediaItem > ) {\n\tconst fileName = useMemo(\n\t\t() => ( item?.source_url ? getFilename( item.source_url ) : null ),\n\t\t[ item?.source_url ]\n\t);\n\n\tif ( ! fileName ) {\n\t\treturn '';\n\t}\n\n\tif ( fileName.length <= TRUNCATE_LENGTH ) {\n\t\treturn (\n\t\t\t<span className=\"dataviews-media-field__filename\">\n\t\t\t\t{ fileName }\n\t\t\t</span>\n\t\t);\n\t}\n\n\t// The full filename is always in the DOM, so assistive tech gets it\n\t// regardless. The Tooltip aids mouse users where the cell visually clips\n\t// (DataViews layouts); in a non-truncating context like the DataForm the\n\t// name wraps in full, making it redundant but harmless.\n\treturn (\n\t\t<Tooltip.Root>\n\t\t\t<Tooltip.Trigger\n\t\t\t\trender={\n\t\t\t\t\t<span className=\"dataviews-media-field__filename\">\n\t\t\t\t\t\t{ fileName }\n\t\t\t\t\t</span>\n\t\t\t\t}\n\t\t\t/>\n\t\t\t<Tooltip.Popup>{ fileName }</Tooltip.Popup>\n\t\t</Tooltip.Root>\n\t);\n}\n"],
5
+ "mappings": ";AAGA,SAAS,eAAe;AACxB,SAAS,mBAAmB;AAE5B,SAAS,eAAe;AA0BrB,cAWD,YAXC;AAhBH,IAAM,kBAAkB;AAET,SAAR,aAA+B;AAAA,EACrC;AACD,GAA2C;AAC1C,QAAM,WAAW;AAAA,IAChB,MAAQ,MAAM,aAAa,YAAa,KAAK,UAAW,IAAI;AAAA,IAC5D,CAAE,MAAM,UAAW;AAAA,EACpB;AAEA,MAAK,CAAE,UAAW;AACjB,WAAO;AAAA,EACR;AAEA,MAAK,SAAS,UAAU,iBAAkB;AACzC,WACC,oBAAC,UAAK,WAAU,mCACb,oBACH;AAAA,EAEF;AAMA,SACC,qBAAC,QAAQ,MAAR,EACA;AAAA;AAAA,MAAC,QAAQ;AAAA,MAAR;AAAA,QACA,QACC,oBAAC,UAAK,WAAU,mCACb,oBACH;AAAA;AAAA,IAEF;AAAA,IACA,oBAAC,QAAQ,OAAR,EAAgB,oBAAU;AAAA,KAC5B;AAEF;",
6
6
  "names": []
7
7
  }
@@ -6,7 +6,7 @@ var mediaDimensionsField = {
6
6
  label: __("Dimensions"),
7
7
  getValue: ({ item }) => item?.media_details?.width && item?.media_details?.height ? sprintf(
8
8
  // translators: 1: Width. 2: Height.
9
- _x("%1$s \xD7 %2$s", "image dimensions"),
9
+ _x("%1$s × %2$s", "image dimensions"),
10
10
  item?.media_details?.width?.toString(),
11
11
  item?.media_details?.height?.toString()
12
12
  ) : "",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/media_dimensions/index.ts"],
4
- "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { __, _x, sprintf } from '@wordpress/i18n';\nimport type { Attachment, Updatable } from '@wordpress/core-data';\nimport type { Field } from '@wordpress/dataviews';\n\nconst mediaDimensionsField: Partial< Field< Updatable< Attachment > > > = {\n\tid: 'media_dimensions',\n\ttype: 'text',\n\tlabel: __( 'Dimensions' ),\n\tgetValue: ( { item } ) =>\n\t\titem?.media_details?.width && item?.media_details?.height\n\t\t\t? sprintf(\n\t\t\t\t\t// translators: 1: Width. 2: Height.\n\t\t\t\t\t_x( '%1$s \u00D7 %2$s', 'image dimensions' ),\n\t\t\t\t\titem?.media_details?.width?.toString(),\n\t\t\t\t\titem?.media_details?.height?.toString()\n\t\t\t )\n\t\t\t: '',\n\tisVisible: ( item ) => {\n\t\treturn !! ( item?.media_details?.width && item?.media_details?.height );\n\t},\n\tenableSorting: false,\n\tfilterBy: false,\n\treadOnly: true,\n};\n\nexport default mediaDimensionsField;\n"],
5
- "mappings": ";AAGA,SAAS,IAAI,IAAI,eAAe;AAIhC,IAAM,uBAAoE;AAAA,EACzE,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,OAAO,GAAI,YAAa;AAAA,EACxB,UAAU,CAAE,EAAE,KAAK,MAClB,MAAM,eAAe,SAAS,MAAM,eAAe,SAChD;AAAA;AAAA,IAEA,GAAI,kBAAe,kBAAmB;AAAA,IACtC,MAAM,eAAe,OAAO,SAAS;AAAA,IACrC,MAAM,eAAe,QAAQ,SAAS;AAAA,EACtC,IACA;AAAA,EACJ,WAAW,CAAE,SAAU;AACtB,WAAO,CAAC,EAAI,MAAM,eAAe,SAAS,MAAM,eAAe;AAAA,EAChE;AAAA,EACA,eAAe;AAAA,EACf,UAAU;AAAA,EACV,UAAU;AACX;AAEA,IAAO,2BAAQ;",
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { __, _x, sprintf } from '@wordpress/i18n';\nimport type { Attachment, Updatable } from '@wordpress/core-data';\nimport type { Field } from '@wordpress/dataviews';\n\nconst mediaDimensionsField: Partial< Field< Updatable< Attachment > > > = {\n\tid: 'media_dimensions',\n\ttype: 'text',\n\tlabel: __( 'Dimensions' ),\n\tgetValue: ( { item } ) =>\n\t\titem?.media_details?.width && item?.media_details?.height\n\t\t\t? sprintf(\n\t\t\t\t\t// translators: 1: Width. 2: Height.\n\t\t\t\t\t_x( '%1$s × %2$s', 'image dimensions' ),\n\t\t\t\t\titem?.media_details?.width?.toString(),\n\t\t\t\t\titem?.media_details?.height?.toString()\n\t\t\t )\n\t\t\t: '',\n\tisVisible: ( item ) => {\n\t\treturn !! ( item?.media_details?.width && item?.media_details?.height );\n\t},\n\tenableSorting: false,\n\tfilterBy: false,\n\treadOnly: true,\n};\n\nexport default mediaDimensionsField;\n"],
5
+ "mappings": ";AAGA,SAAS,IAAI,IAAI,eAAe;AAIhC,IAAM,uBAAoE;AAAA,EACzE,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,OAAO,GAAI,YAAa;AAAA,EACxB,UAAU,CAAE,EAAE,KAAK,MAClB,MAAM,eAAe,SAAS,MAAM,eAAe,SAChD;AAAA;AAAA,IAEA,GAAI,eAAe,kBAAmB;AAAA,IACtC,MAAM,eAAe,OAAO,SAAS;AAAA,IACrC,MAAM,eAAe,QAAQ,SAAS;AAAA,EACtC,IACA;AAAA,EACJ,WAAW,CAAE,SAAU;AACtB,WAAO,CAAC,EAAI,MAAM,eAAe,SAAS,MAAM,eAAe;AAAA,EAChE;AAAA,EACA,eAAe;AAAA,EACf,UAAU;AAAA,EACV,UAAU;AACX;AAEA,IAAO,2BAAQ;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/media_thumbnail/view.tsx"],
4
- "sourcesContent": ["/**\n * External dependencies\n */\nimport clsx from 'clsx';\n\n/**\n * WordPress dependencies\n */\nimport { useSelect } from '@wordpress/data';\nimport { store as coreStore } from '@wordpress/core-data';\nimport {\n\t__experimentalTruncate as Truncate,\n\t__experimentalVStack as VStack,\n\tIcon as WCIcon,\n} from '@wordpress/components';\nimport { useState, useRef, useLayoutEffect } from '@wordpress/element';\nimport type { Attachment } from '@wordpress/core-data';\nimport { getFilename } from '@wordpress/url';\nimport type { DataViewRenderFieldProps } from '@wordpress/dataviews';\n/**\n * Internal dependencies\n */\nimport { getMediaTypeFromMimeType } from '../utils/get-media-type-from-mime-type';\nimport type { MediaItem } from '../types';\n\n/**\n * Given the available image sizes and a target display width, returns the URL\n * of the smallest size whose width is >= the target. Falls back to the largest\n * available size, or the original source_url.\n *\n * @param featuredMedia The media item with size details.\n * @param configSizes The target display size string (e.g. '900px').\n */\nexport function getBestImageUrl(\n\tfeaturedMedia: Attachment | MediaItem,\n\tconfigSizes?: string\n): string {\n\tconst sizes = featuredMedia?.media_details?.sizes;\n\tif ( ! sizes ) {\n\t\treturn featuredMedia.source_url;\n\t}\n\n\tconst sizeEntries = Object.values( sizes );\n\n\tif ( ! sizeEntries.length ) {\n\t\treturn featuredMedia.source_url;\n\t}\n\n\t// Parse target width from config.sizes (e.g. '900px' \u2192 900).\n\tconst targetWidth = configSizes ? parseInt( configSizes, 10 ) : NaN;\n\n\tif ( ! Number.isNaN( targetWidth ) ) {\n\t\t// Filter to entries that have a valid numeric width.\n\t\tconst validEntries = sizeEntries.filter(\n\t\t\t( s ) => typeof s.width === 'number' && ! Number.isNaN( s.width )\n\t\t);\n\n\t\tif ( ! validEntries.length ) {\n\t\t\treturn featuredMedia.source_url;\n\t\t}\n\n\t\t// Sort ascending by width.\n\t\tconst sorted = [ ...validEntries ].sort(\n\t\t\t( a, b ) => a.width - b.width\n\t\t);\n\t\t// Pick the smallest size that is >= target width.\n\t\tconst match = sorted.find( ( s ) => s.width >= targetWidth );\n\t\tif ( match ) {\n\t\t\treturn match.source_url;\n\t\t}\n\t\t// No size large enough \u2014 use the largest available.\n\t\treturn sorted[ sorted.length - 1 ].source_url;\n\t}\n\n\t// If we can't parse the target, fall back to source_url.\n\treturn featuredMedia.source_url;\n}\n\nfunction FallbackView( {\n\titem,\n\tfilename,\n}: {\n\titem: MediaItem;\n\tfilename: string;\n} ) {\n\treturn (\n\t\t<div className=\"dataviews-media-field__media-thumbnail\">\n\t\t\t<VStack\n\t\t\t\tjustify=\"center\"\n\t\t\t\talignment=\"center\"\n\t\t\t\tclassName=\"dataviews-media-field__media-thumbnail__stack\"\n\t\t\t\tspacing={ 0 }\n\t\t\t>\n\t\t\t\t<WCIcon\n\t\t\t\t\tclassName=\"dataviews-media-field__media-thumbnail--icon\"\n\t\t\t\t\ticon={ getMediaTypeFromMimeType( item.mime_type ).icon }\n\t\t\t\t\tsize={ 24 }\n\t\t\t\t/>\n\t\t\t\t{ !! filename && (\n\t\t\t\t\t<div className=\"dataviews-media-field__media-thumbnail__filename\">\n\t\t\t\t\t\t<Truncate className=\"dataviews-media-field__media-thumbnail__filename__truncate\">\n\t\t\t\t\t\t\t{ filename }\n\t\t\t\t\t\t</Truncate>\n\t\t\t\t\t</div>\n\t\t\t\t) }\n\t\t\t</VStack>\n\t\t</div>\n\t);\n}\n\nfunction ImageView( {\n\titem,\n\tconfigSizes,\n\tonError,\n}: {\n\titem: Attachment | MediaItem;\n\tconfigSizes?: string;\n\tonError: () => void;\n} ) {\n\tconst imageUrl = getBestImageUrl( item, configSizes );\n\n\t/*\n\t * Use three states to avoid fade-in animation for cached images:\n\t * 'instant' = image already cached, 'loading' = waiting, 'loaded' = just finished.\n\t *\n\t * useLayoutEffect runs synchronously after DOM mutations but before paint,\n\t * so we can check img.complete to detect disk-cached images and skip the\n\t * fade-in animation entirely.\n\t */\n\tconst imgRef = useRef< HTMLImageElement >( null );\n\tconst [ loadingState, setLoadingState ] = useState<\n\t\t'instant' | 'loading' | 'loaded'\n\t>( 'loading' );\n\n\tuseLayoutEffect( () => {\n\t\tif ( imgRef.current?.complete ) {\n\t\t\tsetLoadingState( 'instant' );\n\t\t} else {\n\t\t\tsetLoadingState( 'loading' );\n\t\t}\n\t}, [ imageUrl ] );\n\n\tconst handleLoad = () => {\n\t\tif ( loadingState === 'loading' ) {\n\t\t\tsetLoadingState( 'loaded' );\n\t\t}\n\t};\n\n\treturn (\n\t\t<div\n\t\t\tclassName={ clsx( 'dataviews-media-field__media-thumbnail', {\n\t\t\t\t'is-loading': loadingState === 'loading',\n\t\t\t\t'is-loaded': loadingState === 'loaded',\n\t\t\t} ) }\n\t\t>\n\t\t\t<img\n\t\t\t\tref={ imgRef }\n\t\t\t\tclassName=\"dataviews-media-field__media-thumbnail--image\"\n\t\t\t\tsrc={ imageUrl }\n\t\t\t\talt={ item.alt_text || item.title.raw }\n\t\t\t\tonLoad={ handleLoad }\n\t\t\t\tonError={ onError }\n\t\t\t\tloading=\"lazy\"\n\t\t\t/>\n\t\t</div>\n\t);\n}\n\nexport default function MediaThumbnailView( {\n\titem,\n\tconfig,\n}: DataViewRenderFieldProps< MediaItem > ) {\n\tconst [ imageError, setImageError ] = useState( false );\n\n\tconst _featuredMedia = useSelect(\n\t\t( select ) => {\n\t\t\t// Avoid the network request if it's not needed. `featured_media` is\n\t\t\t// 0 for images and media without featured media.\n\t\t\tif ( ! item.featured_media ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\treturn select( coreStore ).getEntityRecord< Attachment >(\n\t\t\t\t'postType',\n\t\t\t\t'attachment',\n\t\t\t\titem.featured_media\n\t\t\t);\n\t\t},\n\t\t[ item.featured_media ]\n\t);\n\tconst featuredMedia = item.featured_media ? _featuredMedia : item;\n\n\t// Fetching.\n\tif ( ! featuredMedia ) {\n\t\treturn null;\n\t}\n\n\tconst filename = getFilename( featuredMedia.source_url || '' );\n\n\t// Show fallback if image failed to load or if not an image type.\n\tif (\n\t\timageError ||\n\t\tgetMediaTypeFromMimeType( featuredMedia.mime_type ).type !== 'image'\n\t) {\n\t\treturn (\n\t\t\t<FallbackView item={ featuredMedia } filename={ filename || '' } />\n\t\t);\n\t}\n\n\treturn (\n\t\t<ImageView\n\t\t\titem={ featuredMedia }\n\t\t\tconfigSizes={ config?.sizes }\n\t\t\tonError={ () => setImageError( true ) }\n\t\t/>\n\t);\n}\n"],
4
+ "sourcesContent": ["/**\n * External dependencies\n */\nimport clsx from 'clsx';\n\n/**\n * WordPress dependencies\n */\nimport { useSelect } from '@wordpress/data';\nimport { store as coreStore } from '@wordpress/core-data';\nimport {\n\t__experimentalTruncate as Truncate,\n\t__experimentalVStack as VStack,\n\tIcon as WCIcon,\n} from '@wordpress/components';\nimport { useState, useRef, useLayoutEffect } from '@wordpress/element';\nimport type { Attachment } from '@wordpress/core-data';\nimport { getFilename } from '@wordpress/url';\nimport type { DataViewRenderFieldProps } from '@wordpress/dataviews';\n/**\n * Internal dependencies\n */\nimport { getMediaTypeFromMimeType } from '../utils/get-media-type-from-mime-type';\nimport type { MediaItem } from '../types';\n\n/**\n * Given the available image sizes and a target display width, returns the URL\n * of the smallest size whose width is >= the target. Falls back to the largest\n * available size, or the original source_url.\n *\n * @param featuredMedia The media item with size details.\n * @param configSizes The target display size string (e.g. '900px').\n */\nexport function getBestImageUrl(\n\tfeaturedMedia: Attachment | MediaItem,\n\tconfigSizes?: string\n): string {\n\tconst sizes = featuredMedia?.media_details?.sizes;\n\tif ( ! sizes ) {\n\t\treturn featuredMedia.source_url;\n\t}\n\n\tconst sizeEntries = Object.values( sizes );\n\n\tif ( ! sizeEntries.length ) {\n\t\treturn featuredMedia.source_url;\n\t}\n\n\t// Parse target width from config.sizes (e.g. '900px' 900).\n\tconst targetWidth = configSizes ? parseInt( configSizes, 10 ) : NaN;\n\n\tif ( ! Number.isNaN( targetWidth ) ) {\n\t\t// Filter to entries that have a valid numeric width.\n\t\tconst validEntries = sizeEntries.filter(\n\t\t\t( s ) => typeof s.width === 'number' && ! Number.isNaN( s.width )\n\t\t);\n\n\t\tif ( ! validEntries.length ) {\n\t\t\treturn featuredMedia.source_url;\n\t\t}\n\n\t\t// Sort ascending by width.\n\t\tconst sorted = [ ...validEntries ].sort(\n\t\t\t( a, b ) => a.width - b.width\n\t\t);\n\t\t// Pick the smallest size that is >= target width.\n\t\tconst match = sorted.find( ( s ) => s.width >= targetWidth );\n\t\tif ( match ) {\n\t\t\treturn match.source_url;\n\t\t}\n\t\t// No size large enough use the largest available.\n\t\treturn sorted[ sorted.length - 1 ].source_url;\n\t}\n\n\t// If we can't parse the target, fall back to source_url.\n\treturn featuredMedia.source_url;\n}\n\nfunction FallbackView( {\n\titem,\n\tfilename,\n}: {\n\titem: MediaItem;\n\tfilename: string;\n} ) {\n\treturn (\n\t\t<div className=\"dataviews-media-field__media-thumbnail\">\n\t\t\t<VStack\n\t\t\t\tjustify=\"center\"\n\t\t\t\talignment=\"center\"\n\t\t\t\tclassName=\"dataviews-media-field__media-thumbnail__stack\"\n\t\t\t\tspacing={ 0 }\n\t\t\t>\n\t\t\t\t<WCIcon\n\t\t\t\t\tclassName=\"dataviews-media-field__media-thumbnail--icon\"\n\t\t\t\t\ticon={ getMediaTypeFromMimeType( item.mime_type ).icon }\n\t\t\t\t\tsize={ 24 }\n\t\t\t\t/>\n\t\t\t\t{ !! filename && (\n\t\t\t\t\t<div className=\"dataviews-media-field__media-thumbnail__filename\">\n\t\t\t\t\t\t<Truncate className=\"dataviews-media-field__media-thumbnail__filename__truncate\">\n\t\t\t\t\t\t\t{ filename }\n\t\t\t\t\t\t</Truncate>\n\t\t\t\t\t</div>\n\t\t\t\t) }\n\t\t\t</VStack>\n\t\t</div>\n\t);\n}\n\nfunction ImageView( {\n\titem,\n\tconfigSizes,\n\tonError,\n}: {\n\titem: Attachment | MediaItem;\n\tconfigSizes?: string;\n\tonError: () => void;\n} ) {\n\tconst imageUrl = getBestImageUrl( item, configSizes );\n\n\t/*\n\t * Use three states to avoid fade-in animation for cached images:\n\t * 'instant' = image already cached, 'loading' = waiting, 'loaded' = just finished.\n\t *\n\t * useLayoutEffect runs synchronously after DOM mutations but before paint,\n\t * so we can check img.complete to detect disk-cached images and skip the\n\t * fade-in animation entirely.\n\t */\n\tconst imgRef = useRef< HTMLImageElement >( null );\n\tconst [ loadingState, setLoadingState ] = useState<\n\t\t'instant' | 'loading' | 'loaded'\n\t>( 'loading' );\n\n\tuseLayoutEffect( () => {\n\t\tif ( imgRef.current?.complete ) {\n\t\t\tsetLoadingState( 'instant' );\n\t\t} else {\n\t\t\tsetLoadingState( 'loading' );\n\t\t}\n\t}, [ imageUrl ] );\n\n\tconst handleLoad = () => {\n\t\tif ( loadingState === 'loading' ) {\n\t\t\tsetLoadingState( 'loaded' );\n\t\t}\n\t};\n\n\treturn (\n\t\t<div\n\t\t\tclassName={ clsx( 'dataviews-media-field__media-thumbnail', {\n\t\t\t\t'is-loading': loadingState === 'loading',\n\t\t\t\t'is-loaded': loadingState === 'loaded',\n\t\t\t} ) }\n\t\t>\n\t\t\t<img\n\t\t\t\tref={ imgRef }\n\t\t\t\tclassName=\"dataviews-media-field__media-thumbnail--image\"\n\t\t\t\tsrc={ imageUrl }\n\t\t\t\talt={ item.alt_text || item.title.raw }\n\t\t\t\tonLoad={ handleLoad }\n\t\t\t\tonError={ onError }\n\t\t\t\tloading=\"lazy\"\n\t\t\t/>\n\t\t</div>\n\t);\n}\n\nexport default function MediaThumbnailView( {\n\titem,\n\tconfig,\n}: DataViewRenderFieldProps< MediaItem > ) {\n\tconst [ imageError, setImageError ] = useState( false );\n\n\tconst _featuredMedia = useSelect(\n\t\t( select ) => {\n\t\t\t// Avoid the network request if it's not needed. `featured_media` is\n\t\t\t// 0 for images and media without featured media.\n\t\t\tif ( ! item.featured_media ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\treturn select( coreStore ).getEntityRecord< Attachment >(\n\t\t\t\t'postType',\n\t\t\t\t'attachment',\n\t\t\t\titem.featured_media\n\t\t\t);\n\t\t},\n\t\t[ item.featured_media ]\n\t);\n\tconst featuredMedia = item.featured_media ? _featuredMedia : item;\n\n\t// Fetching.\n\tif ( ! featuredMedia ) {\n\t\treturn null;\n\t}\n\n\tconst filename = getFilename( featuredMedia.source_url || '' );\n\n\t// Show fallback if image failed to load or if not an image type.\n\tif (\n\t\timageError ||\n\t\tgetMediaTypeFromMimeType( featuredMedia.mime_type ).type !== 'image'\n\t) {\n\t\treturn (\n\t\t\t<FallbackView item={ featuredMedia } filename={ filename || '' } />\n\t\t);\n\t}\n\n\treturn (\n\t\t<ImageView\n\t\t\titem={ featuredMedia }\n\t\t\tconfigSizes={ config?.sizes }\n\t\t\tonError={ () => setImageError( true ) }\n\t\t/>\n\t);\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../src/attached_to/edit.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAEjE;;GAEG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAG1C,MAAM,MAAM,YAAY,GAAG;IAC1B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IACX;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,mBAAmB,CAAE,EAC5C,IAAI,EACJ,QAAQ,EACR,EAAE,oBAAoB,CAAE,SAAS,CAAE,+BA0InC"}
1
+ {"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../src/attached_to/edit.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAEjE;;GAEG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAG1C,MAAM,MAAM,YAAY,GAAG;IAC1B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IACX;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,mBAAmB,CAAE,EAC5C,IAAI,EACJ,QAAQ,EACR,EAAE,oBAAoB,CAAE,SAAS,CAAE,+BA6InC"}
@@ -1 +1 @@
1
- {"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../src/filename/view.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAIrE;;GAEG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAO1C,MAAM,CAAC,OAAO,UAAU,YAAY,CAAE,EACrC,IAAI,EACJ,EAAE,wBAAwB,CAAE,SAAS,CAAE,oCAkCvC"}
1
+ {"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../src/filename/view.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAGrE;;GAEG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAO1C,MAAM,CAAC,OAAO,UAAU,YAAY,CAAE,EACrC,IAAI,EACJ,EAAE,wBAAwB,CAAE,SAAS,CAAE,oCAkCvC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/media-fields",
3
- "version": "0.13.1",
3
+ "version": "0.14.0",
4
4
  "description": "Reusable field definitions for displaying and editing media attachment properties in WordPress.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -48,20 +48,19 @@
48
48
  "src/**/*.scss"
49
49
  ],
50
50
  "dependencies": {
51
- "@types/react": "^18.3.27",
52
- "@wordpress/base-styles": "^10.0.1",
53
- "@wordpress/components": "^35.0.1",
54
- "@wordpress/compose": "^8.1.1",
55
- "@wordpress/core-data": "^7.48.1",
56
- "@wordpress/data": "^10.48.1",
57
- "@wordpress/dataviews": "^16.0.1",
58
- "@wordpress/date": "^5.48.1",
59
- "@wordpress/element": "^8.0.1",
60
- "@wordpress/i18n": "^6.21.1",
61
- "@wordpress/icons": "^14.0.1",
62
- "@wordpress/primitives": "^4.48.1",
63
- "@wordpress/ui": "^0.15.1",
64
- "@wordpress/url": "^4.48.1",
51
+ "@wordpress/base-styles": "^10.1.0",
52
+ "@wordpress/components": "^36.0.0",
53
+ "@wordpress/compose": "^8.2.0",
54
+ "@wordpress/core-data": "^7.49.0",
55
+ "@wordpress/data": "^10.49.0",
56
+ "@wordpress/dataviews": "^17.0.0",
57
+ "@wordpress/date": "^5.49.0",
58
+ "@wordpress/element": "^8.1.0",
59
+ "@wordpress/i18n": "^6.22.0",
60
+ "@wordpress/icons": "^15.0.0",
61
+ "@wordpress/primitives": "^4.49.0",
62
+ "@wordpress/ui": "^0.16.0",
63
+ "@wordpress/url": "^4.49.0",
65
64
  "clsx": "^2.1.1"
66
65
  },
67
66
  "devDependencies": {
@@ -71,10 +70,16 @@
71
70
  "@types/jest": "^29.5.14"
72
71
  },
73
72
  "peerDependencies": {
73
+ "@types/react": "^18.3.27",
74
74
  "react": "^18.0.0"
75
75
  },
76
+ "peerDependenciesMeta": {
77
+ "@types/react": {
78
+ "optional": true
79
+ }
80
+ },
76
81
  "publishConfig": {
77
82
  "access": "public"
78
83
  },
79
- "gitHead": "99df7432c5c7cb83ba41146fd1f57f3c19004305"
84
+ "gitHead": "0e7112a4f4fde4ea15bd9060489b8f6fe11eb6ca"
80
85
  }
@@ -75,6 +75,7 @@ export default function MediaAttachedToEdit( {
75
75
  post: 0,
76
76
  _embedded: { ...data?._embedded, 'wp:attached-to': undefined },
77
77
  } );
78
+ setValue( null );
78
79
  setOptions( [] );
79
80
  };
80
81
 
@@ -90,13 +91,16 @@ export default function MediaAttachedToEdit( {
90
91
  {}
91
92
  );
92
93
  setSearchResults( results );
93
- const mappedSuggestions = results.map( ( result ) => {
94
+ const suggestions = results.map( ( result ) => {
94
95
  return {
95
96
  label: result.title,
96
97
  value: result.id.toString(),
97
98
  };
98
99
  } );
99
- setOptions( mappedSuggestions );
100
+ const includeCurrent =
101
+ ! filterValue &&
102
+ suggestions.findIndex( ( s ) => s.value === value ) === -1;
103
+ setOptions( suggestions.concat( includeCurrent ? defaultPost : [] ) );
100
104
  setIsLoading( false );
101
105
  };
102
106
 
@@ -146,23 +150,22 @@ export default function MediaAttachedToEdit( {
146
150
  }
147
151
  };
148
152
 
149
- const help = !! data.post
150
- ? createInterpolateElement(
151
- __(
152
- 'Search for a post or page to attach this media to or <button>detach current</button>.'
153
- ),
154
- {
155
- button: (
156
- <Button
157
- __next40pxDefaultSize
158
- onClick={ handleDetach }
159
- variant="link"
160
- accessibleWhenDisabled
161
- />
162
- ),
163
- }
164
- )
165
- : __( 'Search for a post or page to attach this media to.' );
153
+ const help = createInterpolateElement(
154
+ __(
155
+ 'Search for a post or page to attach this media to or <button>detach current</button>.'
156
+ ),
157
+ {
158
+ button: (
159
+ <Button
160
+ __next40pxDefaultSize
161
+ onClick={ handleDetach }
162
+ variant="link"
163
+ accessibleWhenDisabled
164
+ disabled={ ! value }
165
+ />
166
+ ),
167
+ }
168
+ );
166
169
 
167
170
  return (
168
171
  <ComboboxControl
@@ -4,7 +4,6 @@
4
4
  import { useMemo } from '@wordpress/element';
5
5
  import { getFilename } from '@wordpress/url';
6
6
  import type { DataViewRenderFieldProps } from '@wordpress/dataviews';
7
- // eslint-disable-next-line @wordpress/use-recommended-components -- `Tooltip` is not yet on the recommended `@wordpress/ui` allow-list; landing as a migration step ahead of the wider rollout.
8
7
  import { Tooltip } from '@wordpress/ui';
9
8
 
10
9
  /**