@atlaskit/smart-card 21.2.0 → 22.1.0
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 +56 -0
- package/dist/cjs/extractors/block/index.js +6 -7
- package/dist/cjs/extractors/common/actions/extractPreviewAction.js +16 -19
- package/dist/cjs/state/actions/index.js +54 -10
- package/dist/cjs/state/analytics/types.js +5 -0
- package/dist/cjs/state/analytics/useSmartLinkAnalytics.js +429 -109
- package/dist/cjs/state/hooks-external/useSmartLinkActions.js +5 -3
- package/dist/cjs/utils/analytics/analytics.js +241 -74
- package/dist/cjs/utils/analytics/index.js +32 -5
- package/dist/cjs/utils/mocks.js +28 -2
- package/dist/cjs/version.json +1 -1
- package/dist/cjs/view/BlockCard/actions/PreviewAction.js +2 -2
- package/dist/cjs/view/BlockCard/index.js +6 -5
- package/dist/cjs/view/CardWithUrl/component.js +27 -5
- package/dist/cjs/view/CardWithUrl/loader.js +6 -1
- package/dist/cjs/view/EmbedCard/index.js +3 -2
- package/dist/cjs/view/EmbedModal/components/analytics/index.js +100 -0
- package/dist/cjs/view/EmbedModal/components/analytics/types.js +5 -0
- package/dist/cjs/view/EmbedModal/components/size-experiment/index.js +5 -10
- package/dist/cjs/view/EmbedModal/index.js +54 -15
- package/dist/cjs/view/EmbedModal/types.js +9 -1
- package/dist/cjs/view/FlexibleCard/components/blocks/block/index.js +17 -3
- package/dist/cjs/view/FlexibleCard/components/blocks/preview-block/index.js +5 -2
- package/dist/cjs/view/FlexibleCard/components/common/image-icon/index.js +4 -2
- package/dist/cjs/view/FlexibleCard/components/common/loading-skeleton/index.js +1 -2
- package/dist/cjs/view/FlexibleCard/components/elements/media/index.js +5 -2
- package/dist/cjs/view/HoverCard/components/HoverCardComponent.js +11 -3
- package/dist/cjs/view/HoverCard/components/HoverCardContent.js +36 -8
- package/dist/cjs/view/HoverCard/components/SnippetOrPreview.js +74 -0
- package/dist/cjs/view/HoverCard/index.js +6 -1
- package/dist/cjs/view/HoverCard/styled.js +11 -3
- package/dist/cjs/view/common/Modal.js +29 -4
- package/dist/cjs/view/common/ModalHeader.js +3 -2
- package/dist/es2019/extractors/block/index.js +6 -7
- package/dist/es2019/extractors/common/actions/extractPreviewAction.js +16 -10
- package/dist/es2019/state/actions/index.js +54 -10
- package/dist/es2019/state/analytics/types.js +1 -0
- package/dist/es2019/state/analytics/useSmartLinkAnalytics.js +424 -41
- package/dist/es2019/state/hooks-external/useSmartLinkActions.js +5 -3
- package/dist/es2019/utils/analytics/analytics.js +254 -79
- package/dist/es2019/utils/analytics/index.js +32 -4
- package/dist/es2019/utils/mocks.js +26 -1
- package/dist/es2019/version.json +1 -1
- package/dist/es2019/view/BlockCard/actions/PreviewAction.js +3 -3
- package/dist/es2019/view/BlockCard/index.js +5 -4
- package/dist/es2019/view/CardWithUrl/component.js +27 -5
- package/dist/es2019/view/CardWithUrl/loader.js +6 -1
- package/dist/es2019/view/EmbedCard/index.js +3 -2
- package/dist/es2019/view/EmbedModal/components/analytics/index.js +80 -0
- package/dist/es2019/view/EmbedModal/components/analytics/types.js +1 -0
- package/dist/es2019/view/EmbedModal/components/size-experiment/index.js +5 -9
- package/dist/es2019/view/EmbedModal/index.js +46 -13
- package/dist/es2019/view/EmbedModal/types.js +6 -1
- package/dist/es2019/view/FlexibleCard/components/blocks/block/index.js +17 -7
- package/dist/es2019/view/FlexibleCard/components/blocks/preview-block/index.js +4 -1
- package/dist/es2019/view/FlexibleCard/components/common/image-icon/index.js +4 -2
- package/dist/es2019/view/FlexibleCard/components/common/loading-skeleton/index.js +2 -3
- package/dist/es2019/view/FlexibleCard/components/elements/media/index.js +5 -2
- package/dist/es2019/view/HoverCard/components/HoverCardComponent.js +11 -3
- package/dist/es2019/view/HoverCard/components/HoverCardContent.js +36 -10
- package/dist/es2019/view/HoverCard/components/SnippetOrPreview.js +42 -0
- package/dist/es2019/view/HoverCard/index.js +6 -1
- package/dist/es2019/view/HoverCard/styled.js +8 -0
- package/dist/es2019/view/common/Modal.js +27 -6
- package/dist/es2019/view/common/ModalHeader.js +3 -2
- package/dist/esm/extractors/block/index.js +6 -7
- package/dist/esm/extractors/common/actions/extractPreviewAction.js +17 -19
- package/dist/esm/state/actions/index.js +54 -10
- package/dist/esm/state/analytics/types.js +1 -0
- package/dist/esm/state/analytics/useSmartLinkAnalytics.js +428 -111
- package/dist/esm/state/hooks-external/useSmartLinkActions.js +5 -3
- package/dist/esm/utils/analytics/analytics.js +241 -74
- package/dist/esm/utils/analytics/index.js +31 -4
- package/dist/esm/utils/mocks.js +25 -0
- package/dist/esm/version.json +1 -1
- package/dist/esm/view/BlockCard/actions/PreviewAction.js +3 -3
- package/dist/esm/view/BlockCard/index.js +5 -4
- package/dist/esm/view/CardWithUrl/component.js +27 -5
- package/dist/esm/view/CardWithUrl/loader.js +6 -1
- package/dist/esm/view/EmbedCard/index.js +3 -2
- package/dist/esm/view/EmbedModal/components/analytics/index.js +82 -0
- package/dist/esm/view/EmbedModal/components/analytics/types.js +1 -0
- package/dist/esm/view/EmbedModal/components/size-experiment/index.js +5 -10
- package/dist/esm/view/EmbedModal/index.js +52 -15
- package/dist/esm/view/EmbedModal/types.js +6 -1
- package/dist/esm/view/FlexibleCard/components/blocks/block/index.js +11 -3
- package/dist/esm/view/FlexibleCard/components/blocks/preview-block/index.js +5 -2
- package/dist/esm/view/FlexibleCard/components/common/image-icon/index.js +4 -2
- package/dist/esm/view/FlexibleCard/components/common/loading-skeleton/index.js +1 -2
- package/dist/esm/view/FlexibleCard/components/elements/media/index.js +5 -2
- package/dist/esm/view/HoverCard/components/HoverCardComponent.js +11 -3
- package/dist/esm/view/HoverCard/components/HoverCardContent.js +36 -10
- package/dist/esm/view/HoverCard/components/SnippetOrPreview.js +53 -0
- package/dist/esm/view/HoverCard/index.js +6 -1
- package/dist/esm/view/HoverCard/styled.js +6 -2
- package/dist/esm/view/common/Modal.js +28 -6
- package/dist/esm/view/common/ModalHeader.js +3 -2
- package/dist/types/extractors/block/types.d.ts +4 -2
- package/dist/types/extractors/common/actions/extractPreviewAction.d.ts +7 -5
- package/dist/types/state/analytics/types.d.ts +9 -0
- package/dist/types/state/analytics/useSmartLinkAnalytics.d.ts +41 -24
- package/dist/types/state/hooks/useSmartLink.d.ts +26 -18
- package/dist/types/state/hooks-external/useSmartLinkActions.d.ts +6 -2
- package/dist/types/utils/analytics/analytics.d.ts +19 -21
- package/dist/types/utils/analytics/index.d.ts +2 -2
- package/dist/types/utils/analytics/types.d.ts +91 -0
- package/dist/types/utils/mocks.d.ts +48 -0
- package/dist/types/utils/types.d.ts +3 -1
- package/dist/types/view/BlockCard/actions/PreviewAction.d.ts +4 -0
- package/dist/types/view/BlockCard/index.d.ts +2 -2
- package/dist/types/view/BlockCard/types.d.ts +4 -4
- package/dist/types/view/Card/index.d.ts +1 -1
- package/dist/types/view/EmbedCard/types.d.ts +2 -2
- package/dist/types/view/EmbedModal/components/analytics/index.d.ts +5 -0
- package/dist/types/view/EmbedModal/components/analytics/types.d.ts +6 -0
- package/dist/types/view/EmbedModal/components/size-experiment/index.d.ts +4 -3
- package/dist/types/view/EmbedModal/index.d.ts +3 -1
- package/dist/types/view/EmbedModal/types.d.ts +14 -4
- package/dist/types/view/FlexibleCard/components/blocks/preview-block/types.d.ts +7 -1
- package/dist/types/view/FlexibleCard/components/blocks/types.d.ts +15 -0
- package/dist/types/view/FlexibleCard/components/common/image-icon/types.d.ts +1 -0
- package/dist/types/view/FlexibleCard/components/elements/media/types.d.ts +5 -0
- package/dist/types/view/HoverCard/components/SnippetOrPreview.d.ts +4 -0
- package/dist/types/view/HoverCard/styled.d.ts +2 -0
- package/dist/types/view/HoverCard/types.d.ts +5 -0
- package/dist/types/view/common/Modal.d.ts +6 -8
- package/package.json +1 -1
- package/report.api.md +324 -108
|
@@ -61,7 +61,16 @@ export function CardWithUrlContent({
|
|
|
61
61
|
}, [state.details, url]);
|
|
62
62
|
const handleClickWrapper = useCallback(event => {
|
|
63
63
|
const isModifierKeyPressed = isSpecialEvent(event);
|
|
64
|
-
analytics.ui.cardClickedEvent(
|
|
64
|
+
analytics.ui.cardClickedEvent({
|
|
65
|
+
id,
|
|
66
|
+
display: isFlexibleUi ? 'flexible' : appearance,
|
|
67
|
+
status: state.status,
|
|
68
|
+
definitionId,
|
|
69
|
+
extensionKey,
|
|
70
|
+
isModifierKeyPressed,
|
|
71
|
+
destinationProduct: product,
|
|
72
|
+
destinationSubproduct: subproduct
|
|
73
|
+
});
|
|
65
74
|
|
|
66
75
|
if (onClick) {
|
|
67
76
|
onClick(event);
|
|
@@ -81,7 +90,14 @@ export function CardWithUrlContent({
|
|
|
81
90
|
|
|
82
91
|
if (state.status !== 'pending') {
|
|
83
92
|
measure.create(id, state.status);
|
|
84
|
-
analytics.operational.instrument(
|
|
93
|
+
analytics.operational.instrument({
|
|
94
|
+
id,
|
|
95
|
+
status: state.status,
|
|
96
|
+
definitionId,
|
|
97
|
+
extensionKey,
|
|
98
|
+
resourceType,
|
|
99
|
+
error: state.error
|
|
100
|
+
});
|
|
85
101
|
}
|
|
86
102
|
}, [id, appearance, state.status, state.error, definitionId, extensionKey, resourceType, analytics.operational]); // NB: once the smart-card has rendered into an end state, we capture
|
|
87
103
|
// this as a successful render. These can be one of:
|
|
@@ -90,7 +106,13 @@ export function CardWithUrlContent({
|
|
|
90
106
|
|
|
91
107
|
useEffect(() => {
|
|
92
108
|
if (isFinalState(state.status)) {
|
|
93
|
-
analytics.ui.renderSuccessEvent(
|
|
109
|
+
analytics.ui.renderSuccessEvent({
|
|
110
|
+
display: appearance,
|
|
111
|
+
status: state.status,
|
|
112
|
+
id,
|
|
113
|
+
definitionId,
|
|
114
|
+
extensionKey
|
|
115
|
+
});
|
|
94
116
|
}
|
|
95
117
|
}, [appearance, state.status, url, definitionId, extensionKey, analytics.ui, id]);
|
|
96
118
|
|
|
@@ -154,7 +176,7 @@ export function CardWithUrlContent({
|
|
|
154
176
|
handleErrorRetry: handleRetry,
|
|
155
177
|
handleInvoke: handleInvoke,
|
|
156
178
|
handleFrameClick: handleClickWrapper,
|
|
157
|
-
|
|
179
|
+
analytics: analytics,
|
|
158
180
|
isSelected: isSelected,
|
|
159
181
|
onResolve: onResolve,
|
|
160
182
|
onError: onError,
|
|
@@ -172,7 +194,7 @@ export function CardWithUrlContent({
|
|
|
172
194
|
handleErrorRetry: handleRetry,
|
|
173
195
|
handleFrameClick: handleClickWrapper,
|
|
174
196
|
handleInvoke: handleInvoke,
|
|
175
|
-
|
|
197
|
+
analytics: analytics,
|
|
176
198
|
isSelected: isSelected,
|
|
177
199
|
isFrameVisible: isFrameVisible,
|
|
178
200
|
platform: platform,
|
|
@@ -68,7 +68,12 @@ export function CardWithURLRenderer(props) {
|
|
|
68
68
|
const errorInfo = {
|
|
69
69
|
componentStack
|
|
70
70
|
};
|
|
71
|
-
analytics.ui.renderFailedEvent(
|
|
71
|
+
analytics.ui.renderFailedEvent({
|
|
72
|
+
display: appearance,
|
|
73
|
+
id,
|
|
74
|
+
error,
|
|
75
|
+
errorInfo
|
|
76
|
+
});
|
|
72
77
|
}
|
|
73
78
|
}, [analytics.ui, appearance, id]);
|
|
74
79
|
|
|
@@ -22,7 +22,7 @@ export const EmbedCard = /*#__PURE__*/React.forwardRef(({
|
|
|
22
22
|
handleAuthorize,
|
|
23
23
|
handleErrorRetry,
|
|
24
24
|
handleFrameClick,
|
|
25
|
-
|
|
25
|
+
analytics,
|
|
26
26
|
handleInvoke,
|
|
27
27
|
showActions,
|
|
28
28
|
isSelected,
|
|
@@ -79,7 +79,8 @@ export const EmbedCard = /*#__PURE__*/React.forwardRef(({
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
const resolvedBlockViewProps = extractBlockProps(data, meta, {
|
|
82
|
-
|
|
82
|
+
analytics,
|
|
83
|
+
origin: 'smartLinkEmbed',
|
|
83
84
|
handleInvoke,
|
|
84
85
|
extensionKey: getExtensionKey(details)
|
|
85
86
|
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
import React, { useCallback } from 'react';
|
|
3
|
+
import { EmbedModalSize } from '../../types';
|
|
4
|
+
|
|
5
|
+
const getResizeFrom = size => size === EmbedModalSize.Small ? EmbedModalSize.Large : EmbedModalSize.Small;
|
|
6
|
+
|
|
7
|
+
const withAnalytics = Component => props => {
|
|
8
|
+
const {
|
|
9
|
+
analytics,
|
|
10
|
+
onClose,
|
|
11
|
+
onOpen,
|
|
12
|
+
onOpenFailed,
|
|
13
|
+
onResize,
|
|
14
|
+
origin
|
|
15
|
+
} = props;
|
|
16
|
+
const handleOnOpen = useCallback(context => {
|
|
17
|
+
analytics.screen.modalViewedEvent({
|
|
18
|
+
name: 'embedPreviewModal',
|
|
19
|
+
attributes: {
|
|
20
|
+
origin,
|
|
21
|
+
size: context.size
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
analytics.ui.renderSuccessEvent({
|
|
25
|
+
status: 'resolved',
|
|
26
|
+
display: 'preview'
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
if (onOpen) {
|
|
30
|
+
onOpen(context);
|
|
31
|
+
}
|
|
32
|
+
}, [analytics.screen, analytics.ui, onOpen, origin]);
|
|
33
|
+
const handleOnOpenFailed = useCallback((error, errorInfo) => {
|
|
34
|
+
analytics.ui.renderFailedEvent({
|
|
35
|
+
display: 'preview',
|
|
36
|
+
error,
|
|
37
|
+
errorInfo
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
if (onOpenFailed) {
|
|
41
|
+
onOpenFailed(error, errorInfo);
|
|
42
|
+
}
|
|
43
|
+
}, [analytics.ui, onOpenFailed]);
|
|
44
|
+
const handleOnClose = useCallback(context => {
|
|
45
|
+
analytics.ui.modalClosedEvent({
|
|
46
|
+
actionSubjectId: 'embedPreview',
|
|
47
|
+
attributes: {
|
|
48
|
+
origin,
|
|
49
|
+
previewTime: context.duration,
|
|
50
|
+
size: context.size
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
if (onClose) {
|
|
55
|
+
onClose(context);
|
|
56
|
+
}
|
|
57
|
+
}, [analytics.ui, onClose, origin]);
|
|
58
|
+
const handleOnResize = useCallback(context => {
|
|
59
|
+
analytics.ui.buttonClickedEvent({
|
|
60
|
+
actionSubjectId: 'embedPreviewResize',
|
|
61
|
+
attributes: {
|
|
62
|
+
newSize: context.size,
|
|
63
|
+
origin,
|
|
64
|
+
previousSize: getResizeFrom(context.size)
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
if (onResize) {
|
|
69
|
+
onResize(context);
|
|
70
|
+
}
|
|
71
|
+
}, [analytics.ui, onResize, origin]);
|
|
72
|
+
return /*#__PURE__*/React.createElement(Component, _extends({}, props, {
|
|
73
|
+
onClose: handleOnClose,
|
|
74
|
+
onOpen: handleOnOpen,
|
|
75
|
+
onOpenFailed: handleOnOpenFailed,
|
|
76
|
+
onResize: handleOnResize
|
|
77
|
+
}));
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export default withAnalytics;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,28 +1,24 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/extends";
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import Modal from '../../../common/Modal';
|
|
4
|
-
import {
|
|
4
|
+
import { EmbedModalSize } from '../../types';
|
|
5
5
|
|
|
6
6
|
const withSizeExperiment = Component => props => {
|
|
7
7
|
const {
|
|
8
|
-
featureFlags = {}
|
|
9
|
-
closeLabel = 'Close Preview'
|
|
8
|
+
featureFlags = {}
|
|
10
9
|
} = props;
|
|
11
10
|
const {
|
|
12
|
-
embedModalSize
|
|
11
|
+
embedModalSize: size
|
|
13
12
|
} = featureFlags; // Experiment
|
|
14
13
|
|
|
15
|
-
if (
|
|
16
|
-
const size = embedModalSize === 'large' ? MAX_MODAL_SIZE : MIN_MODAL_SIZE;
|
|
14
|
+
if (size === EmbedModalSize.Large || size === EmbedModalSize.Small) {
|
|
17
15
|
return /*#__PURE__*/React.createElement(Component, _extends({}, props, {
|
|
18
16
|
size: size
|
|
19
17
|
}));
|
|
20
18
|
} // Control
|
|
21
19
|
|
|
22
20
|
|
|
23
|
-
return /*#__PURE__*/React.createElement(Modal,
|
|
24
|
-
closeLabel: closeLabel
|
|
25
|
-
}));
|
|
21
|
+
return /*#__PURE__*/React.createElement(Modal, props);
|
|
26
22
|
};
|
|
27
23
|
|
|
28
24
|
export default withSizeExperiment;
|
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
import React, { useCallback, useState } from 'react';
|
|
1
|
+
import React, { useCallback, useRef, useState } from 'react';
|
|
2
2
|
import ModalDialog, { ModalBody, ModalTransition } from '@atlaskit/modal-dialog';
|
|
3
3
|
import LinkInfo from './components/link-info';
|
|
4
4
|
import { MAX_MODAL_SIZE, MIN_MODAL_SIZE } from './constants';
|
|
5
5
|
import EmbedContent from './components/embed-content';
|
|
6
|
+
import { EmbedModalSize } from './types';
|
|
6
7
|
import withErrorBoundary from './components/error-boundary';
|
|
7
8
|
import withSizeExperiment from './components/size-experiment';
|
|
9
|
+
import withAnalytics from './components/analytics';
|
|
10
|
+
|
|
11
|
+
const toSize = width => width === MAX_MODAL_SIZE ? EmbedModalSize.Large : EmbedModalSize.Small;
|
|
12
|
+
|
|
13
|
+
const toWidth = size => size === EmbedModalSize.Large ? MAX_MODAL_SIZE : MIN_MODAL_SIZE;
|
|
8
14
|
|
|
9
15
|
const EmbedModal = ({
|
|
10
16
|
download: downloadUrl,
|
|
@@ -14,37 +20,64 @@ const EmbedModal = ({
|
|
|
14
20
|
onClose,
|
|
15
21
|
onDownloadActionClick,
|
|
16
22
|
onOpen,
|
|
23
|
+
onResize,
|
|
17
24
|
onViewActionClick,
|
|
18
25
|
providerName,
|
|
19
26
|
showModal,
|
|
20
|
-
size
|
|
27
|
+
size = EmbedModalSize.Small,
|
|
21
28
|
src,
|
|
22
29
|
testId = 'smart-embed-preview-modal',
|
|
23
30
|
title,
|
|
24
31
|
url
|
|
25
32
|
}) => {
|
|
33
|
+
const defaultWidth = toWidth(size);
|
|
26
34
|
const [isOpen, setIsOpen] = useState(showModal);
|
|
27
|
-
const [
|
|
35
|
+
const [width, setWidth] = useState(defaultWidth);
|
|
36
|
+
const openAt = useRef();
|
|
37
|
+
const handleOnOpenComplete = useCallback(() => {
|
|
38
|
+
openAt.current = Date.now();
|
|
39
|
+
|
|
40
|
+
if (onOpen) {
|
|
41
|
+
onOpen({
|
|
42
|
+
size
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}, [onOpen, size]);
|
|
28
46
|
const handleOnClose = useCallback(() => setIsOpen(false), []);
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
47
|
+
const handleOnCloseComplete = useCallback(() => {
|
|
48
|
+
if (onClose) {
|
|
49
|
+
const duration = openAt.current ? Date.now() - openAt.current : undefined;
|
|
50
|
+
onClose({
|
|
51
|
+
duration,
|
|
52
|
+
size: toSize(width)
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}, [onClose, width]);
|
|
56
|
+
const handleOnResizeClick = useCallback(() => {
|
|
57
|
+
const newWidth = width === MIN_MODAL_SIZE ? MAX_MODAL_SIZE : MIN_MODAL_SIZE;
|
|
58
|
+
setWidth(newWidth);
|
|
59
|
+
|
|
60
|
+
if (onResize) {
|
|
61
|
+
onResize({
|
|
62
|
+
size: toSize(newWidth)
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}, [onResize, width]);
|
|
33
66
|
return /*#__PURE__*/React.createElement(ModalTransition, null, isOpen && /*#__PURE__*/React.createElement(ModalDialog, {
|
|
34
67
|
height: "100%",
|
|
35
68
|
onClose: handleOnClose,
|
|
36
|
-
onCloseComplete:
|
|
37
|
-
onOpenComplete:
|
|
69
|
+
onCloseComplete: handleOnCloseComplete,
|
|
70
|
+
onOpenComplete: handleOnOpenComplete,
|
|
38
71
|
testId: testId,
|
|
39
|
-
width:
|
|
72
|
+
width: width
|
|
40
73
|
}, /*#__PURE__*/React.createElement(LinkInfo, {
|
|
41
74
|
downloadUrl: downloadUrl,
|
|
42
75
|
icon: icon,
|
|
43
76
|
providerName: providerName,
|
|
44
77
|
onViewButtonClick: onViewActionClick,
|
|
45
78
|
onDownloadButtonClick: onDownloadActionClick,
|
|
46
|
-
onResizeButtonClick:
|
|
47
|
-
size:
|
|
79
|
+
onResizeButtonClick: handleOnResizeClick,
|
|
80
|
+
size: width,
|
|
48
81
|
title: title,
|
|
49
82
|
testId: testId,
|
|
50
83
|
url: url
|
|
@@ -56,4 +89,4 @@ const EmbedModal = ({
|
|
|
56
89
|
}))));
|
|
57
90
|
};
|
|
58
91
|
|
|
59
|
-
export default withSizeExperiment(withErrorBoundary(EmbedModal));
|
|
92
|
+
export default withSizeExperiment(withAnalytics(withErrorBoundary(EmbedModal)));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** @jsx jsx */
|
|
2
|
-
import React from 'react';
|
|
2
|
+
import React, { useEffect } from 'react';
|
|
3
3
|
import { css, jsx } from '@emotion/core';
|
|
4
4
|
import { ElementName, SmartLinkDirection, SmartLinkSize } from '../../../../../constants';
|
|
5
5
|
import { getBaseStyles, getGapSize, highlightRemoveStyles, renderChildren } from '../utils';
|
|
@@ -37,11 +37,21 @@ const Block = ({
|
|
|
37
37
|
direction = SmartLinkDirection.Horizontal,
|
|
38
38
|
size = SmartLinkSize.Medium,
|
|
39
39
|
testId = 'smart-block',
|
|
40
|
-
overrideCss
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
overrideCss,
|
|
41
|
+
blockRef,
|
|
42
|
+
onRender,
|
|
43
|
+
onTransitionEnd
|
|
44
|
+
}) => {
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
onRender && onRender();
|
|
47
|
+
}, [onRender]);
|
|
48
|
+
return jsx("div", {
|
|
49
|
+
css: [getBlockStyles(direction, size), overrideCss],
|
|
50
|
+
"data-smart-block": true,
|
|
51
|
+
"data-testid": testId,
|
|
52
|
+
onTransitionEnd: onTransitionEnd,
|
|
53
|
+
ref: blockRef
|
|
54
|
+
}, renderChildren(children, size));
|
|
55
|
+
};
|
|
46
56
|
|
|
47
57
|
export default Block;
|
|
@@ -13,6 +13,7 @@ import { Preview } from '../../elements';
|
|
|
13
13
|
const PreviewBlock = ({
|
|
14
14
|
status = SmartLinkStatus.Fallback,
|
|
15
15
|
testId = 'smart-block-preview',
|
|
16
|
+
onError,
|
|
16
17
|
...blockProps
|
|
17
18
|
}) => {
|
|
18
19
|
if (status !== SmartLinkStatus.Resolved) {
|
|
@@ -21,7 +22,9 @@ const PreviewBlock = ({
|
|
|
21
22
|
|
|
22
23
|
return /*#__PURE__*/React.createElement(Block, _extends({}, blockProps, {
|
|
23
24
|
testId: `${testId}-resolved-view`
|
|
24
|
-
}), /*#__PURE__*/React.createElement(Preview,
|
|
25
|
+
}), /*#__PURE__*/React.createElement(Preview, {
|
|
26
|
+
onError: onError
|
|
27
|
+
}));
|
|
25
28
|
};
|
|
26
29
|
|
|
27
30
|
export default PreviewBlock;
|
|
@@ -7,7 +7,8 @@ import LoadingSkeleton from '../loading-skeleton';
|
|
|
7
7
|
const ImageIcon = ({
|
|
8
8
|
defaultIcon,
|
|
9
9
|
testId,
|
|
10
|
-
url
|
|
10
|
+
url,
|
|
11
|
+
onError
|
|
11
12
|
}) => jsx(ImageLoader, {
|
|
12
13
|
src: url,
|
|
13
14
|
loading: jsx(LoadingSkeleton, {
|
|
@@ -17,7 +18,8 @@ const ImageIcon = ({
|
|
|
17
18
|
src: url,
|
|
18
19
|
"data-testid": `${testId}-image`
|
|
19
20
|
}),
|
|
20
|
-
errored: defaultIcon
|
|
21
|
+
errored: defaultIcon,
|
|
22
|
+
onError: onError
|
|
21
23
|
});
|
|
22
24
|
|
|
23
25
|
export default ImageIcon;
|
|
@@ -8,10 +8,9 @@ const LoadingSkeleton = ({
|
|
|
8
8
|
width,
|
|
9
9
|
height
|
|
10
10
|
}) => {
|
|
11
|
-
const animationWidth = width ? `${width}rem` : '20px';
|
|
12
11
|
const animationNameStyles = keyframes`
|
|
13
|
-
0% { background-position:
|
|
14
|
-
100% { background-position:
|
|
12
|
+
0% { background-position: 50% 0; }
|
|
13
|
+
100% { background-position: -50% 0; }
|
|
15
14
|
`;
|
|
16
15
|
const styles = css`
|
|
17
16
|
width: ${width}rem;
|
|
@@ -59,7 +59,8 @@ const Media = ({
|
|
|
59
59
|
overrideCss,
|
|
60
60
|
testId = 'smart-element-media',
|
|
61
61
|
type,
|
|
62
|
-
url
|
|
62
|
+
url,
|
|
63
|
+
onError
|
|
63
64
|
}) => {
|
|
64
65
|
if (!type || !url) {
|
|
65
66
|
return null;
|
|
@@ -72,7 +73,9 @@ const Media = ({
|
|
|
72
73
|
"data-testid": testId
|
|
73
74
|
}, jsx(ImageIcon, {
|
|
74
75
|
testId: `${testId}-image`,
|
|
75
|
-
url: url
|
|
76
|
+
url: url,
|
|
77
|
+
onError: onError,
|
|
78
|
+
defaultIcon: null
|
|
76
79
|
}));
|
|
77
80
|
};
|
|
78
81
|
|
|
@@ -43,7 +43,11 @@ export const HoverCardComponent = ({
|
|
|
43
43
|
//Check its previously open to avoid firing events when moving between the child and hover card components
|
|
44
44
|
if (isOpen === true && cardOpenTime.current) {
|
|
45
45
|
const hoverTime = Date.now() - cardOpenTime.current;
|
|
46
|
-
analytics.ui.hoverCardDismissedEvent(
|
|
46
|
+
analytics.ui.hoverCardDismissedEvent({
|
|
47
|
+
previewDisplay: 'card',
|
|
48
|
+
hoverTime,
|
|
49
|
+
previewInvokeMethod: 'mouse_hover'
|
|
50
|
+
});
|
|
47
51
|
}
|
|
48
52
|
|
|
49
53
|
setIsOpen(false);
|
|
@@ -66,7 +70,10 @@ export const HoverCardComponent = ({
|
|
|
66
70
|
//Check if its previously closed to avoid firing events when moving between the child and hover card components
|
|
67
71
|
if (isOpen === false) {
|
|
68
72
|
cardOpenTime.current = Date.now();
|
|
69
|
-
analytics.ui.hoverCardViewedEvent(
|
|
73
|
+
analytics.ui.hoverCardViewedEvent({
|
|
74
|
+
previewDisplay: hoverDisplay,
|
|
75
|
+
previewInvokeMethod: invokeMethod
|
|
76
|
+
});
|
|
70
77
|
} //If these are undefined then popupOffset is undefined and we fallback to default bottom-start placement
|
|
71
78
|
|
|
72
79
|
|
|
@@ -84,7 +91,8 @@ export const HoverCardComponent = ({
|
|
|
84
91
|
const linkActions = useSmartLinkActions({
|
|
85
92
|
url,
|
|
86
93
|
appearance: SMART_CARD_ANALYTICS_DISPLAY,
|
|
87
|
-
analyticsHandler
|
|
94
|
+
analyticsHandler,
|
|
95
|
+
origin: 'smartLinkPreviewHoverCard'
|
|
88
96
|
});
|
|
89
97
|
const onActionClick = useCallback(actionId => {
|
|
90
98
|
if (actionId === 'preview-content') {
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import ShortcutIcon from '@atlaskit/icon/glyph/shortcut';
|
|
2
2
|
import { extractType } from '@atlaskit/linking-common/extractors';
|
|
3
|
-
import React, { useCallback, useEffect, useMemo } from 'react';
|
|
3
|
+
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
|
|
4
4
|
import { ActionName, SmartLinkPosition, SmartLinkSize } from '../../../constants';
|
|
5
|
-
import extractPreview from '../../../extractors/flexible/extract-preview';
|
|
6
5
|
import { extractMetadata } from '../../../extractors/hover/extractMetadata';
|
|
7
6
|
import { useSmartCardActions } from '../../../state/actions';
|
|
8
7
|
import { getExtensionKey } from '../../../state/helpers';
|
|
9
8
|
import { isSpecialEvent } from '../../../utils';
|
|
10
9
|
import FlexibleCard from '../../FlexibleCard';
|
|
11
|
-
import { FooterBlock, MetadataBlock,
|
|
12
|
-
import { flexibleUiOptions, footerBlockCss, metadataBlockCss, titleBlockCss } from '../styled';
|
|
10
|
+
import { FooterBlock, MetadataBlock, SnippetBlock, TitleBlock } from '../../FlexibleCard/components/blocks';
|
|
11
|
+
import { flexibleUiOptions, footerBlockCss, metadataBlockCss, titleBlockCss, hiddenSnippetStyles } from '../styled';
|
|
13
12
|
import { getSimulatedMetadata, SMART_CARD_ANALYTICS_DISPLAY } from '../utils';
|
|
14
13
|
import HoverCardLoadingView from './HoverCardLoadingView';
|
|
14
|
+
import SnippetOrPreview from './SnippetOrPreview';
|
|
15
15
|
export const getOpenAction = (url, analytics, onActionClick) => ({
|
|
16
16
|
name: ActionName.CustomAction,
|
|
17
17
|
icon: /*#__PURE__*/React.createElement(ShortcutIcon, {
|
|
@@ -25,7 +25,9 @@ export const getOpenAction = (url, analytics, onActionClick) => ({
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
window.open(url, '_blank');
|
|
28
|
-
analytics.ui.hoverCardOpenLinkClickedEvent(
|
|
28
|
+
analytics.ui.hoverCardOpenLinkClickedEvent({
|
|
29
|
+
previewDisplay: 'card'
|
|
30
|
+
});
|
|
29
31
|
},
|
|
30
32
|
testId: 'hover-card-open-button'
|
|
31
33
|
});
|
|
@@ -61,13 +63,22 @@ const HoverCardContent = ({
|
|
|
61
63
|
useEffect(() => {
|
|
62
64
|
// Since hover preview only render on resolved status,
|
|
63
65
|
// there is no need to check for statuses.
|
|
64
|
-
analytics.ui.renderSuccessEvent(
|
|
66
|
+
analytics.ui.renderSuccessEvent({
|
|
67
|
+
display: SMART_CARD_ANALYTICS_DISPLAY,
|
|
68
|
+
status: cardState.status
|
|
69
|
+
});
|
|
65
70
|
}, [analytics.ui, cardState.status]);
|
|
66
71
|
const extensionKey = useMemo(() => getExtensionKey(cardState.details), [cardState.details]);
|
|
67
72
|
const onClick = useCallback(event => {
|
|
68
73
|
const isModifierKeyPressed = isSpecialEvent(event);
|
|
69
|
-
analytics.ui.cardClickedEvent(
|
|
70
|
-
|
|
74
|
+
analytics.ui.cardClickedEvent({
|
|
75
|
+
id,
|
|
76
|
+
display: SMART_CARD_ANALYTICS_DISPLAY,
|
|
77
|
+
status: cardState.status,
|
|
78
|
+
isModifierKeyPressed,
|
|
79
|
+
actionSubjectId: 'titleGoToLink'
|
|
80
|
+
});
|
|
81
|
+
}, [cardState.status, analytics.ui, id]);
|
|
71
82
|
const titleActions = useMemo(() => [getOpenAction(url, analytics, onActionClick)], [url, analytics, onActionClick]);
|
|
72
83
|
const footerActions = useMemo(() => toFooterActions(cardActions, onActionClick), [cardActions, onActionClick]);
|
|
73
84
|
const data = (_cardState$details = cardState.details) === null || _cardState$details === void 0 ? void 0 : _cardState$details.data;
|
|
@@ -79,7 +90,17 @@ const HoverCardContent = ({
|
|
|
79
90
|
subtitle
|
|
80
91
|
} = extractMetadata(getSimulatedMetadata(extensionKey, types));
|
|
81
92
|
const titleMaxLines = subtitle && subtitle.length > 0 ? 1 : 2;
|
|
82
|
-
const
|
|
93
|
+
const snippetHeight = React.useRef(0);
|
|
94
|
+
const snippetBlockRef = useRef(null);
|
|
95
|
+
const onSnippetRender = useCallback(() => {
|
|
96
|
+
var _snippetBlockRef$curr, _snippetBlockRef$curr2;
|
|
97
|
+
|
|
98
|
+
snippetHeight.current = (_snippetBlockRef$curr = (_snippetBlockRef$curr2 = snippetBlockRef.current) === null || _snippetBlockRef$curr2 === void 0 ? void 0 : _snippetBlockRef$curr2.getBoundingClientRect().height) !== null && _snippetBlockRef$curr !== void 0 ? _snippetBlockRef$curr : 0;
|
|
99
|
+
}, []);
|
|
100
|
+
const body = SnippetOrPreview({
|
|
101
|
+
data: data,
|
|
102
|
+
snippetHeight: snippetHeight.current
|
|
103
|
+
});
|
|
83
104
|
const titleBlockProps = {
|
|
84
105
|
actions: titleActions,
|
|
85
106
|
maxLines: titleMaxLines,
|
|
@@ -112,7 +133,12 @@ const HoverCardContent = ({
|
|
|
112
133
|
size: SmartLinkSize.Large,
|
|
113
134
|
overrideCss: metadataBlockCss,
|
|
114
135
|
maxLines: 1
|
|
115
|
-
}), body, /*#__PURE__*/React.createElement(
|
|
136
|
+
}), body, /*#__PURE__*/React.createElement(SnippetBlock, {
|
|
137
|
+
testId: 'hidden-snippet',
|
|
138
|
+
onRender: onSnippetRender,
|
|
139
|
+
blockRef: snippetBlockRef,
|
|
140
|
+
overrideCss: hiddenSnippetStyles
|
|
141
|
+
}), /*#__PURE__*/React.createElement(FooterBlock, {
|
|
116
142
|
actions: footerActions,
|
|
117
143
|
size: SmartLinkSize.Large,
|
|
118
144
|
overrideCss: footerBlockCss
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React, { useCallback, useState, useRef } from 'react';
|
|
2
|
+
import { css } from '@emotion/core';
|
|
3
|
+
import extractPreview from '../../../extractors/flexible/extract-preview';
|
|
4
|
+
import { PreviewBlock, SnippetBlock } from '../../FlexibleCard/components/blocks';
|
|
5
|
+
import { getTransitionStyles } from '../styled';
|
|
6
|
+
|
|
7
|
+
const SnippetOrPreview = ({
|
|
8
|
+
data,
|
|
9
|
+
snippetHeight
|
|
10
|
+
}) => {
|
|
11
|
+
const transitionStarted = useRef(false);
|
|
12
|
+
const previewBlockRef = useRef(null);
|
|
13
|
+
const [showSnippet, setShowSnippet] = useState(false);
|
|
14
|
+
const [previewCss, setPreviewCss] = useState(); // Set Preview to a fixed height to enable transitions
|
|
15
|
+
|
|
16
|
+
const onPreviewRender = useCallback(() => {
|
|
17
|
+
var _previewBlockRef$curr;
|
|
18
|
+
|
|
19
|
+
previewBlockRef.current && setPreviewCss(css`
|
|
20
|
+
height: ${(_previewBlockRef$curr = previewBlockRef.current) === null || _previewBlockRef$curr === void 0 ? void 0 : _previewBlockRef$curr.getBoundingClientRect().height}px;
|
|
21
|
+
`);
|
|
22
|
+
}, []); // On error set Preview to Snippet height with transition
|
|
23
|
+
|
|
24
|
+
const onPreviewError = useCallback(() => {
|
|
25
|
+
if (transitionStarted.current === false) {
|
|
26
|
+
setPreviewCss(getTransitionStyles(snippetHeight));
|
|
27
|
+
transitionStarted.current = true;
|
|
28
|
+
}
|
|
29
|
+
}, [snippetHeight]);
|
|
30
|
+
const onPreviewTransitionEnd = useCallback(() => {
|
|
31
|
+
setShowSnippet(true);
|
|
32
|
+
}, []);
|
|
33
|
+
return !showSnippet && data && extractPreview(data) ? /*#__PURE__*/React.createElement(PreviewBlock, {
|
|
34
|
+
onError: onPreviewError,
|
|
35
|
+
overrideCss: previewCss,
|
|
36
|
+
onTransitionEnd: onPreviewTransitionEnd,
|
|
37
|
+
blockRef: previewBlockRef,
|
|
38
|
+
onRender: onPreviewRender
|
|
39
|
+
}) : /*#__PURE__*/React.createElement(SnippetBlock, null);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export default SnippetOrPreview;
|
|
@@ -22,7 +22,12 @@ const HoverCardWithErrorBoundary = props => {
|
|
|
22
22
|
}, [createAnalyticsEvent]);
|
|
23
23
|
const analytics = useSmartLinkAnalytics(url, analyticsHandler, id);
|
|
24
24
|
const onError = useCallback((error, info) => {
|
|
25
|
-
analytics.ui.renderFailedEvent(
|
|
25
|
+
analytics.ui.renderFailedEvent({
|
|
26
|
+
display: SMART_CARD_ANALYTICS_DISPLAY,
|
|
27
|
+
id,
|
|
28
|
+
error,
|
|
29
|
+
errorInfo: info
|
|
30
|
+
});
|
|
26
31
|
}, [analytics.ui, id]);
|
|
27
32
|
return jsx(ErrorBoundary, {
|
|
28
33
|
fallback: children,
|
|
@@ -83,4 +83,12 @@ export const skeletonContainer = css`
|
|
|
83
83
|
flex-direction: column;
|
|
84
84
|
gap: 0.625rem;
|
|
85
85
|
align-items: center;
|
|
86
|
+
`;
|
|
87
|
+
export const hiddenSnippetStyles = css`
|
|
88
|
+
visibility: hidden;
|
|
89
|
+
position: absolute;
|
|
90
|
+
`;
|
|
91
|
+
export const getTransitionStyles = snippetHeight => css`
|
|
92
|
+
transition: height 300ms ease-in-out;
|
|
93
|
+
height: ${snippetHeight}px;
|
|
86
94
|
`;
|