-
Notifications
You must be signed in to change notification settings - Fork 4.3k
/
Copy pathlink-preview.js
141 lines (127 loc) · 3.56 KB
/
link-preview.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/**
* External dependencies
*/
import classnames from 'classnames';
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import {
Button,
ExternalLink,
__experimentalTruncate as Truncate,
Tooltip,
} from '@wordpress/components';
import { filterURLForDisplay, safeDecodeURI } from '@wordpress/url';
import { Icon, globe, info, linkOff, edit } from '@wordpress/icons';
import { __unstableStripHTML as stripHTML } from '@wordpress/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,
additionalControls,
isEditing,
} ) {
// 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 ), 24 ) ) ||
'';
// url can be undefined if the href attribute is unset
const isEmptyURL = ! value?.url?.length;
const displayTitle =
! isEmptyURL &&
stripHTML( richData?.title || value?.title || displayURL );
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={ __( 'Currently selected' ) }
className={ classnames( 'block-editor-link-control__search-item', {
'is-current': true,
'is-rich': hasRichData,
'is-fetching': !! isFetching,
'is-preview': true,
'is-error': isEmptyURL,
'is-url-title': displayTitle === displayURL,
} ) }
>
<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 ? (
<>
<Tooltip text={ value.url }>
<ExternalLink
className="block-editor-link-control__search-item-title"
href={ value.url }
>
<Truncate numberOfLines={ 1 }>
{ displayTitle }
</Truncate>
</ExternalLink>
</Tooltip>
{ value?.url && displayTitle !== displayURL && (
<span className="block-editor-link-control__search-item-info">
<Truncate numberOfLines={ 1 }>
{ displayURL }
</Truncate>
</span>
) }
</>
) : (
<span className="block-editor-link-control__search-item-error-notice">
{ __( 'Link is empty' ) }
</span>
) }
</span>
</span>
<Button
icon={ edit }
label={ __( 'Edit' ) }
className="block-editor-link-control__search-item-action"
onClick={ onEditClick }
size="compact"
disabled={ isEditing }
/>
{ hasUnlinkControl && (
<Button
icon={ linkOff }
label={ __( 'Unlink' ) }
className="block-editor-link-control__search-item-action block-editor-link-control__unlink"
onClick={ onRemove }
size="compact"
/>
) }
<ViewerSlot fillProps={ value } />
</div>
{ additionalControls && additionalControls() }
</div>
);
}