@atlaskit/smart-card 17.7.6 → 17.7.9

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 (54) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/dist/cjs/hooks.js +13 -0
  3. package/dist/cjs/state/analytics/useSmartLinkAnalytics.js +2 -2
  4. package/dist/cjs/state/hooks-external/useSmartLinkActions.js +71 -0
  5. package/dist/cjs/utils/analytics/analytics.js +3 -2
  6. package/dist/cjs/utils/mocks.js +7 -1
  7. package/dist/cjs/version.json +1 -1
  8. package/dist/cjs/view/BlockCard/index.js +2 -2
  9. package/dist/cjs/view/CardWithUrl/component.js +12 -6
  10. package/dist/cjs/view/FlexibleCard/components/blocks/title-block/resolved/index.js +4 -2
  11. package/dist/cjs/view/FlexibleCard/components/container/index.js +5 -3
  12. package/dist/cjs/view/FlexibleCard/components/elements/link/index.js +3 -1
  13. package/dist/cjs/view/FlexibleCard/components/elements/media/index.js +12 -4
  14. package/dist/cjs/view/FlexibleCard/index.js +8 -3
  15. package/dist/es2019/hooks.js +1 -0
  16. package/dist/es2019/state/analytics/useSmartLinkAnalytics.js +1 -1
  17. package/dist/es2019/state/hooks-external/useSmartLinkActions.js +42 -0
  18. package/dist/es2019/utils/analytics/analytics.js +3 -2
  19. package/dist/es2019/utils/mocks.js +5 -0
  20. package/dist/es2019/version.json +1 -1
  21. package/dist/es2019/view/BlockCard/index.js +2 -2
  22. package/dist/es2019/view/CardWithUrl/component.js +11 -7
  23. package/dist/es2019/view/FlexibleCard/components/blocks/title-block/resolved/index.js +3 -1
  24. package/dist/es2019/view/FlexibleCard/components/container/index.js +5 -3
  25. package/dist/es2019/view/FlexibleCard/components/elements/link/index.js +3 -1
  26. package/dist/es2019/view/FlexibleCard/components/elements/media/index.js +37 -4
  27. package/dist/es2019/view/FlexibleCard/index.js +8 -3
  28. package/dist/esm/hooks.js +1 -0
  29. package/dist/esm/state/analytics/useSmartLinkAnalytics.js +2 -2
  30. package/dist/esm/state/hooks-external/useSmartLinkActions.js +54 -0
  31. package/dist/esm/utils/analytics/analytics.js +3 -2
  32. package/dist/esm/utils/mocks.js +5 -0
  33. package/dist/esm/version.json +1 -1
  34. package/dist/esm/view/BlockCard/index.js +2 -2
  35. package/dist/esm/view/CardWithUrl/component.js +13 -7
  36. package/dist/esm/view/FlexibleCard/components/blocks/title-block/resolved/index.js +4 -2
  37. package/dist/esm/view/FlexibleCard/components/container/index.js +5 -3
  38. package/dist/esm/view/FlexibleCard/components/elements/link/index.js +3 -1
  39. package/dist/esm/view/FlexibleCard/components/elements/media/index.js +12 -4
  40. package/dist/esm/view/FlexibleCard/index.js +8 -3
  41. package/dist/types/hooks.d.ts +1 -0
  42. package/dist/types/state/analytics/useSmartLinkAnalytics.d.ts +1 -1
  43. package/dist/types/state/hooks/useSmartLink.d.ts +1 -1
  44. package/dist/types/state/hooks-external/useSmartLinkActions.d.ts +45 -0
  45. package/dist/types/utils/analytics/analytics.d.ts +2 -2
  46. package/dist/types/utils/mocks.d.ts +5 -0
  47. package/dist/types/view/BlockCard/types.d.ts +1 -1
  48. package/dist/types/view/Card/types.d.ts +1 -1
  49. package/dist/types/view/FlexibleCard/components/blocks/title-block/types.d.ts +2 -0
  50. package/dist/types/view/FlexibleCard/components/container/types.d.ts +2 -0
  51. package/dist/types/view/FlexibleCard/components/elements/link/types.d.ts +2 -0
  52. package/dist/types/view/FlexibleCard/types.d.ts +1 -0
  53. package/hooks/package.json +7 -0
  54. package/package.json +3 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,49 @@
1
1
  # @atlaskit/smart-card
2
2
 
3
+ ## 17.7.9
4
+
5
+ ### Patch Changes
6
+
7
+ - [`63d4f963f72`](https://bitbucket.org/atlassian/atlassian-frontend/commits/63d4f963f72) - Flexible UI: Set PreviewBlock image aspect ratio to 16:9
8
+
9
+ ## 17.7.8
10
+
11
+ ### Patch Changes
12
+
13
+ - [`d75ce5b847d`](https://bitbucket.org/atlassian/atlassian-frontend/commits/d75ce5b847d) - Add link click analytics to flexible ui title block component
14
+
15
+ ## 17.7.7
16
+
17
+ ### Patch Changes
18
+
19
+ - [`c01f6404d0c`](https://bitbucket.org/atlassian/atlassian-frontend/commits/c01f6404d0c) - Add ability to trigger actions for a Smart Link from outside of the Smart Link card.
20
+
21
+ Example usage:
22
+
23
+ ```tsx
24
+ import { useSmartLinkActions } from '@atlaskit/smart-card/hooks';
25
+
26
+ const ExampleToolbar = () => {
27
+ const actions = useSmartLinkActions({
28
+ url,
29
+ appearance: 'block',
30
+ analyticsHandler: analytics,
31
+ });
32
+
33
+ return (
34
+ <ExampleToolbarWrapper>
35
+ {actions.map((action) => (
36
+ <Tooltip content={action.text}>
37
+ <ExampleToolbarItem key={action.id} onClick={action.invoke}>
38
+ {idToIcon[action.id] ?? action.id}
39
+ </ExampleToolbarItem>
40
+ </Tooltip>
41
+ ))}
42
+ </ExampleToolbarWrapper>
43
+ );
44
+ };
45
+ ```
46
+
3
47
  ## 17.7.6
4
48
 
5
49
  ### Patch Changes
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "useSmartLinkActions", {
7
+ enumerable: true,
8
+ get: function get() {
9
+ return _useSmartLinkActions.useSmartLinkActions;
10
+ }
11
+ });
12
+
13
+ var _useSmartLinkActions = require("./state/hooks-external/useSmartLinkActions");
@@ -20,8 +20,8 @@ var useSmartLinkAnalytics = function useSmartLinkAnalytics(dispatchAnalytics) {
20
20
  authAlternateAccountEvent: function authAlternateAccountEvent(display, definitionId, extensionKey) {
21
21
  return dispatchAnalytics((0, _analytics.uiAuthAlternateAccountEvent)(display, definitionId, extensionKey));
22
22
  },
23
- cardClickedEvent: function cardClickedEvent(display, definitionId, extensionKey) {
24
- return dispatchAnalytics((0, _analytics.uiCardClickedEvent)(display, definitionId, extensionKey));
23
+ cardClickedEvent: function cardClickedEvent(display, definitionId, extensionKey, isModifierKeyPressed) {
24
+ return dispatchAnalytics((0, _analytics.uiCardClickedEvent)(display, definitionId, extensionKey, isModifierKeyPressed));
25
25
  },
26
26
  actionClickedEvent: function actionClickedEvent(id, extensionKey, actionType, display, invokeType) {
27
27
  (0, _ufoExperiences.startUfoExperience)('smart-link-action-invocation', id, {
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.useSmartLinkActions = useSmartLinkActions;
9
+
10
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
11
+
12
+ var _react = require("react");
13
+
14
+ var _uuid = _interopRequireDefault(require("uuid"));
15
+
16
+ var _block = require("../../extractors/block");
17
+
18
+ var _actions = require("../actions");
19
+
20
+ var _analytics = require("../analytics");
21
+
22
+ var _store = require("../store");
23
+
24
+ var _helpers = require("../helpers");
25
+
26
+ function useSmartLinkActions(_ref) {
27
+ var url = _ref.url,
28
+ appearance = _ref.appearance,
29
+ analyticsHandler = _ref.analyticsHandler,
30
+ _ref$platform = _ref.platform,
31
+ platform = _ref$platform === void 0 ? 'web' : _ref$platform;
32
+ var id = (0, _react.useMemo)(function () {
33
+ return (0, _uuid.default)();
34
+ }, []);
35
+
36
+ var _useState = (0, _react.useState)([]),
37
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
38
+ actions = _useState2[0],
39
+ setActions = _useState2[1];
40
+
41
+ var linkState = (0, _store.useSmartCardState)(url);
42
+ var linkAnalytics = (0, _analytics.useSmartLinkAnalytics)(analyticsHandler);
43
+ var linkActions = (0, _actions.useSmartCardActions)(id, url, linkAnalytics);
44
+ (0, _react.useEffect)(function () {
45
+ if (!linkState.details) {
46
+ return;
47
+ }
48
+
49
+ var cardProperties = (0, _block.extractBlockProps)(linkState.details.data, linkState.details.meta, {
50
+ handleInvoke: function handleInvoke(opts) {
51
+ return linkActions.invoke(opts, appearance);
52
+ },
53
+ handleAnalytics: analyticsHandler,
54
+ extensionKey: (0, _helpers.getExtensionKey)(linkState.details)
55
+ }, undefined, platform);
56
+
57
+ if (!cardProperties.actions || cardProperties.actions.length === 0) {
58
+ return;
59
+ }
60
+
61
+ var cardActions = cardProperties.actions.map(function (action) {
62
+ return {
63
+ id: action.id,
64
+ text: action.text,
65
+ invoke: action.promise
66
+ };
67
+ });
68
+ setActions(cardActions);
69
+ }, [linkState, linkActions, analyticsHandler, appearance, platform]);
70
+ return actions;
71
+ }
@@ -230,7 +230,7 @@ var uiAuthAlternateAccountEvent = function uiAuthAlternateAccountEvent(display,
230
230
 
231
231
  exports.uiAuthAlternateAccountEvent = uiAuthAlternateAccountEvent;
232
232
 
233
- var uiCardClickedEvent = function uiCardClickedEvent(display, definitionId, extensionKey) {
233
+ var uiCardClickedEvent = function uiCardClickedEvent(display, definitionId, extensionKey, isModifierKeyPressed) {
234
234
  return {
235
235
  action: 'clicked',
236
236
  actionSubject: 'smartLink',
@@ -238,7 +238,8 @@ var uiCardClickedEvent = function uiCardClickedEvent(display, definitionId, exte
238
238
  attributes: _objectSpread(_objectSpread({}, context), {}, {
239
239
  definitionId: definitionId || '',
240
240
  extensionKey: extensionKey || '',
241
- display: display
241
+ display: display,
242
+ isModifierKeyPressed: isModifierKeyPressed
242
243
  })
243
244
  };
244
245
  };
@@ -5,7 +5,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
- exports.waitFor = exports.mocks = exports.fakeResponse = exports.fakeFactory = void 0;
8
+ exports.waitFor = exports.mocks = exports.mockContext = exports.fakeResponse = exports.fakeFactory = void 0;
9
9
 
10
10
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
11
11
 
@@ -27,6 +27,12 @@ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflec
27
27
 
28
28
  function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
29
29
 
30
+ var mockContext = {
31
+ '@vocab': 'https://www.w3.org/ns/activitystreams#',
32
+ atlassian: 'https://schema.atlassian.com/ns/vocabulary#',
33
+ schema: 'http://schema.org/'
34
+ };
35
+ exports.mockContext = mockContext;
30
36
  var mocks = {
31
37
  success: {
32
38
  meta: {
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/smart-card",
3
- "version": "17.7.6",
3
+ "version": "17.7.9",
4
4
  "sideEffects": false
5
5
  }
@@ -104,7 +104,7 @@ var BlockCard = function BlockCard(_ref) {
104
104
  handleAuthorize = _ref.handleAuthorize,
105
105
  handleErrorRetry = _ref.handleErrorRetry,
106
106
  handleFrameClick = _ref.handleFrameClick,
107
- handlePreviewAnalytics = _ref.handlePreviewAnalytics,
107
+ handleAnalytics = _ref.handleAnalytics,
108
108
  handleInvoke = _ref.handleInvoke,
109
109
  renderers = _ref.renderers,
110
110
  isSelected = _ref.isSelected,
@@ -115,7 +115,7 @@ var BlockCard = function BlockCard(_ref) {
115
115
  var data = details && details.data || (0, _jsonld.getEmptyJsonLd)();
116
116
  var meta = details && details.meta;
117
117
  var extractorOpts = {
118
- handleAnalytics: handlePreviewAnalytics,
118
+ handleAnalytics: handleAnalytics,
119
119
  handleInvoke: handleInvoke,
120
120
  extensionKey: (0, _helpers.getExtensionKey)(details)
121
121
  };
@@ -63,7 +63,10 @@ function CardWithUrlContent(_ref) {
63
63
  var definitionId = (0, _helpers.getDefinitionId)(state.details);
64
64
  var extensionKey = (0, _helpers.getExtensionKey)(state.details);
65
65
  var resourceType = (0, _helpers.getResourceType)(state.details);
66
- var services = (0, _helpers.getServices)(state.details); // Setup UI handlers.
66
+ var services = (0, _helpers.getServices)(state.details);
67
+ var isFlexibleUi = (0, _react.useMemo)(function () {
68
+ return (0, _flexible.isFlexibleUiCard)(children);
69
+ }, [children]); // Setup UI handlers.
67
70
 
68
71
  var handleClick = (0, _react.useCallback)(function (event) {
69
72
  var clickUrl = (0, _helpers.getClickUrl)(url, state.details);
@@ -71,11 +74,12 @@ function CardWithUrlContent(_ref) {
71
74
  }, [state.details, url]);
72
75
  var handleClickWrapper = (0, _react.useCallback)(function (event) {
73
76
  if (state.status === 'resolved') {
74
- analytics.ui.cardClickedEvent(appearance, definitionId, extensionKey);
77
+ var isModifierKeyPressed = (0, _utils.isSpecialEvent)(event);
78
+ analytics.ui.cardClickedEvent(isFlexibleUi ? 'flexible' : appearance, definitionId, extensionKey, isModifierKeyPressed);
75
79
  }
76
80
 
77
81
  onClick ? onClick(event) : handleClick(event);
78
- }, [state.status, analytics.ui, appearance, definitionId, extensionKey, onClick, handleClick]);
82
+ }, [state.status, analytics.ui, appearance, definitionId, extensionKey, onClick, handleClick, isFlexibleUi]);
79
83
  var handleAuthorize = (0, _react.useCallback)(function () {
80
84
  return actions.authorize(appearance);
81
85
  }, [actions, appearance]);
@@ -109,13 +113,15 @@ function CardWithUrlContent(_ref) {
109
113
  throw error;
110
114
  }
111
115
 
112
- if ((0, _flexible.isFlexibleUiCard)(children)) {
116
+ if (isFlexibleUi) {
113
117
  return /*#__PURE__*/_react.default.createElement(_FlexibleCard.default, {
114
118
  cardState: state,
115
119
  onAuthorize: services.length && handleAuthorize || undefined,
120
+ onClick: handleClickWrapper,
116
121
  renderers: renderers,
117
122
  ui: ui,
118
- url: url
123
+ url: url,
124
+ testId: testId
119
125
  }, children);
120
126
  }
121
127
 
@@ -143,7 +149,7 @@ function CardWithUrlContent(_ref) {
143
149
  handleErrorRetry: handleRetry,
144
150
  handleInvoke: handleInvoke,
145
151
  handleFrameClick: handleClickWrapper,
146
- handlePreviewAnalytics: dispatchAnalytics,
152
+ handleAnalytics: dispatchAnalytics,
147
153
  isSelected: isSelected,
148
154
  onResolve: onResolve,
149
155
  testId: testId,
@@ -33,7 +33,7 @@ var _utils = require("../../utils");
33
33
 
34
34
  var _actionGroup = _interopRequireDefault(require("../../action-group"));
35
35
 
36
- var _excluded = ["maxLines", "metadata", "position", "subtitle", "actions", "testId", "theme", "text", "showActionOnHover"];
36
+ var _excluded = ["maxLines", "metadata", "position", "subtitle", "actions", "testId", "theme", "onClick", "text", "showActionOnHover"];
37
37
 
38
38
  var _templateObject;
39
39
 
@@ -54,6 +54,7 @@ var TitleBlockResolvedView = function TitleBlockResolvedView(_ref) {
54
54
  actions = _ref$actions === void 0 ? [] : _ref$actions,
55
55
  testId = _ref.testId,
56
56
  theme = _ref.theme,
57
+ onClick = _ref.onClick,
57
58
  text = _ref.text,
58
59
  showActionOnHover = _ref.showActionOnHover,
59
60
  blockProps = (0, _objectWithoutProperties2.default)(_ref, _excluded);
@@ -79,7 +80,8 @@ var TitleBlockResolvedView = function TitleBlockResolvedView(_ref) {
79
80
  width: _constants.SmartLinkWidth.Flexible
80
81
  }, (0, _core.jsx)(_elements.Title, (0, _extends2.default)({
81
82
  maxLines: maxLines,
82
- theme: theme
83
+ theme: theme,
84
+ onClick: onClick
83
85
  }, overrideText)), subtitleElements && (0, _core.jsx)(_elementGroup.default, {
84
86
  direction: _constants.SmartLinkDirection.Horizontal
85
87
  }, subtitleElements)), metadataElements && (0, _core.jsx)(_elementGroup.default, {
@@ -63,11 +63,12 @@ var getContainerStyles = function getContainerStyles(size, hideBackground, hideE
63
63
 
64
64
  exports.getContainerStyles = getContainerStyles;
65
65
 
66
- var renderChildren = function renderChildren(children, containerSize, containerTheme, status, retry) {
66
+ var renderChildren = function renderChildren(children, containerSize, containerTheme, status, retry, onClick) {
67
67
  return _react.default.Children.map(children, function (child) {
68
68
  if ( /*#__PURE__*/_react.default.isValidElement(child) && (0, _flexible.isFlexibleUiBlock)(child)) {
69
69
  var blockSize = child.props.size;
70
70
  return /*#__PURE__*/_react.default.cloneElement(child, {
71
+ onClick: onClick,
71
72
  retry: (0, _flexible.isFlexibleUiTitleBlock)(child) ? retry : undefined,
72
73
  size: blockSize || containerSize,
73
74
  status: status,
@@ -92,12 +93,13 @@ var Container = function Container(_ref) {
92
93
  _ref$testId = _ref.testId,
93
94
  testId = _ref$testId === void 0 ? 'smart-links-container' : _ref$testId,
94
95
  _ref$theme = _ref.theme,
95
- theme = _ref$theme === void 0 ? _constants.SmartLinkTheme.Link : _ref$theme;
96
+ theme = _ref$theme === void 0 ? _constants.SmartLinkTheme.Link : _ref$theme,
97
+ onClick = _ref.onClick;
96
98
  return (0, _core.jsx)("div", {
97
99
  css: getContainerStyles(size, hideBackground, hideElevation, hidePadding),
98
100
  "data-smart-link-container": true,
99
101
  "data-testid": testId
100
- }, renderChildren(children, size, theme, status, retry));
102
+ }, renderChildren(children, size, theme, status, retry, onClick));
101
103
  };
102
104
 
103
105
  var _default = Container;
@@ -66,7 +66,8 @@ var Link = function Link(_ref) {
66
66
  text = _ref.text,
67
67
  _ref$theme = _ref.theme,
68
68
  theme = _ref$theme === void 0 ? _constants.SmartLinkTheme.Link : _ref$theme,
69
- url = _ref.url;
69
+ url = _ref.url,
70
+ onClick = _ref.onClick;
70
71
  return (0, _core.jsx)("span", {
71
72
  css: containerStyles
72
73
  }, (0, _core.jsx)(_tooltip.default, {
@@ -77,6 +78,7 @@ var Link = function Link(_ref) {
77
78
  css: getAnchorStyles(size, theme, getMaxLines(maxLines)),
78
79
  "data-smart-element-link": true,
79
80
  "data-testid": testId,
81
+ onClick: onClick,
80
82
  href: url
81
83
  }, text)));
82
84
  };
@@ -17,9 +17,17 @@ var _imageIcon = _interopRequireDefault(require("../../common/image-icon"));
17
17
 
18
18
  var _templateObject;
19
19
 
20
- var styles = function styles(url) {
21
- return (0, _core.css)(_templateObject || (_templateObject = (0, _taggedTemplateLiteral2.default)(["\n display: flex;\n justify-content: center;\n width: 100%;\n > img {\n max-width: 100%;\n max-height: 100%;\n }\n"])));
22
- };
20
+ /**
21
+ * Media: Image
22
+ * [aspect-ratio: 16 / 9] The context box is fixed to aspect ratio of 16:9.
23
+ * [object-fit: cover] The replaced content is sized to maintain
24
+ * its aspect ratio while filling the element's entire content box.
25
+ * If the object's aspect ratio does not match the aspect ratio of its box,
26
+ * then the object will be clipped to fit.
27
+ * [object-position] Center alignment of the selected replaced element's
28
+ * contents within the element's box.
29
+ */
30
+ var styles = (0, _core.css)(_templateObject || (_templateObject = (0, _taggedTemplateLiteral2.default)(["\n aspect-ratio: 16 / 9;\n display: flex;\n width: 100%;\n\n // fallback\n @supports not (aspect-ratio: auto) {\n padding-top: 56.25%; // 16:9 ratio (9 / 16 = 0.5625)\n height: 0;\n position: relative;\n overflow: hidden;\n }\n\n > img {\n min-height: 100%;\n min-width: 100%;\n max-height: 100%;\n max-width: 100%;\n object-fit: cover;\n object-position: center center;\n\n // fallback\n @supports not (aspect-ratio: auto) {\n position: absolute;\n transform: translate(-50%, -50%);\n left: 50%;\n top: 50%;\n width: auto;\n height: auto;\n }\n }\n"])));
23
31
 
24
32
  var Media = function Media(_ref) {
25
33
  var _ref$testId = _ref.testId,
@@ -32,7 +40,7 @@ var Media = function Media(_ref) {
32
40
  }
33
41
 
34
42
  return (0, _core.jsx)("div", {
35
- css: styles(url),
43
+ css: styles,
36
44
  "data-smart-element-media": true,
37
45
  "data-testid": testId
38
46
  }, (0, _core.jsx)(_imageIcon.default, {
@@ -23,7 +23,9 @@ var FlexibleCard = function FlexibleCard(_ref) {
23
23
  onAuthorize = _ref.onAuthorize,
24
24
  renderers = _ref.renderers,
25
25
  ui = _ref.ui,
26
- url = _ref.url;
26
+ url = _ref.url,
27
+ onClick = _ref.onClick,
28
+ testId = _ref.testId;
27
29
  var cardType = cardState.status,
28
30
  details = cardState.details;
29
31
  var status = cardType;
@@ -31,9 +33,12 @@ var FlexibleCard = function FlexibleCard(_ref) {
31
33
  var retry = (0, _utils.getRetryOptions)(url, status, details, onAuthorize);
32
34
  return /*#__PURE__*/_react.default.createElement(_flexibleUiContext.FlexibleUiContext.Provider, {
33
35
  value: context
34
- }, /*#__PURE__*/_react.default.createElement(_container.default, (0, _extends2.default)({}, ui, {
36
+ }, /*#__PURE__*/_react.default.createElement(_container.default, (0, _extends2.default)({
37
+ testId: testId
38
+ }, ui, {
35
39
  retry: retry,
36
- status: status
40
+ status: status,
41
+ onClick: onClick
37
42
  }), children));
38
43
  };
39
44
 
@@ -0,0 +1 @@
1
+ export { useSmartLinkActions } from './state/hooks-external/useSmartLinkActions';
@@ -5,7 +5,7 @@ export const useSmartLinkAnalytics = dispatchAnalytics => {
5
5
  const ui = useMemo(() => ({
6
6
  authEvent: (display, definitionId, extensionKey) => dispatchAnalytics(uiAuthEvent(display, definitionId, extensionKey)),
7
7
  authAlternateAccountEvent: (display, definitionId, extensionKey) => dispatchAnalytics(uiAuthAlternateAccountEvent(display, definitionId, extensionKey)),
8
- cardClickedEvent: (display, definitionId, extensionKey) => dispatchAnalytics(uiCardClickedEvent(display, definitionId, extensionKey)),
8
+ cardClickedEvent: (display, definitionId, extensionKey, isModifierKeyPressed) => dispatchAnalytics(uiCardClickedEvent(display, definitionId, extensionKey, isModifierKeyPressed)),
9
9
  actionClickedEvent: (id, extensionKey, actionType, display, invokeType) => {
10
10
  startUfoExperience('smart-link-action-invocation', id, {
11
11
  actionType,
@@ -0,0 +1,42 @@
1
+ import { useEffect, useMemo, useState } from 'react';
2
+ import uuid from 'uuid';
3
+ import { extractBlockProps as extractCardProps } from '../../extractors/block';
4
+ import { useSmartCardActions as useLinkActions } from '../actions';
5
+ import { useSmartLinkAnalytics as useLinkAnalytics } from '../analytics';
6
+ import { useSmartCardState as useLinkState } from '../store';
7
+ import { getExtensionKey } from '../helpers';
8
+ export function useSmartLinkActions({
9
+ url,
10
+ appearance,
11
+ analyticsHandler,
12
+ platform = 'web'
13
+ }) {
14
+ const id = useMemo(() => uuid(), []);
15
+ const [actions, setActions] = useState([]);
16
+ const linkState = useLinkState(url);
17
+ const linkAnalytics = useLinkAnalytics(analyticsHandler);
18
+ const linkActions = useLinkActions(id, url, linkAnalytics);
19
+ useEffect(() => {
20
+ if (!linkState.details) {
21
+ return;
22
+ }
23
+
24
+ const cardProperties = extractCardProps(linkState.details.data, linkState.details.meta, {
25
+ handleInvoke: opts => linkActions.invoke(opts, appearance),
26
+ handleAnalytics: analyticsHandler,
27
+ extensionKey: getExtensionKey(linkState.details)
28
+ }, undefined, platform);
29
+
30
+ if (!cardProperties.actions || cardProperties.actions.length === 0) {
31
+ return;
32
+ }
33
+
34
+ const cardActions = cardProperties.actions.map(action => ({
35
+ id: action.id,
36
+ text: action.text,
37
+ invoke: action.promise
38
+ }));
39
+ setActions(cardActions);
40
+ }, [linkState, linkActions, analyticsHandler, appearance, platform]);
41
+ return actions;
42
+ }
@@ -169,14 +169,15 @@ export const uiAuthAlternateAccountEvent = (display, definitionId, extensionKey)
169
169
  display
170
170
  }
171
171
  });
172
- export const uiCardClickedEvent = (display, definitionId, extensionKey) => ({
172
+ export const uiCardClickedEvent = (display, definitionId, extensionKey, isModifierKeyPressed) => ({
173
173
  action: 'clicked',
174
174
  actionSubject: 'smartLink',
175
175
  eventType: 'ui',
176
176
  attributes: { ...context,
177
177
  definitionId: definitionId || '',
178
178
  extensionKey: extensionKey || '',
179
- display
179
+ display,
180
+ isModifierKeyPressed
180
181
  }
181
182
  });
182
183
  export const uiActionClickedEvent = (extensionKey, actionType, display) => ({
@@ -1,4 +1,9 @@
1
1
  import CardClient from '../client';
2
+ export const mockContext = {
3
+ '@vocab': 'https://www.w3.org/ns/activitystreams#',
4
+ atlassian: 'https://schema.atlassian.com/ns/vocabulary#',
5
+ schema: 'http://schema.org/'
6
+ };
2
7
  export const mocks = {
3
8
  success: {
4
9
  meta: {
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/smart-card",
3
- "version": "17.7.6",
3
+ "version": "17.7.9",
4
4
  "sideEffects": false
5
5
  }
@@ -25,7 +25,7 @@ export const BlockCard = ({
25
25
  handleAuthorize,
26
26
  handleErrorRetry,
27
27
  handleFrameClick,
28
- handlePreviewAnalytics,
28
+ handleAnalytics,
29
29
  handleInvoke,
30
30
  renderers,
31
31
  isSelected,
@@ -39,7 +39,7 @@ export const BlockCard = ({
39
39
  const data = details && details.data || getEmptyJsonLd();
40
40
  const meta = details && details.meta;
41
41
  const extractorOpts = {
42
- handleAnalytics: handlePreviewAnalytics,
42
+ handleAnalytics,
43
43
  handleInvoke,
44
44
  extensionKey: getExtensionKey(details)
45
45
  };
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useCallback } from 'react';
1
+ import React, { useEffect, useCallback, useMemo } from 'react';
2
2
  import { isSpecialEvent } from '../../utils';
3
3
  import * as measure from '../../utils/performance';
4
4
  import { getDefinitionId, getServices, isFinalState, getClickUrl, getResourceType, getExtensionKey } from '../../state/helpers';
@@ -38,7 +38,8 @@ export function CardWithUrlContent({
38
38
  const definitionId = getDefinitionId(state.details);
39
39
  const extensionKey = getExtensionKey(state.details);
40
40
  const resourceType = getResourceType(state.details);
41
- const services = getServices(state.details); // Setup UI handlers.
41
+ const services = getServices(state.details);
42
+ let isFlexibleUi = useMemo(() => isFlexibleUiCard(children), [children]); // Setup UI handlers.
42
43
 
43
44
  const handleClick = useCallback(event => {
44
45
  const clickUrl = getClickUrl(url, state.details);
@@ -46,11 +47,12 @@ export function CardWithUrlContent({
46
47
  }, [state.details, url]);
47
48
  const handleClickWrapper = useCallback(event => {
48
49
  if (state.status === 'resolved') {
49
- analytics.ui.cardClickedEvent(appearance, definitionId, extensionKey);
50
+ const isModifierKeyPressed = isSpecialEvent(event);
51
+ analytics.ui.cardClickedEvent(isFlexibleUi ? 'flexible' : appearance, definitionId, extensionKey, isModifierKeyPressed);
50
52
  }
51
53
 
52
54
  onClick ? onClick(event) : handleClick(event);
53
- }, [state.status, analytics.ui, appearance, definitionId, extensionKey, onClick, handleClick]);
55
+ }, [state.status, analytics.ui, appearance, definitionId, extensionKey, onClick, handleClick, isFlexibleUi]);
54
56
  const handleAuthorize = useCallback(() => actions.authorize(appearance), [actions, appearance]);
55
57
  const handleRetry = useCallback(() => {
56
58
  actions.reload();
@@ -80,13 +82,15 @@ export function CardWithUrlContent({
80
82
  throw error;
81
83
  }
82
84
 
83
- if (isFlexibleUiCard(children)) {
85
+ if (isFlexibleUi) {
84
86
  return /*#__PURE__*/React.createElement(FlexibleCard, {
85
87
  cardState: state,
86
88
  onAuthorize: services.length && handleAuthorize || undefined,
89
+ onClick: handleClickWrapper,
87
90
  renderers: renderers,
88
91
  ui: ui,
89
- url: url
92
+ url: url,
93
+ testId: testId
90
94
  }, children);
91
95
  }
92
96
 
@@ -114,7 +118,7 @@ export function CardWithUrlContent({
114
118
  handleErrorRetry: handleRetry,
115
119
  handleInvoke: handleInvoke,
116
120
  handleFrameClick: handleClickWrapper,
117
- handlePreviewAnalytics: dispatchAnalytics,
121
+ handleAnalytics: dispatchAnalytics,
118
122
  isSelected: isSelected,
119
123
  onResolve: onResolve,
120
124
  testId: testId,
@@ -29,6 +29,7 @@ const TitleBlockResolvedView = ({
29
29
  actions = [],
30
30
  testId,
31
31
  theme,
32
+ onClick,
32
33
  text,
33
34
  showActionOnHover,
34
35
  ...blockProps
@@ -50,7 +51,8 @@ const TitleBlockResolvedView = ({
50
51
  width: SmartLinkWidth.Flexible
51
52
  }, jsx(Title, _extends({
52
53
  maxLines: maxLines,
53
- theme: theme
54
+ theme: theme,
55
+ onClick: onClick
54
56
  }, overrideText)), subtitleElements && jsx(ElementGroup, {
55
57
  direction: SmartLinkDirection.Horizontal
56
58
  }, subtitleElements)), metadataElements && jsx(ElementGroup, {
@@ -56,12 +56,13 @@ export const getContainerStyles = (size, hideBackground, hideElevation, hidePadd
56
56
  ${hideElevation ? '' : elevationStyles}
57
57
  `;
58
58
 
59
- const renderChildren = (children, containerSize, containerTheme, status, retry) => React.Children.map(children, child => {
59
+ const renderChildren = (children, containerSize, containerTheme, status, retry, onClick) => React.Children.map(children, child => {
60
60
  if ( /*#__PURE__*/React.isValidElement(child) && isFlexibleUiBlock(child)) {
61
61
  const {
62
62
  size: blockSize
63
63
  } = child.props;
64
64
  return /*#__PURE__*/React.cloneElement(child, {
65
+ onClick,
65
66
  retry: isFlexibleUiTitleBlock(child) ? retry : undefined,
66
67
  size: blockSize || containerSize,
67
68
  status,
@@ -79,11 +80,12 @@ const Container = ({
79
80
  size = SmartLinkSize.Medium,
80
81
  status,
81
82
  testId = 'smart-links-container',
82
- theme = SmartLinkTheme.Link
83
+ theme = SmartLinkTheme.Link,
84
+ onClick
83
85
  }) => jsx("div", {
84
86
  css: getContainerStyles(size, hideBackground, hideElevation, hidePadding),
85
87
  "data-smart-link-container": true,
86
88
  "data-testid": testId
87
- }, renderChildren(children, size, theme, status, retry));
89
+ }, renderChildren(children, size, theme, status, retry, onClick));
88
90
 
89
91
  export default Container;
@@ -70,7 +70,8 @@ const Link = ({
70
70
  testId = 'smart-element-link',
71
71
  text,
72
72
  theme = SmartLinkTheme.Link,
73
- url
73
+ url,
74
+ onClick
74
75
  }) => jsx("span", {
75
76
  css: containerStyles
76
77
  }, jsx(Tooltip, {
@@ -81,6 +82,7 @@ const Link = ({
81
82
  css: getAnchorStyles(size, theme, getMaxLines(maxLines)),
82
83
  "data-smart-element-link": true,
83
84
  "data-testid": testId,
85
+ onClick: onClick,
84
86
  href: url
85
87
  }, text)));
86
88