@atlaskit/smart-card 20.0.4 → 20.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.
Files changed (76) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/cjs/state/actions/constants.js +4 -2
  3. package/dist/cjs/state/actions/index.js +51 -19
  4. package/dist/cjs/state/analytics/useSmartLinkAnalytics.js +26 -6
  5. package/dist/cjs/version.json +1 -1
  6. package/dist/cjs/view/BlockCard/index.js +29 -0
  7. package/dist/cjs/view/CardWithUrl/component.js +7 -2
  8. package/dist/cjs/view/CardWithUrl/loader.js +7 -9
  9. package/dist/cjs/view/EmbedCard/index.js +29 -0
  10. package/dist/cjs/view/FlexibleCard/components/blocks/element-group/index.js +2 -2
  11. package/dist/cjs/view/FlexibleCard/index.js +34 -7
  12. package/dist/cjs/view/HoverCard/components/HoverCardComponent.js +143 -0
  13. package/dist/cjs/view/HoverCard/components/{hover-card-content.js → HoverCardContent.js} +29 -25
  14. package/dist/cjs/view/HoverCard/index.js +25 -126
  15. package/dist/cjs/view/HoverCard/styled.js +11 -1
  16. package/dist/cjs/view/HoverCard/utils.js +3 -3
  17. package/dist/cjs/view/InlineCard/index.js +29 -0
  18. package/dist/es2019/state/actions/constants.js +2 -1
  19. package/dist/es2019/state/actions/index.js +46 -18
  20. package/dist/es2019/state/analytics/useSmartLinkAnalytics.js +24 -7
  21. package/dist/es2019/version.json +1 -1
  22. package/dist/es2019/view/BlockCard/index.js +29 -0
  23. package/dist/es2019/view/CardWithUrl/component.js +7 -2
  24. package/dist/es2019/view/CardWithUrl/loader.js +8 -10
  25. package/dist/es2019/view/EmbedCard/index.js +29 -0
  26. package/dist/es2019/view/FlexibleCard/components/blocks/element-group/index.js +4 -0
  27. package/dist/es2019/view/FlexibleCard/index.js +32 -7
  28. package/dist/es2019/view/HoverCard/components/HoverCardComponent.js +102 -0
  29. package/dist/es2019/view/HoverCard/components/{hover-card-content.js → HoverCardContent.js} +18 -21
  30. package/dist/es2019/view/HoverCard/index.js +26 -97
  31. package/dist/es2019/view/HoverCard/styled.js +8 -0
  32. package/dist/es2019/view/HoverCard/utils.js +1 -1
  33. package/dist/es2019/view/InlineCard/index.js +29 -0
  34. package/dist/esm/state/actions/constants.js +2 -1
  35. package/dist/esm/state/actions/index.js +51 -20
  36. package/dist/esm/state/analytics/useSmartLinkAnalytics.js +27 -7
  37. package/dist/esm/version.json +1 -1
  38. package/dist/esm/view/BlockCard/index.js +29 -0
  39. package/dist/esm/view/CardWithUrl/component.js +7 -2
  40. package/dist/esm/view/CardWithUrl/loader.js +8 -10
  41. package/dist/esm/view/EmbedCard/index.js +29 -0
  42. package/dist/esm/view/FlexibleCard/components/blocks/element-group/index.js +2 -2
  43. package/dist/esm/view/FlexibleCard/index.js +33 -7
  44. package/dist/esm/view/HoverCard/components/HoverCardComponent.js +114 -0
  45. package/dist/esm/view/HoverCard/components/{hover-card-content.js → HoverCardContent.js} +20 -22
  46. package/dist/esm/view/HoverCard/index.js +24 -109
  47. package/dist/esm/view/HoverCard/styled.js +8 -0
  48. package/dist/esm/view/HoverCard/utils.js +1 -1
  49. package/dist/esm/view/InlineCard/index.js +29 -0
  50. package/dist/types/state/actions/constants.d.ts +1 -0
  51. package/dist/types/state/actions/index.d.ts +1 -0
  52. package/dist/types/state/analytics/useSmartLinkAnalytics.d.ts +9 -0
  53. package/dist/types/state/hooks/useSmartLink.d.ts +3 -0
  54. package/dist/types/view/BlockCard/types.d.ts +2 -0
  55. package/dist/types/view/Card/index.d.ts +1 -1
  56. package/dist/types/view/Card/types.d.ts +2 -1
  57. package/dist/types/view/CardWithUrl/component.d.ts +1 -1
  58. package/dist/types/view/CardWithUrl/types.d.ts +2 -1
  59. package/dist/types/view/EmbedCard/components/styled.d.ts +16 -16
  60. package/dist/types/view/EmbedCard/types.d.ts +2 -0
  61. package/dist/types/view/FlexibleCard/types.d.ts +9 -4
  62. package/dist/types/view/HoverCard/components/HoverCardComponent.d.ts +4 -0
  63. package/dist/types/view/HoverCard/components/HoverCardContent.d.ts +9 -0
  64. package/dist/types/view/HoverCard/index.d.ts +2 -4
  65. package/dist/types/view/HoverCard/styled.d.ts +2 -0
  66. package/dist/types/view/HoverCard/types.d.ts +8 -0
  67. package/dist/types/view/HoverCard/utils.d.ts +1 -1
  68. package/dist/types/view/InlineCard/Frame/styled.d.ts +1 -1
  69. package/dist/types/view/InlineCard/Icon.d.ts +3 -3
  70. package/dist/types/view/InlineCard/IconAndTitleLayout/styled.d.ts +9 -9
  71. package/dist/types/view/InlineCard/ResolvingView/styled.d.ts +13 -5
  72. package/dist/types/view/InlineCard/styled.d.ts +8 -4
  73. package/dist/types/view/InlineCard/types.d.ts +2 -1
  74. package/dist/types/view/types.d.ts +6 -0
  75. package/package.json +4 -4
  76. package/dist/types/view/HoverCard/components/hover-card-content.d.ts +0 -4
@@ -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 { uiRenderFailedEvent, fireSmartLinkEvent } from '../../utils/analytics';
4
+ import { fireSmartLinkEvent } from '../../utils/analytics';
5
5
  import { clearMarks, clearMeasures } from '../../utils/performance';
6
6
  import { ErrorBoundary } from 'react-error-boundary';
7
- import { failUfoExperience, startUfoExperience } from '../../state/analytics/ufoExperiences';
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(
@@ -32,6 +32,7 @@ export function CardWithURLRenderer(props) {
32
32
  onClick = props.onClick,
33
33
  container = props.container,
34
34
  onResolve = props.onResolve,
35
+ onError = props.onError,
35
36
  testId = props.testId,
36
37
  showActions = props.showActions,
37
38
  inheritDimensions = props.inheritDimensions,
@@ -56,6 +57,7 @@ export function CardWithURLRenderer(props) {
56
57
 
57
58
  fireSmartLinkEvent(analyticsPayload, createAnalyticsEvent);
58
59
  }, [appearance, createAnalyticsEvent]);
60
+ var analytics = useSmartLinkAnalytics(url !== null && url !== void 0 ? url : '', dispatchAnalytics, id);
59
61
  var logError = useCallback(function (error, info) {
60
62
  var componentStack = info.componentStack; // NB: APIErrors are thrown in response to Object Resolver Service.
61
63
  // In these cases, control is handed back to the Editor. We do not
@@ -69,15 +71,10 @@ export function CardWithURLRenderer(props) {
69
71
  else {
70
72
  var errorInfo = {
71
73
  componentStack: componentStack
72
- }; // Start and fail the smart-link-rendered experience. If it has already
73
- // been started nothing happens.
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));
74
+ };
75
+ analytics.ui.renderFailedEvent(appearance, id, error, errorInfo);
79
76
  }
80
- }, [appearance, dispatchAnalytics, id]);
77
+ }, [analytics.ui, appearance, id]);
81
78
 
82
79
  if (!url) {
83
80
  throw new Error('@atlaskit/smart-card: url property is missing.');
@@ -93,6 +90,7 @@ export function CardWithURLRenderer(props) {
93
90
  dispatchAnalytics: dispatchAnalytics,
94
91
  container: container,
95
92
  onResolve: onResolve,
93
+ onError: onError,
96
94
  testId: testId,
97
95
  showActions: showActions,
98
96
  inheritDimensions: inheritDimensions,
@@ -30,6 +30,7 @@ export var EmbedCard = /*#__PURE__*/React.forwardRef(function (_ref, iframeRef)
30
30
  isFrameVisible = _ref.isFrameVisible,
31
31
  platform = _ref.platform,
32
32
  onResolve = _ref.onResolve,
33
+ onError = _ref.onError,
33
34
  testId = _ref.testId,
34
35
  inheritDimensions = _ref.inheritDimensions;
35
36
  var data = details && details.data || getEmptyJsonLd();
@@ -89,6 +90,13 @@ export var EmbedCard = /*#__PURE__*/React.forwardRef(function (_ref, iframeRef)
89
90
  }
90
91
 
91
92
  case 'unauthorized':
93
+ if (onError) {
94
+ onError({
95
+ url: url,
96
+ status: status
97
+ });
98
+ }
99
+
92
100
  var unauthorisedViewProps = extractEmbedProps(data, meta, platform);
93
101
  return /*#__PURE__*/React.createElement(EmbedCardUnauthorisedView, _extends({}, unauthorisedViewProps, {
94
102
  isSelected: isSelected,
@@ -98,6 +106,13 @@ export var EmbedCard = /*#__PURE__*/React.forwardRef(function (_ref, iframeRef)
98
106
  }));
99
107
 
100
108
  case 'forbidden':
109
+ if (onError) {
110
+ onError({
111
+ url: url,
112
+ status: status
113
+ });
114
+ }
115
+
101
116
  var forbiddenViewProps = extractEmbedProps(data, meta, platform);
102
117
  var cardMetadata = (_details$meta = details === null || details === void 0 ? void 0 : details.meta) !== null && _details$meta !== void 0 ? _details$meta : getUnauthorizedJsonLd().meta;
103
118
  var requestAccessContext = extractRequestAccessContext({
@@ -114,6 +129,13 @@ export var EmbedCard = /*#__PURE__*/React.forwardRef(function (_ref, iframeRef)
114
129
  }));
115
130
 
116
131
  case 'not_found':
132
+ if (onError) {
133
+ onError({
134
+ url: url,
135
+ status: status
136
+ });
137
+ }
138
+
117
139
  var notFoundViewProps = extractEmbedProps(data, meta, platform);
118
140
  return /*#__PURE__*/React.createElement(EmbedCardNotFoundView, _extends({}, notFoundViewProps, {
119
141
  isSelected: isSelected,
@@ -123,6 +145,13 @@ export var EmbedCard = /*#__PURE__*/React.forwardRef(function (_ref, iframeRef)
123
145
 
124
146
  case 'fallback':
125
147
  case 'errored':
148
+ if (onError) {
149
+ onError({
150
+ url: url,
151
+ status: status
152
+ });
153
+ }
154
+
126
155
  return /*#__PURE__*/React.createElement(EmbedCardErroredView, {
127
156
  onRetry: handleErrorRetry,
128
157
  inheritDimensions: inheritDimensions,
@@ -12,11 +12,11 @@ import { getMaxLineHeight, getTruncateStyles } from '../../utils';
12
12
  var getAlignmentStyles = function getAlignmentStyles(align) {
13
13
  switch (align) {
14
14
  case SmartLinkAlignment.Right:
15
- return css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n justify-content: flex-end;\n text-align: right;\n "])));
15
+ return css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n -webkit-box-align: end;\n -ms-flex-align: end;\n justify-content: flex-end;\n text-align: right;\n "])));
16
16
 
17
17
  case SmartLinkAlignment.Left:
18
18
  default:
19
- return css(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n justify-content: flex-start;\n text-align: left;\n "])));
19
+ return css(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n -webkit-box-align: start;\n -ms-flex-align: start;\n justify-content: flex-start;\n text-align: left;\n "])));
20
20
  }
21
21
  };
22
22
 
@@ -1,5 +1,6 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
2
  import React, { useEffect } from 'react';
3
+ import { SmartLinkStatus } from '../../constants';
3
4
  import Container from './components/container';
4
5
  import { FlexibleUiContext } from '../../state/flexible-ui-context';
5
6
  import { getContextByStatus, getRetryOptions } from './utils';
@@ -14,24 +15,49 @@ var FlexibleCard = function FlexibleCard(_ref) {
14
15
  var cardState = _ref.cardState,
15
16
  children = _ref.children,
16
17
  onAuthorize = _ref.onAuthorize,
18
+ onError = _ref.onError,
19
+ onResolve = _ref.onResolve,
17
20
  renderers = _ref.renderers,
18
21
  ui = _ref.ui,
19
22
  url = _ref.url,
20
23
  onClick = _ref.onClick,
21
- testId = _ref.testId,
22
- onResolve = _ref.onResolve;
24
+ testId = _ref.testId;
23
25
  var cardType = cardState.status,
24
26
  details = cardState.details;
25
27
  var status = cardType;
26
28
  var context = getContextByStatus(url, status, details, renderers);
27
29
  var retry = getRetryOptions(url, status, details, onAuthorize);
30
+
31
+ var _ref2 = context || {},
32
+ title = _ref2.title;
33
+
28
34
  useEffect(function () {
29
- if (status === 'resolved' && onResolve) {
30
- onResolve({
31
- url: url
32
- });
35
+ switch (status) {
36
+ case SmartLinkStatus.Resolved:
37
+ if (onResolve) {
38
+ onResolve({
39
+ title: title,
40
+ url: url
41
+ });
42
+ }
43
+
44
+ break;
45
+
46
+ case SmartLinkStatus.Errored:
47
+ case SmartLinkStatus.Fallback:
48
+ case SmartLinkStatus.Forbidden:
49
+ case SmartLinkStatus.NotFound:
50
+ case SmartLinkStatus.Unauthorized:
51
+ if (onError) {
52
+ onError({
53
+ status: status,
54
+ url: url
55
+ });
56
+ }
57
+
58
+ break;
33
59
  }
34
- }, [onResolve, status, url]);
60
+ }, [onError, onResolve, status, title, url]);
35
61
  return /*#__PURE__*/React.createElement(FlexibleUiContext.Provider, {
36
62
  value: context
37
63
  }, /*#__PURE__*/React.createElement(Container, _extends({
@@ -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,17 @@
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 { extractMetadata } from '../../../extractors/hover/extractMetadata';
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 { ActionName, SmartLinkPosition, SmartLinkSize, SmartLinkTheme } from '../../../constants';
6
+ import { extractMetadata } from '../../../extractors/hover/extractMetadata';
7
+ import { useSmartCardActions } from '../../../state/actions';
8
+ import { getExtensionKey } from '../../../state/helpers';
9
+ import { isSpecialEvent } from '../../../utils';
6
10
  import FlexibleCard from '../../FlexibleCard';
7
11
  import { FooterBlock, MetadataBlock, PreviewBlock, SnippetBlock, TitleBlock } from '../../FlexibleCard/components/blocks';
8
- import { isSpecialEvent } from '../../../utils';
9
- import ShortcutIcon from '@atlaskit/icon/glyph/shortcut';
10
- import { getExtensionKey } from '../../../state/helpers';
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) {
12
+ import { flexibleUiOptions, footerBlockCss, metadataBlockCss, titleBlockCss } from '../styled';
13
+ import { getSimulatedMetadata, SMART_CARD_ANALYTICS_DISPLAY } from '../utils';
14
+ export var getOpenAction = function getOpenAction(url, analytics, onActionClick) {
22
15
  return {
23
16
  name: ActionName.CustomAction,
24
17
  icon: /*#__PURE__*/React.createElement(ShortcutIcon, {
@@ -37,8 +30,7 @@ var getOpenAction = function getOpenAction(url, analytics, onActionClick) {
37
30
  testId: 'hover-card-open-button'
38
31
  };
39
32
  };
40
-
41
- var toFooterActions = function toFooterActions(cardActions, onActionClick) {
33
+ export var toFooterActions = function toFooterActions(cardActions, onActionClick) {
42
34
  return cardActions.map(function (action) {
43
35
  return {
44
36
  content: action.text,
@@ -58,7 +50,9 @@ var toFooterActions = function toFooterActions(cardActions, onActionClick) {
58
50
  var HoverCardContent = function HoverCardContent(_ref) {
59
51
  var _cardState$details;
60
52
 
61
- var analytics = _ref.analytics,
53
+ var _ref$id = _ref.id,
54
+ id = _ref$id === void 0 ? '' : _ref$id,
55
+ analytics = _ref.analytics,
62
56
  _ref$cardActions = _ref.cardActions,
63
57
  cardActions = _ref$cardActions === void 0 ? [] : _ref$cardActions,
64
58
  cardState = _ref.cardState,
@@ -66,17 +60,21 @@ var HoverCardContent = function HoverCardContent(_ref) {
66
60
  onResolve = _ref.onResolve,
67
61
  renderers = _ref.renderers,
68
62
  url = _ref.url;
63
+ var actions = useSmartCardActions(id, url, analytics);
64
+ useEffect(function () {
65
+ actions.loadMetadata();
66
+ }, [actions]);
69
67
  useEffect(function () {
70
68
  // Since hover preview only render on resolved status,
71
69
  // there is no need to check for statuses.
72
- analytics.ui.renderSuccessEvent(HOVER_CARD_ANALYTICS_DISPLAY, cardState.status);
70
+ analytics.ui.renderSuccessEvent(SMART_CARD_ANALYTICS_DISPLAY, cardState.status);
73
71
  }, [analytics.ui, cardState.status]);
74
72
  var extensionKey = useMemo(function () {
75
73
  return getExtensionKey(cardState.details);
76
74
  }, [cardState.details]);
77
75
  var onClick = useCallback(function (event) {
78
76
  var isModifierKeyPressed = isSpecialEvent(event);
79
- analytics.ui.cardClickedEvent(undefined, HOVER_CARD_ANALYTICS_DISPLAY, cardState.status, undefined, undefined, isModifierKeyPressed, undefined, undefined, undefined, 'titleGoToLink');
77
+ analytics.ui.cardClickedEvent(undefined, SMART_CARD_ANALYTICS_DISPLAY, cardState.status, undefined, undefined, isModifierKeyPressed, undefined, undefined, undefined, 'titleGoToLink');
80
78
  }, [cardState.status, analytics.ui]);
81
79
  var titleActions = useMemo(function () {
82
80
  return [getOpenAction(url, analytics, onActionClick)];
@@ -1,121 +1,36 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
- import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
2
 
4
3
  /** @jsx jsx */
5
- import { jsx } from '@emotion/core';
6
- import React, { useCallback, useRef } from 'react';
7
- import Popup from '@atlaskit/popup';
8
- import { useSmartLinkActions } from '../../state/hooks-external/useSmartLinkActions';
9
- import { HoverCardContainer } from './styled';
10
4
  import { withAnalyticsContext, withAnalyticsEvents } from '@atlaskit/analytics-next';
11
- import { fireSmartLinkEvent } from '../../utils/analytics';
12
- import { useSmartCardState as useLinkState } from '../../state/store';
5
+ import { jsx } from '@emotion/core';
6
+ import { useCallback } from 'react';
7
+ import { ErrorBoundary } from 'react-error-boundary';
13
8
  import { useSmartLinkAnalytics } from '../../state/analytics';
14
- import { useSmartLinkRenderers } from '../../state/renderers';
15
- import HoverCardContent from './components/hover-card-content';
16
- import { HOVER_CARD_ANALYTICS_DISPLAY } from './utils';
17
- export var hoverCardClassName = 'smart-links-hover-preview';
18
- export var HoverCardComponent = function HoverCardComponent(_ref) {
19
- var children = _ref.children,
20
- id = _ref.id,
21
- url = _ref.url,
22
- createAnalyticsEvent = _ref.createAnalyticsEvent;
9
+ import { fireSmartLinkEvent } from '../../utils/analytics';
10
+ import { HoverCardComponent } from './components/HoverCardComponent';
11
+ import { SMART_CARD_ANALYTICS_DISPLAY } from './utils';
12
+
13
+ var HoverCardWithErrorBoundary = function HoverCardWithErrorBoundary(props) {
14
+ var url = props.url,
15
+ id = props.id,
16
+ children = props.children,
17
+ createAnalyticsEvent = props.createAnalyticsEvent;
23
18
  var analyticsHandler = useCallback(function (analyticsPayload) {
24
19
  fireSmartLinkEvent(analyticsPayload, createAnalyticsEvent);
25
20
  }, [createAnalyticsEvent]);
26
- var delay = 300;
27
-
28
- var _React$useState = React.useState(false),
29
- _React$useState2 = _slicedToArray(_React$useState, 2),
30
- isOpen = _React$useState2[0],
31
- setIsOpen = _React$useState2[1];
32
-
33
- var fadeOutTimeoutId = useRef();
34
- var fadeInTimeoutId = useRef();
35
- var cardOpenTime = useRef();
36
- var renderers = useSmartLinkRenderers();
37
- var linkState = useLinkState(url);
38
21
  var analytics = useSmartLinkAnalytics(url, analyticsHandler, id);
39
- var hideCard = useCallback(function () {
40
- //Check its previously open to avoid firing events when moving between the child and hover card components
41
- if (isOpen === true && cardOpenTime.current) {
42
- var hoverTime = Date.now() - cardOpenTime.current;
43
- analytics.ui.hoverCardDismissedEvent('card', hoverTime, 'mouse_hover');
44
- }
45
-
46
- setIsOpen(false);
47
- }, [analytics.ui, isOpen]);
48
- var initHideCard = useCallback(function () {
49
- if (fadeInTimeoutId.current) {
50
- clearTimeout(fadeInTimeoutId.current);
51
- }
52
-
53
- fadeOutTimeoutId.current = setTimeout(function () {
54
- return hideCard();
55
- }, delay);
56
- }, [hideCard]);
57
- var initShowCard = useCallback(function () {
58
- if (fadeOutTimeoutId.current) {
59
- clearTimeout(fadeOutTimeoutId.current);
60
- }
61
-
62
- fadeInTimeoutId.current = setTimeout(function () {
63
- //Check if its previously closed to avoid firing events when moving between the child and hover card components
64
- if (isOpen === false) {
65
- cardOpenTime.current = Date.now();
66
- analytics.ui.hoverCardViewedEvent('card', 'mouse_hover');
67
- }
68
-
69
- setIsOpen(true);
70
- }, delay);
71
- }, [delay, isOpen, analytics.ui]);
72
- var linkActions = useSmartLinkActions({
73
- url: url,
74
- appearance: HOVER_CARD_ANALYTICS_DISPLAY,
75
- analyticsHandler: analyticsHandler
76
- });
77
- var onActionClick = useCallback(function (actionId) {
78
- if (actionId === 'preview-content') {
79
- hideCard();
80
- }
81
- }, [hideCard]); // Stop hover preview content to propagate event to parent.
82
-
83
- var onClick = useCallback(function (e) {
84
- return e.stopPropagation();
85
- }, []);
86
- return jsx(Popup, {
87
- testId: "hover-card",
88
- isOpen: isOpen,
89
- onClose: hideCard,
90
- placement: "bottom-start",
91
- content: function content(_ref2) {
92
- var update = _ref2.update;
93
- return jsx("div", {
94
- onMouseEnter: initShowCard,
95
- onMouseLeave: initHideCard,
96
- className: hoverCardClassName,
97
- css: HoverCardContainer,
98
- onClick: onClick
99
- }, jsx(HoverCardContent, {
100
- analytics: analytics,
101
- cardActions: linkActions,
102
- cardState: linkState,
103
- onActionClick: onActionClick,
104
- onResolve: update,
105
- renderers: renderers,
106
- url: url
107
- }));
108
- },
109
- trigger: function trigger(triggerProps) {
110
- return jsx("span", _extends({}, triggerProps, {
111
- onMouseEnter: initShowCard,
112
- onMouseLeave: initHideCard
113
- }), children);
114
- },
115
- zIndex: 511 // Temporary fix for Confluence inline comment on editor mod has z-index of 500, Jira issue view has z-index of 510
116
-
117
- });
22
+ var onError = useCallback(function (error, info) {
23
+ analytics.ui.renderFailedEvent(SMART_CARD_ANALYTICS_DISPLAY, id, error, info);
24
+ }, [analytics.ui, id]);
25
+ return jsx(ErrorBoundary, {
26
+ fallback: children,
27
+ onError: onError
28
+ }, jsx(HoverCardComponent, _extends({}, props, {
29
+ analyticsHandler: analyticsHandler,
30
+ analytics: analytics
31
+ }), children));
118
32
  };
33
+
119
34
  export var HoverCard = withAnalyticsContext({
120
35
  source: 'smartLinkPreviewHoverCard'
121
- })(withAnalyticsEvents()(HoverCardComponent));
36
+ })(withAnalyticsEvents()(HoverCardWithErrorBoundary));
@@ -4,6 +4,14 @@ var _templateObject, _templateObject2, _templateObject3, _templateObject4, _temp
4
4
 
5
5
  import { css } from '@emotion/core';
6
6
  import { loadingPlaceholderClassName } from '../../index';
7
+ import { SmartLinkSize, SmartLinkTheme } from '../../constants';
8
+ export var flexibleUiOptions = {
9
+ hideElevation: true,
10
+ size: SmartLinkSize.Medium,
11
+ // eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage
12
+ theme: SmartLinkTheme.Black,
13
+ hidePadding: true
14
+ };
7
15
  var blockGap = '0.5rem';
8
16
  var elementGap = '0.5rem';
9
17
  var separatorCss = css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n [data-separator] + [data-separator]:before {\n margin-right: ", ";\n }\n"])), elementGap);
@@ -1,5 +1,5 @@
1
1
  import { ElementName } from '../../constants';
2
- export var HOVER_CARD_ANALYTICS_DISPLAY = 'flexible';
2
+ export var SMART_CARD_ANALYTICS_DISPLAY = 'flexible';
3
3
  export var getSimulatedMetadata = function getSimulatedMetadata() {
4
4
  var extensionKey = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
5
5
  var types = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
@@ -22,6 +22,7 @@ export var InlineCard = function InlineCard(_ref) {
22
22
  isSelected = _ref.isSelected,
23
23
  renderers = _ref.renderers,
24
24
  onResolve = _ref.onResolve,
25
+ onError = _ref.onError,
25
26
  testId = _ref.testId,
26
27
  inlinePreloaderStyle = _ref.inlinePreloaderStyle,
27
28
  showHoverPreview = _ref.showHoverPreview;
@@ -61,6 +62,13 @@ export var InlineCard = function InlineCard(_ref) {
61
62
  }));
62
63
 
63
64
  case 'unauthorized':
65
+ if (onError) {
66
+ onError({
67
+ url: url,
68
+ status: status
69
+ });
70
+ }
71
+
64
72
  var provider = extractProvider(cardDetails);
65
73
  return /*#__PURE__*/React.createElement(InlineCardUnauthorizedView, {
66
74
  icon: provider && provider.icon,
@@ -72,6 +80,13 @@ export var InlineCard = function InlineCard(_ref) {
72
80
  });
73
81
 
74
82
  case 'forbidden':
83
+ if (onError) {
84
+ onError({
85
+ url: url,
86
+ status: status
87
+ });
88
+ }
89
+
75
90
  var providerForbidden = extractProvider(cardDetails);
76
91
  var cardMetadata = (_details$meta = details === null || details === void 0 ? void 0 : details.meta) !== null && _details$meta !== void 0 ? _details$meta : getUnauthorizedJsonLd().meta;
77
92
  var requestAccessContext = extractRequestAccessContext({
@@ -91,6 +106,13 @@ export var InlineCard = function InlineCard(_ref) {
91
106
  });
92
107
 
93
108
  case 'not_found':
109
+ if (onError) {
110
+ onError({
111
+ url: url,
112
+ status: status
113
+ });
114
+ }
115
+
94
116
  var providerNotFound = extractProvider(cardDetails);
95
117
  return /*#__PURE__*/React.createElement(InlineCardErroredView, {
96
118
  url: url,
@@ -103,6 +125,13 @@ export var InlineCard = function InlineCard(_ref) {
103
125
 
104
126
  case 'fallback':
105
127
  case 'errored':
128
+ if (onError) {
129
+ onError({
130
+ url: url,
131
+ status: status
132
+ });
133
+ }
134
+
106
135
  return /*#__PURE__*/React.createElement(CardLinkView, {
107
136
  link: url,
108
137
  isSelected: isSelected,
@@ -3,3 +3,4 @@ export declare const ANALYTICS_ERROR = "errored";
3
3
  export declare const ANALYTICS_FALLBACK = "fallback";
4
4
  export declare const ERROR_MESSAGE_OAUTH = "Provider.authFlow is not set to OAuth2.";
5
5
  export declare const ERROR_MESSAGE_FATAL = "Fatal error resolving URL";
6
+ export declare const ERROR_MESSAGE_METADATA = "Error resolving metadata.";
@@ -8,4 +8,5 @@ export declare const useSmartCardActions: (id: string, url: string, analytics: A
8
8
  reload: () => void;
9
9
  authorize: (appearance: CardAppearance) => void;
10
10
  invoke: (opts: InvokeClientOpts | InvokeServerOpts, appearance: CardInnerAppearance) => Promise<JsonLd.Response | void>;
11
+ loadMetadata: () => Promise<void> | undefined;
11
12
  };
@@ -1,3 +1,4 @@
1
+ import { ErrorInfo } from 'react';
1
2
  import { CardType, APIError } from '@atlaskit/linking-common';
2
3
  import { AnalyticsHandler } from '../../utils/types';
3
4
  import { CardInnerAppearance } from '../../view/Card/types';
@@ -83,6 +84,14 @@ export declare const useSmartLinkAnalytics: (url: string, dispatchAnalytics: Ana
83
84
  * @param extensionKey The extensionKey of the Smart Link resovler invoked.
84
85
  */
85
86
  renderSuccessEvent: (display: CardInnerAppearance, status: CardType, id?: string, definitionId?: string | undefined, extensionKey?: string | undefined) => void;
87
+ /**
88
+ * This fires an event that represents when a Smart Link renders unsuccessfuly.
89
+ * @param display Whether the card was an Inline, Block, Embed or Flexible UI.
90
+ * @param id The unique ID for this Smart Link.
91
+ * @param error: An error representing why the Smart Link render failed.
92
+ * @param errorInfo: Additional details about the error including the stack trace.
93
+ */
94
+ renderFailedEvent: (display: CardInnerAppearance, id: string | undefined, error: Error, errorInfo: ErrorInfo) => void;
86
95
  /**
87
96
  * This fires an event that represents a hover preview being opened.
88
97
  * @param hoverDisplay Whether the hover preview was displayed as a card or embed.