@atlaskit/smart-card 24.0.0 → 24.0.2

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.
Files changed (52) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/cjs/state/analytics/useMouseDownEvent.js +24 -0
  3. package/dist/cjs/utils/analytics/click.js +121 -0
  4. package/dist/cjs/utils/index.js +10 -0
  5. package/dist/cjs/version.json +1 -1
  6. package/dist/cjs/view/BlockCard/components/ContentHeader.js +4 -0
  7. package/dist/cjs/view/BlockCard/index.js +1 -0
  8. package/dist/cjs/view/BlockCard/views/flexible/FlexibleResolvedView.js +2 -0
  9. package/dist/cjs/view/CardWithUrl/component.js +24 -9
  10. package/dist/cjs/view/EmbedCard/components/ExpandedFrame.js +4 -1
  11. package/dist/cjs/view/EmbedModal/components/link-info/link-info-button/index.js +3 -0
  12. package/dist/cjs/view/FlexibleCard/components/blocks/title-block/index.js +3 -0
  13. package/dist/cjs/view/FlexibleCard/components/container/layered-link/index.js +3 -0
  14. package/dist/cjs/view/FlexibleCard/components/elements/link/index.js +3 -0
  15. package/dist/cjs/view/HoverCard/components/HoverCardContent.js +6 -1
  16. package/dist/cjs/view/InlineCard/Frame/index.js +4 -0
  17. package/dist/es2019/state/analytics/useMouseDownEvent.js +18 -0
  18. package/dist/es2019/utils/analytics/click.js +106 -0
  19. package/dist/es2019/utils/index.js +10 -0
  20. package/dist/es2019/version.json +1 -1
  21. package/dist/es2019/view/BlockCard/components/ContentHeader.js +19 -14
  22. package/dist/es2019/view/BlockCard/index.js +1 -0
  23. package/dist/es2019/view/BlockCard/views/flexible/FlexibleResolvedView.js +2 -0
  24. package/dist/es2019/view/CardWithUrl/component.js +25 -9
  25. package/dist/es2019/view/EmbedCard/components/ExpandedFrame.js +4 -1
  26. package/dist/es2019/view/EmbedModal/components/link-info/link-info-button/index.js +3 -0
  27. package/dist/es2019/view/FlexibleCard/components/blocks/title-block/index.js +3 -0
  28. package/dist/es2019/view/FlexibleCard/components/container/layered-link/index.js +14 -9
  29. package/dist/es2019/view/FlexibleCard/components/elements/link/index.js +3 -0
  30. package/dist/es2019/view/HoverCard/components/HoverCardContent.js +7 -1
  31. package/dist/es2019/view/InlineCard/Frame/index.js +3 -0
  32. package/dist/esm/state/analytics/useMouseDownEvent.js +17 -0
  33. package/dist/esm/utils/analytics/click.js +109 -0
  34. package/dist/esm/utils/index.js +10 -0
  35. package/dist/esm/version.json +1 -1
  36. package/dist/esm/view/BlockCard/components/ContentHeader.js +3 -0
  37. package/dist/esm/view/BlockCard/index.js +1 -0
  38. package/dist/esm/view/BlockCard/views/flexible/FlexibleResolvedView.js +2 -0
  39. package/dist/esm/view/CardWithUrl/component.js +24 -9
  40. package/dist/esm/view/EmbedCard/components/ExpandedFrame.js +4 -1
  41. package/dist/esm/view/EmbedModal/components/link-info/link-info-button/index.js +3 -0
  42. package/dist/esm/view/FlexibleCard/components/blocks/title-block/index.js +3 -0
  43. package/dist/esm/view/FlexibleCard/components/container/layered-link/index.js +3 -0
  44. package/dist/esm/view/FlexibleCard/components/elements/link/index.js +3 -0
  45. package/dist/esm/view/HoverCard/components/HoverCardContent.js +6 -1
  46. package/dist/esm/view/InlineCard/Frame/index.js +3 -0
  47. package/dist/types/state/analytics/useMouseDownEvent.d.ts +3 -0
  48. package/dist/types/utils/analytics/click.d.ts +21 -0
  49. package/dist/types/utils/analytics/types.d.ts +16 -0
  50. package/dist/types/utils/index.d.ts +9 -0
  51. package/dist/types/view/FlexibleCard/components/elements/link/types.d.ts +4 -0
  52. package/package.json +4 -2
@@ -1,21 +1,26 @@
1
1
  /** @jsx jsx */
2
2
  import { jsx } from '@emotion/react';
3
+ import useMouseDownEvent from '../../../state/analytics/useMouseDownEvent';
3
4
  export const blockCardContentHeaderClassName = 'block-card-content-header';
4
5
  export const ContentHeader = ({
5
6
  onClick,
6
7
  link,
7
8
  children
8
- }) => jsx("a", {
9
- onClick: onClick,
10
- href: link,
11
- target: "_blank",
12
- css: {
13
- display: 'flex',
14
- alignItems: 'flex-start',
15
- // EDM-713: fixes copy-paste from renderer to editor for Firefox
16
- // due to HTML its unwrapping behaviour on paste.
17
- MozUserSelect: 'none'
18
- },
19
- "data-trello-do-not-use-override": "block-card-content-header",
20
- className: blockCardContentHeaderClassName
21
- }, children);
9
+ }) => {
10
+ const onMouseDown = useMouseDownEvent();
11
+ return jsx("a", {
12
+ onClick: onClick,
13
+ onMouseDown: onMouseDown,
14
+ href: link,
15
+ target: "_blank",
16
+ css: {
17
+ display: 'flex',
18
+ alignItems: 'flex-start',
19
+ // EDM-713: fixes copy-paste from renderer to editor for Firefox
20
+ // due to HTML its unwrapping behaviour on paste.
21
+ MozUserSelect: 'none'
22
+ },
23
+ "data-trello-do-not-use-override": "block-card-content-header",
24
+ className: blockCardContentHeaderClassName
25
+ }, children);
26
+ };
@@ -70,6 +70,7 @@ export const BlockCard = ({
70
70
  cardState,
71
71
  url,
72
72
  testId,
73
+ onClick: handleFrameClick,
73
74
  onError,
74
75
  onResolve,
75
76
  renderers,
@@ -63,6 +63,8 @@ const FlexibleResolvedView = ({
63
63
  name: ElementName.ViewCount
64
64
  }, {
65
65
  name: ElementName.VoteCount
66
+ }, {
67
+ name: ElementName.ChecklistProgress
66
68
  }, {
67
69
  name: ElementName.DueOn
68
70
  }],
@@ -1,4 +1,5 @@
1
1
  import React, { useEffect, useCallback, useMemo } from 'react';
2
+ import { useAnalyticsEvents } from '@atlaskit/analytics-next';
2
3
  import { useFeatureFlag } from '@atlaskit/link-provider';
3
4
  import { isSpecialEvent } from '../../utils';
4
5
  import * as measure from '../../utils/performance';
@@ -11,6 +12,7 @@ import { isFlexibleUiCard } from '../../utils/flexible';
11
12
  import FlexibleCard from '../FlexibleCard';
12
13
  import { APIError } from '../..';
13
14
  import { CardDisplay } from '../../constants';
15
+ import { fireLinkClickedEvent } from '../../utils/analytics/click';
14
16
  export function CardWithUrlContent({
15
17
  id,
16
18
  url,
@@ -33,6 +35,10 @@ export function CardWithUrlContent({
33
35
  showAuthTooltip: showAuthTooltipProp,
34
36
  analyticsEvents
35
37
  }) {
38
+ const {
39
+ createAnalyticsEvent
40
+ } = useAnalyticsEvents();
41
+
36
42
  // Get state, actions for this card.
37
43
  const {
38
44
  state,
@@ -55,10 +61,6 @@ export function CardWithUrlContent({
55
61
  const enableFlexibleBlockCardFlag = Boolean(useFeatureFlag('enableFlexibleBlockCard'));
56
62
 
57
63
  // Setup UI handlers.
58
- const handleClick = useCallback(event => {
59
- const clickUrl = getClickUrl(url, state.details);
60
- isSpecialEvent(event) ? window.open(clickUrl, '_blank') : window.open(clickUrl, '_self');
61
- }, [state.details, url]);
62
64
  const handleClickWrapper = useCallback(event => {
63
65
  const isModifierKeyPressed = isSpecialEvent(event);
64
66
  analytics.ui.cardClickedEvent({
@@ -71,12 +73,26 @@ export function CardWithUrlContent({
71
73
  destinationProduct: product,
72
74
  destinationSubproduct: subproduct
73
75
  });
74
- if (onClick) {
75
- onClick(event);
76
- } else if (!isFlexibleUi) {
77
- handleClick(event);
76
+ if (!onClick && !isFlexibleUi) {
77
+ const clickUrl = getClickUrl(url, state.details);
78
+ // Ctrl+left click on mac typically doesn't trigger onClick
79
+ // The event could have potentially had `e.preventDefault()` called on it by now
80
+ // event by smart card internally
81
+ // If it has been called then only then can `isModifierKeyPressed` be true.
82
+ const target = isModifierKeyPressed ? '_blank' : '_self';
83
+ window.open(clickUrl, target);
84
+ fireLinkClickedEvent(createAnalyticsEvent)(event, {
85
+ attributes: {
86
+ clickOutcome: target === '_blank' ? 'clickThroughNewTabOrWindow' : 'clickThrough'
87
+ }
88
+ });
89
+ } else {
90
+ if (onClick) {
91
+ onClick(event);
92
+ }
93
+ fireLinkClickedEvent(createAnalyticsEvent)(event);
78
94
  }
79
- }, [id, state.status, analytics.ui, appearance, definitionId, extensionKey, onClick, handleClick, isFlexibleUi, product, subproduct]);
95
+ }, [id, url, state.details, state.status, analytics.ui, appearance, definitionId, extensionKey, onClick, isFlexibleUi, product, subproduct, createAnalyticsEvent]);
80
96
  const handleAuthorize = useCallback(() => actions.authorize(appearance), [actions, appearance]);
81
97
  const handleRetry = useCallback(() => {
82
98
  actions.reload();
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { className, LinkWrapper, Wrapper, Header, IconWrapper, TextWrapper, Content } from './styled';
3
3
  import { handleClickCommon } from '../../BlockCard/utils/handlers';
4
+ import useMouseDownEvent from '../../../state/analytics/useMouseDownEvent';
4
5
  export const ExpandedFrame = ({
5
6
  isPlaceholder = false,
6
7
  children,
@@ -19,6 +20,7 @@ export const ExpandedFrame = ({
19
20
  }) => {
20
21
  const isInteractive = () => !isPlaceholder && (Boolean(href) || Boolean(onClick));
21
22
  const handleClick = event => handleClickCommon(event, onClick);
23
+ const handleMouseDown = useMouseDownEvent();
22
24
  const renderHeader = () => /*#__PURE__*/React.createElement(Header, {
23
25
  className: "embed-header"
24
26
  }, /*#__PURE__*/React.createElement(IconWrapper, {
@@ -27,7 +29,8 @@ export const ExpandedFrame = ({
27
29
  isPlaceholder: isPlaceholder
28
30
  }, !isPlaceholder && /*#__PURE__*/React.createElement("a", {
29
31
  href: href,
30
- onClick: handleClick
32
+ onClick: handleClick,
33
+ onMouseDown: handleMouseDown
31
34
  }, text)));
32
35
  const renderContent = () => /*#__PURE__*/React.createElement(Content, {
33
36
  "data-testid": "embed-content-wrapper",
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import Tooltip from '@atlaskit/tooltip';
3
3
  import Button from '@atlaskit/button/custom-theme-button';
4
+ import useMouseDownEvent from '../../../../../state/analytics/useMouseDownEvent';
4
5
  const LinkInfoButton = ({
5
6
  content,
6
7
  href,
@@ -9,6 +10,7 @@ const LinkInfoButton = ({
9
10
  target,
10
11
  testId
11
12
  }) => {
13
+ const onMouseDown = useMouseDownEvent();
12
14
  return /*#__PURE__*/React.createElement(Tooltip, {
13
15
  content: content,
14
16
  hideTooltipOnClick: true,
@@ -20,6 +22,7 @@ const LinkInfoButton = ({
20
22
  href: href,
21
23
  iconBefore: icon,
22
24
  onClick: onClick,
25
+ onMouseDown: onMouseDown,
23
26
  spacing: "none",
24
27
  target: target,
25
28
  testId: `${testId}-button`
@@ -1,6 +1,7 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
2
  import React, { useCallback, useState } from 'react';
3
3
  import { css } from '@emotion/react';
4
+ import useMouseDownEvent from '../../../../../state/analytics/useMouseDownEvent';
4
5
  import { SmartLinkStatus } from '../../../../../constants';
5
6
  import TitleBlockResolvedView from './resolved';
6
7
  import TitleBlockErroredView from './errored';
@@ -90,10 +91,12 @@ const TitleBlock = ({
90
91
  const overrideText = !!text ? {
91
92
  text
92
93
  } : {};
94
+ const onMouseDown = useMouseDownEvent();
93
95
  const title = /*#__PURE__*/React.createElement(Title, _extends({
94
96
  hideTooltip: hideTitleTooltip,
95
97
  maxLines: maxLines,
96
98
  onClick: onClick,
99
+ onMouseDown: onMouseDown,
97
100
  target: anchorTarget,
98
101
  theme: theme
99
102
  }, overrideText));
@@ -1,6 +1,7 @@
1
1
  /** @jsx jsx */
2
2
  import React from 'react';
3
3
  import { jsx, css } from '@emotion/react';
4
+ import useMouseDownEvent from '../../../../../state/analytics/useMouseDownEvent';
4
5
  const styles = css`
5
6
  // Stretch the invisible link over the whole of the post.
6
7
  // Hide the link’s text.
@@ -47,13 +48,17 @@ const LayeredLink = ({
47
48
  testId,
48
49
  text,
49
50
  url
50
- }) => jsx("a", {
51
- className: "layered-link",
52
- css: styles,
53
- "data-testid": `${testId}-layered-link`,
54
- href: url,
55
- onClick: onClick,
56
- target: target,
57
- tabIndex: -1 // Hide tab index and let the title link be the link.
58
- }, text);
51
+ }) => {
52
+ const onMouseDown = useMouseDownEvent();
53
+ return jsx("a", {
54
+ className: "layered-link",
55
+ css: styles,
56
+ "data-testid": `${testId}-layered-link`,
57
+ href: url,
58
+ onClick: onClick,
59
+ onMouseDown: onMouseDown,
60
+ target: target,
61
+ tabIndex: -1 // Hide tab index and let the title link be the link.
62
+ }, text);
63
+ };
59
64
  export default LayeredLink;
@@ -5,6 +5,7 @@ import Tooltip from '@atlaskit/tooltip';
5
5
  import { SmartLinkSize, SmartLinkTheme } from '../../../../../constants';
6
6
  import { getLinkLineHeight, getLinkSizeStyles, getTruncateStyles, hasWhiteSpace } from '../../utils';
7
7
  import { tokens } from '../../../../../utils/token';
8
+ import useMouseDownEvent from '../../../../../state/analytics/useMouseDownEvent';
8
9
  const DEFAULT_MAX_LINES = 2;
9
10
  const MAXIMUM_MAX_LINES = 2;
10
11
  const MINIMUM_MAX_LINES = 1;
@@ -83,6 +84,7 @@ const Link = ({
83
84
  onClick,
84
85
  target
85
86
  }) => {
87
+ const onMouseDown = useMouseDownEvent();
86
88
  const hasSpace = useMemo(() => text ? hasWhiteSpace(text) : false, [text]);
87
89
  const anchor = jsx("a", {
88
90
  css: [getAnchorStyles(size, theme, getMaxLines(maxLines), hasSpace), overrideCss],
@@ -90,6 +92,7 @@ const Link = ({
90
92
  "data-smart-element-link": true,
91
93
  "data-testid": testId,
92
94
  onClick: onClick,
95
+ onMouseDown: onMouseDown,
93
96
  href: url,
94
97
  target: target || '_blank'
95
98
  }, text);
@@ -3,6 +3,7 @@ import { jsx } from '@emotion/react';
3
3
  import ShortcutIcon from '@atlaskit/icon/glyph/shortcut';
4
4
  import CopyIcon from '@atlaskit/icon/glyph/copy';
5
5
  import { extractType } from '@atlaskit/linking-common/extractors';
6
+ import { useAnalyticsEvents } from '@atlaskit/analytics-next';
6
7
  import React, { useCallback, useEffect, useMemo } from 'react';
7
8
  import { ActionName, CardDisplay, SmartLinkPosition, SmartLinkSize } from '../../../constants';
8
9
  import { extractMetadata } from '../../../extractors/hover/extractMetadata';
@@ -16,6 +17,7 @@ import HoverCardResolvedView from './views/resolved';
16
17
  import { FormattedMessage } from 'react-intl-next';
17
18
  import { messages } from '../../../messages';
18
19
  import { useSmartCardActions } from '../../../state/actions';
20
+ import { fireLinkClickedEvent } from '../../../utils/analytics/click';
19
21
  export const hoverCardClassName = 'smart-links-hover-preview';
20
22
  export const getOpenAction = (url, analytics, onActionClick) => ({
21
23
  name: ActionName.CustomAction,
@@ -60,6 +62,9 @@ const HoverCardContent = ({
60
62
  onMouseLeave
61
63
  }) => {
62
64
  var _cardState$details;
65
+ const {
66
+ createAnalyticsEvent
67
+ } = useAnalyticsEvents();
63
68
  const extensionKey = useMemo(() => getExtensionKey(cardState.details), [cardState.details]);
64
69
  const actions = useSmartCardActions(id, url, analytics);
65
70
  useEffect(() => {
@@ -74,7 +79,8 @@ const HoverCardContent = ({
74
79
  isModifierKeyPressed,
75
80
  actionSubjectId: 'titleGoToLink'
76
81
  });
77
- }, [cardState.status, analytics.ui, id]);
82
+ fireLinkClickedEvent(createAnalyticsEvent)(event);
83
+ }, [createAnalyticsEvent, cardState.status, analytics.ui, id]);
78
84
  const titleActions = useMemo(() => [getCopyAction(url), getOpenAction(url, analytics, onActionClick)], [url, analytics, onActionClick]);
79
85
  const data = (_cardState$details = cardState.details) === null || _cardState$details === void 0 ? void 0 : _cardState$details.data;
80
86
  const types = data ? extractType(data) : undefined;
@@ -1,6 +1,7 @@
1
1
  import React, { useCallback } from 'react';
2
2
  import { useGlobalTheme } from '@atlaskit/theme/components';
3
3
  import { WrapperAnchor, WrapperSpan } from './styled';
4
+ import useMouseDownEvent from '../../../state/analytics/useMouseDownEvent';
4
5
  export const Frame = props => {
5
6
  const {
6
7
  isSelected,
@@ -28,6 +29,7 @@ export const Frame = props => {
28
29
  onClick(event);
29
30
  }
30
31
  }, [onClick]);
32
+ const handleMouseDown = useMouseDownEvent();
31
33
  const isInteractive = Boolean(onClick);
32
34
 
33
35
  // Depending on whenever Frame was given onClick or link itself we display span or anchor elements
@@ -44,6 +46,7 @@ export const Frame = props => {
44
46
  tabIndex: isInteractive ? 0 : undefined,
45
47
  role: isInteractive ? 'button' : undefined,
46
48
  onClick: handleClick,
49
+ onMouseDown: handleMouseDown,
47
50
  onKeyPress: handleKeyPress,
48
51
  "data-testid": testId,
49
52
  className: className
@@ -0,0 +1,17 @@
1
+ import { useCallback } from 'react';
2
+ import { useAnalyticsEvents } from '@atlaskit/analytics-next';
3
+ import { fireLinkClickedEvent } from '../../utils/analytics/click';
4
+ var useMouseDownEvent = function useMouseDownEvent(onMouseDown) {
5
+ var _useAnalyticsEvents = useAnalyticsEvents(),
6
+ createAnalyticsEvent = _useAnalyticsEvents.createAnalyticsEvent;
7
+ return useCallback(function (event) {
8
+ onMouseDown === null || onMouseDown === void 0 ? void 0 : onMouseDown(event);
9
+
10
+ // ignore left clicks
11
+ // these would be handled by `onClick` handler instead
12
+ if (event.button !== 0) {
13
+ fireLinkClickedEvent(createAnalyticsEvent)(event);
14
+ }
15
+ }, [onMouseDown, createAnalyticsEvent]);
16
+ };
17
+ export default useMouseDownEvent;
@@ -0,0 +1,109 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
3
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
4
+ import { browser } from '@atlaskit/linking-common/user-agent';
5
+ import { ANALYTICS_CHANNEL } from './analytics';
6
+ export var buttonMap = new Map([[undefined, 'none'], [0, 'left'], [1, 'middle'], [2, 'right']]);
7
+ export var getKeys = function getKeys(e) {
8
+ return ['alt', 'ctrl', 'meta', 'shift'].filter(function (key) {
9
+ return e["".concat(key, "Key")] === true;
10
+ });
11
+ };
12
+ var isContentEditable = function isContentEditable(el) {
13
+ return el instanceof HTMLElement && el.isContentEditable;
14
+ };
15
+ export function getLinkClickOutcome(e, clickType) {
16
+ var _browser = browser(),
17
+ mac = _browser.mac,
18
+ safari = _browser.safari;
19
+ if (e.defaultPrevented) {
20
+ return 'prevented';
21
+ }
22
+ /**
23
+ * If the link/parent is content editable then left click won't have typical effect
24
+ */
25
+ if (isContentEditable(e.currentTarget) && ['left', 'middle'].includes(clickType)) {
26
+ return 'contentEditable';
27
+ }
28
+ switch (clickType) {
29
+ case 'left':
30
+ {
31
+ // Meta key = Cmd for macOS, Windows key sometimes for Windows (otherwise false)
32
+ // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/metaKey
33
+ if (e.metaKey) {
34
+ return mac ? 'clickThroughNewTabOrWindow' : 'clickThrough';
35
+ }
36
+ if (e.shiftKey) {
37
+ // Alt/option click in safari typically adds the link to bookmarks
38
+ if (safari) {
39
+ return 'alt';
40
+ }
41
+ return 'clickThroughNewTabOrWindow';
42
+ }
43
+ if (e.ctrlKey) {
44
+ // Ctrl+Left on macOS defaults to triggering a right click instead (so won't trigger onClick)
45
+ // but if this behaviour is disabled, likely outcome is clickThrough
46
+ if (mac) {
47
+ return 'clickThrough';
48
+ }
49
+ return 'clickThroughNewTabOrWindow';
50
+ }
51
+ if (e.altKey) {
52
+ return 'alt';
53
+ }
54
+ var target = e.currentTarget.getAttribute('target');
55
+ if (target === '_blank') {
56
+ return 'clickThroughNewTabOrWindow';
57
+ }
58
+ return 'clickThrough';
59
+ }
60
+ case 'middle':
61
+ {
62
+ return 'clickThroughNewTabOrWindow';
63
+ }
64
+ case 'right':
65
+ {
66
+ return 'contextMenu';
67
+ }
68
+ }
69
+ return '_unknown';
70
+ }
71
+ var linkClickedEvent = function linkClickedEvent(_ref) {
72
+ var clickType = _ref.clickType,
73
+ clickOutcome = _ref.clickOutcome,
74
+ keysHeld = _ref.keysHeld;
75
+ return {
76
+ action: 'clicked',
77
+ actionSubject: 'link',
78
+ eventType: 'ui',
79
+ attributes: {
80
+ clickType: clickType,
81
+ clickOutcome: clickOutcome,
82
+ keysHeld: keysHeld
83
+ }
84
+ };
85
+ };
86
+ export var createLinkClickedPayload = function createLinkClickedPayload(event) {
87
+ var clickType = buttonMap.get(event.button);
88
+ if (!clickType) {
89
+ return;
90
+ }
91
+ var clickOutcome = getLinkClickOutcome(event, clickType);
92
+ var keysHeld = getKeys(event);
93
+ return linkClickedEvent({
94
+ clickType: clickType,
95
+ clickOutcome: clickOutcome,
96
+ keysHeld: keysHeld
97
+ });
98
+ };
99
+ export var fireLinkClickedEvent = function fireLinkClickedEvent(createAnalyticsEvent) {
100
+ return function (event) {
101
+ var overrides = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
102
+ var payload = createLinkClickedPayload(event);
103
+ if (payload) {
104
+ createAnalyticsEvent(_objectSpread(_objectSpread(_objectSpread({}, payload), overrides), {}, {
105
+ attributes: _objectSpread(_objectSpread({}, payload.attributes), overrides === null || overrides === void 0 ? void 0 : overrides.attributes)
106
+ })).fire(ANALYTICS_CHANNEL);
107
+ }
108
+ };
109
+ };
@@ -12,6 +12,16 @@ export var isSpecialEvent = function isSpecialEvent(evt) {
12
12
  export var isIframe = function isIframe() {
13
13
  return window.parent !== parent;
14
14
  };
15
+
16
+ /**
17
+ * Meta key = cmd on mac, windows key on windows
18
+ * Ctrl key on mac by default triggers a right click instead of left click
19
+ * Ctrl key on Windows has the same behaviour of cmd key of mac (open in new tab)
20
+ *
21
+ * `isSpecialKey` on a mouse event on mac with default behaviour should be equivalent to opening in new tab
22
+ * On Windows it will be equivalent to opening a new tab, unless its the Window key that is held
23
+ * in which case typically only a standard clickthrough will occur, this is likely a small portion of events
24
+ */
15
25
  export var isSpecialKey = function isSpecialKey(event) {
16
26
  return event.metaKey || event.ctrlKey;
17
27
  };
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/smart-card",
3
- "version": "24.0.0",
3
+ "version": "24.0.2",
4
4
  "sideEffects": false
5
5
  }
@@ -1,12 +1,15 @@
1
1
  /** @jsx jsx */
2
2
  import { jsx } from '@emotion/react';
3
+ import useMouseDownEvent from '../../../state/analytics/useMouseDownEvent';
3
4
  export var blockCardContentHeaderClassName = 'block-card-content-header';
4
5
  export var ContentHeader = function ContentHeader(_ref) {
5
6
  var onClick = _ref.onClick,
6
7
  link = _ref.link,
7
8
  children = _ref.children;
9
+ var onMouseDown = useMouseDownEvent();
8
10
  return jsx("a", {
9
11
  onClick: onClick,
12
+ onMouseDown: onMouseDown,
10
13
  href: link,
11
14
  target: "_blank",
12
15
  css: {
@@ -65,6 +65,7 @@ export var BlockCard = function BlockCard(_ref) {
65
65
  cardState: cardState,
66
66
  url: url,
67
67
  testId: testId,
68
+ onClick: handleFrameClick,
68
69
  onError: onError,
69
70
  onResolve: onResolve,
70
71
  renderers: renderers,
@@ -71,6 +71,8 @@ var FlexibleResolvedView = function FlexibleResolvedView(_ref) {
71
71
  name: ElementName.ViewCount
72
72
  }, {
73
73
  name: ElementName.VoteCount
74
+ }, {
75
+ name: ElementName.ChecklistProgress
74
76
  }, {
75
77
  name: ElementName.DueOn
76
78
  }],
@@ -1,4 +1,5 @@
1
1
  import React, { useEffect, useCallback, useMemo } from 'react';
2
+ import { useAnalyticsEvents } from '@atlaskit/analytics-next';
2
3
  import { useFeatureFlag } from '@atlaskit/link-provider';
3
4
  import { isSpecialEvent } from '../../utils';
4
5
  import * as measure from '../../utils/performance';
@@ -11,6 +12,7 @@ import { isFlexibleUiCard } from '../../utils/flexible';
11
12
  import FlexibleCard from '../FlexibleCard';
12
13
  import { APIError } from '../..';
13
14
  import { CardDisplay } from '../../constants';
15
+ import { fireLinkClickedEvent } from '../../utils/analytics/click';
14
16
  export function CardWithUrlContent(_ref) {
15
17
  var id = _ref.id,
16
18
  url = _ref.url,
@@ -32,6 +34,9 @@ export function CardWithUrlContent(_ref) {
32
34
  showHoverPreview = _ref.showHoverPreview,
33
35
  showAuthTooltipProp = _ref.showAuthTooltip,
34
36
  analyticsEvents = _ref.analyticsEvents;
37
+ var _useAnalyticsEvents = useAnalyticsEvents(),
38
+ createAnalyticsEvent = _useAnalyticsEvents.createAnalyticsEvent;
39
+
35
40
  // Get state, actions for this card.
36
41
  var _useSmartLink = useSmartLink(id, url, dispatchAnalytics),
37
42
  state = _useSmartLink.state,
@@ -55,10 +60,6 @@ export function CardWithUrlContent(_ref) {
55
60
  var enableFlexibleBlockCardFlag = Boolean(useFeatureFlag('enableFlexibleBlockCard'));
56
61
 
57
62
  // Setup UI handlers.
58
- var handleClick = useCallback(function (event) {
59
- var clickUrl = getClickUrl(url, state.details);
60
- isSpecialEvent(event) ? window.open(clickUrl, '_blank') : window.open(clickUrl, '_self');
61
- }, [state.details, url]);
62
63
  var handleClickWrapper = useCallback(function (event) {
63
64
  var isModifierKeyPressed = isSpecialEvent(event);
64
65
  analytics.ui.cardClickedEvent({
@@ -71,12 +72,26 @@ export function CardWithUrlContent(_ref) {
71
72
  destinationProduct: product,
72
73
  destinationSubproduct: subproduct
73
74
  });
74
- if (onClick) {
75
- onClick(event);
76
- } else if (!isFlexibleUi) {
77
- handleClick(event);
75
+ if (!onClick && !isFlexibleUi) {
76
+ var clickUrl = getClickUrl(url, state.details);
77
+ // Ctrl+left click on mac typically doesn't trigger onClick
78
+ // The event could have potentially had `e.preventDefault()` called on it by now
79
+ // event by smart card internally
80
+ // If it has been called then only then can `isModifierKeyPressed` be true.
81
+ var target = isModifierKeyPressed ? '_blank' : '_self';
82
+ window.open(clickUrl, target);
83
+ fireLinkClickedEvent(createAnalyticsEvent)(event, {
84
+ attributes: {
85
+ clickOutcome: target === '_blank' ? 'clickThroughNewTabOrWindow' : 'clickThrough'
86
+ }
87
+ });
88
+ } else {
89
+ if (onClick) {
90
+ onClick(event);
91
+ }
92
+ fireLinkClickedEvent(createAnalyticsEvent)(event);
78
93
  }
79
- }, [id, state.status, analytics.ui, appearance, definitionId, extensionKey, onClick, handleClick, isFlexibleUi, product, subproduct]);
94
+ }, [id, url, state.details, state.status, analytics.ui, appearance, definitionId, extensionKey, onClick, isFlexibleUi, product, subproduct, createAnalyticsEvent]);
80
95
  var handleAuthorize = useCallback(function () {
81
96
  return actions.authorize(appearance);
82
97
  }, [actions, appearance]);
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { className, LinkWrapper, Wrapper, Header, IconWrapper, TextWrapper, Content } from './styled';
3
3
  import { handleClickCommon } from '../../BlockCard/utils/handlers';
4
+ import useMouseDownEvent from '../../../state/analytics/useMouseDownEvent';
4
5
  export var ExpandedFrame = function ExpandedFrame(_ref) {
5
6
  var _ref$isPlaceholder = _ref.isPlaceholder,
6
7
  isPlaceholder = _ref$isPlaceholder === void 0 ? false : _ref$isPlaceholder,
@@ -25,6 +26,7 @@ export var ExpandedFrame = function ExpandedFrame(_ref) {
25
26
  var handleClick = function handleClick(event) {
26
27
  return handleClickCommon(event, onClick);
27
28
  };
29
+ var handleMouseDown = useMouseDownEvent();
28
30
  var renderHeader = function renderHeader() {
29
31
  return /*#__PURE__*/React.createElement(Header, {
30
32
  className: "embed-header"
@@ -34,7 +36,8 @@ export var ExpandedFrame = function ExpandedFrame(_ref) {
34
36
  isPlaceholder: isPlaceholder
35
37
  }, !isPlaceholder && /*#__PURE__*/React.createElement("a", {
36
38
  href: href,
37
- onClick: handleClick
39
+ onClick: handleClick,
40
+ onMouseDown: handleMouseDown
38
41
  }, text)));
39
42
  };
40
43
  var renderContent = function renderContent() {
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import Tooltip from '@atlaskit/tooltip';
3
3
  import Button from '@atlaskit/button/custom-theme-button';
4
+ import useMouseDownEvent from '../../../../../state/analytics/useMouseDownEvent';
4
5
  var LinkInfoButton = function LinkInfoButton(_ref) {
5
6
  var content = _ref.content,
6
7
  href = _ref.href,
@@ -8,6 +9,7 @@ var LinkInfoButton = function LinkInfoButton(_ref) {
8
9
  onClick = _ref.onClick,
9
10
  target = _ref.target,
10
11
  testId = _ref.testId;
12
+ var onMouseDown = useMouseDownEvent();
11
13
  return /*#__PURE__*/React.createElement(Tooltip, {
12
14
  content: content,
13
15
  hideTooltipOnClick: true,
@@ -19,6 +21,7 @@ var LinkInfoButton = function LinkInfoButton(_ref) {
19
21
  href: href,
20
22
  iconBefore: icon,
21
23
  onClick: onClick,
24
+ onMouseDown: onMouseDown,
22
25
  spacing: "none",
23
26
  target: target,
24
27
  testId: "".concat(testId, "-button")
@@ -6,6 +6,7 @@ var _excluded = ["actions", "anchorTarget", "hideTitleTooltip", "maxLines", "onA
6
6
  var _templateObject, _templateObject2;
7
7
  import React, { useCallback, useState } from 'react';
8
8
  import { css } from '@emotion/react';
9
+ import useMouseDownEvent from '../../../../../state/analytics/useMouseDownEvent';
9
10
  import { SmartLinkStatus } from '../../../../../constants';
10
11
  import TitleBlockResolvedView from './resolved';
11
12
  import TitleBlockErroredView from './errored';
@@ -89,10 +90,12 @@ var TitleBlock = function TitleBlock(_ref) {
89
90
  var overrideText = !!text ? {
90
91
  text: text
91
92
  } : {};
93
+ var onMouseDown = useMouseDownEvent();
92
94
  var title = /*#__PURE__*/React.createElement(Title, _extends({
93
95
  hideTooltip: hideTitleTooltip,
94
96
  maxLines: maxLines,
95
97
  onClick: onClick,
98
+ onMouseDown: onMouseDown,
96
99
  target: anchorTarget,
97
100
  theme: theme
98
101
  }, overrideText));