@atlaskit/smart-card 22.0.0 → 22.1.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 (109) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/cjs/__tests_external__/index.js +53 -0
  3. package/dist/cjs/__tests_external__/page-objects/BaseCard.js +115 -0
  4. package/dist/cjs/__tests_external__/page-objects/BlockCard.js +43 -0
  5. package/dist/cjs/__tests_external__/page-objects/EmbedCard.js +43 -0
  6. package/dist/cjs/__tests_external__/page-objects/InlineCard.js +43 -0
  7. package/dist/cjs/__tests_external__/test-cases/card.js +27 -0
  8. package/dist/cjs/__tests_external__/test-cases/embed.js +27 -0
  9. package/dist/cjs/__tests_external__/test-cases/inline.js +27 -0
  10. package/dist/cjs/__tests_external__/test-cases/types.js +5 -0
  11. package/dist/cjs/extractors/block/index.js +6 -7
  12. package/dist/cjs/extractors/common/actions/extractPreviewAction.js +16 -27
  13. package/dist/cjs/state/analytics/useSmartLinkAnalytics.js +43 -0
  14. package/dist/cjs/state/hooks-external/useSmartLinkActions.js +5 -3
  15. package/dist/cjs/utils/analytics/analytics.js +2 -2
  16. package/dist/cjs/utils/mocks.js +28 -2
  17. package/dist/cjs/version.json +1 -1
  18. package/dist/cjs/view/BlockCard/actions/PreviewAction.js +2 -2
  19. package/dist/cjs/view/BlockCard/index.js +6 -5
  20. package/dist/cjs/view/CardWithUrl/component.js +2 -2
  21. package/dist/cjs/view/EmbedCard/index.js +3 -2
  22. package/dist/cjs/view/EmbedModal/components/analytics/index.js +100 -0
  23. package/dist/cjs/view/EmbedModal/components/analytics/types.js +5 -0
  24. package/dist/cjs/view/EmbedModal/components/size-experiment/index.js +5 -10
  25. package/dist/cjs/view/EmbedModal/index.js +54 -15
  26. package/dist/cjs/view/EmbedModal/types.js +9 -1
  27. package/dist/cjs/view/HoverCard/components/HoverCardComponent.js +2 -1
  28. package/dist/cjs/view/InlineCard/IconAndTitleLayout/styled.js +2 -2
  29. package/dist/cjs/view/common/Modal.js +29 -4
  30. package/dist/cjs/view/common/ModalHeader.js +3 -2
  31. package/dist/es2019/__tests_external__/index.js +6 -0
  32. package/dist/es2019/__tests_external__/page-objects/BaseCard.js +61 -0
  33. package/dist/es2019/__tests_external__/page-objects/BlockCard.js +8 -0
  34. package/dist/es2019/__tests_external__/page-objects/EmbedCard.js +8 -0
  35. package/dist/es2019/__tests_external__/page-objects/InlineCard.js +8 -0
  36. package/dist/es2019/__tests_external__/test-cases/card.js +14 -0
  37. package/dist/es2019/__tests_external__/test-cases/embed.js +14 -0
  38. package/dist/es2019/__tests_external__/test-cases/inline.js +14 -0
  39. package/dist/es2019/__tests_external__/test-cases/types.js +1 -0
  40. package/dist/es2019/extractors/block/index.js +6 -7
  41. package/dist/es2019/extractors/common/actions/extractPreviewAction.js +16 -18
  42. package/dist/es2019/state/analytics/useSmartLinkAnalytics.js +46 -3
  43. package/dist/es2019/state/hooks-external/useSmartLinkActions.js +5 -3
  44. package/dist/es2019/utils/analytics/analytics.js +1 -1
  45. package/dist/es2019/utils/mocks.js +26 -1
  46. package/dist/es2019/version.json +1 -1
  47. package/dist/es2019/view/BlockCard/actions/PreviewAction.js +3 -3
  48. package/dist/es2019/view/BlockCard/index.js +5 -4
  49. package/dist/es2019/view/CardWithUrl/component.js +2 -2
  50. package/dist/es2019/view/EmbedCard/index.js +3 -2
  51. package/dist/es2019/view/EmbedModal/components/analytics/index.js +80 -0
  52. package/dist/es2019/view/EmbedModal/components/analytics/types.js +1 -0
  53. package/dist/es2019/view/EmbedModal/components/size-experiment/index.js +5 -9
  54. package/dist/es2019/view/EmbedModal/index.js +46 -13
  55. package/dist/es2019/view/EmbedModal/types.js +6 -1
  56. package/dist/es2019/view/HoverCard/components/HoverCardComponent.js +2 -1
  57. package/dist/es2019/view/InlineCard/IconAndTitleLayout/styled.js +0 -2
  58. package/dist/es2019/view/common/Modal.js +27 -6
  59. package/dist/es2019/view/common/ModalHeader.js +3 -2
  60. package/dist/esm/__tests_external__/index.js +6 -0
  61. package/dist/esm/__tests_external__/page-objects/BaseCard.js +101 -0
  62. package/dist/esm/__tests_external__/page-objects/BlockCard.js +28 -0
  63. package/dist/esm/__tests_external__/page-objects/EmbedCard.js +28 -0
  64. package/dist/esm/__tests_external__/page-objects/InlineCard.js +28 -0
  65. package/dist/esm/__tests_external__/test-cases/card.js +16 -0
  66. package/dist/esm/__tests_external__/test-cases/embed.js +16 -0
  67. package/dist/esm/__tests_external__/test-cases/inline.js +16 -0
  68. package/dist/esm/__tests_external__/test-cases/types.js +1 -0
  69. package/dist/esm/extractors/block/index.js +6 -7
  70. package/dist/esm/extractors/common/actions/extractPreviewAction.js +17 -27
  71. package/dist/esm/state/analytics/useSmartLinkAnalytics.js +45 -2
  72. package/dist/esm/state/hooks-external/useSmartLinkActions.js +5 -3
  73. package/dist/esm/utils/analytics/analytics.js +2 -2
  74. package/dist/esm/utils/mocks.js +25 -0
  75. package/dist/esm/version.json +1 -1
  76. package/dist/esm/view/BlockCard/actions/PreviewAction.js +3 -3
  77. package/dist/esm/view/BlockCard/index.js +5 -4
  78. package/dist/esm/view/CardWithUrl/component.js +2 -2
  79. package/dist/esm/view/EmbedCard/index.js +3 -2
  80. package/dist/esm/view/EmbedModal/components/analytics/index.js +82 -0
  81. package/dist/esm/view/EmbedModal/components/analytics/types.js +1 -0
  82. package/dist/esm/view/EmbedModal/components/size-experiment/index.js +5 -10
  83. package/dist/esm/view/EmbedModal/index.js +52 -15
  84. package/dist/esm/view/EmbedModal/types.js +6 -1
  85. package/dist/esm/view/HoverCard/components/HoverCardComponent.js +2 -1
  86. package/dist/esm/view/InlineCard/IconAndTitleLayout/styled.js +2 -2
  87. package/dist/esm/view/common/Modal.js +28 -6
  88. package/dist/esm/view/common/ModalHeader.js +3 -2
  89. package/dist/types/extractors/block/types.d.ts +4 -2
  90. package/dist/types/extractors/common/actions/extractPreviewAction.d.ts +7 -5
  91. package/dist/types/state/analytics/useSmartLinkAnalytics.d.ts +23 -1
  92. package/dist/types/state/hooks/useSmartLink.d.ts +9 -0
  93. package/dist/types/state/hooks-external/useSmartLinkActions.d.ts +6 -2
  94. package/dist/types/utils/mocks.d.ts +48 -0
  95. package/dist/types/utils/types.d.ts +3 -1
  96. package/dist/types/view/BlockCard/actions/PreviewAction.d.ts +4 -0
  97. package/dist/types/view/BlockCard/index.d.ts +2 -2
  98. package/dist/types/view/BlockCard/types.d.ts +4 -4
  99. package/dist/types/view/Card/index.d.ts +1 -1
  100. package/dist/types/view/EmbedCard/types.d.ts +2 -2
  101. package/dist/types/view/EmbedModal/components/analytics/index.d.ts +5 -0
  102. package/dist/types/view/EmbedModal/components/analytics/types.d.ts +6 -0
  103. package/dist/types/view/EmbedModal/components/size-experiment/index.d.ts +4 -3
  104. package/dist/types/view/EmbedModal/index.d.ts +3 -1
  105. package/dist/types/view/EmbedModal/types.d.ts +14 -4
  106. package/dist/types/view/HoverCard/index.d.ts +1 -1
  107. package/dist/types/view/common/Modal.d.ts +6 -8
  108. package/package.json +22 -22
  109. package/report.api.md +35 -3
@@ -0,0 +1,14 @@
1
+ import { InProductTestCase } from '@atlaskit/in-product-testing';
2
+ import { EmbedCardPageObject } from '../page-objects/EmbedCard';
3
+ export const embedSmartLinkRendersTestCase = ({
4
+ url,
5
+ status = 'resolved'
6
+ }) => new InProductTestCase({
7
+ title: 'Embed Smart Link is visible in the resolved state',
8
+ id: 'embed-smart-link-resolved',
9
+ assertions: cy => {
10
+ const embedCard = new EmbedCardPageObject(cy);
11
+ embedCard.assertHrefRendered(url);
12
+ embedCard.expectCardReady(1, status);
13
+ }
14
+ });
@@ -0,0 +1,14 @@
1
+ import { InProductTestCase } from '@atlaskit/in-product-testing';
2
+ import { InlineCardPageObject } from '../page-objects/InlineCard';
3
+ export const inlineSmartLinkRendersTestCase = ({
4
+ url,
5
+ status = 'resolved'
6
+ }) => new InProductTestCase({
7
+ title: 'Inline Smart Link is visible in the resolved state',
8
+ id: 'inline-smart-link-resolved',
9
+ assertions: cy => {
10
+ const inlineCard = new InlineCardPageObject(cy);
11
+ inlineCard.assertHrefRendered(url);
12
+ inlineCard.expectCardReady(1, status);
13
+ }
14
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -28,15 +28,14 @@ const extractBlockDetails = jsonLd => [extractCommentCount(jsonLd), extractProgr
28
28
  export const extractBlockActions = (props, jsonLd, opts, platform) => {
29
29
  if (opts) {
30
30
  const {
31
- featureFlags,
32
- handleInvoke,
33
- handleAnalytics,
34
- extensionKey,
35
- source,
36
- testId
31
+ handleInvoke
37
32
  } = opts;
38
33
  const actions = extractActions(jsonLd, handleInvoke);
39
- const previewAction = extractPreviewAction(extensionKey, props, jsonLd, handleInvoke, handleAnalytics, testId, platform, source, featureFlags); // The previewAction should always be the last action
34
+ const previewAction = extractPreviewAction({ ...opts,
35
+ viewProps: props,
36
+ jsonLd,
37
+ platform
38
+ }); // The previewAction should always be the last action
40
39
 
41
40
  if (previewAction) {
42
41
  actions.push(previewAction);
@@ -1,6 +1,5 @@
1
- import { uiRenderSuccessEvent, uiRenderFailedEvent } from '../../../utils/analytics';
2
1
  import { extractDownloadUrl } from '../detail';
3
- import { extractProvider, extractPreview } from '@atlaskit/linking-common/extractors';
2
+ import { extractPreview, extractProvider } from '@atlaskit/linking-common/extractors';
4
3
  import { PreviewAction } from '../../../view/BlockCard';
5
4
 
6
5
  const getMetadataFromJsonLd = (jsonLd, platform) => {
@@ -39,7 +38,18 @@ const getInvokeOpts = (key, action, source) => ({
39
38
  }
40
39
  });
41
40
 
42
- export const extractPreviewAction = (extensionKey = 'empty-object-provider', viewProps, jsonLd, handleInvoke, handleAnalytics, testId, platform, source, featureFlags) => {
41
+ export const extractPreviewAction = ({
42
+ extensionKey = 'empty-object-provider',
43
+ viewProps,
44
+ jsonLd,
45
+ handleInvoke,
46
+ testId,
47
+ platform,
48
+ origin,
49
+ source = 'block',
50
+ featureFlags,
51
+ analytics
52
+ }) => {
43
53
  // Extract metadata from view props & raw JSON-LD.
44
54
  const metadataFromJsonLd = getMetadataFromJsonLd(jsonLd, platform);
45
55
  const metadataFromViewProps = getMetadataFromResolvedProps(viewProps);
@@ -51,22 +61,10 @@ export const extractPreviewAction = (extensionKey = 'empty-object-provider', vie
51
61
  // Build action using instrumentation hooks.
52
62
  const key = extensionKey;
53
63
  const previewAction = PreviewAction({ ...metadata,
64
+ analytics,
65
+ origin,
54
66
  featureFlags,
55
67
  testId,
56
- onOpen: () => {
57
- handleAnalytics(uiRenderSuccessEvent({
58
- display: 'preview',
59
- status: 'resolved',
60
- extensionKey: key
61
- }));
62
- },
63
- onOpenFailed: (error, errorInfo) => {
64
- handleAnalytics(uiRenderFailedEvent({
65
- display: 'preview',
66
- error,
67
- errorInfo
68
- }));
69
- },
70
68
  onDownloadActionClick: () => {
71
69
  handleInvoke(getInvokeOpts(key, 'DownloadAction'));
72
70
  },
@@ -76,7 +74,7 @@ export const extractPreviewAction = (extensionKey = 'empty-object-provider', vie
76
74
  }); // Setup props to go through proper Redux 'invocation' flow
77
75
  // for analytics, further state management if required in future.
78
76
 
79
- const previewActionProps = getInvokeOpts(key, 'PreviewAction', source !== null && source !== void 0 ? source : 'block'); // - Promise invoked by the action invocation handler; open preview.
77
+ const previewActionProps = getInvokeOpts(key, 'PreviewAction', source); // - Promise invoked by the action invocation handler; open preview.
80
78
 
81
79
  previewActionProps.action.promise = previewAction.promise; // - Promise invoked on click of `Preview` on block card; trigger above promise.
82
80
 
@@ -1,8 +1,8 @@
1
1
  import { useMemo } from 'react';
2
2
  import { getUrl } from '@atlaskit/linking-common';
3
- import { uiAuthEvent, uiAuthAlternateAccountEvent, uiCardClickedEvent, uiActionClickedEvent, uiClosedAuthEvent, uiRenderSuccessEvent, uiRenderFailedEvent, uiHoverCardViewedEvent, uiHoverCardDismissedEvent, uiHoverCardOpenLinkClickedEvent, invokeSucceededEvent, invokeFailedEvent, connectSucceededEvent, connectFailedEvent, trackAppAccountConnected, screenAuthPopupEvent, instrumentEvent } from '../../utils/analytics';
3
+ import { connectFailedEvent, connectSucceededEvent, context, instrumentEvent, invokeFailedEvent, invokeSucceededEvent, screenAuthPopupEvent, trackAppAccountConnected, uiActionClickedEvent, uiAuthAlternateAccountEvent, uiAuthEvent, uiCardClickedEvent, uiClosedAuthEvent, uiHoverCardDismissedEvent, uiHoverCardOpenLinkClickedEvent, uiHoverCardViewedEvent, uiRenderFailedEvent, uiRenderSuccessEvent } from '../../utils/analytics';
4
4
  import { failUfoExperience, startUfoExperience, succeedUfoExperience } from './ufoExperiences';
5
- import { getDefinitionId, getExtensionKey, getResourceType, getSubproduct, getProduct } from '../helpers';
5
+ import { getDefinitionId, getExtensionKey, getProduct, getResourceType, getSubproduct } from '../helpers';
6
6
  import { useSmartLinkContext } from '@atlaskit/link-provider';
7
7
 
8
8
  const applyCommonAttributes = (event, commonAttributes) => {
@@ -104,6 +104,21 @@ export const useSmartLinkAnalytics = (url, dispatchAnalytics, id, defaultLocatio
104
104
  location
105
105
  }), commonAttributes)),
106
106
 
107
+ /**
108
+ * This fires an event that represents when a user
109
+ * click a button.
110
+ * @param data A partial analytics event payload
111
+ */
112
+ buttonClickedEvent: data => dispatchAnalytics(applyCommonAttributes({
113
+ action: 'clicked',
114
+ actionSubject: 'button',
115
+ actionSubjectId: data.actionSubjectId,
116
+ attributes: { ...context,
117
+ ...data.attributes
118
+ },
119
+ eventType: 'ui'
120
+ }, commonAttributes)),
121
+
107
122
  /**
108
123
  * This fires an event that represents when a user clicks on a Smart Link.
109
124
  * @param id The unique ID for this Smart Link.
@@ -235,6 +250,20 @@ export const useSmartLinkAnalytics = (url, dispatchAnalytics, id, defaultLocatio
235
250
  location
236
251
  }), commonAttributes)),
237
252
 
253
+ /**
254
+ * This fires an event that represents when a user close a modal.
255
+ * @param data A partial analytics event payload
256
+ */
257
+ modalClosedEvent: data => dispatchAnalytics(applyCommonAttributes({
258
+ action: 'closed',
259
+ actionSubject: 'modal',
260
+ actionSubjectId: data.actionSubjectId,
261
+ attributes: { ...context,
262
+ ...data.attributes
263
+ },
264
+ eventType: 'ui'
265
+ }, commonAttributes)),
266
+
238
267
  /**
239
268
  * This fires an event that represents when a Smart Link was rendered successfully.
240
269
  * Note: this fires even if the Smart Link request errored out.
@@ -596,7 +625,21 @@ export const useSmartLinkAnalytics = (url, dispatchAnalytics, id, defaultLocatio
596
625
  destinationProduct,
597
626
  destinationSubproduct,
598
627
  location
599
- }), commonAttributes))
628
+ }), commonAttributes)),
629
+
630
+ /**
631
+ * This fires an event that represents when a user view a modal.
632
+ * @param data A partial analytics event payload
633
+ */
634
+ modalViewedEvent: data => dispatchAnalytics(applyCommonAttributes({
635
+ action: 'viewed',
636
+ actionSubject: data.name,
637
+ attributes: { ...context,
638
+ ...data.attributes
639
+ },
640
+ eventType: 'screen',
641
+ name: data.name
642
+ }, commonAttributes))
600
643
  }), [commonAttributes, dispatchAnalytics]);
601
644
  return useMemo(() => ({
602
645
  ui,
@@ -10,7 +10,8 @@ export function useSmartLinkActions({
10
10
  url,
11
11
  appearance,
12
12
  analyticsHandler,
13
- platform = 'web'
13
+ platform = 'web',
14
+ origin
14
15
  }) {
15
16
  const id = useMemo(() => uuid(), []);
16
17
  const [actions, setActions] = useState([]);
@@ -32,7 +33,8 @@ export function useSmartLinkActions({
32
33
  const cardProperties = extractCardProps(linkState.details.data, linkState.details.meta, {
33
34
  featureFlags,
34
35
  handleInvoke: opts => linkActions.invoke(opts, appearance),
35
- handleAnalytics: analyticsHandler,
36
+ analytics: linkAnalytics,
37
+ origin,
36
38
  extensionKey: getExtensionKey(linkState.details),
37
39
  source: appearance
38
40
  }, undefined, platform);
@@ -47,6 +49,6 @@ export function useSmartLinkActions({
47
49
  invoke: action.promise
48
50
  }));
49
51
  setActions(cardActions);
50
- }, [linkState, linkActions, analyticsHandler, appearance, platform, embedModalSize]);
52
+ }, [linkState, linkActions, linkAnalytics, appearance, platform, embedModalSize, origin]);
51
53
  return actions;
52
54
  }
@@ -369,7 +369,7 @@ export const uiRenderFailedEvent = ({
369
369
  actionSubject: 'smartLink',
370
370
  action: 'renderFailed',
371
371
  eventType: 'ui',
372
- attributes: {
372
+ attributes: { ...context,
373
373
  error,
374
374
  errorInfo,
375
375
  display,
@@ -109,6 +109,18 @@ export const mocks = {
109
109
  data: {
110
110
  status: 'CompletedStatus'
111
111
  }
112
+ },
113
+ analytics: {
114
+ status: 'resolved',
115
+ details: {
116
+ meta: {
117
+ definitionId: 'spaghetti-id',
118
+ key: 'spaghetti-key',
119
+ resourceType: 'spaghetti-resource',
120
+ subproduct: 'spaghetti-subproduct',
121
+ product: 'spaghetti-product'
122
+ }
123
+ }
112
124
  }
113
125
  };
114
126
  export const fakeResponse = () => Promise.resolve(mocks.success);
@@ -126,4 +138,17 @@ export const fakeFactory = (implementation, implementationPost, implementationPr
126
138
  }
127
139
 
128
140
  };
129
- export const waitFor = (time = 1) => new Promise(res => setTimeout(res, time));
141
+ export const waitFor = (time = 1) => new Promise(res => setTimeout(res, time));
142
+ export const mockAnalytics = {
143
+ ui: {
144
+ buttonClickedEvent: () => {},
145
+ modalClosedEvent: () => {},
146
+ renderSuccessEvent: () => {},
147
+ renderFailedEvent: () => {}
148
+ },
149
+ operational: {},
150
+ track: {},
151
+ screen: {
152
+ modalViewedEvent: () => {}
153
+ }
154
+ };
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/smart-card",
3
- "version": "22.0.0",
3
+ "version": "22.1.2",
4
4
  "sideEffects": false
5
5
  }
@@ -1,7 +1,7 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
2
  import React from 'react';
3
3
  import ReactDOM from 'react-dom';
4
- import { IntlProvider, FormattedMessage } from 'react-intl-next';
4
+ import { FormattedMessage, IntlProvider } from 'react-intl-next';
5
5
  import { messages } from '../../../messages';
6
6
 
7
7
  /*
@@ -36,9 +36,9 @@ export async function previewFunction({
36
36
  ReactDOM.render( /*#__PURE__*/React.createElement(IntlProvider, {
37
37
  locale: "en"
38
38
  }, /*#__PURE__*/React.createElement(Modal.default, _extends({}, rest, {
39
- onClose: () => {
39
+ onClose: context => {
40
40
  if (popupMountPoint) {
41
- onClose();
41
+ onClose(context);
42
42
  ReactDOM.unmountComponentAtNode(popupMountPoint);
43
43
  }
44
44
  }
@@ -5,7 +5,6 @@ import { extractBlockProps } from '../../extractors/block';
5
5
  import { getEmptyJsonLd, getUnauthorizedJsonLd } from '../../utils/jsonld';
6
6
  import { extractRequestAccessContext } from '../../extractors/common/context';
7
7
  import { CardLinkView } from '../LinkView';
8
- export { default as PreviewAction } from './actions/PreviewAction';
9
8
  import { AuthorizeAction } from './actions/AuthorizeAction';
10
9
  import { ForbiddenAction } from './actions/ForbiddenAction';
11
10
  import { ResolvedView as BlockCardResolvedView } from './views/ResolvedView';
@@ -15,6 +14,7 @@ import { UnauthorizedView as BlockCardUnauthorisedView } from './views/Unauthori
15
14
  import { ForbiddenView as BlockCardForbiddenView } from './views/ForbiddenView';
16
15
  import { ErroredView as BlockCardErroredView } from './views/ErroredView';
17
16
  import { useFeatureFlag } from '@atlaskit/link-provider';
17
+ export { default as PreviewAction } from './actions/PreviewAction';
18
18
  export { ForbiddenAction, AuthorizeAction, BlockCardResolvedView, BlockCardResolvingView, BlockCardUnauthorisedView, BlockCardForbiddenView, BlockCardErroredView, BlockCardNotFoundView };
19
19
  export const BlockCard = ({
20
20
  url,
@@ -26,7 +26,6 @@ export const BlockCard = ({
26
26
  handleAuthorize,
27
27
  handleErrorRetry,
28
28
  handleFrameClick,
29
- handleAnalytics,
30
29
  handleInvoke,
31
30
  renderers,
32
31
  isSelected,
@@ -34,7 +33,8 @@ export const BlockCard = ({
34
33
  onError,
35
34
  testId,
36
35
  showActions,
37
- platform
36
+ platform,
37
+ analytics
38
38
  }) => {
39
39
  var _details$meta, _forbiddenViewProps$c;
40
40
 
@@ -48,8 +48,9 @@ export const BlockCard = ({
48
48
  const data = details && details.data || getEmptyJsonLd();
49
49
  const meta = details && details.meta;
50
50
  const extractorOpts = {
51
+ analytics,
52
+ origin: 'smartLinkCard',
51
53
  featureFlags,
52
- handleAnalytics,
53
54
  handleInvoke,
54
55
  extensionKey: getExtensionKey(details)
55
56
  };
@@ -176,7 +176,7 @@ export function CardWithUrlContent({
176
176
  handleErrorRetry: handleRetry,
177
177
  handleInvoke: handleInvoke,
178
178
  handleFrameClick: handleClickWrapper,
179
- handleAnalytics: dispatchAnalytics,
179
+ analytics: analytics,
180
180
  isSelected: isSelected,
181
181
  onResolve: onResolve,
182
182
  onError: onError,
@@ -194,7 +194,7 @@ export function CardWithUrlContent({
194
194
  handleErrorRetry: handleRetry,
195
195
  handleFrameClick: handleClickWrapper,
196
196
  handleInvoke: handleInvoke,
197
- handleAnalytics: dispatchAnalytics,
197
+ analytics: analytics,
198
198
  isSelected: isSelected,
199
199
  isFrameVisible: isFrameVisible,
200
200
  platform: platform,
@@ -22,7 +22,7 @@ export const EmbedCard = /*#__PURE__*/React.forwardRef(({
22
22
  handleAuthorize,
23
23
  handleErrorRetry,
24
24
  handleFrameClick,
25
- handleAnalytics,
25
+ analytics,
26
26
  handleInvoke,
27
27
  showActions,
28
28
  isSelected,
@@ -79,7 +79,8 @@ export const EmbedCard = /*#__PURE__*/React.forwardRef(({
79
79
  }
80
80
 
81
81
  const resolvedBlockViewProps = extractBlockProps(data, meta, {
82
- handleAnalytics,
82
+ analytics,
83
+ origin: 'smartLinkEmbed',
83
84
  handleInvoke,
84
85
  extensionKey: getExtensionKey(details)
85
86
  });
@@ -0,0 +1,80 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ import React, { useCallback } from 'react';
3
+ import { EmbedModalSize } from '../../types';
4
+
5
+ const getResizeFrom = size => size === EmbedModalSize.Small ? EmbedModalSize.Large : EmbedModalSize.Small;
6
+
7
+ const withAnalytics = Component => props => {
8
+ const {
9
+ analytics,
10
+ onClose,
11
+ onOpen,
12
+ onOpenFailed,
13
+ onResize,
14
+ origin
15
+ } = props;
16
+ const handleOnOpen = useCallback(context => {
17
+ analytics.screen.modalViewedEvent({
18
+ name: 'embedPreviewModal',
19
+ attributes: {
20
+ origin,
21
+ size: context.size
22
+ }
23
+ });
24
+ analytics.ui.renderSuccessEvent({
25
+ status: 'resolved',
26
+ display: 'preview'
27
+ });
28
+
29
+ if (onOpen) {
30
+ onOpen(context);
31
+ }
32
+ }, [analytics.screen, analytics.ui, onOpen, origin]);
33
+ const handleOnOpenFailed = useCallback((error, errorInfo) => {
34
+ analytics.ui.renderFailedEvent({
35
+ display: 'preview',
36
+ error,
37
+ errorInfo
38
+ });
39
+
40
+ if (onOpenFailed) {
41
+ onOpenFailed(error, errorInfo);
42
+ }
43
+ }, [analytics.ui, onOpenFailed]);
44
+ const handleOnClose = useCallback(context => {
45
+ analytics.ui.modalClosedEvent({
46
+ actionSubjectId: 'embedPreview',
47
+ attributes: {
48
+ origin,
49
+ previewTime: context.duration,
50
+ size: context.size
51
+ }
52
+ });
53
+
54
+ if (onClose) {
55
+ onClose(context);
56
+ }
57
+ }, [analytics.ui, onClose, origin]);
58
+ const handleOnResize = useCallback(context => {
59
+ analytics.ui.buttonClickedEvent({
60
+ actionSubjectId: 'embedPreviewResize',
61
+ attributes: {
62
+ newSize: context.size,
63
+ origin,
64
+ previousSize: getResizeFrom(context.size)
65
+ }
66
+ });
67
+
68
+ if (onResize) {
69
+ onResize(context);
70
+ }
71
+ }, [analytics.ui, onResize, origin]);
72
+ return /*#__PURE__*/React.createElement(Component, _extends({}, props, {
73
+ onClose: handleOnClose,
74
+ onOpen: handleOnOpen,
75
+ onOpenFailed: handleOnOpenFailed,
76
+ onResize: handleOnResize
77
+ }));
78
+ };
79
+
80
+ export default withAnalytics;
@@ -1,28 +1,24 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
2
  import React from 'react';
3
3
  import Modal from '../../../common/Modal';
4
- import { MAX_MODAL_SIZE, MIN_MODAL_SIZE } from '../../constants';
4
+ import { EmbedModalSize } from '../../types';
5
5
 
6
6
  const withSizeExperiment = Component => props => {
7
7
  const {
8
- featureFlags = {},
9
- closeLabel = 'Close Preview'
8
+ featureFlags = {}
10
9
  } = props;
11
10
  const {
12
- embedModalSize
11
+ embedModalSize: size
13
12
  } = featureFlags; // Experiment
14
13
 
15
- if (embedModalSize === 'large' || embedModalSize === 'small') {
16
- const size = embedModalSize === 'large' ? MAX_MODAL_SIZE : MIN_MODAL_SIZE;
14
+ if (size === EmbedModalSize.Large || size === EmbedModalSize.Small) {
17
15
  return /*#__PURE__*/React.createElement(Component, _extends({}, props, {
18
16
  size: size
19
17
  }));
20
18
  } // Control
21
19
 
22
20
 
23
- return /*#__PURE__*/React.createElement(Modal, _extends({}, props, {
24
- closeLabel: closeLabel
25
- }));
21
+ return /*#__PURE__*/React.createElement(Modal, props);
26
22
  };
27
23
 
28
24
  export default withSizeExperiment;
@@ -1,10 +1,16 @@
1
- import React, { useCallback, useState } from 'react';
1
+ import React, { useCallback, useRef, useState } from 'react';
2
2
  import ModalDialog, { ModalBody, ModalTransition } from '@atlaskit/modal-dialog';
3
3
  import LinkInfo from './components/link-info';
4
4
  import { MAX_MODAL_SIZE, MIN_MODAL_SIZE } from './constants';
5
5
  import EmbedContent from './components/embed-content';
6
+ import { EmbedModalSize } from './types';
6
7
  import withErrorBoundary from './components/error-boundary';
7
8
  import withSizeExperiment from './components/size-experiment';
9
+ import withAnalytics from './components/analytics';
10
+
11
+ const toSize = width => width === MAX_MODAL_SIZE ? EmbedModalSize.Large : EmbedModalSize.Small;
12
+
13
+ const toWidth = size => size === EmbedModalSize.Large ? MAX_MODAL_SIZE : MIN_MODAL_SIZE;
8
14
 
9
15
  const EmbedModal = ({
10
16
  download: downloadUrl,
@@ -14,37 +20,64 @@ const EmbedModal = ({
14
20
  onClose,
15
21
  onDownloadActionClick,
16
22
  onOpen,
23
+ onResize,
17
24
  onViewActionClick,
18
25
  providerName,
19
26
  showModal,
20
- size: defaultSize = MIN_MODAL_SIZE,
27
+ size = EmbedModalSize.Small,
21
28
  src,
22
29
  testId = 'smart-embed-preview-modal',
23
30
  title,
24
31
  url
25
32
  }) => {
33
+ const defaultWidth = toWidth(size);
26
34
  const [isOpen, setIsOpen] = useState(showModal);
27
- const [size, setSize] = useState(defaultSize);
35
+ const [width, setWidth] = useState(defaultWidth);
36
+ const openAt = useRef();
37
+ const handleOnOpenComplete = useCallback(() => {
38
+ openAt.current = Date.now();
39
+
40
+ if (onOpen) {
41
+ onOpen({
42
+ size
43
+ });
44
+ }
45
+ }, [onOpen, size]);
28
46
  const handleOnClose = useCallback(() => setIsOpen(false), []);
29
- const handleOnSizeClick = useCallback(() => {
30
- const newSize = size === MIN_MODAL_SIZE ? MAX_MODAL_SIZE : MIN_MODAL_SIZE;
31
- setSize(newSize);
32
- }, [size]);
47
+ const handleOnCloseComplete = useCallback(() => {
48
+ if (onClose) {
49
+ const duration = openAt.current ? Date.now() - openAt.current : undefined;
50
+ onClose({
51
+ duration,
52
+ size: toSize(width)
53
+ });
54
+ }
55
+ }, [onClose, width]);
56
+ const handleOnResizeClick = useCallback(() => {
57
+ const newWidth = width === MIN_MODAL_SIZE ? MAX_MODAL_SIZE : MIN_MODAL_SIZE;
58
+ setWidth(newWidth);
59
+
60
+ if (onResize) {
61
+ onResize({
62
+ size: toSize(newWidth)
63
+ });
64
+ }
65
+ }, [onResize, width]);
33
66
  return /*#__PURE__*/React.createElement(ModalTransition, null, isOpen && /*#__PURE__*/React.createElement(ModalDialog, {
34
67
  height: "100%",
35
68
  onClose: handleOnClose,
36
- onCloseComplete: onClose,
37
- onOpenComplete: onOpen,
69
+ onCloseComplete: handleOnCloseComplete,
70
+ onOpenComplete: handleOnOpenComplete,
38
71
  testId: testId,
39
- width: size
72
+ width: width
40
73
  }, /*#__PURE__*/React.createElement(LinkInfo, {
41
74
  downloadUrl: downloadUrl,
42
75
  icon: icon,
43
76
  providerName: providerName,
44
77
  onViewButtonClick: onViewActionClick,
45
78
  onDownloadButtonClick: onDownloadActionClick,
46
- onResizeButtonClick: handleOnSizeClick,
47
- size: size,
79
+ onResizeButtonClick: handleOnResizeClick,
80
+ size: width,
48
81
  title: title,
49
82
  testId: testId,
50
83
  url: url
@@ -56,4 +89,4 @@ const EmbedModal = ({
56
89
  }))));
57
90
  };
58
91
 
59
- export default withSizeExperiment(withErrorBoundary(EmbedModal));
92
+ export default withSizeExperiment(withAnalytics(withErrorBoundary(EmbedModal)));
@@ -1 +1,6 @@
1
- export {};
1
+ export let EmbedModalSize;
2
+
3
+ (function (EmbedModalSize) {
4
+ EmbedModalSize["Large"] = "large";
5
+ EmbedModalSize["Small"] = "small";
6
+ })(EmbedModalSize || (EmbedModalSize = {}));
@@ -91,7 +91,8 @@ export const HoverCardComponent = ({
91
91
  const linkActions = useSmartLinkActions({
92
92
  url,
93
93
  appearance: SMART_CARD_ANALYTICS_DISPLAY,
94
- analyticsHandler
94
+ analyticsHandler,
95
+ origin: 'smartLinkPreviewHoverCard'
95
96
  });
96
97
  const onActionClick = useCallback(actionId => {
97
98
  if (actionId === 'preview-content') {
@@ -64,14 +64,12 @@ export const LozengeWrapper = styled.span`
64
64
  vertical-align: 1px;
65
65
  & > span {
66
66
  margin-left: 4px;
67
- padding: 2px 0 2px 0;
68
67
  }
69
68
  `; // TODO: Replace overrides with proper AtlasKit solution.
70
69
 
71
70
  export const LozengeBlockWrapper = styled.span`
72
71
  & > span {
73
72
  margin-left: 4px;
74
- padding: 2px 0 2px 0;
75
73
  }
76
74
  `;
77
75
  export const RightIconPositionWrapper = styled.span`