@jetbrains/ring-ui 5.0.97 → 5.0.98
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/components/clipboard/clipboard-fallback.d.ts +2 -0
- package/components/clipboard/clipboard-fallback.js +44 -0
- package/components/clipboard/clipboard.d.ts +5 -0
- package/components/clipboard/clipboard.js +41 -0
- package/components/user-card/card.d.ts +15 -0
- package/components/user-card/card.js +33 -13
- package/components/user-card/user-card.css +55 -5
- package/dist/_helpers/card.js +52 -10
- package/dist/clipboard/clipboard-fallback.d.ts +2 -0
- package/dist/clipboard/clipboard-fallback.js +42 -0
- package/dist/clipboard/clipboard.d.ts +5 -0
- package/dist/clipboard/clipboard.js +91 -0
- package/dist/style.css +1 -1
- package/dist/user-card/card.d.ts +15 -0
- package/dist/user-card/card.js +35 -0
- package/dist/user-card/smart-user-card-tooltip.js +12 -0
- package/dist/user-card/tooltip.js +14 -0
- package/dist/user-card/user-card.js +21 -9
- package/dist/user-card-ng/user-card-ng.js +17 -6
- package/package.json +1 -1
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export function copyTextToClipboard(str) {
|
|
2
|
+
const el = document.createElement('textarea');
|
|
3
|
+
el.value = str;
|
|
4
|
+
el.setAttribute('readonly', '');
|
|
5
|
+
el.style.position = 'absolute';
|
|
6
|
+
el.style.left = '-9999px';
|
|
7
|
+
document.body.appendChild(el);
|
|
8
|
+
const selection = document.getSelection();
|
|
9
|
+
// Should restore previous selection
|
|
10
|
+
const selected = (selection && selection.rangeCount > 0)
|
|
11
|
+
? selection.getRangeAt(0)
|
|
12
|
+
: false;
|
|
13
|
+
el.select();
|
|
14
|
+
document.execCommand('copy');
|
|
15
|
+
document.body.removeChild(el);
|
|
16
|
+
if (selected && selection) {
|
|
17
|
+
selection.removeAllRanges();
|
|
18
|
+
selection.addRange(selected);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function copyHTMLToClipboard(str) {
|
|
22
|
+
const el = document.createElement('div');
|
|
23
|
+
el.innerHTML = str;
|
|
24
|
+
el.setAttribute('readonly', '');
|
|
25
|
+
el.style.position = 'absolute';
|
|
26
|
+
el.style.left = '-9999px';
|
|
27
|
+
document.body.appendChild(el);
|
|
28
|
+
const selection = document.getSelection();
|
|
29
|
+
// Should restore previous selection
|
|
30
|
+
const selected = (selection && selection.rangeCount > 0)
|
|
31
|
+
? selection.getRangeAt(0)
|
|
32
|
+
: false;
|
|
33
|
+
selection?.removeAllRanges();
|
|
34
|
+
const range = document.createRange();
|
|
35
|
+
range.selectNode(el);
|
|
36
|
+
selection?.addRange(range);
|
|
37
|
+
document.execCommand('copy');
|
|
38
|
+
selection?.removeAllRanges();
|
|
39
|
+
document.execCommand('copy');
|
|
40
|
+
document.body.removeChild(el);
|
|
41
|
+
if (selected && selection) {
|
|
42
|
+
selection.addRange(selected);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
declare const clipboard: {
|
|
2
|
+
copyText: (text: string, successMessage?: string | undefined, errorMessage?: string | undefined, delay?: number) => Promise<void>;
|
|
3
|
+
copyHTML: (html: string, successMessage?: string | undefined, errorMessage?: string | undefined, delay?: number) => Promise<void>;
|
|
4
|
+
};
|
|
5
|
+
export default clipboard;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import alertService from '../alert-service/alert-service';
|
|
2
|
+
import { copyHTMLToClipboard, copyTextToClipboard } from './clipboard-fallback';
|
|
3
|
+
const ALERT_DELAY = 1000;
|
|
4
|
+
function getClipboardImplementation() {
|
|
5
|
+
if (navigator.clipboard && !window.isSecureContext) {
|
|
6
|
+
return {
|
|
7
|
+
copy: (text) => navigator.clipboard.writeText(text),
|
|
8
|
+
copyHTML: (html) => navigator.clipboard.write([
|
|
9
|
+
new ClipboardItem({
|
|
10
|
+
['text/html']: new Blob([html], { type: 'text/html' })
|
|
11
|
+
})
|
|
12
|
+
])
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
copy: (str) => Promise.resolve(copyTextToClipboard(str)),
|
|
17
|
+
copyHTML: (html) => Promise.resolve(copyHTMLToClipboard(html))
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
async function copy(text, successMessage, errorMessage, delay = ALERT_DELAY, isHtml = false) {
|
|
21
|
+
try {
|
|
22
|
+
const clipboardImpl = getClipboardImplementation();
|
|
23
|
+
const copyMethod = isHtml ? clipboardImpl.copyHTML : clipboardImpl.copy;
|
|
24
|
+
await copyMethod(text);
|
|
25
|
+
if (successMessage) {
|
|
26
|
+
alertService.successMessage(successMessage, delay);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
if (errorMessage) {
|
|
31
|
+
alertService.error(errorMessage, delay);
|
|
32
|
+
}
|
|
33
|
+
// eslint-disable-next-line no-console
|
|
34
|
+
console.error(e);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const clipboard = {
|
|
38
|
+
copyText: async (text, successMessage, errorMessage, delay = ALERT_DELAY) => await copy(text, successMessage, errorMessage, delay),
|
|
39
|
+
copyHTML: async (html, successMessage, errorMessage, delay = ALERT_DELAY) => await copy(html, successMessage, errorMessage, delay, true)
|
|
40
|
+
};
|
|
41
|
+
export default clipboard;
|
|
@@ -9,11 +9,16 @@ export interface UserCardUser {
|
|
|
9
9
|
online?: boolean | null | undefined;
|
|
10
10
|
banned?: boolean | null | undefined;
|
|
11
11
|
banReason?: string | undefined;
|
|
12
|
+
unverifiedEmail?: boolean | null | undefined;
|
|
12
13
|
}
|
|
13
14
|
export interface UserCardWording {
|
|
14
15
|
banned: string;
|
|
15
16
|
online: string;
|
|
16
17
|
offline: string;
|
|
18
|
+
copyToClipboard: string;
|
|
19
|
+
copiedToClipboard: string;
|
|
20
|
+
copingToClipboardError: string;
|
|
21
|
+
unverified: string;
|
|
17
22
|
}
|
|
18
23
|
export interface UserCardProps extends HTMLAttributes<HTMLDivElement> {
|
|
19
24
|
user: UserCardUser;
|
|
@@ -35,11 +40,16 @@ export default class UserCard extends PureComponent<UserCardProps> {
|
|
|
35
40
|
online: PropTypes.Requireable<boolean>;
|
|
36
41
|
banned: PropTypes.Requireable<boolean>;
|
|
37
42
|
banReason: PropTypes.Requireable<string>;
|
|
43
|
+
unverifiedEmail: PropTypes.Requireable<boolean>;
|
|
38
44
|
}>>>;
|
|
39
45
|
wording: PropTypes.Requireable<PropTypes.InferProps<{
|
|
40
46
|
banned: PropTypes.Validator<string>;
|
|
41
47
|
online: PropTypes.Validator<string>;
|
|
42
48
|
offline: PropTypes.Validator<string>;
|
|
49
|
+
copyToClipboard: PropTypes.Validator<string>;
|
|
50
|
+
copiedToClipboard: PropTypes.Validator<string>;
|
|
51
|
+
copingToClipboardError: PropTypes.Validator<string>;
|
|
52
|
+
unverified: PropTypes.Requireable<string>;
|
|
43
53
|
}>>;
|
|
44
54
|
};
|
|
45
55
|
static defaultProps: {
|
|
@@ -47,8 +57,13 @@ export default class UserCard extends PureComponent<UserCardProps> {
|
|
|
47
57
|
banned: string;
|
|
48
58
|
online: string;
|
|
49
59
|
offline: string;
|
|
60
|
+
copyToClipboard: string;
|
|
61
|
+
copiedToClipboard: string;
|
|
62
|
+
copingToClipboardError: string;
|
|
63
|
+
unverified: string;
|
|
50
64
|
};
|
|
51
65
|
};
|
|
66
|
+
copyEmail: () => void;
|
|
52
67
|
render(): JSX.Element;
|
|
53
68
|
}
|
|
54
69
|
export type UserCardAttrs = JSX.LibraryManagedAttributes<typeof UserCard, UserCardProps>;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import React, { PureComponent } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import classNames from 'classnames';
|
|
4
|
-
import
|
|
4
|
+
import copyIcon from '@jetbrains/icons/copy';
|
|
5
|
+
import Avatar, { Size as AvatarSize } from '../avatar/avatar';
|
|
5
6
|
import Link from '../link/link';
|
|
7
|
+
import clipboard from '../clipboard/clipboard';
|
|
6
8
|
import badgeStyles from '../badge/badge.css';
|
|
9
|
+
import Icon, { Size as IconSize } from '../icon/icon';
|
|
7
10
|
import styles from './user-card.css';
|
|
8
11
|
export default class UserCard extends PureComponent {
|
|
9
12
|
static propTypes = {
|
|
@@ -18,47 +21,64 @@ export default class UserCard extends PureComponent {
|
|
|
18
21
|
href: PropTypes.string,
|
|
19
22
|
online: PropTypes.bool,
|
|
20
23
|
banned: PropTypes.bool,
|
|
21
|
-
banReason: PropTypes.string
|
|
24
|
+
banReason: PropTypes.string,
|
|
25
|
+
unverifiedEmail: PropTypes.bool
|
|
22
26
|
}).isRequired,
|
|
23
27
|
wording: PropTypes.shape({
|
|
24
28
|
banned: PropTypes.string.isRequired,
|
|
25
29
|
online: PropTypes.string.isRequired,
|
|
26
|
-
offline: PropTypes.string.isRequired
|
|
30
|
+
offline: PropTypes.string.isRequired,
|
|
31
|
+
copyToClipboard: PropTypes.string.isRequired,
|
|
32
|
+
copiedToClipboard: PropTypes.string.isRequired,
|
|
33
|
+
copingToClipboardError: PropTypes.string.isRequired,
|
|
34
|
+
unverified: PropTypes.string
|
|
27
35
|
})
|
|
28
36
|
};
|
|
29
37
|
static defaultProps = {
|
|
30
38
|
wording: {
|
|
31
39
|
banned: 'banned',
|
|
32
40
|
online: 'online',
|
|
33
|
-
offline: 'offline'
|
|
41
|
+
offline: 'offline',
|
|
42
|
+
copyToClipboard: 'Copy to clipboard',
|
|
43
|
+
copiedToClipboard: 'Email was copied to clipboard',
|
|
44
|
+
copingToClipboardError: 'Failed to copy to clipboard',
|
|
45
|
+
unverified: 'Unverified'
|
|
34
46
|
}
|
|
35
47
|
};
|
|
48
|
+
copyEmail = () => {
|
|
49
|
+
const { user, wording } = this.props;
|
|
50
|
+
clipboard.copyText(user.email || '', wording.copiedToClipboard, wording.copingToClipboardError);
|
|
51
|
+
};
|
|
36
52
|
render() {
|
|
37
53
|
const { children, info, className, user, wording, ...restProps } = this.props;
|
|
38
54
|
const classes = classNames(className, {});
|
|
39
55
|
const userActiveStatusClasses = classNames(styles.userActiveStatus, user.online ? styles.online : '');
|
|
40
56
|
return (<div className={classes} {...restProps}>
|
|
41
57
|
<div className={styles.userInformationContainer}>
|
|
42
|
-
<Avatar size={
|
|
58
|
+
<Avatar size={AvatarSize.Size56} url={user.avatarUrl}/>
|
|
43
59
|
<div className={styles.userInformation}>
|
|
44
|
-
<div>
|
|
60
|
+
<div className={styles.userNameLine}>
|
|
45
61
|
{user.href && (<Link href={user.href} className={styles.userName}>
|
|
46
62
|
{user.name}
|
|
47
63
|
</Link>)}
|
|
48
64
|
{!user.href && <span className={styles.userName}>{user.name}</span>}
|
|
65
|
+
{typeof user.online === 'boolean' &&
|
|
66
|
+
(<span className={userActiveStatusClasses} title={user.online ? wording.online : wording.offline}/>)}
|
|
49
67
|
{!!info && <span className={styles.userNameInfo}>{info}</span>}
|
|
50
68
|
{user.banned &&
|
|
51
69
|
(<span className={classNames(badgeStyles.badge, badgeStyles.invalid)} title={user.banReason}>{wording.banned}</span>)}
|
|
52
70
|
</div>
|
|
53
|
-
<div>
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
71
|
+
<div className={styles.userLogin}>{user.login}</div>
|
|
72
|
+
{user.email && (<span className={styles.userEmailWrapper}>
|
|
73
|
+
<Link pseudo onClick={this.copyEmail} className={styles.userEmail}>
|
|
74
|
+
{user.email}
|
|
75
|
+
</Link>
|
|
76
|
+
{user.unverifiedEmail && (<span className={styles.unverifiedLabel}>{wording.unverified}</span>)}
|
|
77
|
+
<Icon title={wording.copyToClipboard} className={styles.userCopyIcon} onClick={this.copyEmail} glyph={copyIcon} size={IconSize.Size14} suppressSizeWarning/>
|
|
78
|
+
</span>)}
|
|
79
|
+
{children}
|
|
59
80
|
</div>
|
|
60
81
|
</div>
|
|
61
|
-
{children}
|
|
62
82
|
</div>);
|
|
63
83
|
}
|
|
64
84
|
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
.userInformationContainer {
|
|
10
10
|
display: flex;
|
|
11
|
-
align-items:
|
|
11
|
+
align-items: start;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
.userInformation {
|
|
@@ -22,20 +22,70 @@
|
|
|
22
22
|
line-height: 18px;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
.userNameLine {
|
|
26
|
+
height: var(--ring-line-height-lowest);
|
|
27
|
+
|
|
28
|
+
white-space: nowrap;
|
|
29
|
+
|
|
30
|
+
line-height: var(--ring-line-height-lowest);
|
|
31
|
+
}
|
|
32
|
+
|
|
25
33
|
.userName {
|
|
26
34
|
display: inline-block;
|
|
27
35
|
|
|
28
36
|
margin-right: 4px;
|
|
29
|
-
margin-bottom: 3px;
|
|
30
37
|
|
|
31
38
|
font-size: 16px;
|
|
32
39
|
font-weight: 600;
|
|
33
40
|
}
|
|
34
41
|
|
|
42
|
+
.userLogin {
|
|
43
|
+
margin-bottom: 7px;
|
|
44
|
+
|
|
45
|
+
color: var(--ring-secondary-color);
|
|
46
|
+
|
|
47
|
+
font-size: var(--ring-font-size-smaller);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.userEmail {
|
|
51
|
+
margin-right: 4px;
|
|
52
|
+
|
|
53
|
+
font-size: var(--ring-font-size);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.userCopyIcon {
|
|
57
|
+
cursor: pointer;
|
|
58
|
+
|
|
59
|
+
opacity: 0;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.userCopyIcon svg {
|
|
63
|
+
margin-left: 4px;
|
|
64
|
+
|
|
65
|
+
color: var(--ring-link-hover-color);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.userEmailWrapper:hover .userCopyIcon {
|
|
69
|
+
transition: opacity 300ms ease-out;
|
|
70
|
+
|
|
71
|
+
opacity: 1;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.userEmailWrapper:hover .userEmail {
|
|
75
|
+
color: var(--ring-link-hover-color);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.unverifiedLabel {
|
|
79
|
+
margin: 0 4px;
|
|
80
|
+
|
|
81
|
+
color: var(--ring-secondary-color);
|
|
82
|
+
|
|
83
|
+
font-size: var(--ring-font-size-smaller);
|
|
84
|
+
}
|
|
85
|
+
|
|
35
86
|
.userNameInfo {
|
|
36
87
|
display: inline-block;
|
|
37
88
|
|
|
38
|
-
margin-right: 4px;
|
|
39
89
|
margin-bottom: 3px;
|
|
40
90
|
}
|
|
41
91
|
|
|
@@ -44,8 +94,8 @@
|
|
|
44
94
|
|
|
45
95
|
width: unit;
|
|
46
96
|
height: unit;
|
|
47
|
-
|
|
48
|
-
margin-
|
|
97
|
+
margin-right: var(--ring-unit);
|
|
98
|
+
margin-left: 6px;
|
|
49
99
|
|
|
50
100
|
border-radius: 50%;
|
|
51
101
|
background-color: var(--ring-icon-secondary-color);
|
package/dist/_helpers/card.js
CHANGED
|
@@ -2,13 +2,27 @@ import { _ as _defineProperty, a as _extends } from './_rollupPluginBabelHelpers
|
|
|
2
2
|
import React, { PureComponent } from 'react';
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
import classNames from 'classnames';
|
|
5
|
+
import copyIcon from '@jetbrains/icons/copy';
|
|
5
6
|
import Avatar, { Size } from '../avatar/avatar.js';
|
|
6
7
|
import Link from '../link/link.js';
|
|
8
|
+
import clipboard from '../clipboard/clipboard.js';
|
|
7
9
|
import { m as modules_6c9187df } from './badge.js';
|
|
10
|
+
import Icon from '../icon/icon.js';
|
|
11
|
+
import { Size as Size$1 } from '../icon/icon__constants.js';
|
|
8
12
|
|
|
9
|
-
var modules_a4196c17 = {"unit":"8px","light":"light_rui_6e59","userCardSpaced":"userCardSpaced_rui_6e59","userInformationContainer":"userInformationContainer_rui_6e59","userInformation":"userInformation_rui_6e59","userName":"userName_rui_6e59","userNameInfo":"userNameInfo_rui_6e59","userActiveStatus":"userActiveStatus_rui_6e59","online":"online_rui_6e59"};
|
|
13
|
+
var modules_a4196c17 = {"unit":"8px","light":"light_rui_6e59","userCardSpaced":"userCardSpaced_rui_6e59","userInformationContainer":"userInformationContainer_rui_6e59","userInformation":"userInformation_rui_6e59","userNameLine":"userNameLine_rui_6e59","userName":"userName_rui_6e59","userLogin":"userLogin_rui_6e59","userEmail":"userEmail_rui_6e59","userCopyIcon":"userCopyIcon_rui_6e59","userEmailWrapper":"userEmailWrapper_rui_6e59","unverifiedLabel":"unverifiedLabel_rui_6e59","userNameInfo":"userNameInfo_rui_6e59","userActiveStatus":"userActiveStatus_rui_6e59","online":"online_rui_6e59"};
|
|
10
14
|
|
|
11
15
|
class UserCard extends PureComponent {
|
|
16
|
+
constructor() {
|
|
17
|
+
super(...arguments);
|
|
18
|
+
_defineProperty(this, "copyEmail", () => {
|
|
19
|
+
const {
|
|
20
|
+
user,
|
|
21
|
+
wording
|
|
22
|
+
} = this.props;
|
|
23
|
+
clipboard.copyText(user.email || '', wording.copiedToClipboard, wording.copingToClipboardError);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
12
26
|
render() {
|
|
13
27
|
const {
|
|
14
28
|
children,
|
|
@@ -29,20 +43,39 @@ class UserCard extends PureComponent {
|
|
|
29
43
|
url: user.avatarUrl
|
|
30
44
|
}), /*#__PURE__*/React.createElement("div", {
|
|
31
45
|
className: modules_a4196c17.userInformation
|
|
32
|
-
}, /*#__PURE__*/React.createElement("div",
|
|
46
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
47
|
+
className: modules_a4196c17.userNameLine
|
|
48
|
+
}, user.href && /*#__PURE__*/React.createElement(Link, {
|
|
33
49
|
href: user.href,
|
|
34
50
|
className: modules_a4196c17.userName
|
|
35
51
|
}, user.name), !user.href && /*#__PURE__*/React.createElement("span", {
|
|
36
52
|
className: modules_a4196c17.userName
|
|
37
|
-
}, user.name),
|
|
53
|
+
}, user.name), typeof user.online === 'boolean' && /*#__PURE__*/React.createElement("span", {
|
|
54
|
+
className: userActiveStatusClasses,
|
|
55
|
+
title: user.online ? wording.online : wording.offline
|
|
56
|
+
}), !!info && /*#__PURE__*/React.createElement("span", {
|
|
38
57
|
className: modules_a4196c17.userNameInfo
|
|
39
58
|
}, info), user.banned && /*#__PURE__*/React.createElement("span", {
|
|
40
59
|
className: classNames(modules_6c9187df.badge, modules_6c9187df.invalid),
|
|
41
60
|
title: user.banReason
|
|
42
|
-
}, wording.banned)), /*#__PURE__*/React.createElement("div",
|
|
43
|
-
className:
|
|
44
|
-
|
|
45
|
-
|
|
61
|
+
}, wording.banned)), /*#__PURE__*/React.createElement("div", {
|
|
62
|
+
className: modules_a4196c17.userLogin
|
|
63
|
+
}, user.login), user.email && /*#__PURE__*/React.createElement("span", {
|
|
64
|
+
className: modules_a4196c17.userEmailWrapper
|
|
65
|
+
}, /*#__PURE__*/React.createElement(Link, {
|
|
66
|
+
pseudo: true,
|
|
67
|
+
onClick: this.copyEmail,
|
|
68
|
+
className: modules_a4196c17.userEmail
|
|
69
|
+
}, user.email), user.unverifiedEmail && /*#__PURE__*/React.createElement("span", {
|
|
70
|
+
className: modules_a4196c17.unverifiedLabel
|
|
71
|
+
}, wording.unverified), /*#__PURE__*/React.createElement(Icon, {
|
|
72
|
+
title: wording.copyToClipboard,
|
|
73
|
+
className: modules_a4196c17.userCopyIcon,
|
|
74
|
+
onClick: this.copyEmail,
|
|
75
|
+
glyph: copyIcon,
|
|
76
|
+
size: Size$1.Size14,
|
|
77
|
+
suppressSizeWarning: true
|
|
78
|
+
})), children)));
|
|
46
79
|
}
|
|
47
80
|
}
|
|
48
81
|
_defineProperty(UserCard, "propTypes", {
|
|
@@ -57,19 +90,28 @@ _defineProperty(UserCard, "propTypes", {
|
|
|
57
90
|
href: PropTypes.string,
|
|
58
91
|
online: PropTypes.bool,
|
|
59
92
|
banned: PropTypes.bool,
|
|
60
|
-
banReason: PropTypes.string
|
|
93
|
+
banReason: PropTypes.string,
|
|
94
|
+
unverifiedEmail: PropTypes.bool
|
|
61
95
|
}).isRequired,
|
|
62
96
|
wording: PropTypes.shape({
|
|
63
97
|
banned: PropTypes.string.isRequired,
|
|
64
98
|
online: PropTypes.string.isRequired,
|
|
65
|
-
offline: PropTypes.string.isRequired
|
|
99
|
+
offline: PropTypes.string.isRequired,
|
|
100
|
+
copyToClipboard: PropTypes.string.isRequired,
|
|
101
|
+
copiedToClipboard: PropTypes.string.isRequired,
|
|
102
|
+
copingToClipboardError: PropTypes.string.isRequired,
|
|
103
|
+
unverified: PropTypes.string
|
|
66
104
|
})
|
|
67
105
|
});
|
|
68
106
|
_defineProperty(UserCard, "defaultProps", {
|
|
69
107
|
wording: {
|
|
70
108
|
banned: 'banned',
|
|
71
109
|
online: 'online',
|
|
72
|
-
offline: 'offline'
|
|
110
|
+
offline: 'offline',
|
|
111
|
+
copyToClipboard: 'Copy to clipboard',
|
|
112
|
+
copiedToClipboard: 'Email was copied to clipboard',
|
|
113
|
+
copingToClipboardError: 'Failed to copy to clipboard',
|
|
114
|
+
unverified: 'Unverified'
|
|
73
115
|
}
|
|
74
116
|
});
|
|
75
117
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
function copyTextToClipboard(str) {
|
|
2
|
+
const el = document.createElement('textarea');
|
|
3
|
+
el.value = str;
|
|
4
|
+
el.setAttribute('readonly', '');
|
|
5
|
+
el.style.position = 'absolute';
|
|
6
|
+
el.style.left = '-9999px';
|
|
7
|
+
document.body.appendChild(el);
|
|
8
|
+
const selection = document.getSelection();
|
|
9
|
+
// Should restore previous selection
|
|
10
|
+
const selected = selection && selection.rangeCount > 0 ? selection.getRangeAt(0) : false;
|
|
11
|
+
el.select();
|
|
12
|
+
document.execCommand('copy');
|
|
13
|
+
document.body.removeChild(el);
|
|
14
|
+
if (selected && selection) {
|
|
15
|
+
selection.removeAllRanges();
|
|
16
|
+
selection.addRange(selected);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function copyHTMLToClipboard(str) {
|
|
20
|
+
const el = document.createElement('div');
|
|
21
|
+
el.innerHTML = str;
|
|
22
|
+
el.setAttribute('readonly', '');
|
|
23
|
+
el.style.position = 'absolute';
|
|
24
|
+
el.style.left = '-9999px';
|
|
25
|
+
document.body.appendChild(el);
|
|
26
|
+
const selection = document.getSelection();
|
|
27
|
+
// Should restore previous selection
|
|
28
|
+
const selected = selection && selection.rangeCount > 0 ? selection.getRangeAt(0) : false;
|
|
29
|
+
selection?.removeAllRanges();
|
|
30
|
+
const range = document.createRange();
|
|
31
|
+
range.selectNode(el);
|
|
32
|
+
selection?.addRange(range);
|
|
33
|
+
document.execCommand('copy');
|
|
34
|
+
selection?.removeAllRanges();
|
|
35
|
+
document.execCommand('copy');
|
|
36
|
+
document.body.removeChild(el);
|
|
37
|
+
if (selected && selection) {
|
|
38
|
+
selection.addRange(selected);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export { copyHTMLToClipboard, copyTextToClipboard };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
declare const clipboard: {
|
|
2
|
+
copyText: (text: string, successMessage?: string | undefined, errorMessage?: string | undefined, delay?: number) => Promise<void>;
|
|
3
|
+
copyHTML: (html: string, successMessage?: string | undefined, errorMessage?: string | undefined, delay?: number) => Promise<void>;
|
|
4
|
+
};
|
|
5
|
+
export default clipboard;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import alertService from '../alert-service/alert-service.js';
|
|
2
|
+
import { copyTextToClipboard, copyHTMLToClipboard } from './clipboard-fallback.js';
|
|
3
|
+
import '../_helpers/_rollupPluginBabelHelpers.js';
|
|
4
|
+
import 'react';
|
|
5
|
+
import '../global/react-render-adapter.js';
|
|
6
|
+
import 'react-dom';
|
|
7
|
+
import '../global/get-uid.js';
|
|
8
|
+
import '../alert/alert.js';
|
|
9
|
+
import 'classnames';
|
|
10
|
+
import 'prop-types';
|
|
11
|
+
import '@jetbrains/icons/exception';
|
|
12
|
+
import '@jetbrains/icons/checkmark';
|
|
13
|
+
import '@jetbrains/icons/warning';
|
|
14
|
+
import '@jetbrains/icons/close';
|
|
15
|
+
import '../icon/icon.js';
|
|
16
|
+
import 'util-deprecate';
|
|
17
|
+
import '../icon/icon__constants.js';
|
|
18
|
+
import '../_helpers/icon.js';
|
|
19
|
+
import '../icon/icon__svg.js';
|
|
20
|
+
import '../global/memoize.js';
|
|
21
|
+
import '../loader-inline/loader-inline.js';
|
|
22
|
+
import '../global/data-tests.js';
|
|
23
|
+
import '../_helpers/loader-inline.js';
|
|
24
|
+
import '../global/dom.js';
|
|
25
|
+
import '../button/button.js';
|
|
26
|
+
import 'focus-visible';
|
|
27
|
+
import '@jetbrains/icons/chevron-10px';
|
|
28
|
+
import '../link/clickableLink.js';
|
|
29
|
+
import '../global/controls-height.js';
|
|
30
|
+
import '../_helpers/button__classes.js';
|
|
31
|
+
import '../_helpers/theme.js';
|
|
32
|
+
import '../popup/popup.target.js';
|
|
33
|
+
import '../popup/popup.js';
|
|
34
|
+
import '../global/schedule-raf.js';
|
|
35
|
+
import '../shortcuts/shortcuts.js';
|
|
36
|
+
import '../shortcuts/core.js';
|
|
37
|
+
import 'combokeys';
|
|
38
|
+
import '../global/sniffer.js';
|
|
39
|
+
import 'sniffr';
|
|
40
|
+
import '../tab-trap/tab-trap.js';
|
|
41
|
+
import '../popup/position.js';
|
|
42
|
+
import '../popup/popup.consts.js';
|
|
43
|
+
import '../alert/container.js';
|
|
44
|
+
|
|
45
|
+
const ALERT_DELAY = 1000;
|
|
46
|
+
function getClipboardImplementation() {
|
|
47
|
+
if (navigator.clipboard && !window.isSecureContext) {
|
|
48
|
+
return {
|
|
49
|
+
copy: text => navigator.clipboard.writeText(text),
|
|
50
|
+
copyHTML: html => navigator.clipboard.write([new ClipboardItem({
|
|
51
|
+
['text/html']: new Blob([html], {
|
|
52
|
+
type: 'text/html'
|
|
53
|
+
})
|
|
54
|
+
})])
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
copy: str => Promise.resolve(copyTextToClipboard(str)),
|
|
59
|
+
copyHTML: html => Promise.resolve(copyHTMLToClipboard(html))
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
async function copy(text, successMessage, errorMessage) {
|
|
63
|
+
let delay = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ALERT_DELAY;
|
|
64
|
+
let isHtml = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
|
65
|
+
try {
|
|
66
|
+
const clipboardImpl = getClipboardImplementation();
|
|
67
|
+
const copyMethod = isHtml ? clipboardImpl.copyHTML : clipboardImpl.copy;
|
|
68
|
+
await copyMethod(text);
|
|
69
|
+
if (successMessage) {
|
|
70
|
+
alertService.successMessage(successMessage, delay);
|
|
71
|
+
}
|
|
72
|
+
} catch (e) {
|
|
73
|
+
if (errorMessage) {
|
|
74
|
+
alertService.error(errorMessage, delay);
|
|
75
|
+
}
|
|
76
|
+
// eslint-disable-next-line no-console
|
|
77
|
+
console.error(e);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const clipboard = {
|
|
81
|
+
copyText: async function (text, successMessage, errorMessage) {
|
|
82
|
+
let delay = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ALERT_DELAY;
|
|
83
|
+
return await copy(text, successMessage, errorMessage, delay);
|
|
84
|
+
},
|
|
85
|
+
copyHTML: async function (html, successMessage, errorMessage) {
|
|
86
|
+
let delay = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ALERT_DELAY;
|
|
87
|
+
return await copy(html, successMessage, errorMessage, delay, true);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export { clipboard as default };
|