@atlaskit/smart-card 20.0.4 → 20.0.5
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 +6 -0
- package/dist/cjs/state/analytics/useSmartLinkAnalytics.js +26 -6
- package/dist/cjs/version.json +1 -1
- package/dist/cjs/view/CardWithUrl/loader.js +5 -9
- package/dist/cjs/view/HoverCard/components/HoverCardComponent.js +143 -0
- package/dist/cjs/view/HoverCard/components/{hover-card-content.js → HoverCardContent.js} +21 -25
- package/dist/cjs/view/HoverCard/index.js +25 -126
- package/dist/cjs/view/HoverCard/styled.js +11 -1
- package/dist/cjs/view/HoverCard/utils.js +3 -3
- package/dist/es2019/state/analytics/useSmartLinkAnalytics.js +24 -7
- package/dist/es2019/version.json +1 -1
- package/dist/es2019/view/CardWithUrl/loader.js +6 -10
- package/dist/es2019/view/HoverCard/components/HoverCardComponent.js +102 -0
- package/dist/es2019/view/HoverCard/components/{hover-card-content.js → HoverCardContent.js} +12 -21
- package/dist/es2019/view/HoverCard/index.js +26 -97
- package/dist/es2019/view/HoverCard/styled.js +8 -0
- package/dist/es2019/view/HoverCard/utils.js +1 -1
- package/dist/esm/state/analytics/useSmartLinkAnalytics.js +27 -7
- package/dist/esm/version.json +1 -1
- package/dist/esm/view/CardWithUrl/loader.js +6 -10
- package/dist/esm/view/HoverCard/components/HoverCardComponent.js +114 -0
- package/dist/esm/view/HoverCard/components/{hover-card-content.js → HoverCardContent.js} +12 -21
- package/dist/esm/view/HoverCard/index.js +24 -109
- package/dist/esm/view/HoverCard/styled.js +8 -0
- package/dist/esm/view/HoverCard/utils.js +1 -1
- package/dist/types/state/analytics/useSmartLinkAnalytics.d.ts +9 -0
- package/dist/types/state/hooks/useSmartLink.d.ts +2 -0
- package/dist/types/view/HoverCard/components/HoverCardComponent.d.ts +4 -0
- package/dist/types/view/HoverCard/components/HoverCardContent.d.ts +9 -0
- package/dist/types/view/HoverCard/index.d.ts +2 -4
- package/dist/types/view/HoverCard/styled.d.ts +2 -0
- package/dist/types/view/HoverCard/types.d.ts +7 -0
- package/dist/types/view/HoverCard/utils.d.ts +1 -1
- package/package.json +1 -1
- package/dist/types/view/HoverCard/components/hover-card-content.d.ts +0 -4
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React, { lazy, useEffect, useState, Suspense, useCallback } from 'react';
|
|
2
2
|
import uuid from 'uuid';
|
|
3
|
-
import {
|
|
3
|
+
import { fireSmartLinkEvent } from '../../utils/analytics';
|
|
4
4
|
import { clearMarks, clearMeasures } from '../../utils/performance';
|
|
5
5
|
import { ErrorBoundary } from 'react-error-boundary';
|
|
6
|
-
import {
|
|
6
|
+
import { useSmartLinkAnalytics } from '../../state/analytics';
|
|
7
7
|
import { LoadingCardLink } from './component-lazy/LazyFallback';
|
|
8
8
|
const LazyCardWithUrlContent = /*#__PURE__*/lazy(() => import(
|
|
9
9
|
/* webpackChunkName: "@atlaskit-internal_smartcard-urlcardcontent" */
|
|
@@ -50,6 +50,7 @@ export function CardWithURLRenderer(props) {
|
|
|
50
50
|
|
|
51
51
|
fireSmartLinkEvent(analyticsPayload, createAnalyticsEvent);
|
|
52
52
|
}, [appearance, createAnalyticsEvent]);
|
|
53
|
+
const analytics = useSmartLinkAnalytics(url !== null && url !== void 0 ? url : '', dispatchAnalytics, id);
|
|
53
54
|
const logError = useCallback((error, info) => {
|
|
54
55
|
const {
|
|
55
56
|
componentStack
|
|
@@ -65,15 +66,10 @@ export function CardWithURLRenderer(props) {
|
|
|
65
66
|
else {
|
|
66
67
|
const errorInfo = {
|
|
67
68
|
componentStack
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
startUfoExperience('smart-link-rendered', id);
|
|
72
|
-
failUfoExperience('smart-link-rendered', id);
|
|
73
|
-
failUfoExperience('smart-link-authenticated', id);
|
|
74
|
-
dispatchAnalytics(uiRenderFailedEvent(appearance, error, errorInfo));
|
|
69
|
+
};
|
|
70
|
+
analytics.ui.renderFailedEvent(appearance, id, error, errorInfo);
|
|
75
71
|
}
|
|
76
|
-
}, [
|
|
72
|
+
}, [analytics.ui, appearance, id]);
|
|
77
73
|
|
|
78
74
|
if (!url) {
|
|
79
75
|
throw new Error('@atlaskit/smart-card: url property is missing.');
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
|
|
3
|
+
/** @jsx jsx */
|
|
4
|
+
import Popup from '@atlaskit/popup';
|
|
5
|
+
import { jsx } from '@emotion/core';
|
|
6
|
+
import React, { useCallback, useRef } from 'react';
|
|
7
|
+
import { useSmartLinkActions } from '../../../state/hooks-external/useSmartLinkActions';
|
|
8
|
+
import { useSmartLinkRenderers } from '../../../state/renderers';
|
|
9
|
+
import { useSmartCardState as useLinkState } from '../../../state/store';
|
|
10
|
+
import HoverCardContent from '../components/HoverCardContent';
|
|
11
|
+
import { HoverCardContainer } from '../styled';
|
|
12
|
+
import { SMART_CARD_ANALYTICS_DISPLAY } from '../utils';
|
|
13
|
+
export const hoverCardClassName = 'smart-links-hover-preview';
|
|
14
|
+
export const HoverCardComponent = ({
|
|
15
|
+
children,
|
|
16
|
+
url,
|
|
17
|
+
analyticsHandler,
|
|
18
|
+
analytics
|
|
19
|
+
}) => {
|
|
20
|
+
const delay = 300;
|
|
21
|
+
const [isOpen, setIsOpen] = React.useState(false);
|
|
22
|
+
const fadeOutTimeoutId = useRef();
|
|
23
|
+
const fadeInTimeoutId = useRef();
|
|
24
|
+
const cardOpenTime = useRef();
|
|
25
|
+
const renderers = useSmartLinkRenderers();
|
|
26
|
+
const linkState = useLinkState(url);
|
|
27
|
+
const hoverDisplay = 'card';
|
|
28
|
+
const invokeMethod = 'mouse_hover';
|
|
29
|
+
const hideCard = useCallback(() => {
|
|
30
|
+
//Check its previously open to avoid firing events when moving between the child and hover card components
|
|
31
|
+
if (isOpen === true && cardOpenTime.current) {
|
|
32
|
+
const hoverTime = Date.now() - cardOpenTime.current;
|
|
33
|
+
analytics.ui.hoverCardDismissedEvent('card', hoverTime, 'mouse_hover');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
setIsOpen(false);
|
|
37
|
+
}, [analytics.ui, isOpen]);
|
|
38
|
+
const initHideCard = useCallback(() => {
|
|
39
|
+
if (fadeInTimeoutId.current) {
|
|
40
|
+
clearTimeout(fadeInTimeoutId.current);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
fadeOutTimeoutId.current = setTimeout(() => hideCard(), delay);
|
|
44
|
+
}, [hideCard]);
|
|
45
|
+
const initShowCard = useCallback(() => {
|
|
46
|
+
if (fadeOutTimeoutId.current) {
|
|
47
|
+
clearTimeout(fadeOutTimeoutId.current);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
fadeInTimeoutId.current = setTimeout(() => {
|
|
51
|
+
//Check if its previously closed to avoid firing events when moving between the child and hover card components
|
|
52
|
+
if (isOpen === false) {
|
|
53
|
+
cardOpenTime.current = Date.now();
|
|
54
|
+
analytics.ui.hoverCardViewedEvent(hoverDisplay, invokeMethod);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
setIsOpen(true);
|
|
58
|
+
}, delay);
|
|
59
|
+
}, [delay, isOpen, analytics.ui]);
|
|
60
|
+
const linkActions = useSmartLinkActions({
|
|
61
|
+
url,
|
|
62
|
+
appearance: SMART_CARD_ANALYTICS_DISPLAY,
|
|
63
|
+
analyticsHandler
|
|
64
|
+
});
|
|
65
|
+
const onActionClick = useCallback(actionId => {
|
|
66
|
+
if (actionId === 'preview-content') {
|
|
67
|
+
hideCard();
|
|
68
|
+
}
|
|
69
|
+
}, [hideCard]); // Stop hover preview content to propagate event to parent.
|
|
70
|
+
|
|
71
|
+
const onClick = useCallback(e => e.stopPropagation(), []);
|
|
72
|
+
return jsx(Popup, {
|
|
73
|
+
testId: "hover-card",
|
|
74
|
+
isOpen: isOpen,
|
|
75
|
+
onClose: hideCard,
|
|
76
|
+
placement: "bottom-start",
|
|
77
|
+
content: ({
|
|
78
|
+
update
|
|
79
|
+
}) => jsx("div", {
|
|
80
|
+
onMouseEnter: initShowCard,
|
|
81
|
+
onMouseLeave: initHideCard,
|
|
82
|
+
onClick: onClick,
|
|
83
|
+
css: HoverCardContainer // class name for trello to exclude click events
|
|
84
|
+
,
|
|
85
|
+
className: hoverCardClassName
|
|
86
|
+
}, jsx(HoverCardContent, {
|
|
87
|
+
analytics: analytics,
|
|
88
|
+
cardActions: linkActions,
|
|
89
|
+
cardState: linkState,
|
|
90
|
+
onActionClick: onActionClick,
|
|
91
|
+
onResolve: update,
|
|
92
|
+
renderers: renderers,
|
|
93
|
+
url: url
|
|
94
|
+
})),
|
|
95
|
+
trigger: triggerProps => jsx("span", _extends({}, triggerProps, {
|
|
96
|
+
onMouseEnter: initShowCard,
|
|
97
|
+
onMouseLeave: initHideCard
|
|
98
|
+
}), children),
|
|
99
|
+
zIndex: 511 // Temporary fix for Confluence inline comment on editor mod has z-index of 500, Jira issue view has z-index of 510
|
|
100
|
+
|
|
101
|
+
});
|
|
102
|
+
};
|
|
@@ -1,24 +1,16 @@
|
|
|
1
|
+
import ShortcutIcon from '@atlaskit/icon/glyph/shortcut';
|
|
2
|
+
import { extractType } from '@atlaskit/linking-common/extractors';
|
|
1
3
|
import React, { useCallback, useEffect, useMemo } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { getSimulatedMetadata, HOVER_CARD_ANALYTICS_DISPLAY } from '../utils';
|
|
4
|
+
import { ActionName, SmartLinkPosition, SmartLinkSize } from '../../../constants';
|
|
4
5
|
import extractPreview from '../../../extractors/flexible/extract-preview';
|
|
5
|
-
import {
|
|
6
|
+
import { extractMetadata } from '../../../extractors/hover/extractMetadata';
|
|
7
|
+
import { getExtensionKey } from '../../../state/helpers';
|
|
8
|
+
import { isSpecialEvent } from '../../../utils';
|
|
6
9
|
import FlexibleCard from '../../FlexibleCard';
|
|
7
10
|
import { FooterBlock, MetadataBlock, PreviewBlock, SnippetBlock, TitleBlock } from '../../FlexibleCard/components/blocks';
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
import { titleBlockCss, metadataBlockCss, footerBlockCss } from '../styled';
|
|
12
|
-
import { extractType } from '@atlaskit/linking-common/extractors';
|
|
13
|
-
const flexibleUiOptions = {
|
|
14
|
-
hideElevation: true,
|
|
15
|
-
size: SmartLinkSize.Medium,
|
|
16
|
-
// eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage
|
|
17
|
-
theme: SmartLinkTheme.Black,
|
|
18
|
-
hidePadding: true
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const getOpenAction = (url, analytics, onActionClick) => ({
|
|
11
|
+
import { flexibleUiOptions, footerBlockCss, metadataBlockCss, titleBlockCss } from '../styled';
|
|
12
|
+
import { getSimulatedMetadata, SMART_CARD_ANALYTICS_DISPLAY } from '../utils';
|
|
13
|
+
export const getOpenAction = (url, analytics, onActionClick) => ({
|
|
22
14
|
name: ActionName.CustomAction,
|
|
23
15
|
icon: /*#__PURE__*/React.createElement(ShortcutIcon, {
|
|
24
16
|
label: "open in new tab",
|
|
@@ -35,8 +27,7 @@ const getOpenAction = (url, analytics, onActionClick) => ({
|
|
|
35
27
|
},
|
|
36
28
|
testId: 'hover-card-open-button'
|
|
37
29
|
});
|
|
38
|
-
|
|
39
|
-
const toFooterActions = (cardActions, onActionClick) => cardActions.map(action => ({
|
|
30
|
+
export const toFooterActions = (cardActions, onActionClick) => cardActions.map(action => ({
|
|
40
31
|
content: action.text,
|
|
41
32
|
name: ActionName.CustomAction,
|
|
42
33
|
onClick: () => {
|
|
@@ -63,12 +54,12 @@ const HoverCardContent = ({
|
|
|
63
54
|
useEffect(() => {
|
|
64
55
|
// Since hover preview only render on resolved status,
|
|
65
56
|
// there is no need to check for statuses.
|
|
66
|
-
analytics.ui.renderSuccessEvent(
|
|
57
|
+
analytics.ui.renderSuccessEvent(SMART_CARD_ANALYTICS_DISPLAY, cardState.status);
|
|
67
58
|
}, [analytics.ui, cardState.status]);
|
|
68
59
|
const extensionKey = useMemo(() => getExtensionKey(cardState.details), [cardState.details]);
|
|
69
60
|
const onClick = useCallback(event => {
|
|
70
61
|
const isModifierKeyPressed = isSpecialEvent(event);
|
|
71
|
-
analytics.ui.cardClickedEvent(undefined,
|
|
62
|
+
analytics.ui.cardClickedEvent(undefined, SMART_CARD_ANALYTICS_DISPLAY, cardState.status, undefined, undefined, isModifierKeyPressed, undefined, undefined, undefined, 'titleGoToLink');
|
|
72
63
|
}, [cardState.status, analytics.ui]);
|
|
73
64
|
const titleActions = useMemo(() => [getOpenAction(url, analytics, onActionClick)], [url, analytics, onActionClick]);
|
|
74
65
|
const footerActions = useMemo(() => toFooterActions(cardActions, onActionClick), [cardActions, onActionClick]);
|
|
@@ -1,109 +1,38 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/extends";
|
|
2
2
|
|
|
3
3
|
/** @jsx jsx */
|
|
4
|
-
import { jsx } from '@emotion/core';
|
|
5
|
-
import React, { useCallback, useRef } from 'react';
|
|
6
|
-
import Popup from '@atlaskit/popup';
|
|
7
|
-
import { useSmartLinkActions } from '../../state/hooks-external/useSmartLinkActions';
|
|
8
|
-
import { HoverCardContainer } from './styled';
|
|
9
4
|
import { withAnalyticsContext, withAnalyticsEvents } from '@atlaskit/analytics-next';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
5
|
+
import { jsx } from '@emotion/core';
|
|
6
|
+
import { useCallback } from 'react';
|
|
7
|
+
import { ErrorBoundary } from 'react-error-boundary';
|
|
12
8
|
import { useSmartLinkAnalytics } from '../../state/analytics';
|
|
13
|
-
import {
|
|
14
|
-
import
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
9
|
+
import { fireSmartLinkEvent } from '../../utils/analytics';
|
|
10
|
+
import { HoverCardComponent } from './components/HoverCardComponent';
|
|
11
|
+
import { SMART_CARD_ANALYTICS_DISPLAY } from './utils';
|
|
12
|
+
|
|
13
|
+
const HoverCardWithErrorBoundary = props => {
|
|
14
|
+
const {
|
|
15
|
+
url,
|
|
16
|
+
id,
|
|
17
|
+
children,
|
|
18
|
+
createAnalyticsEvent
|
|
19
|
+
} = props;
|
|
23
20
|
const analyticsHandler = useCallback(analyticsPayload => {
|
|
24
21
|
fireSmartLinkEvent(analyticsPayload, createAnalyticsEvent);
|
|
25
22
|
}, [createAnalyticsEvent]);
|
|
26
|
-
const delay = 300;
|
|
27
|
-
const [isOpen, setIsOpen] = React.useState(false);
|
|
28
|
-
const fadeOutTimeoutId = useRef();
|
|
29
|
-
const fadeInTimeoutId = useRef();
|
|
30
|
-
const cardOpenTime = useRef();
|
|
31
|
-
const renderers = useSmartLinkRenderers();
|
|
32
|
-
const linkState = useLinkState(url);
|
|
33
23
|
const analytics = useSmartLinkAnalytics(url, analyticsHandler, id);
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (fadeInTimeoutId.current) {
|
|
45
|
-
clearTimeout(fadeInTimeoutId.current);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
fadeOutTimeoutId.current = setTimeout(() => hideCard(), delay);
|
|
49
|
-
}, [hideCard]);
|
|
50
|
-
const initShowCard = useCallback(() => {
|
|
51
|
-
if (fadeOutTimeoutId.current) {
|
|
52
|
-
clearTimeout(fadeOutTimeoutId.current);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
fadeInTimeoutId.current = setTimeout(() => {
|
|
56
|
-
//Check if its previously closed to avoid firing events when moving between the child and hover card components
|
|
57
|
-
if (isOpen === false) {
|
|
58
|
-
cardOpenTime.current = Date.now();
|
|
59
|
-
analytics.ui.hoverCardViewedEvent('card', 'mouse_hover');
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
setIsOpen(true);
|
|
63
|
-
}, delay);
|
|
64
|
-
}, [delay, isOpen, analytics.ui]);
|
|
65
|
-
const linkActions = useSmartLinkActions({
|
|
66
|
-
url,
|
|
67
|
-
appearance: HOVER_CARD_ANALYTICS_DISPLAY,
|
|
68
|
-
analyticsHandler
|
|
69
|
-
});
|
|
70
|
-
const onActionClick = useCallback(actionId => {
|
|
71
|
-
if (actionId === 'preview-content') {
|
|
72
|
-
hideCard();
|
|
73
|
-
}
|
|
74
|
-
}, [hideCard]); // Stop hover preview content to propagate event to parent.
|
|
75
|
-
|
|
76
|
-
const onClick = useCallback(e => e.stopPropagation(), []);
|
|
77
|
-
return jsx(Popup, {
|
|
78
|
-
testId: "hover-card",
|
|
79
|
-
isOpen: isOpen,
|
|
80
|
-
onClose: hideCard,
|
|
81
|
-
placement: "bottom-start",
|
|
82
|
-
content: ({
|
|
83
|
-
update
|
|
84
|
-
}) => jsx("div", {
|
|
85
|
-
onMouseEnter: initShowCard,
|
|
86
|
-
onMouseLeave: initHideCard,
|
|
87
|
-
className: hoverCardClassName,
|
|
88
|
-
css: HoverCardContainer,
|
|
89
|
-
onClick: onClick
|
|
90
|
-
}, jsx(HoverCardContent, {
|
|
91
|
-
analytics: analytics,
|
|
92
|
-
cardActions: linkActions,
|
|
93
|
-
cardState: linkState,
|
|
94
|
-
onActionClick: onActionClick,
|
|
95
|
-
onResolve: update,
|
|
96
|
-
renderers: renderers,
|
|
97
|
-
url: url
|
|
98
|
-
})),
|
|
99
|
-
trigger: triggerProps => jsx("span", _extends({}, triggerProps, {
|
|
100
|
-
onMouseEnter: initShowCard,
|
|
101
|
-
onMouseLeave: initHideCard
|
|
102
|
-
}), children),
|
|
103
|
-
zIndex: 511 // Temporary fix for Confluence inline comment on editor mod has z-index of 500, Jira issue view has z-index of 510
|
|
104
|
-
|
|
105
|
-
});
|
|
24
|
+
const onError = useCallback((error, info) => {
|
|
25
|
+
analytics.ui.renderFailedEvent(SMART_CARD_ANALYTICS_DISPLAY, id, error, info);
|
|
26
|
+
}, [analytics.ui, id]);
|
|
27
|
+
return jsx(ErrorBoundary, {
|
|
28
|
+
fallback: children,
|
|
29
|
+
onError: onError
|
|
30
|
+
}, jsx(HoverCardComponent, _extends({}, props, {
|
|
31
|
+
analyticsHandler: analyticsHandler,
|
|
32
|
+
analytics: analytics
|
|
33
|
+
}), children));
|
|
106
34
|
};
|
|
35
|
+
|
|
107
36
|
export const HoverCard = withAnalyticsContext({
|
|
108
37
|
source: 'smartLinkPreviewHoverCard'
|
|
109
|
-
})(withAnalyticsEvents()(
|
|
38
|
+
})(withAnalyticsEvents()(HoverCardWithErrorBoundary));
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { css } from '@emotion/core';
|
|
2
2
|
import { loadingPlaceholderClassName } from '../../index';
|
|
3
|
+
import { SmartLinkSize, SmartLinkTheme } from '../../constants';
|
|
4
|
+
export const flexibleUiOptions = {
|
|
5
|
+
hideElevation: true,
|
|
6
|
+
size: SmartLinkSize.Medium,
|
|
7
|
+
// eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage
|
|
8
|
+
theme: SmartLinkTheme.Black,
|
|
9
|
+
hidePadding: true
|
|
10
|
+
};
|
|
3
11
|
const blockGap = '0.5rem';
|
|
4
12
|
const elementGap = '0.5rem';
|
|
5
13
|
const separatorCss = css`
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ElementName } from '../../constants';
|
|
2
|
-
export const
|
|
2
|
+
export const SMART_CARD_ANALYTICS_DISPLAY = 'flexible';
|
|
3
3
|
export const getSimulatedMetadata = (extensionKey = '', types = []) => {
|
|
4
4
|
switch (extensionKey) {
|
|
5
5
|
case 'bitbucket-object-provider':
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
2
|
import { getUrl } from '@atlaskit/linking-common';
|
|
3
|
-
import { uiAuthEvent, uiAuthAlternateAccountEvent, uiCardClickedEvent, uiActionClickedEvent, uiClosedAuthEvent, uiRenderSuccessEvent, uiHoverCardViewedEvent, uiHoverCardDismissedEvent, uiHoverCardOpenLinkClickedEvent, invokeSucceededEvent as _invokeSucceededEvent, invokeFailedEvent as _invokeFailedEvent, connectSucceededEvent as _connectSucceededEvent, connectFailedEvent as _connectFailedEvent, trackAppAccountConnected, screenAuthPopupEvent, instrumentEvent } from '../../utils/analytics';
|
|
3
|
+
import { uiAuthEvent, uiAuthAlternateAccountEvent, uiCardClickedEvent, uiActionClickedEvent, uiClosedAuthEvent, uiRenderSuccessEvent, uiRenderFailedEvent, uiHoverCardViewedEvent, uiHoverCardDismissedEvent, uiHoverCardOpenLinkClickedEvent, invokeSucceededEvent as _invokeSucceededEvent, invokeFailedEvent as _invokeFailedEvent, connectSucceededEvent as _connectSucceededEvent, connectFailedEvent as _connectFailedEvent, trackAppAccountConnected, screenAuthPopupEvent, instrumentEvent } from '../../utils/analytics';
|
|
4
4
|
import { failUfoExperience, startUfoExperience, succeedUfoExperience } from './ufoExperiences';
|
|
5
5
|
import { getDefinitionId, getExtensionKey, getResourceType, getSubproduct, getProduct } from '../helpers';
|
|
6
6
|
import { useSmartLinkContext } from '@atlaskit/link-provider';
|
|
@@ -20,12 +20,13 @@ export var useSmartLinkAnalytics = function useSmartLinkAnalytics(url, dispatchA
|
|
|
20
20
|
var _useSmartLinkContext = useSmartLinkContext(),
|
|
21
21
|
store = _useSmartLinkContext.store;
|
|
22
22
|
|
|
23
|
-
var state = getUrl(store, url);
|
|
24
|
-
var
|
|
25
|
-
var
|
|
26
|
-
var
|
|
27
|
-
var
|
|
28
|
-
var
|
|
23
|
+
var state = store ? getUrl(store, url) : undefined;
|
|
24
|
+
var details = state ? state.details : undefined;
|
|
25
|
+
var extractedDefinitionId = getDefinitionId(details);
|
|
26
|
+
var extractedExtensionKey = getExtensionKey(details);
|
|
27
|
+
var extractedResourceType = getResourceType(details);
|
|
28
|
+
var extractedSubproduct = getSubproduct(details);
|
|
29
|
+
var extractedProduct = getProduct(details);
|
|
29
30
|
/** Contains all ui analytics events */
|
|
30
31
|
|
|
31
32
|
var ui = useMemo(function () {
|
|
@@ -160,6 +161,25 @@ export var useSmartLinkAnalytics = function useSmartLinkAnalytics(url, dispatchA
|
|
|
160
161
|
dispatchAnalytics(uiRenderSuccessEvent(display, status, definitionId, extensionKey));
|
|
161
162
|
},
|
|
162
163
|
|
|
164
|
+
/**
|
|
165
|
+
* This fires an event that represents when a Smart Link renders unsuccessfuly.
|
|
166
|
+
* @param display Whether the card was an Inline, Block, Embed or Flexible UI.
|
|
167
|
+
* @param id The unique ID for this Smart Link.
|
|
168
|
+
* @param error: An error representing why the Smart Link render failed.
|
|
169
|
+
* @param errorInfo: Additional details about the error including the stack trace.
|
|
170
|
+
*/
|
|
171
|
+
renderFailedEvent: function renderFailedEvent(display) {
|
|
172
|
+
var id = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultId;
|
|
173
|
+
var error = arguments.length > 2 ? arguments[2] : undefined;
|
|
174
|
+
var errorInfo = arguments.length > 3 ? arguments[3] : undefined;
|
|
175
|
+
// Start and fail the smart-link-rendered experience. If it has already
|
|
176
|
+
// been started nothing happens.
|
|
177
|
+
startUfoExperience('smart-link-rendered', id);
|
|
178
|
+
failUfoExperience('smart-link-rendered', id);
|
|
179
|
+
failUfoExperience('smart-link-authenticated', id);
|
|
180
|
+
dispatchAnalytics(uiRenderFailedEvent(display, error, errorInfo));
|
|
181
|
+
},
|
|
182
|
+
|
|
163
183
|
/**
|
|
164
184
|
* This fires an event that represents a hover preview being opened.
|
|
165
185
|
* @param hoverDisplay Whether the hover preview was displayed as a card or embed.
|
package/dist/esm/version.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
2
2
|
import React, { lazy, useEffect, useState, Suspense, useCallback } from 'react';
|
|
3
3
|
import uuid from 'uuid';
|
|
4
|
-
import {
|
|
4
|
+
import { fireSmartLinkEvent } from '../../utils/analytics';
|
|
5
5
|
import { clearMarks, clearMeasures } from '../../utils/performance';
|
|
6
6
|
import { ErrorBoundary } from 'react-error-boundary';
|
|
7
|
-
import {
|
|
7
|
+
import { useSmartLinkAnalytics } from '../../state/analytics';
|
|
8
8
|
import { LoadingCardLink } from './component-lazy/LazyFallback';
|
|
9
9
|
var LazyCardWithUrlContent = /*#__PURE__*/lazy(function () {
|
|
10
10
|
return import(
|
|
@@ -56,6 +56,7 @@ export function CardWithURLRenderer(props) {
|
|
|
56
56
|
|
|
57
57
|
fireSmartLinkEvent(analyticsPayload, createAnalyticsEvent);
|
|
58
58
|
}, [appearance, createAnalyticsEvent]);
|
|
59
|
+
var analytics = useSmartLinkAnalytics(url !== null && url !== void 0 ? url : '', dispatchAnalytics, id);
|
|
59
60
|
var logError = useCallback(function (error, info) {
|
|
60
61
|
var componentStack = info.componentStack; // NB: APIErrors are thrown in response to Object Resolver Service.
|
|
61
62
|
// In these cases, control is handed back to the Editor. We do not
|
|
@@ -69,15 +70,10 @@ export function CardWithURLRenderer(props) {
|
|
|
69
70
|
else {
|
|
70
71
|
var errorInfo = {
|
|
71
72
|
componentStack: componentStack
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
startUfoExperience('smart-link-rendered', id);
|
|
76
|
-
failUfoExperience('smart-link-rendered', id);
|
|
77
|
-
failUfoExperience('smart-link-authenticated', id);
|
|
78
|
-
dispatchAnalytics(uiRenderFailedEvent(appearance, error, errorInfo));
|
|
73
|
+
};
|
|
74
|
+
analytics.ui.renderFailedEvent(appearance, id, error, errorInfo);
|
|
79
75
|
}
|
|
80
|
-
}, [
|
|
76
|
+
}, [analytics.ui, appearance, id]);
|
|
81
77
|
|
|
82
78
|
if (!url) {
|
|
83
79
|
throw new Error('@atlaskit/smart-card: url property is missing.');
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
3
|
+
|
|
4
|
+
/** @jsx jsx */
|
|
5
|
+
import Popup from '@atlaskit/popup';
|
|
6
|
+
import { jsx } from '@emotion/core';
|
|
7
|
+
import React, { useCallback, useRef } from 'react';
|
|
8
|
+
import { useSmartLinkActions } from '../../../state/hooks-external/useSmartLinkActions';
|
|
9
|
+
import { useSmartLinkRenderers } from '../../../state/renderers';
|
|
10
|
+
import { useSmartCardState as useLinkState } from '../../../state/store';
|
|
11
|
+
import HoverCardContent from '../components/HoverCardContent';
|
|
12
|
+
import { HoverCardContainer } from '../styled';
|
|
13
|
+
import { SMART_CARD_ANALYTICS_DISPLAY } from '../utils';
|
|
14
|
+
export var hoverCardClassName = 'smart-links-hover-preview';
|
|
15
|
+
export var HoverCardComponent = function HoverCardComponent(_ref) {
|
|
16
|
+
var children = _ref.children,
|
|
17
|
+
url = _ref.url,
|
|
18
|
+
analyticsHandler = _ref.analyticsHandler,
|
|
19
|
+
analytics = _ref.analytics;
|
|
20
|
+
var delay = 300;
|
|
21
|
+
|
|
22
|
+
var _React$useState = React.useState(false),
|
|
23
|
+
_React$useState2 = _slicedToArray(_React$useState, 2),
|
|
24
|
+
isOpen = _React$useState2[0],
|
|
25
|
+
setIsOpen = _React$useState2[1];
|
|
26
|
+
|
|
27
|
+
var fadeOutTimeoutId = useRef();
|
|
28
|
+
var fadeInTimeoutId = useRef();
|
|
29
|
+
var cardOpenTime = useRef();
|
|
30
|
+
var renderers = useSmartLinkRenderers();
|
|
31
|
+
var linkState = useLinkState(url);
|
|
32
|
+
var hoverDisplay = 'card';
|
|
33
|
+
var invokeMethod = 'mouse_hover';
|
|
34
|
+
var hideCard = useCallback(function () {
|
|
35
|
+
//Check its previously open to avoid firing events when moving between the child and hover card components
|
|
36
|
+
if (isOpen === true && cardOpenTime.current) {
|
|
37
|
+
var hoverTime = Date.now() - cardOpenTime.current;
|
|
38
|
+
analytics.ui.hoverCardDismissedEvent('card', hoverTime, 'mouse_hover');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
setIsOpen(false);
|
|
42
|
+
}, [analytics.ui, isOpen]);
|
|
43
|
+
var initHideCard = useCallback(function () {
|
|
44
|
+
if (fadeInTimeoutId.current) {
|
|
45
|
+
clearTimeout(fadeInTimeoutId.current);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
fadeOutTimeoutId.current = setTimeout(function () {
|
|
49
|
+
return hideCard();
|
|
50
|
+
}, delay);
|
|
51
|
+
}, [hideCard]);
|
|
52
|
+
var initShowCard = useCallback(function () {
|
|
53
|
+
if (fadeOutTimeoutId.current) {
|
|
54
|
+
clearTimeout(fadeOutTimeoutId.current);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
fadeInTimeoutId.current = setTimeout(function () {
|
|
58
|
+
//Check if its previously closed to avoid firing events when moving between the child and hover card components
|
|
59
|
+
if (isOpen === false) {
|
|
60
|
+
cardOpenTime.current = Date.now();
|
|
61
|
+
analytics.ui.hoverCardViewedEvent(hoverDisplay, invokeMethod);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
setIsOpen(true);
|
|
65
|
+
}, delay);
|
|
66
|
+
}, [delay, isOpen, analytics.ui]);
|
|
67
|
+
var linkActions = useSmartLinkActions({
|
|
68
|
+
url: url,
|
|
69
|
+
appearance: SMART_CARD_ANALYTICS_DISPLAY,
|
|
70
|
+
analyticsHandler: analyticsHandler
|
|
71
|
+
});
|
|
72
|
+
var onActionClick = useCallback(function (actionId) {
|
|
73
|
+
if (actionId === 'preview-content') {
|
|
74
|
+
hideCard();
|
|
75
|
+
}
|
|
76
|
+
}, [hideCard]); // Stop hover preview content to propagate event to parent.
|
|
77
|
+
|
|
78
|
+
var onClick = useCallback(function (e) {
|
|
79
|
+
return e.stopPropagation();
|
|
80
|
+
}, []);
|
|
81
|
+
return jsx(Popup, {
|
|
82
|
+
testId: "hover-card",
|
|
83
|
+
isOpen: isOpen,
|
|
84
|
+
onClose: hideCard,
|
|
85
|
+
placement: "bottom-start",
|
|
86
|
+
content: function content(_ref2) {
|
|
87
|
+
var update = _ref2.update;
|
|
88
|
+
return jsx("div", {
|
|
89
|
+
onMouseEnter: initShowCard,
|
|
90
|
+
onMouseLeave: initHideCard,
|
|
91
|
+
onClick: onClick,
|
|
92
|
+
css: HoverCardContainer // class name for trello to exclude click events
|
|
93
|
+
,
|
|
94
|
+
className: hoverCardClassName
|
|
95
|
+
}, jsx(HoverCardContent, {
|
|
96
|
+
analytics: analytics,
|
|
97
|
+
cardActions: linkActions,
|
|
98
|
+
cardState: linkState,
|
|
99
|
+
onActionClick: onActionClick,
|
|
100
|
+
onResolve: update,
|
|
101
|
+
renderers: renderers,
|
|
102
|
+
url: url
|
|
103
|
+
}));
|
|
104
|
+
},
|
|
105
|
+
trigger: function trigger(triggerProps) {
|
|
106
|
+
return jsx("span", _extends({}, triggerProps, {
|
|
107
|
+
onMouseEnter: initShowCard,
|
|
108
|
+
onMouseLeave: initHideCard
|
|
109
|
+
}), children);
|
|
110
|
+
},
|
|
111
|
+
zIndex: 511 // Temporary fix for Confluence inline comment on editor mod has z-index of 500, Jira issue view has z-index of 510
|
|
112
|
+
|
|
113
|
+
});
|
|
114
|
+
};
|
|
@@ -1,24 +1,16 @@
|
|
|
1
|
+
import ShortcutIcon from '@atlaskit/icon/glyph/shortcut';
|
|
2
|
+
import { extractType } from '@atlaskit/linking-common/extractors';
|
|
1
3
|
import React, { useCallback, useEffect, useMemo } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { getSimulatedMetadata, HOVER_CARD_ANALYTICS_DISPLAY } from '../utils';
|
|
4
|
+
import { ActionName, SmartLinkPosition, SmartLinkSize } from '../../../constants';
|
|
4
5
|
import extractPreview from '../../../extractors/flexible/extract-preview';
|
|
5
|
-
import {
|
|
6
|
+
import { extractMetadata } from '../../../extractors/hover/extractMetadata';
|
|
7
|
+
import { getExtensionKey } from '../../../state/helpers';
|
|
8
|
+
import { isSpecialEvent } from '../../../utils';
|
|
6
9
|
import FlexibleCard from '../../FlexibleCard';
|
|
7
10
|
import { FooterBlock, MetadataBlock, PreviewBlock, SnippetBlock, TitleBlock } from '../../FlexibleCard/components/blocks';
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
import { titleBlockCss, metadataBlockCss, footerBlockCss } from '../styled';
|
|
12
|
-
import { extractType } from '@atlaskit/linking-common/extractors';
|
|
13
|
-
var flexibleUiOptions = {
|
|
14
|
-
hideElevation: true,
|
|
15
|
-
size: SmartLinkSize.Medium,
|
|
16
|
-
// eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage
|
|
17
|
-
theme: SmartLinkTheme.Black,
|
|
18
|
-
hidePadding: true
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
var getOpenAction = function getOpenAction(url, analytics, onActionClick) {
|
|
11
|
+
import { flexibleUiOptions, footerBlockCss, metadataBlockCss, titleBlockCss } from '../styled';
|
|
12
|
+
import { getSimulatedMetadata, SMART_CARD_ANALYTICS_DISPLAY } from '../utils';
|
|
13
|
+
export var getOpenAction = function getOpenAction(url, analytics, onActionClick) {
|
|
22
14
|
return {
|
|
23
15
|
name: ActionName.CustomAction,
|
|
24
16
|
icon: /*#__PURE__*/React.createElement(ShortcutIcon, {
|
|
@@ -37,8 +29,7 @@ var getOpenAction = function getOpenAction(url, analytics, onActionClick) {
|
|
|
37
29
|
testId: 'hover-card-open-button'
|
|
38
30
|
};
|
|
39
31
|
};
|
|
40
|
-
|
|
41
|
-
var toFooterActions = function toFooterActions(cardActions, onActionClick) {
|
|
32
|
+
export var toFooterActions = function toFooterActions(cardActions, onActionClick) {
|
|
42
33
|
return cardActions.map(function (action) {
|
|
43
34
|
return {
|
|
44
35
|
content: action.text,
|
|
@@ -69,14 +60,14 @@ var HoverCardContent = function HoverCardContent(_ref) {
|
|
|
69
60
|
useEffect(function () {
|
|
70
61
|
// Since hover preview only render on resolved status,
|
|
71
62
|
// there is no need to check for statuses.
|
|
72
|
-
analytics.ui.renderSuccessEvent(
|
|
63
|
+
analytics.ui.renderSuccessEvent(SMART_CARD_ANALYTICS_DISPLAY, cardState.status);
|
|
73
64
|
}, [analytics.ui, cardState.status]);
|
|
74
65
|
var extensionKey = useMemo(function () {
|
|
75
66
|
return getExtensionKey(cardState.details);
|
|
76
67
|
}, [cardState.details]);
|
|
77
68
|
var onClick = useCallback(function (event) {
|
|
78
69
|
var isModifierKeyPressed = isSpecialEvent(event);
|
|
79
|
-
analytics.ui.cardClickedEvent(undefined,
|
|
70
|
+
analytics.ui.cardClickedEvent(undefined, SMART_CARD_ANALYTICS_DISPLAY, cardState.status, undefined, undefined, isModifierKeyPressed, undefined, undefined, undefined, 'titleGoToLink');
|
|
80
71
|
}, [cardState.status, analytics.ui]);
|
|
81
72
|
var titleActions = useMemo(function () {
|
|
82
73
|
return [getOpenAction(url, analytics, onActionClick)];
|