@gechiui/block-editor
Version:
169 lines (152 loc) • 4.26 kB
JavaScript
/**
* External dependencies
*/
import classnames from 'classnames';
/**
* GeChiUI dependencies
*/
import { __ } from '@gechiui/i18n';
import {
Button,
ExternalLink,
__experimentalText as Text,
} from '@gechiui/components';
import { filterURLForDisplay, safeDecodeURI } from '@gechiui/url';
import { Icon, globe, info, linkOff, edit } from '@gechiui/icons';
import { __unstableStripHTML as stripHTML } from '@gechiui/dom';
/**
* Internal dependencies
*/
import { ViewerSlot } from './viewer-slot';
import useRichUrlData from './use-rich-url-data';
export default function LinkPreview( {
value,
onEditClick,
hasRichPreviews = false,
hasUnlinkControl = false,
onRemove,
} ) {
// Avoid fetching if rich previews are not desired.
const showRichPreviews = hasRichPreviews ? value?.url : null;
const { richData, isFetching } = useRichUrlData( showRichPreviews );
// Rich data may be an empty object so test for that.
const hasRichData = richData && Object.keys( richData ).length;
const displayURL =
( value && filterURLForDisplay( safeDecodeURI( value.url ), 16 ) ) ||
'';
const displayTitle = richData?.title || value?.title || displayURL;
// url can be undefined if the href attribute is unset
const isEmptyURL = ! value?.url?.length;
let icon;
if ( richData?.icon ) {
icon = <img src={ richData?.icon } alt="" />;
} else if ( isEmptyURL ) {
icon = <Icon icon={ info } size={ 32 } />;
} else {
icon = <Icon icon={ globe } />;
}
return (
<div
aria-label={ __( '当前选择' ) }
aria-selected="true"
className={ classnames( 'block-editor-link-control__search-item', {
'is-current': true,
'is-rich': hasRichData,
'is-fetching': !! isFetching,
'is-preview': true,
'is-error': isEmptyURL,
} ) }
>
<div className="block-editor-link-control__search-item-top">
<span className="block-editor-link-control__search-item-header">
<span
className={ classnames(
'block-editor-link-control__search-item-icon',
{
'is-image': richData?.icon,
}
) }
>
{ icon }
</span>
<span className="block-editor-link-control__search-item-details">
{ ! isEmptyURL ? (
<>
<ExternalLink
className="block-editor-link-control__search-item-title"
href={ value.url }
>
{ stripHTML( displayTitle ) }
</ExternalLink>
{ value?.url && (
<span className="block-editor-link-control__search-item-info">
{ displayURL }
</span>
) }
</>
) : (
<span className="block-editor-link-control__search-item-error-notice">
Link is empty
</span>
) }
</span>
</span>
<Button
icon={ edit }
label={ __( '编辑' ) }
className="block-editor-link-control__search-item-action"
onClick={ onEditClick }
iconSize={ 24 }
/>
{ hasUnlinkControl && (
<Button
icon={ linkOff }
label={ __( '移除链接' ) }
className="block-editor-link-control__search-item-action block-editor-link-control__unlink"
onClick={ onRemove }
iconSize={ 24 }
/>
) }
<ViewerSlot fillProps={ value } />
</div>
{ ( ( hasRichData &&
( richData?.image || richData?.description ) ) ||
isFetching ) && (
<div className="block-editor-link-control__search-item-bottom">
{ ( richData?.image || isFetching ) && (
<div
aria-hidden={ ! richData?.image }
className={ classnames(
'block-editor-link-control__search-item-image',
{
'is-placeholder': ! richData?.image,
}
) }
>
{ richData?.image && (
<img src={ richData?.image } alt="" />
) }
</div>
) }
{ ( richData?.description || isFetching ) && (
<div
aria-hidden={ ! richData?.description }
className={ classnames(
'block-editor-link-control__search-item-description',
{
'is-placeholder': ! richData?.description,
}
) }
>
{ richData?.description && (
<Text truncate numberOfLines="2">
{ richData.description }
</Text>
) }
</div>
) }
</div>
) }
</div>
);
}