@atlaskit/smart-card 26.9.16 → 26.9.18
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 +12 -0
- package/dist/cjs/version.json +1 -1
- package/dist/cjs/view/CardWithUrl/component.js +5 -2
- package/dist/cjs/view/FlexibleCard/components/elements/avatar-group/index.js +1 -2
- package/dist/cjs/view/InlineCard/Icon.js +0 -2
- package/dist/cjs/view/RedesignedInlineCard/ErroredView/index.js +90 -0
- package/dist/cjs/view/RedesignedInlineCard/ForbiddenView/index.js +129 -0
- package/dist/cjs/view/RedesignedInlineCard/Frame/index.js +63 -0
- package/dist/cjs/view/RedesignedInlineCard/Frame/styled.js +70 -0
- package/dist/cjs/view/RedesignedInlineCard/Icon.js +43 -0
- package/dist/cjs/view/RedesignedInlineCard/IconAndTitleLayout/index.js +151 -0
- package/dist/cjs/view/RedesignedInlineCard/IconAndTitleLayout/styled.js +56 -0
- package/dist/cjs/view/RedesignedInlineCard/ResolvedView/index.js +83 -0
- package/dist/cjs/view/RedesignedInlineCard/ResolvingView/index.js +69 -0
- package/dist/cjs/view/RedesignedInlineCard/ResolvingView/styled.js +13 -0
- package/dist/cjs/view/RedesignedInlineCard/UnauthorisedView/index.js +113 -0
- package/dist/cjs/view/RedesignedInlineCard/index.js +183 -0
- package/dist/cjs/view/RedesignedInlineCard/styled.js +31 -0
- package/dist/cjs/view/RedesignedInlineCard/types.js +5 -0
- package/dist/cjs/view/RedesignedInlineCard/utils/withFrameStyleControl.js +42 -0
- package/dist/es2019/version.json +1 -1
- package/dist/es2019/view/CardWithUrl/component.js +5 -2
- package/dist/es2019/view/FlexibleCard/components/elements/avatar-group/index.js +3 -2
- package/dist/es2019/view/InlineCard/Icon.js +0 -2
- package/dist/es2019/view/RedesignedInlineCard/ErroredView/index.js +66 -0
- package/dist/es2019/view/RedesignedInlineCard/ForbiddenView/index.js +107 -0
- package/dist/es2019/view/RedesignedInlineCard/Frame/index.js +55 -0
- package/dist/es2019/view/RedesignedInlineCard/Frame/styled.js +107 -0
- package/dist/es2019/view/RedesignedInlineCard/Icon.js +45 -0
- package/dist/es2019/view/RedesignedInlineCard/IconAndTitleLayout/index.js +124 -0
- package/dist/es2019/view/RedesignedInlineCard/IconAndTitleLayout/styled.js +97 -0
- package/dist/es2019/view/RedesignedInlineCard/ResolvedView/index.js +55 -0
- package/dist/es2019/view/RedesignedInlineCard/ResolvingView/index.js +44 -0
- package/dist/es2019/view/RedesignedInlineCard/ResolvingView/styled.js +6 -0
- package/dist/es2019/view/RedesignedInlineCard/UnauthorisedView/index.js +86 -0
- package/dist/es2019/view/RedesignedInlineCard/index.js +149 -0
- package/dist/es2019/view/RedesignedInlineCard/styled.js +52 -0
- package/dist/es2019/view/RedesignedInlineCard/types.js +1 -0
- package/dist/es2019/view/RedesignedInlineCard/utils/withFrameStyleControl.js +33 -0
- package/dist/esm/version.json +1 -1
- package/dist/esm/view/CardWithUrl/component.js +5 -2
- package/dist/esm/view/FlexibleCard/components/elements/avatar-group/index.js +1 -2
- package/dist/esm/view/InlineCard/Icon.js +0 -2
- package/dist/esm/view/RedesignedInlineCard/ErroredView/index.js +82 -0
- package/dist/esm/view/RedesignedInlineCard/ForbiddenView/index.js +121 -0
- package/dist/esm/view/RedesignedInlineCard/Frame/index.js +53 -0
- package/dist/esm/view/RedesignedInlineCard/Frame/styled.js +61 -0
- package/dist/esm/view/RedesignedInlineCard/Icon.js +34 -0
- package/dist/esm/view/RedesignedInlineCard/IconAndTitleLayout/index.js +143 -0
- package/dist/esm/view/RedesignedInlineCard/IconAndTitleLayout/styled.js +38 -0
- package/dist/esm/view/RedesignedInlineCard/ResolvedView/index.js +75 -0
- package/dist/esm/view/RedesignedInlineCard/ResolvingView/index.js +61 -0
- package/dist/esm/view/RedesignedInlineCard/ResolvingView/styled.js +5 -0
- package/dist/esm/view/RedesignedInlineCard/UnauthorisedView/index.js +105 -0
- package/dist/esm/view/RedesignedInlineCard/index.js +146 -0
- package/dist/esm/view/RedesignedInlineCard/styled.js +20 -0
- package/dist/esm/view/RedesignedInlineCard/types.js +1 -0
- package/dist/esm/view/RedesignedInlineCard/utils/withFrameStyleControl.js +35 -0
- package/dist/types/view/RedesignedInlineCard/ErroredView/index.d.ts +22 -0
- package/dist/types/view/RedesignedInlineCard/ForbiddenView/index.d.ts +29 -0
- package/dist/types/view/RedesignedInlineCard/Frame/index.d.ts +15 -0
- package/dist/types/view/RedesignedInlineCard/Frame/styled.d.ts +15 -0
- package/dist/types/view/RedesignedInlineCard/Icon.d.ts +12 -0
- package/dist/types/view/RedesignedInlineCard/IconAndTitleLayout/index.d.ts +28 -0
- package/dist/types/view/RedesignedInlineCard/IconAndTitleLayout/styled.d.ts +36 -0
- package/dist/types/view/RedesignedInlineCard/ResolvedView/index.d.ts +32 -0
- package/dist/types/view/RedesignedInlineCard/ResolvingView/index.d.ts +17 -0
- package/dist/types/view/RedesignedInlineCard/ResolvingView/styled.d.ts +9 -0
- package/dist/types/view/RedesignedInlineCard/UnauthorisedView/index.d.ts +32 -0
- package/dist/types/view/RedesignedInlineCard/index.d.ts +9 -0
- package/dist/types/view/RedesignedInlineCard/styled.d.ts +17 -0
- package/dist/types/view/RedesignedInlineCard/types.d.ts +25 -0
- package/dist/types/view/RedesignedInlineCard/utils/withFrameStyleControl.d.ts +9 -0
- package/dist/types-ts4.5/view/RedesignedInlineCard/ErroredView/index.d.ts +22 -0
- package/dist/types-ts4.5/view/RedesignedInlineCard/ForbiddenView/index.d.ts +29 -0
- package/dist/types-ts4.5/view/RedesignedInlineCard/Frame/index.d.ts +15 -0
- package/dist/types-ts4.5/view/RedesignedInlineCard/Frame/styled.d.ts +15 -0
- package/dist/types-ts4.5/view/RedesignedInlineCard/Icon.d.ts +12 -0
- package/dist/types-ts4.5/view/RedesignedInlineCard/IconAndTitleLayout/index.d.ts +28 -0
- package/dist/types-ts4.5/view/RedesignedInlineCard/IconAndTitleLayout/styled.d.ts +36 -0
- package/dist/types-ts4.5/view/RedesignedInlineCard/ResolvedView/index.d.ts +32 -0
- package/dist/types-ts4.5/view/RedesignedInlineCard/ResolvingView/index.d.ts +17 -0
- package/dist/types-ts4.5/view/RedesignedInlineCard/ResolvingView/styled.d.ts +9 -0
- package/dist/types-ts4.5/view/RedesignedInlineCard/UnauthorisedView/index.d.ts +32 -0
- package/dist/types-ts4.5/view/RedesignedInlineCard/index.d.ts +9 -0
- package/dist/types-ts4.5/view/RedesignedInlineCard/styled.d.ts +17 -0
- package/dist/types-ts4.5/view/RedesignedInlineCard/types.d.ts +25 -0
- package/dist/types-ts4.5/view/RedesignedInlineCard/utils/withFrameStyleControl.d.ts +9 -0
- package/package.json +6 -3
|
@@ -30,9 +30,7 @@ export const Shimmer = ({
|
|
|
30
30
|
}) => {
|
|
31
31
|
const skeletonCustomStyles = {
|
|
32
32
|
position: 'absolute',
|
|
33
|
-
// eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage
|
|
34
33
|
top: '50%',
|
|
35
|
-
// eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage
|
|
36
34
|
left: '50%',
|
|
37
35
|
transform: 'translate(-50%, -50%)',
|
|
38
36
|
marginRight: "var(--ds-space-050, 4px)"
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { R300 } from '@atlaskit/theme/colors';
|
|
4
|
+
import ErrorIcon from '@atlaskit/icon/glyph/error';
|
|
5
|
+
import Button from '@atlaskit/button/custom-theme-button';
|
|
6
|
+
import { Frame } from '../Frame';
|
|
7
|
+
import { IconAndTitleLayout } from '../IconAndTitleLayout';
|
|
8
|
+
import { AKIconWrapper } from '../Icon';
|
|
9
|
+
import { messages } from '../../../messages';
|
|
10
|
+
import { FormattedMessage } from 'react-intl-next';
|
|
11
|
+
import { IconStyledButton } from '../styled';
|
|
12
|
+
import withFrameStyleControl from '../utils/withFrameStyleControl';
|
|
13
|
+
export class InlineCardErroredView extends React.Component {
|
|
14
|
+
constructor(...args) {
|
|
15
|
+
super(...args);
|
|
16
|
+
_defineProperty(this, "frameRef", /*#__PURE__*/React.createRef());
|
|
17
|
+
_defineProperty(this, "handleRetry", event => {
|
|
18
|
+
const {
|
|
19
|
+
onRetry
|
|
20
|
+
} = this.props;
|
|
21
|
+
if (onRetry) {
|
|
22
|
+
event.preventDefault();
|
|
23
|
+
event.stopPropagation();
|
|
24
|
+
onRetry();
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
_defineProperty(this, "renderActionButton", () => {
|
|
28
|
+
const {
|
|
29
|
+
onRetry
|
|
30
|
+
} = this.props;
|
|
31
|
+
const ActionButton = withFrameStyleControl(Button, this.frameRef);
|
|
32
|
+
return onRetry && /*#__PURE__*/React.createElement(ActionButton, {
|
|
33
|
+
spacing: "none",
|
|
34
|
+
component: IconStyledButton,
|
|
35
|
+
onClick: this.handleRetry,
|
|
36
|
+
role: "button"
|
|
37
|
+
}, /*#__PURE__*/React.createElement(FormattedMessage, messages.try_again));
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
render() {
|
|
41
|
+
const {
|
|
42
|
+
url,
|
|
43
|
+
onClick,
|
|
44
|
+
isSelected,
|
|
45
|
+
testId = 'inline-card-errored-view',
|
|
46
|
+
icon,
|
|
47
|
+
message
|
|
48
|
+
} = this.props;
|
|
49
|
+
return /*#__PURE__*/React.createElement(Frame, {
|
|
50
|
+
testId: testId,
|
|
51
|
+
isSelected: isSelected,
|
|
52
|
+
ref: this.frameRef
|
|
53
|
+
}, /*#__PURE__*/React.createElement(IconAndTitleLayout, {
|
|
54
|
+
icon: icon || /*#__PURE__*/React.createElement(AKIconWrapper, null, /*#__PURE__*/React.createElement(ErrorIcon, {
|
|
55
|
+
label: "error",
|
|
56
|
+
size: "small",
|
|
57
|
+
primaryColor: `var(--ds-icon-danger, ${R300})`,
|
|
58
|
+
testId: "errored-view-default-icon"
|
|
59
|
+
})),
|
|
60
|
+
link: url,
|
|
61
|
+
title: url,
|
|
62
|
+
onClick: onClick,
|
|
63
|
+
rightSide: message
|
|
64
|
+
}), this.renderActionButton());
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { R400, N500 } from '@atlaskit/theme/colors';
|
|
5
|
+
import LockIcon from '@atlaskit/icon/glyph/lock-filled';
|
|
6
|
+
import Button from '@atlaskit/button/custom-theme-button';
|
|
7
|
+
import { Frame } from '../Frame';
|
|
8
|
+
import { IconAndTitleLayout } from '../IconAndTitleLayout';
|
|
9
|
+
import { AKIconWrapper } from '../Icon';
|
|
10
|
+
import { messages } from '../../../messages';
|
|
11
|
+
import { FormattedMessage } from 'react-intl-next';
|
|
12
|
+
import { IconStyledButton } from '../styled';
|
|
13
|
+
import Lozenge from '@atlaskit/lozenge';
|
|
14
|
+
import { LozengeWrapper } from '../IconAndTitleLayout/styled';
|
|
15
|
+
import withFrameStyleControl from '../utils/withFrameStyleControl';
|
|
16
|
+
const FallbackForbiddenIcon = /*#__PURE__*/React.createElement(AKIconWrapper, null, /*#__PURE__*/React.createElement(LockIcon, {
|
|
17
|
+
label: "error",
|
|
18
|
+
size: "small",
|
|
19
|
+
primaryColor: `var(--ds-icon-danger, ${R400})`,
|
|
20
|
+
testId: "forbidden-view-fallback-icon"
|
|
21
|
+
}));
|
|
22
|
+
export class InlineCardForbiddenView extends React.Component {
|
|
23
|
+
constructor(...args) {
|
|
24
|
+
var _this$props, _this$props$requestAc;
|
|
25
|
+
super(...args);
|
|
26
|
+
_defineProperty(this, "frameRef", /*#__PURE__*/React.createRef());
|
|
27
|
+
_defineProperty(this, "state", {
|
|
28
|
+
hasRequestAccessContextMessage: !!((_this$props = this.props) !== null && _this$props !== void 0 && (_this$props$requestAc = _this$props.requestAccessContext) !== null && _this$props$requestAc !== void 0 && _this$props$requestAc.callToActionMessageKey)
|
|
29
|
+
});
|
|
30
|
+
_defineProperty(this, "handleRetry", event => {
|
|
31
|
+
const {
|
|
32
|
+
onAuthorise
|
|
33
|
+
} = this.props;
|
|
34
|
+
event.preventDefault();
|
|
35
|
+
event.stopPropagation();
|
|
36
|
+
if (onAuthorise) {
|
|
37
|
+
onAuthorise();
|
|
38
|
+
} else {
|
|
39
|
+
var _this$props2, _this$props2$requestA, _this$props2$requestA2;
|
|
40
|
+
(_this$props2 = this.props) === null || _this$props2 === void 0 ? void 0 : (_this$props2$requestA = _this$props2.requestAccessContext) === null || _this$props2$requestA === void 0 ? void 0 : (_this$props2$requestA2 = _this$props2$requestA.action) === null || _this$props2$requestA2 === void 0 ? void 0 : _this$props2$requestA2.promise();
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
_defineProperty(this, "renderForbiddenAccessMessage", () => {
|
|
44
|
+
var _this$props3, _this$props3$requestA;
|
|
45
|
+
if ((_this$props3 = this.props) !== null && _this$props3 !== void 0 && (_this$props3$requestA = _this$props3.requestAccessContext) !== null && _this$props3$requestA !== void 0 && _this$props3$requestA.callToActionMessageKey) {
|
|
46
|
+
const {
|
|
47
|
+
callToActionMessageKey
|
|
48
|
+
} = this.props.requestAccessContext;
|
|
49
|
+
return /*#__PURE__*/React.createElement(FormattedMessage, _extends({}, messages[callToActionMessageKey], {
|
|
50
|
+
values: {
|
|
51
|
+
context: this.props.context
|
|
52
|
+
}
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(FormattedMessage, messages.invalid_permissions, formattedMessage => {
|
|
56
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, formattedMessage);
|
|
57
|
+
}));
|
|
58
|
+
});
|
|
59
|
+
_defineProperty(this, "renderActionButton", () => {
|
|
60
|
+
const {
|
|
61
|
+
onAuthorise
|
|
62
|
+
} = this.props;
|
|
63
|
+
const ActionButton = withFrameStyleControl(Button, this.frameRef);
|
|
64
|
+
if (this.state.hasRequestAccessContextMessage) {
|
|
65
|
+
return /*#__PURE__*/React.createElement(ActionButton, {
|
|
66
|
+
spacing: "none",
|
|
67
|
+
onClick: this.handleRetry,
|
|
68
|
+
component: IconStyledButton,
|
|
69
|
+
testId: "button-connect-other-account",
|
|
70
|
+
role: "button"
|
|
71
|
+
}, this.renderForbiddenAccessMessage());
|
|
72
|
+
}
|
|
73
|
+
if (onAuthorise) {
|
|
74
|
+
return /*#__PURE__*/React.createElement(Button, {
|
|
75
|
+
spacing: "none",
|
|
76
|
+
onClick: this.handleRetry,
|
|
77
|
+
appearance: "subtle-link",
|
|
78
|
+
testId: "button-connect-other-account",
|
|
79
|
+
role: "button"
|
|
80
|
+
}, /*#__PURE__*/React.createElement(LozengeWrapper, null, /*#__PURE__*/React.createElement(Lozenge, {
|
|
81
|
+
appearance: 'moved'
|
|
82
|
+
}, this.renderForbiddenAccessMessage())));
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
render() {
|
|
88
|
+
const {
|
|
89
|
+
url,
|
|
90
|
+
icon,
|
|
91
|
+
onClick,
|
|
92
|
+
isSelected,
|
|
93
|
+
testId = 'inline-card-forbidden-view'
|
|
94
|
+
} = this.props;
|
|
95
|
+
return /*#__PURE__*/React.createElement(Frame, {
|
|
96
|
+
testId: testId,
|
|
97
|
+
isSelected: isSelected,
|
|
98
|
+
ref: this.frameRef
|
|
99
|
+
}, /*#__PURE__*/React.createElement(IconAndTitleLayout, {
|
|
100
|
+
icon: icon ? icon : FallbackForbiddenIcon,
|
|
101
|
+
link: url,
|
|
102
|
+
title: url,
|
|
103
|
+
onClick: onClick,
|
|
104
|
+
titleColor: `var(--ds-text-subtle, ${N500})`
|
|
105
|
+
}), this.renderActionButton());
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React, { useCallback, forwardRef } from 'react';
|
|
2
|
+
import { useGlobalTheme } from '@atlaskit/theme/components';
|
|
3
|
+
import { WrapperAnchor, WrapperSpan } from './styled';
|
|
4
|
+
import { useMouseDownEvent } from '../../../state/analytics/useLinkClicked';
|
|
5
|
+
export const Frame = /*#__PURE__*/forwardRef((props, ref) => {
|
|
6
|
+
const {
|
|
7
|
+
isSelected,
|
|
8
|
+
children,
|
|
9
|
+
onClick,
|
|
10
|
+
link,
|
|
11
|
+
withoutBackground,
|
|
12
|
+
testId,
|
|
13
|
+
className
|
|
14
|
+
} = props;
|
|
15
|
+
const handleClick = useCallback(event => {
|
|
16
|
+
if (onClick) {
|
|
17
|
+
event.preventDefault();
|
|
18
|
+
event.stopPropagation();
|
|
19
|
+
onClick(event);
|
|
20
|
+
}
|
|
21
|
+
}, [onClick]);
|
|
22
|
+
const handleKeyPress = useCallback(event => {
|
|
23
|
+
if (event.key !== ' ' && event.key !== 'Enter') {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (onClick) {
|
|
27
|
+
event.preventDefault();
|
|
28
|
+
event.stopPropagation();
|
|
29
|
+
onClick(event);
|
|
30
|
+
}
|
|
31
|
+
}, [onClick]);
|
|
32
|
+
const handleMouseDown = useMouseDownEvent();
|
|
33
|
+
const isInteractive = Boolean(onClick);
|
|
34
|
+
|
|
35
|
+
// Depending on whenever Frame was given onClick or link itself we display span or anchor elements
|
|
36
|
+
const Wrapper = link || onClick ? WrapperAnchor : WrapperSpan;
|
|
37
|
+
|
|
38
|
+
// TODO Theming doesn't work right now in editor. Required React context does not trickle down atm.
|
|
39
|
+
// It will be worked as part of https://product-fabric.atlassian.net/jira/servicedesk/projects/DTR/queues/issue/DTR-154
|
|
40
|
+
return /*#__PURE__*/React.createElement(Wrapper, {
|
|
41
|
+
theme: useGlobalTheme(),
|
|
42
|
+
href: link,
|
|
43
|
+
withoutBackground: withoutBackground,
|
|
44
|
+
isSelected: isSelected,
|
|
45
|
+
isInteractive: isInteractive,
|
|
46
|
+
tabIndex: isInteractive ? 0 : undefined,
|
|
47
|
+
role: isInteractive ? 'button' : undefined,
|
|
48
|
+
onClick: handleClick,
|
|
49
|
+
onMouseDown: handleMouseDown,
|
|
50
|
+
onKeyPress: handleKeyPress,
|
|
51
|
+
"data-testid": testId,
|
|
52
|
+
className: className,
|
|
53
|
+
ref: ref
|
|
54
|
+
}, children);
|
|
55
|
+
});
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import styled from '@emotion/styled';
|
|
2
|
+
import { B50, B100, B200, B400, N20, N40, N500 } from '@atlaskit/theme/colors';
|
|
3
|
+
import { themed } from '@atlaskit/theme/components';
|
|
4
|
+
const BACKGROUND_COLOR_DARK = '#262B31';
|
|
5
|
+
const selected = `
|
|
6
|
+
cursor: pointer;
|
|
7
|
+
box-shadow: 0 0 0 2px ${`var(--ds-border-selected, ${B100})`};
|
|
8
|
+
outline: none;
|
|
9
|
+
user-select: none;
|
|
10
|
+
&, :hover, :focus, :active {
|
|
11
|
+
text-decoration: none;
|
|
12
|
+
}
|
|
13
|
+
&:hover {
|
|
14
|
+
border: 1px solid ${`var(--ds-border-input, ${N40})`};
|
|
15
|
+
}
|
|
16
|
+
`;
|
|
17
|
+
const isInteractive = ({
|
|
18
|
+
isInteractive
|
|
19
|
+
}) => {
|
|
20
|
+
if (isInteractive) {
|
|
21
|
+
return `
|
|
22
|
+
:hover {
|
|
23
|
+
background-color: ${themed({
|
|
24
|
+
light: `var(--ds-background-neutral-subtle-hovered, ${N20})`,
|
|
25
|
+
dark: `var(--ds-background-neutral-subtle-hovered, ${BACKGROUND_COLOR_DARK})`
|
|
26
|
+
})};
|
|
27
|
+
}
|
|
28
|
+
:active {
|
|
29
|
+
background-color: ${themed({
|
|
30
|
+
light: `var(--ds-background-selected, ${B50})`,
|
|
31
|
+
dark: `var(--ds-background-selected, ${BACKGROUND_COLOR_DARK})`
|
|
32
|
+
})};
|
|
33
|
+
}
|
|
34
|
+
:focus {
|
|
35
|
+
${selected}
|
|
36
|
+
}
|
|
37
|
+
`;
|
|
38
|
+
} else {
|
|
39
|
+
return '';
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
const isSelected = ({
|
|
43
|
+
isSelected
|
|
44
|
+
}) => {
|
|
45
|
+
if (isSelected) {
|
|
46
|
+
return selected;
|
|
47
|
+
} else {
|
|
48
|
+
return 'user-select: text';
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/*
|
|
53
|
+
Inline smart cards should have the following layout:
|
|
54
|
+
------------------------------------
|
|
55
|
+
| icon | title | action OR lozenge |
|
|
56
|
+
------------------------------------
|
|
57
|
+
The aim is to ensure (1) all children are
|
|
58
|
+
in line with each other, (2) are vertically
|
|
59
|
+
centered.
|
|
60
|
+
*/
|
|
61
|
+
// NB: `padding` consistent with @mentions.
|
|
62
|
+
// NB: `display: inline` required for `box-decoration-break` to work.
|
|
63
|
+
// NB: `box-decoration-break` required for retaining properties (border-radius) on wrap.
|
|
64
|
+
const baseWrapperStyle = props => `
|
|
65
|
+
line-height: 22px;
|
|
66
|
+
padding: 2px 0px;
|
|
67
|
+
${props.withoutBackground ? `padding-left: 0; margin-left:-2px;` : ''}
|
|
68
|
+
display: inline;
|
|
69
|
+
box-decoration-break: clone;
|
|
70
|
+
border-radius: ${"var(--ds-border-radius-100, 3px)"};
|
|
71
|
+
color: ${themed({
|
|
72
|
+
light: `var(--ds-link, ${B400})`,
|
|
73
|
+
dark: "var(--ds-link, #4794FF)"
|
|
74
|
+
})(props)};
|
|
75
|
+
|
|
76
|
+
background-color: ${props.withoutBackground ? '' : themed({
|
|
77
|
+
light: "var(--ds-surface-raised, white)",
|
|
78
|
+
dark: `var(--ds-surface-raised, ${BACKGROUND_COLOR_DARK})`
|
|
79
|
+
})(props)};
|
|
80
|
+
|
|
81
|
+
${isSelected(props)};
|
|
82
|
+
|
|
83
|
+
${props.withoutBackground ? '' : themed({
|
|
84
|
+
light: `border: 1px solid ${`var(--ds-border-input, ${N40})`};`,
|
|
85
|
+
dark: `border: 1px solid ${`var(--ds-border-input, ${N500})`};`
|
|
86
|
+
})(props)}
|
|
87
|
+
&:hover {
|
|
88
|
+
${themed({
|
|
89
|
+
light: `border-color: ${`var(--ds-border-accent-blue, ${B200})`};`,
|
|
90
|
+
dark: `border-color: ${`var(--ds-border-accent-blue, ${B200})`};`
|
|
91
|
+
})(props)}
|
|
92
|
+
}
|
|
93
|
+
&, :hover, :focus, :active {
|
|
94
|
+
${props.withoutBackground ? '' : 'text-decoration: none;'}
|
|
95
|
+
}
|
|
96
|
+
transition: 0.1s all ease-in-out;
|
|
97
|
+
-moz-user-select: none;
|
|
98
|
+
`;
|
|
99
|
+
export const WrapperAnchor = styled.a`
|
|
100
|
+
${baseWrapperStyle}
|
|
101
|
+
${isInteractive}
|
|
102
|
+
`;
|
|
103
|
+
WrapperAnchor.displayName = 'WrapperAnchor';
|
|
104
|
+
export const WrapperSpan = styled.span`
|
|
105
|
+
${baseWrapperStyle}
|
|
106
|
+
`;
|
|
107
|
+
WrapperSpan.displayName = 'WrapperSpan';
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import styled from '@emotion/styled';
|
|
2
|
+
import { Skeleton } from '@atlaskit/linking-common';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
// TODO: Figure out a more scalable/responsive solution
|
|
6
|
+
// for vertical alignment.
|
|
7
|
+
// Current rationale: vertically positioned at the top of
|
|
8
|
+
// the smart card container (when set to 0). Offset this
|
|
9
|
+
// to position it with appropriate whitespace from the top.
|
|
10
|
+
export const Icon = styled.img`
|
|
11
|
+
height: 14px;
|
|
12
|
+
width: 14px;
|
|
13
|
+
margin-right: ${"var(--ds-space-050, 4px)"};
|
|
14
|
+
border-radius: 2px;
|
|
15
|
+
user-select: none;
|
|
16
|
+
position: absolute;
|
|
17
|
+
top: 50%;
|
|
18
|
+
left: 50%;
|
|
19
|
+
transform: translate(-50%, -50%);
|
|
20
|
+
`;
|
|
21
|
+
|
|
22
|
+
// Used for 'untrue' icons which claim to be 16x16 but
|
|
23
|
+
// are less than that in height/width.
|
|
24
|
+
// TODO: Replace this override with proper AtlasKit solution.
|
|
25
|
+
export const AKIconWrapper = styled.span`
|
|
26
|
+
margin-right: calc(-1 * ${"var(--ds-space-025, 2px)"});
|
|
27
|
+
`;
|
|
28
|
+
export const Shimmer = ({
|
|
29
|
+
testId
|
|
30
|
+
}) => {
|
|
31
|
+
const skeletonCustomStyles = {
|
|
32
|
+
position: 'absolute',
|
|
33
|
+
top: '50%',
|
|
34
|
+
left: '50%',
|
|
35
|
+
transform: 'translate(-50%, -50%)',
|
|
36
|
+
marginRight: "var(--ds-space-050, 4px)"
|
|
37
|
+
};
|
|
38
|
+
return /*#__PURE__*/React.createElement(Skeleton, {
|
|
39
|
+
width: 14,
|
|
40
|
+
height: 14,
|
|
41
|
+
borderRadius: 2,
|
|
42
|
+
testId: testId,
|
|
43
|
+
style: skeletonCustomStyles
|
|
44
|
+
});
|
|
45
|
+
};
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import ImageLoader from 'react-render-image';
|
|
4
|
+
import { Icon, Shimmer } from '../Icon';
|
|
5
|
+
import { IconEmptyWrapper, IconPositionWrapper, IconTitleWrapper, IconWrapper, TitleWrapper, EmojiWrapper, TitleWrapperClassName } from './styled';
|
|
6
|
+
import LinkIcon from '@atlaskit/icon/glyph/link';
|
|
7
|
+
import { LinkAppearance, NoLinkAppearance } from '../styled';
|
|
8
|
+
export class IconAndTitleLayout extends React.Component {
|
|
9
|
+
constructor(...args) {
|
|
10
|
+
super(...args);
|
|
11
|
+
_defineProperty(this, "handleClick", event => {
|
|
12
|
+
const {
|
|
13
|
+
onClick
|
|
14
|
+
} = this.props;
|
|
15
|
+
if (onClick) {
|
|
16
|
+
event.preventDefault();
|
|
17
|
+
event.stopPropagation();
|
|
18
|
+
onClick(event);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
_defineProperty(this, "handleKeyPress", event => {
|
|
22
|
+
const {
|
|
23
|
+
onClick
|
|
24
|
+
} = this.props;
|
|
25
|
+
if (event.key !== ' ' && event.key !== 'Enter') {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (onClick) {
|
|
29
|
+
event.preventDefault();
|
|
30
|
+
event.stopPropagation();
|
|
31
|
+
onClick(event);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
renderAtlaskitIcon() {
|
|
36
|
+
const {
|
|
37
|
+
icon,
|
|
38
|
+
emoji
|
|
39
|
+
} = this.props;
|
|
40
|
+
if (emoji) {
|
|
41
|
+
return /*#__PURE__*/React.createElement(EmojiWrapper, null, emoji);
|
|
42
|
+
}
|
|
43
|
+
if (!icon || typeof icon === 'string') {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
return /*#__PURE__*/React.createElement(IconWrapper, null, icon);
|
|
47
|
+
}
|
|
48
|
+
renderImageIcon(errored, testId) {
|
|
49
|
+
const {
|
|
50
|
+
icon: url
|
|
51
|
+
} = this.props;
|
|
52
|
+
if (!url || typeof url !== 'string') {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
return /*#__PURE__*/React.createElement(ImageLoader, {
|
|
56
|
+
src: url,
|
|
57
|
+
loaded: /*#__PURE__*/React.createElement(Icon, {
|
|
58
|
+
className: "smart-link-icon",
|
|
59
|
+
src: url,
|
|
60
|
+
"data-testid": `${testId}-image`
|
|
61
|
+
}),
|
|
62
|
+
errored: errored,
|
|
63
|
+
loading: /*#__PURE__*/React.createElement(Shimmer, {
|
|
64
|
+
testId: `${testId}-loading`
|
|
65
|
+
})
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
renderIconPlaceholder(testId) {
|
|
69
|
+
const {
|
|
70
|
+
defaultIcon
|
|
71
|
+
} = this.props;
|
|
72
|
+
if (defaultIcon) {
|
|
73
|
+
return /*#__PURE__*/React.createElement(IconWrapper, null, defaultIcon);
|
|
74
|
+
}
|
|
75
|
+
return /*#__PURE__*/React.createElement(IconWrapper, null, /*#__PURE__*/React.createElement(LinkIcon, {
|
|
76
|
+
label: "link",
|
|
77
|
+
size: "small",
|
|
78
|
+
testId: `${testId}-default`
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
renderIcon(testId) {
|
|
82
|
+
// We render two kinds of icons here:
|
|
83
|
+
// - Image: acquired from either DAC or Teamwork Platform Apps;
|
|
84
|
+
// - Atlaskit Icon: an Atlaskit SVG;
|
|
85
|
+
// Each of these are scaled down to 12x12.
|
|
86
|
+
const icon = this.renderAtlaskitIcon();
|
|
87
|
+
if (icon) {
|
|
88
|
+
return icon;
|
|
89
|
+
}
|
|
90
|
+
const placeholder = this.renderIconPlaceholder(testId);
|
|
91
|
+
const image = this.renderImageIcon(placeholder, testId);
|
|
92
|
+
return image || placeholder;
|
|
93
|
+
}
|
|
94
|
+
render() {
|
|
95
|
+
const {
|
|
96
|
+
children,
|
|
97
|
+
title,
|
|
98
|
+
titleColor,
|
|
99
|
+
titleTextColor,
|
|
100
|
+
link,
|
|
101
|
+
rightSide,
|
|
102
|
+
testId = 'inline-card-icon-and-title'
|
|
103
|
+
} = this.props;
|
|
104
|
+
const titlePart = /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(IconPositionWrapper, null, children || /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(IconEmptyWrapper, null), this.renderIcon(testId))), /*#__PURE__*/React.createElement(TitleWrapper, {
|
|
105
|
+
style: {
|
|
106
|
+
color: titleTextColor
|
|
107
|
+
},
|
|
108
|
+
className: TitleWrapperClassName
|
|
109
|
+
}, title));
|
|
110
|
+
return /*#__PURE__*/React.createElement(IconTitleWrapper, {
|
|
111
|
+
style: {
|
|
112
|
+
color: titleColor
|
|
113
|
+
},
|
|
114
|
+
"data-testid": testId
|
|
115
|
+
}, link ? /*#__PURE__*/React.createElement(LinkAppearance, {
|
|
116
|
+
href: link,
|
|
117
|
+
onClick: this.handleClick,
|
|
118
|
+
onKeyPress: this.handleKeyPress
|
|
119
|
+
}, titlePart) : titlePart, rightSide ? /*#__PURE__*/React.createElement(NoLinkAppearance, null, rightSide) : null);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
_defineProperty(IconAndTitleLayout, "defaultProps", {
|
|
123
|
+
rightSideSpacer: true
|
|
124
|
+
});
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import styled from '@emotion/styled';
|
|
2
|
+
// TODO: remove this override behaviour for @atlaskit/icon-object
|
|
3
|
+
export const IconObjectOverrides = `
|
|
4
|
+
& > span {
|
|
5
|
+
height: 16px;
|
|
6
|
+
width: 14px;
|
|
7
|
+
position: absolute;
|
|
8
|
+
top: 3px;
|
|
9
|
+
left: 0;
|
|
10
|
+
line-height: 14px;
|
|
11
|
+
& > svg {
|
|
12
|
+
position: absolute;
|
|
13
|
+
top: 50%;
|
|
14
|
+
left: 50%;
|
|
15
|
+
transform: translate(-50%, -50%);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
`;
|
|
19
|
+
// TODO: remove this override behaviour for @atlaskit/icon
|
|
20
|
+
export const IconOverrides = `
|
|
21
|
+
|
|
22
|
+
& > * > span {
|
|
23
|
+
height: 16px;
|
|
24
|
+
width: 14px;
|
|
25
|
+
position: absolute;
|
|
26
|
+
left: 0;
|
|
27
|
+
& > svg {
|
|
28
|
+
position: absolute;
|
|
29
|
+
top: 50%;
|
|
30
|
+
left: 50%;
|
|
31
|
+
transform: translate(-50%, -50%);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
`;
|
|
35
|
+
|
|
36
|
+
// Wraps all icons represented in Inline Links. Icons have three sources/types:
|
|
37
|
+
// - JSON-LD: from the generator.icon property coming back from ORS.
|
|
38
|
+
// - @atlaskit/icon: for lock icons, unauthorized, etc.
|
|
39
|
+
// - @atlaskit/icon-object: for object icons, e.g. repository, branch, etc.
|
|
40
|
+
// NB: the first set of overrides style icons imported from @atlaskit/icon-object correctly.
|
|
41
|
+
// NB: the second set of overrides style icons imported from @atlaskit/icon correctly.
|
|
42
|
+
export const IconWrapper = styled.span`
|
|
43
|
+
user-select: none;
|
|
44
|
+
${IconOverrides}
|
|
45
|
+
${IconObjectOverrides}
|
|
46
|
+
`;
|
|
47
|
+
|
|
48
|
+
// Wraps all emoji in Inline Links similar to icon
|
|
49
|
+
export const EmojiWrapper = styled.span`
|
|
50
|
+
display: inline-block;
|
|
51
|
+
margin-right: ${"var(--ds-space-025, 2px)"};
|
|
52
|
+
user-select: none;
|
|
53
|
+
${IconOverrides}
|
|
54
|
+
${IconObjectOverrides}
|
|
55
|
+
`;
|
|
56
|
+
|
|
57
|
+
// The main 'wrapping' element, title of the content.
|
|
58
|
+
// NB: `white-space` adds little whitespace before wrapping.
|
|
59
|
+
// NB: `word-break` line breaks as soon as an overflow takes place.
|
|
60
|
+
export const IconTitleWrapper = styled.span`
|
|
61
|
+
white-space: pre-wrap;
|
|
62
|
+
word-break: break-all;
|
|
63
|
+
box-decoration-break: clone;
|
|
64
|
+
padding: ${"var(--ds-space-025, 2px)"} ${"var(--ds-space-050, 4px)"};
|
|
65
|
+
`;
|
|
66
|
+
|
|
67
|
+
// TODO: Replace overrides with proper AtlasKit solution.
|
|
68
|
+
export const LozengeWrapper = styled.span`
|
|
69
|
+
display: inline-block;
|
|
70
|
+
vertical-align: 1px;
|
|
71
|
+
margin: 0 ${"var(--ds-space-050, 4px)"} 0 ${"var(--ds-space-025, 2px)"};
|
|
72
|
+
`;
|
|
73
|
+
export const RightIconPositionWrapper = styled.span`
|
|
74
|
+
margin-left: ${"var(--ds-space-025, 2px)"};
|
|
75
|
+
position: relative;
|
|
76
|
+
display: inline-block;
|
|
77
|
+
`;
|
|
78
|
+
|
|
79
|
+
// The following components are used to absolutely position icons in the vertical center.
|
|
80
|
+
// - IconPositionWrapper: the `relative` parent which has no height in itself.
|
|
81
|
+
// - IconEmptyWrapper: the child which forces `IconPositionWrapper` to have a height.
|
|
82
|
+
export const IconPositionWrapper = styled.span`
|
|
83
|
+
margin-right: ${"var(--ds-space-050, 4px)"};
|
|
84
|
+
position: relative;
|
|
85
|
+
display: inline-block;
|
|
86
|
+
`;
|
|
87
|
+
export const IconEmptyWrapper = styled.span`
|
|
88
|
+
width: 14px;
|
|
89
|
+
height: 100%;
|
|
90
|
+
display: inline-block;
|
|
91
|
+
opacity: 0;
|
|
92
|
+
`;
|
|
93
|
+
|
|
94
|
+
// With emotion it's not possible to use reference to `TitleWrapper` as part of a selector,
|
|
95
|
+
// To achieve same result we use classname instead.
|
|
96
|
+
export const TitleWrapperClassName = 'smart-link-title-wrapper';
|
|
97
|
+
export const TitleWrapper = styled.span``;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Frame } from '../Frame';
|
|
3
|
+
import Lozenge from '@atlaskit/lozenge';
|
|
4
|
+
import { IconAndTitleLayout } from '../IconAndTitleLayout';
|
|
5
|
+
import { LozengeWrapper } from '../IconAndTitleLayout/styled';
|
|
6
|
+
import { HoverCard } from '../../HoverCard/index';
|
|
7
|
+
export class InlineCardResolvedView extends React.Component {
|
|
8
|
+
renderLozenge() {
|
|
9
|
+
const {
|
|
10
|
+
lozenge
|
|
11
|
+
} = this.props;
|
|
12
|
+
if (!lozenge) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
return /*#__PURE__*/React.createElement(LozengeWrapper, null, /*#__PURE__*/React.createElement(Lozenge, {
|
|
16
|
+
testId: "inline-card-resolved-view-lozenge",
|
|
17
|
+
appearance: lozenge.appearance || 'default',
|
|
18
|
+
isBold: lozenge.isBold
|
|
19
|
+
}, lozenge.text));
|
|
20
|
+
}
|
|
21
|
+
render() {
|
|
22
|
+
const {
|
|
23
|
+
id,
|
|
24
|
+
title = '',
|
|
25
|
+
isSelected,
|
|
26
|
+
onClick,
|
|
27
|
+
icon,
|
|
28
|
+
link,
|
|
29
|
+
testId = 'inline-card-resolved-view',
|
|
30
|
+
titleTextColor,
|
|
31
|
+
titlePrefix,
|
|
32
|
+
showHoverPreview = false,
|
|
33
|
+
showServerActions = false
|
|
34
|
+
} = this.props;
|
|
35
|
+
const inlineCardResolvedView = /*#__PURE__*/React.createElement(Frame, {
|
|
36
|
+
testId: testId,
|
|
37
|
+
link: link,
|
|
38
|
+
isSelected: isSelected,
|
|
39
|
+
onClick: onClick
|
|
40
|
+
}, /*#__PURE__*/React.createElement(IconAndTitleLayout, {
|
|
41
|
+
emoji: titlePrefix,
|
|
42
|
+
icon: icon,
|
|
43
|
+
title: title,
|
|
44
|
+
titleTextColor: titleTextColor
|
|
45
|
+
}), this.renderLozenge());
|
|
46
|
+
if (showHoverPreview && link) {
|
|
47
|
+
return /*#__PURE__*/React.createElement(HoverCard, {
|
|
48
|
+
id: id,
|
|
49
|
+
showServerActions: showServerActions,
|
|
50
|
+
url: link
|
|
51
|
+
}, inlineCardResolvedView);
|
|
52
|
+
}
|
|
53
|
+
return inlineCardResolvedView;
|
|
54
|
+
}
|
|
55
|
+
}
|