-
Notifications
You must be signed in to change notification settings - Fork 4.3k
/
Copy pathlink-preview.js
159 lines (145 loc) · 4.22 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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/**
* External dependencies
*/
import classnames from 'classnames';
/**
* WordPress dependencies
*/
import { __, sprintf } from '@wordpress/i18n';
import {
Button,
ExternalLink,
__experimentalTruncate as Truncate,
} from '@wordpress/components';
import { useCopyToClipboard } from '@wordpress/compose';
import { filterURLForDisplay, safeDecodeURI } from '@wordpress/url';
import { Icon, globe, info, linkOff, edit, copySmall } from '@wordpress/icons';
import { __unstableStripHTML as stripHTML } from '@wordpress/dom';
import { useDispatch, useSelect } from '@wordpress/data';
import { store as noticesStore } from '@wordpress/notices';
import { store as preferencesStore } from '@wordpress/preferences';
/**
* 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,
} ) {
const showIconLabels = useSelect(
( select ) =>
select( preferencesStore ).get( 'core', 'showIconLabels' ),
[]
);
// 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 } />;
}
const { createNotice } = useDispatch( noticesStore );
const ref = useCopyToClipboard( value.url, () => {
createNotice( 'info', __( 'Link copied to clipboard.' ), {
isDismissible: true,
type: 'snackbar',
} );
} );
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 ? (
<>
<ExternalLink
className="block-editor-link-control__search-item-title"
href={ value.url }
>
<Truncate numberOfLines={ 1 }>
{ displayTitle }
</Truncate>
</ExternalLink>
{ 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 link' ) }
onClick={ onEditClick }
size="compact"
/>
{ hasUnlinkControl && (
<Button
icon={ linkOff }
label={ __( 'Remove link' ) }
onClick={ onRemove }
size="compact"
/>
) }
<Button
icon={ copySmall }
label={ sprintf(
// Translators: %s is a placeholder for the link URL and an optional colon, (if a Link URL is present).
__( 'Copy link%s' ), // Ends up looking like "Copy link: https://example.com".
isEmptyURL || showIconLabels ? '' : ': ' + value.url
) }
ref={ ref }
disabled={ isEmptyURL }
size="compact"
/>
<ViewerSlot fillProps={ value } />
</div>
</div>
);
}