@atlaskit/smart-card 17.7.5 → 17.7.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -0
- package/dist/cjs/hooks.js +13 -0
- package/dist/cjs/state/analytics/useSmartLinkAnalytics.js +2 -2
- package/dist/cjs/state/hooks-external/useSmartLinkActions.js +71 -0
- package/dist/cjs/utils/analytics/analytics.js +3 -2
- package/dist/cjs/utils/mocks.js +7 -1
- package/dist/cjs/version.json +1 -1
- package/dist/cjs/view/BlockCard/index.js +2 -2
- package/dist/cjs/view/CardWithUrl/component.js +12 -6
- package/dist/cjs/view/FlexibleCard/components/blocks/title-block/resolved/index.js +4 -2
- package/dist/cjs/view/FlexibleCard/components/container/index.js +5 -3
- package/dist/cjs/view/FlexibleCard/components/elements/link/index.js +3 -1
- package/dist/cjs/view/FlexibleCard/index.js +8 -3
- package/dist/es2019/hooks.js +1 -0
- package/dist/es2019/state/analytics/useSmartLinkAnalytics.js +1 -1
- package/dist/es2019/state/hooks-external/useSmartLinkActions.js +42 -0
- package/dist/es2019/utils/analytics/analytics.js +3 -2
- package/dist/es2019/utils/mocks.js +5 -0
- package/dist/es2019/version.json +1 -1
- package/dist/es2019/view/BlockCard/index.js +2 -2
- package/dist/es2019/view/CardWithUrl/component.js +11 -7
- package/dist/es2019/view/FlexibleCard/components/blocks/title-block/resolved/index.js +3 -1
- package/dist/es2019/view/FlexibleCard/components/container/index.js +5 -3
- package/dist/es2019/view/FlexibleCard/components/elements/link/index.js +3 -1
- package/dist/es2019/view/FlexibleCard/index.js +8 -3
- package/dist/esm/hooks.js +1 -0
- package/dist/esm/state/analytics/useSmartLinkAnalytics.js +2 -2
- package/dist/esm/state/hooks-external/useSmartLinkActions.js +54 -0
- package/dist/esm/utils/analytics/analytics.js +3 -2
- package/dist/esm/utils/mocks.js +5 -0
- package/dist/esm/version.json +1 -1
- package/dist/esm/view/BlockCard/index.js +2 -2
- package/dist/esm/view/CardWithUrl/component.js +13 -7
- package/dist/esm/view/FlexibleCard/components/blocks/title-block/resolved/index.js +4 -2
- package/dist/esm/view/FlexibleCard/components/container/index.js +5 -3
- package/dist/esm/view/FlexibleCard/components/elements/link/index.js +3 -1
- package/dist/esm/view/FlexibleCard/index.js +8 -3
- package/dist/types/hooks.d.ts +1 -0
- package/dist/types/state/analytics/useSmartLinkAnalytics.d.ts +1 -1
- package/dist/types/state/hooks/useSmartLink.d.ts +1 -1
- package/dist/types/state/hooks-external/useSmartLinkActions.d.ts +45 -0
- package/dist/types/utils/analytics/analytics.d.ts +2 -2
- package/dist/types/utils/mocks.d.ts +5 -0
- package/dist/types/view/BlockCard/types.d.ts +1 -1
- package/dist/types/view/Card/types.d.ts +1 -1
- package/dist/types/view/FlexibleCard/components/blocks/title-block/types.d.ts +2 -0
- package/dist/types/view/FlexibleCard/components/container/types.d.ts +2 -0
- package/dist/types/view/FlexibleCard/components/elements/link/types.d.ts +2 -0
- package/dist/types/view/FlexibleCard/types.d.ts +1 -0
- package/hooks/package.json +7 -0
- package/package.json +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,49 @@
|
|
|
1
1
|
# @atlaskit/smart-card
|
|
2
2
|
|
|
3
|
+
## 17.7.8
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`d75ce5b847d`](https://bitbucket.org/atlassian/atlassian-frontend/commits/d75ce5b847d) - Add link click analytics to flexible ui title block component
|
|
8
|
+
|
|
9
|
+
## 17.7.7
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [`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.
|
|
14
|
+
|
|
15
|
+
Example usage:
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { useSmartLinkActions } from '@atlaskit/smart-card/hooks';
|
|
19
|
+
|
|
20
|
+
const ExampleToolbar = () => {
|
|
21
|
+
const actions = useSmartLinkActions({
|
|
22
|
+
url,
|
|
23
|
+
appearance: 'block',
|
|
24
|
+
analyticsHandler: analytics,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<ExampleToolbarWrapper>
|
|
29
|
+
{actions.map((action) => (
|
|
30
|
+
<Tooltip content={action.text}>
|
|
31
|
+
<ExampleToolbarItem key={action.id} onClick={action.invoke}>
|
|
32
|
+
{idToIcon[action.id] ?? action.id}
|
|
33
|
+
</ExampleToolbarItem>
|
|
34
|
+
</Tooltip>
|
|
35
|
+
))}
|
|
36
|
+
</ExampleToolbarWrapper>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## 17.7.6
|
|
42
|
+
|
|
43
|
+
### Patch Changes
|
|
44
|
+
|
|
45
|
+
- [`0e5c8b501d6`](https://bitbucket.org/atlassian/atlassian-frontend/commits/0e5c8b501d6) - add test for when hover preview prop is not provided to inline card
|
|
46
|
+
|
|
3
47
|
## 17.7.5
|
|
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
|
};
|
package/dist/cjs/utils/mocks.js
CHANGED
|
@@ -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: {
|
package/dist/cjs/version.json
CHANGED
|
@@ -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
|
-
|
|
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:
|
|
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);
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
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
|
};
|
|
@@ -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)({
|
|
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: {
|
package/dist/es2019/version.json
CHANGED
|
@@ -25,7 +25,7 @@ export const BlockCard = ({
|
|
|
25
25
|
handleAuthorize,
|
|
26
26
|
handleErrorRetry,
|
|
27
27
|
handleFrameClick,
|
|
28
|
-
|
|
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
|
|
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);
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
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
|
|
|
@@ -10,7 +10,9 @@ const FlexibleCard = ({
|
|
|
10
10
|
onAuthorize,
|
|
11
11
|
renderers,
|
|
12
12
|
ui,
|
|
13
|
-
url
|
|
13
|
+
url,
|
|
14
|
+
onClick,
|
|
15
|
+
testId
|
|
14
16
|
}) => {
|
|
15
17
|
const {
|
|
16
18
|
status: cardType,
|
|
@@ -21,9 +23,12 @@ const FlexibleCard = ({
|
|
|
21
23
|
const retry = getRetryOptions(url, status, details, onAuthorize);
|
|
22
24
|
return /*#__PURE__*/React.createElement(FlexibleUiContext.Provider, {
|
|
23
25
|
value: context
|
|
24
|
-
}, /*#__PURE__*/React.createElement(Container, _extends({
|
|
26
|
+
}, /*#__PURE__*/React.createElement(Container, _extends({
|
|
27
|
+
testId: testId
|
|
28
|
+
}, ui, {
|
|
25
29
|
retry: retry,
|
|
26
|
-
status: status
|
|
30
|
+
status: status,
|
|
31
|
+
onClick: onClick
|
|
27
32
|
}), children));
|
|
28
33
|
};
|
|
29
34
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useSmartLinkActions } from './state/hooks-external/useSmartLinkActions';
|
|
@@ -10,8 +10,8 @@ export var useSmartLinkAnalytics = function useSmartLinkAnalytics(dispatchAnalyt
|
|
|
10
10
|
authAlternateAccountEvent: function authAlternateAccountEvent(display, definitionId, extensionKey) {
|
|
11
11
|
return dispatchAnalytics(uiAuthAlternateAccountEvent(display, definitionId, extensionKey));
|
|
12
12
|
},
|
|
13
|
-
cardClickedEvent: function cardClickedEvent(display, definitionId, extensionKey) {
|
|
14
|
-
return dispatchAnalytics(uiCardClickedEvent(display, definitionId, extensionKey));
|
|
13
|
+
cardClickedEvent: function cardClickedEvent(display, definitionId, extensionKey, isModifierKeyPressed) {
|
|
14
|
+
return dispatchAnalytics(uiCardClickedEvent(display, definitionId, extensionKey, isModifierKeyPressed));
|
|
15
15
|
},
|
|
16
16
|
actionClickedEvent: function actionClickedEvent(id, extensionKey, actionType, display, invokeType) {
|
|
17
17
|
startUfoExperience('smart-link-action-invocation', id, {
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
2
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
3
|
+
import uuid from 'uuid';
|
|
4
|
+
import { extractBlockProps as extractCardProps } from '../../extractors/block';
|
|
5
|
+
import { useSmartCardActions as useLinkActions } from '../actions';
|
|
6
|
+
import { useSmartLinkAnalytics as useLinkAnalytics } from '../analytics';
|
|
7
|
+
import { useSmartCardState as useLinkState } from '../store';
|
|
8
|
+
import { getExtensionKey } from '../helpers';
|
|
9
|
+
export function useSmartLinkActions(_ref) {
|
|
10
|
+
var url = _ref.url,
|
|
11
|
+
appearance = _ref.appearance,
|
|
12
|
+
analyticsHandler = _ref.analyticsHandler,
|
|
13
|
+
_ref$platform = _ref.platform,
|
|
14
|
+
platform = _ref$platform === void 0 ? 'web' : _ref$platform;
|
|
15
|
+
var id = useMemo(function () {
|
|
16
|
+
return uuid();
|
|
17
|
+
}, []);
|
|
18
|
+
|
|
19
|
+
var _useState = useState([]),
|
|
20
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
21
|
+
actions = _useState2[0],
|
|
22
|
+
setActions = _useState2[1];
|
|
23
|
+
|
|
24
|
+
var linkState = useLinkState(url);
|
|
25
|
+
var linkAnalytics = useLinkAnalytics(analyticsHandler);
|
|
26
|
+
var linkActions = useLinkActions(id, url, linkAnalytics);
|
|
27
|
+
useEffect(function () {
|
|
28
|
+
if (!linkState.details) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
var cardProperties = extractCardProps(linkState.details.data, linkState.details.meta, {
|
|
33
|
+
handleInvoke: function handleInvoke(opts) {
|
|
34
|
+
return linkActions.invoke(opts, appearance);
|
|
35
|
+
},
|
|
36
|
+
handleAnalytics: analyticsHandler,
|
|
37
|
+
extensionKey: getExtensionKey(linkState.details)
|
|
38
|
+
}, undefined, platform);
|
|
39
|
+
|
|
40
|
+
if (!cardProperties.actions || cardProperties.actions.length === 0) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
var cardActions = cardProperties.actions.map(function (action) {
|
|
45
|
+
return {
|
|
46
|
+
id: action.id,
|
|
47
|
+
text: action.text,
|
|
48
|
+
invoke: action.promise
|
|
49
|
+
};
|
|
50
|
+
});
|
|
51
|
+
setActions(cardActions);
|
|
52
|
+
}, [linkState, linkActions, analyticsHandler, appearance, platform]);
|
|
53
|
+
return actions;
|
|
54
|
+
}
|
|
@@ -182,7 +182,7 @@ export var uiAuthAlternateAccountEvent = function uiAuthAlternateAccountEvent(di
|
|
|
182
182
|
})
|
|
183
183
|
};
|
|
184
184
|
};
|
|
185
|
-
export var uiCardClickedEvent = function uiCardClickedEvent(display, definitionId, extensionKey) {
|
|
185
|
+
export var uiCardClickedEvent = function uiCardClickedEvent(display, definitionId, extensionKey, isModifierKeyPressed) {
|
|
186
186
|
return {
|
|
187
187
|
action: 'clicked',
|
|
188
188
|
actionSubject: 'smartLink',
|
|
@@ -190,7 +190,8 @@ export var uiCardClickedEvent = function uiCardClickedEvent(display, definitionI
|
|
|
190
190
|
attributes: _objectSpread(_objectSpread({}, context), {}, {
|
|
191
191
|
definitionId: definitionId || '',
|
|
192
192
|
extensionKey: extensionKey || '',
|
|
193
|
-
display: display
|
|
193
|
+
display: display,
|
|
194
|
+
isModifierKeyPressed: isModifierKeyPressed
|
|
194
195
|
})
|
|
195
196
|
};
|
|
196
197
|
};
|
package/dist/esm/utils/mocks.js
CHANGED
|
@@ -11,6 +11,11 @@ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflec
|
|
|
11
11
|
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; } }
|
|
12
12
|
|
|
13
13
|
import CardClient from '../client';
|
|
14
|
+
export var mockContext = {
|
|
15
|
+
'@vocab': 'https://www.w3.org/ns/activitystreams#',
|
|
16
|
+
atlassian: 'https://schema.atlassian.com/ns/vocabulary#',
|
|
17
|
+
schema: 'http://schema.org/'
|
|
18
|
+
};
|
|
14
19
|
export var mocks = {
|
|
15
20
|
success: {
|
|
16
21
|
meta: {
|
package/dist/esm/version.json
CHANGED
|
@@ -26,7 +26,7 @@ export var BlockCard = function BlockCard(_ref) {
|
|
|
26
26
|
handleAuthorize = _ref.handleAuthorize,
|
|
27
27
|
handleErrorRetry = _ref.handleErrorRetry,
|
|
28
28
|
handleFrameClick = _ref.handleFrameClick,
|
|
29
|
-
|
|
29
|
+
handleAnalytics = _ref.handleAnalytics,
|
|
30
30
|
handleInvoke = _ref.handleInvoke,
|
|
31
31
|
renderers = _ref.renderers,
|
|
32
32
|
isSelected = _ref.isSelected,
|
|
@@ -37,7 +37,7 @@ export var BlockCard = function BlockCard(_ref) {
|
|
|
37
37
|
var data = details && details.data || getEmptyJsonLd();
|
|
38
38
|
var meta = details && details.meta;
|
|
39
39
|
var extractorOpts = {
|
|
40
|
-
handleAnalytics:
|
|
40
|
+
handleAnalytics: handleAnalytics,
|
|
41
41
|
handleInvoke: handleInvoke,
|
|
42
42
|
extensionKey: getExtensionKey(details)
|
|
43
43
|
};
|
|
@@ -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,10 @@ export function CardWithUrlContent(_ref) {
|
|
|
38
38
|
var definitionId = getDefinitionId(state.details);
|
|
39
39
|
var extensionKey = getExtensionKey(state.details);
|
|
40
40
|
var resourceType = getResourceType(state.details);
|
|
41
|
-
var services = getServices(state.details);
|
|
41
|
+
var services = getServices(state.details);
|
|
42
|
+
var isFlexibleUi = useMemo(function () {
|
|
43
|
+
return isFlexibleUiCard(children);
|
|
44
|
+
}, [children]); // Setup UI handlers.
|
|
42
45
|
|
|
43
46
|
var handleClick = useCallback(function (event) {
|
|
44
47
|
var clickUrl = getClickUrl(url, state.details);
|
|
@@ -46,11 +49,12 @@ export function CardWithUrlContent(_ref) {
|
|
|
46
49
|
}, [state.details, url]);
|
|
47
50
|
var handleClickWrapper = useCallback(function (event) {
|
|
48
51
|
if (state.status === 'resolved') {
|
|
49
|
-
|
|
52
|
+
var isModifierKeyPressed = isSpecialEvent(event);
|
|
53
|
+
analytics.ui.cardClickedEvent(isFlexibleUi ? 'flexible' : appearance, definitionId, extensionKey, isModifierKeyPressed);
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
onClick ? onClick(event) : handleClick(event);
|
|
53
|
-
}, [state.status, analytics.ui, appearance, definitionId, extensionKey, onClick, handleClick]);
|
|
57
|
+
}, [state.status, analytics.ui, appearance, definitionId, extensionKey, onClick, handleClick, isFlexibleUi]);
|
|
54
58
|
var handleAuthorize = useCallback(function () {
|
|
55
59
|
return actions.authorize(appearance);
|
|
56
60
|
}, [actions, appearance]);
|
|
@@ -84,13 +88,15 @@ export function CardWithUrlContent(_ref) {
|
|
|
84
88
|
throw error;
|
|
85
89
|
}
|
|
86
90
|
|
|
87
|
-
if (
|
|
91
|
+
if (isFlexibleUi) {
|
|
88
92
|
return /*#__PURE__*/React.createElement(FlexibleCard, {
|
|
89
93
|
cardState: state,
|
|
90
94
|
onAuthorize: services.length && handleAuthorize || undefined,
|
|
95
|
+
onClick: handleClickWrapper,
|
|
91
96
|
renderers: renderers,
|
|
92
97
|
ui: ui,
|
|
93
|
-
url: url
|
|
98
|
+
url: url,
|
|
99
|
+
testId: testId
|
|
94
100
|
}, children);
|
|
95
101
|
}
|
|
96
102
|
|
|
@@ -118,7 +124,7 @@ export function CardWithUrlContent(_ref) {
|
|
|
118
124
|
handleErrorRetry: handleRetry,
|
|
119
125
|
handleInvoke: handleInvoke,
|
|
120
126
|
handleFrameClick: handleClickWrapper,
|
|
121
|
-
|
|
127
|
+
handleAnalytics: dispatchAnalytics,
|
|
122
128
|
isSelected: isSelected,
|
|
123
129
|
onResolve: onResolve,
|
|
124
130
|
testId: testId,
|
|
@@ -2,7 +2,7 @@ import _extends from "@babel/runtime/helpers/extends";
|
|
|
2
2
|
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
3
3
|
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
|
|
4
4
|
import _taggedTemplateLiteral from "@babel/runtime/helpers/taggedTemplateLiteral";
|
|
5
|
-
var _excluded = ["maxLines", "metadata", "position", "subtitle", "actions", "testId", "theme", "text", "showActionOnHover"];
|
|
5
|
+
var _excluded = ["maxLines", "metadata", "position", "subtitle", "actions", "testId", "theme", "onClick", "text", "showActionOnHover"];
|
|
6
6
|
|
|
7
7
|
var _templateObject;
|
|
8
8
|
|
|
@@ -28,6 +28,7 @@ var TitleBlockResolvedView = function TitleBlockResolvedView(_ref) {
|
|
|
28
28
|
actions = _ref$actions === void 0 ? [] : _ref$actions,
|
|
29
29
|
testId = _ref.testId,
|
|
30
30
|
theme = _ref.theme,
|
|
31
|
+
onClick = _ref.onClick,
|
|
31
32
|
text = _ref.text,
|
|
32
33
|
showActionOnHover = _ref.showActionOnHover,
|
|
33
34
|
blockProps = _objectWithoutProperties(_ref, _excluded);
|
|
@@ -53,7 +54,8 @@ var TitleBlockResolvedView = function TitleBlockResolvedView(_ref) {
|
|
|
53
54
|
width: SmartLinkWidth.Flexible
|
|
54
55
|
}, jsx(Title, _extends({
|
|
55
56
|
maxLines: maxLines,
|
|
56
|
-
theme: theme
|
|
57
|
+
theme: theme,
|
|
58
|
+
onClick: onClick
|
|
57
59
|
}, overrideText)), subtitleElements && jsx(ElementGroup, {
|
|
58
60
|
direction: SmartLinkDirection.Horizontal
|
|
59
61
|
}, subtitleElements)), metadataElements && jsx(ElementGroup, {
|
|
@@ -48,11 +48,12 @@ export var getContainerStyles = function getContainerStyles(size, hideBackground
|
|
|
48
48
|
return css(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n display: flex;\n gap: ", " 0;\n flex-direction: column;\n min-width: 0;\n overflow: hidden;\n ", "\n ", "\n ", "\n"])), getGap(size), hideBackground ? '' : "background-color: ".concat(tokens.background, ";"), hidePadding ? '' : "padding: ".concat(getPadding(size), ";"), hideElevation ? '' : elevationStyles);
|
|
49
49
|
};
|
|
50
50
|
|
|
51
|
-
var renderChildren = function renderChildren(children, containerSize, containerTheme, status, retry) {
|
|
51
|
+
var renderChildren = function renderChildren(children, containerSize, containerTheme, status, retry, onClick) {
|
|
52
52
|
return React.Children.map(children, function (child) {
|
|
53
53
|
if ( /*#__PURE__*/React.isValidElement(child) && isFlexibleUiBlock(child)) {
|
|
54
54
|
var blockSize = child.props.size;
|
|
55
55
|
return /*#__PURE__*/React.cloneElement(child, {
|
|
56
|
+
onClick: onClick,
|
|
56
57
|
retry: isFlexibleUiTitleBlock(child) ? retry : undefined,
|
|
57
58
|
size: blockSize || containerSize,
|
|
58
59
|
status: status,
|
|
@@ -77,12 +78,13 @@ var Container = function Container(_ref) {
|
|
|
77
78
|
_ref$testId = _ref.testId,
|
|
78
79
|
testId = _ref$testId === void 0 ? 'smart-links-container' : _ref$testId,
|
|
79
80
|
_ref$theme = _ref.theme,
|
|
80
|
-
theme = _ref$theme === void 0 ? SmartLinkTheme.Link : _ref$theme
|
|
81
|
+
theme = _ref$theme === void 0 ? SmartLinkTheme.Link : _ref$theme,
|
|
82
|
+
onClick = _ref.onClick;
|
|
81
83
|
return jsx("div", {
|
|
82
84
|
css: getContainerStyles(size, hideBackground, hideElevation, hidePadding),
|
|
83
85
|
"data-smart-link-container": true,
|
|
84
86
|
"data-testid": testId
|
|
85
|
-
}, renderChildren(children, size, theme, status, retry));
|
|
87
|
+
}, renderChildren(children, size, theme, status, retry, onClick));
|
|
86
88
|
};
|
|
87
89
|
|
|
88
90
|
export default Container;
|
|
@@ -52,7 +52,8 @@ var Link = function Link(_ref) {
|
|
|
52
52
|
text = _ref.text,
|
|
53
53
|
_ref$theme = _ref.theme,
|
|
54
54
|
theme = _ref$theme === void 0 ? SmartLinkTheme.Link : _ref$theme,
|
|
55
|
-
url = _ref.url
|
|
55
|
+
url = _ref.url,
|
|
56
|
+
onClick = _ref.onClick;
|
|
56
57
|
return jsx("span", {
|
|
57
58
|
css: containerStyles
|
|
58
59
|
}, jsx(Tooltip, {
|
|
@@ -63,6 +64,7 @@ var Link = function Link(_ref) {
|
|
|
63
64
|
css: getAnchorStyles(size, theme, getMaxLines(maxLines)),
|
|
64
65
|
"data-smart-element-link": true,
|
|
65
66
|
"data-testid": testId,
|
|
67
|
+
onClick: onClick,
|
|
66
68
|
href: url
|
|
67
69
|
}, text)));
|
|
68
70
|
};
|
|
@@ -10,7 +10,9 @@ var FlexibleCard = function FlexibleCard(_ref) {
|
|
|
10
10
|
onAuthorize = _ref.onAuthorize,
|
|
11
11
|
renderers = _ref.renderers,
|
|
12
12
|
ui = _ref.ui,
|
|
13
|
-
url = _ref.url
|
|
13
|
+
url = _ref.url,
|
|
14
|
+
onClick = _ref.onClick,
|
|
15
|
+
testId = _ref.testId;
|
|
14
16
|
var cardType = cardState.status,
|
|
15
17
|
details = cardState.details;
|
|
16
18
|
var status = cardType;
|
|
@@ -18,9 +20,12 @@ var FlexibleCard = function FlexibleCard(_ref) {
|
|
|
18
20
|
var retry = getRetryOptions(url, status, details, onAuthorize);
|
|
19
21
|
return /*#__PURE__*/React.createElement(FlexibleUiContext.Provider, {
|
|
20
22
|
value: context
|
|
21
|
-
}, /*#__PURE__*/React.createElement(Container, _extends({
|
|
23
|
+
}, /*#__PURE__*/React.createElement(Container, _extends({
|
|
24
|
+
testId: testId
|
|
25
|
+
}, ui, {
|
|
22
26
|
retry: retry,
|
|
23
|
-
status: status
|
|
27
|
+
status: status,
|
|
28
|
+
onClick: onClick
|
|
24
29
|
}), children));
|
|
25
30
|
};
|
|
26
31
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useSmartLinkActions } from './state/hooks-external/useSmartLinkActions';
|
|
@@ -7,7 +7,7 @@ export declare const useSmartLinkAnalytics: (dispatchAnalytics: AnalyticsHandler
|
|
|
7
7
|
ui: {
|
|
8
8
|
authEvent: (display: CardInnerAppearance, definitionId?: string | undefined, extensionKey?: string | undefined) => void;
|
|
9
9
|
authAlternateAccountEvent: (display: CardInnerAppearance, definitionId?: string | undefined, extensionKey?: string | undefined) => void;
|
|
10
|
-
cardClickedEvent: (display: CardInnerAppearance, definitionId?: string | undefined, extensionKey?: string | undefined) => void;
|
|
10
|
+
cardClickedEvent: (display: CardInnerAppearance, definitionId?: string | undefined, extensionKey?: string | undefined, isModifierKeyPressed?: boolean | undefined) => void;
|
|
11
11
|
actionClickedEvent: (id: string, extensionKey: string, actionType: string, display: CardInnerAppearance, invokeType: InvokeType) => void;
|
|
12
12
|
closedAuthEvent: (display: CardInnerAppearance, definitionId?: string | undefined, extensionKey?: string | undefined) => void;
|
|
13
13
|
renderSuccessEvent: (display: CardInnerAppearance, id: string, definitionId?: string | undefined, extensionKey?: string | undefined) => void;
|
|
@@ -12,7 +12,7 @@ export declare function useSmartLink(id: string, url: string, dispatchAnalytics:
|
|
|
12
12
|
ui: {
|
|
13
13
|
authEvent: (display: import("../../view/Card/types").CardInnerAppearance, definitionId?: string | undefined, extensionKey?: string | undefined) => void;
|
|
14
14
|
authAlternateAccountEvent: (display: import("../../view/Card/types").CardInnerAppearance, definitionId?: string | undefined, extensionKey?: string | undefined) => void;
|
|
15
|
-
cardClickedEvent: (display: import("../../view/Card/types").CardInnerAppearance, definitionId?: string | undefined, extensionKey?: string | undefined) => void;
|
|
15
|
+
cardClickedEvent: (display: import("../../view/Card/types").CardInnerAppearance, definitionId?: string | undefined, extensionKey?: string | undefined, isModifierKeyPressed?: boolean | undefined) => void;
|
|
16
16
|
actionClickedEvent: (id: string, extensionKey: string, actionType: string, display: import("../../view/Card/types").CardInnerAppearance, invokeType: import("../../model/invoke-opts").InvokeType) => void;
|
|
17
17
|
closedAuthEvent: (display: import("../../view/Card/types").CardInnerAppearance, definitionId?: string | undefined, extensionKey?: string | undefined) => void;
|
|
18
18
|
renderSuccessEvent: (display: import("../../view/Card/types").CardInnerAppearance, id: string, definitionId?: string | undefined, extensionKey?: string | undefined) => void;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { JsonLd } from 'json-ld-types';
|
|
3
|
+
import type { AnalyticsHandler } from '../../utils/types';
|
|
4
|
+
import type { CardAppearance } from '../../view/Card/types';
|
|
5
|
+
export interface LinkAction {
|
|
6
|
+
/**
|
|
7
|
+
* Unique ID for the action.
|
|
8
|
+
* @example `delete-action`
|
|
9
|
+
*/
|
|
10
|
+
id: string;
|
|
11
|
+
/**
|
|
12
|
+
* Text to render for the action.
|
|
13
|
+
* @description Use this in tooltips and UI.
|
|
14
|
+
* @example `Delete`.
|
|
15
|
+
*/
|
|
16
|
+
text: React.ReactNode;
|
|
17
|
+
/**
|
|
18
|
+
* Promise to invoke on triggering this action.
|
|
19
|
+
* @example Clicking on `Delete` leading to deletion of content.
|
|
20
|
+
*/
|
|
21
|
+
invoke: () => Promise<any>;
|
|
22
|
+
}
|
|
23
|
+
export interface UseSmartLinkActionsOpts {
|
|
24
|
+
/**
|
|
25
|
+
* Smart Link URL for which actions will be invoked.
|
|
26
|
+
* @example https://start.atlassian.com
|
|
27
|
+
*/
|
|
28
|
+
url: string;
|
|
29
|
+
/**
|
|
30
|
+
* Appearance under which these actions will be invoked.
|
|
31
|
+
* @example `block` for card views.
|
|
32
|
+
*/
|
|
33
|
+
appearance: CardAppearance;
|
|
34
|
+
/**
|
|
35
|
+
* Callback for sending analytics events.
|
|
36
|
+
* @description Accepts an analytics payload and fires it to a system.
|
|
37
|
+
*/
|
|
38
|
+
analyticsHandler: AnalyticsHandler;
|
|
39
|
+
/**
|
|
40
|
+
* Platform on which actions are being invoked.
|
|
41
|
+
* @default 'web'
|
|
42
|
+
*/
|
|
43
|
+
platform?: JsonLd.Primitives.Platforms;
|
|
44
|
+
}
|
|
45
|
+
export declare function useSmartLinkActions({ url, appearance, analyticsHandler, platform, }: UseSmartLinkActionsOpts): LinkAction[];
|
|
@@ -22,8 +22,8 @@ export declare const connectFailedEvent: (definitionId?: string | undefined, ext
|
|
|
22
22
|
export declare const trackAppAccountConnected: (definitionId?: string | undefined, extensionKey?: string | undefined) => AnalyticsPayload;
|
|
23
23
|
export declare const uiAuthEvent: (display: CardInnerAppearance, definitionId?: string | undefined, extensionKey?: string | undefined) => AnalyticsPayload;
|
|
24
24
|
export declare const uiAuthAlternateAccountEvent: (display: CardInnerAppearance, definitionId?: string | undefined, extensionKey?: string | undefined) => AnalyticsPayload;
|
|
25
|
-
export declare const uiCardClickedEvent: (display: CardInnerAppearance, definitionId?: string | undefined, extensionKey?: string | undefined) => AnalyticsPayload;
|
|
26
|
-
export declare const uiActionClickedEvent: (extensionKey: string, actionType: string, display?: "embed" | "block" | "inline" | "preview" | undefined) => AnalyticsPayload;
|
|
25
|
+
export declare const uiCardClickedEvent: (display: CardInnerAppearance, definitionId?: string | undefined, extensionKey?: string | undefined, isModifierKeyPressed?: boolean | undefined) => AnalyticsPayload;
|
|
26
|
+
export declare const uiActionClickedEvent: (extensionKey: string, actionType: string, display?: "embed" | "block" | "inline" | "preview" | "flexible" | undefined) => AnalyticsPayload;
|
|
27
27
|
export declare const uiClosedAuthEvent: (display: CardInnerAppearance, definitionId?: string | undefined, extensionKey?: string | undefined) => AnalyticsPayload;
|
|
28
28
|
export declare const screenAuthPopupEvent: (definitionId?: string | undefined, extensionKey?: string | undefined) => AnalyticsPayload;
|
|
29
29
|
export declare const uiRenderSuccessEvent: (display: CardInnerAppearance, definitionId?: string | undefined, extensionKey?: string | undefined) => AnalyticsPayload;
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { JsonLd } from 'json-ld-types';
|
|
2
|
+
export declare const mockContext: {
|
|
3
|
+
readonly '@vocab': "https://www.w3.org/ns/activitystreams#";
|
|
4
|
+
readonly atlassian: "https://schema.atlassian.com/ns/vocabulary#";
|
|
5
|
+
readonly schema: "http://schema.org/";
|
|
6
|
+
};
|
|
2
7
|
export declare const mocks: {
|
|
3
8
|
success: JsonLd.Response<JsonLd.Data.BaseData>;
|
|
4
9
|
notFound: JsonLd.Response<JsonLd.Data.BaseData>;
|
|
@@ -10,7 +10,7 @@ export declare type BlockCardProps = {
|
|
|
10
10
|
authFlow?: CardAuthFlowOpts['authFlow'];
|
|
11
11
|
handleAuthorize: (() => void) | undefined;
|
|
12
12
|
handleErrorRetry: () => void;
|
|
13
|
-
|
|
13
|
+
handleAnalytics: AnalyticsHandler;
|
|
14
14
|
handleInvoke: InvokeHandler;
|
|
15
15
|
handleFrameClick: React.EventHandler<React.MouseEvent | React.KeyboardEvent>;
|
|
16
16
|
isSelected?: boolean;
|
|
@@ -4,7 +4,7 @@ import { JsonLd } from 'json-ld-types';
|
|
|
4
4
|
import { FlexibleUiOptions } from '../FlexibleCard/types';
|
|
5
5
|
import { InlinePreloaderStyle } from '../types';
|
|
6
6
|
export declare type CardAppearance = 'inline' | 'block' | 'embed';
|
|
7
|
-
export declare type CardInnerAppearance = CardAppearance | 'preview';
|
|
7
|
+
export declare type CardInnerAppearance = CardAppearance | 'preview' | 'flexible';
|
|
8
8
|
export declare type CardPlatform = JsonLd.Primitives.Platforms;
|
|
9
9
|
export declare type OnResolveCallback = (data: {
|
|
10
10
|
url?: string;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
1
2
|
import { BlockProps, ElementItem, ActionItem } from '../types';
|
|
2
3
|
import { SmartLinkPosition, SmartLinkTheme } from '../../../../../constants';
|
|
3
4
|
import { RetryOptions } from '../../../types';
|
|
@@ -11,4 +12,5 @@ export declare type TitleBlockProps = BlockProps & {
|
|
|
11
12
|
theme?: SmartLinkTheme;
|
|
12
13
|
text?: string;
|
|
13
14
|
showActionOnHover?: boolean;
|
|
15
|
+
onClick?: React.EventHandler<React.MouseEvent | React.KeyboardEvent>;
|
|
14
16
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
1
2
|
import { SmartLinkSize, SmartLinkStatus, SmartLinkTheme } from '../../../../constants';
|
|
2
3
|
import { RetryOptions } from '../../types';
|
|
3
4
|
export declare type ContainerProps = {
|
|
@@ -9,4 +10,5 @@ export declare type ContainerProps = {
|
|
|
9
10
|
status?: SmartLinkStatus;
|
|
10
11
|
testId?: string;
|
|
11
12
|
theme?: SmartLinkTheme;
|
|
13
|
+
onClick?: React.EventHandler<React.MouseEvent | React.KeyboardEvent>;
|
|
12
14
|
};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
1
2
|
import { ElementProps } from '../types';
|
|
2
3
|
import { SmartLinkTheme } from '../../../../../constants';
|
|
3
4
|
export declare type LinkProps = ElementProps & {
|
|
5
|
+
onClick?: React.EventHandler<React.MouseEvent | React.KeyboardEvent>;
|
|
4
6
|
maxLines?: number;
|
|
5
7
|
text?: string;
|
|
6
8
|
theme?: SmartLinkTheme;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/smart-card",
|
|
3
|
-
"version": "17.7.
|
|
3
|
+
"version": "17.7.8",
|
|
4
4
|
"description": "Smart card component",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -111,6 +111,7 @@
|
|
|
111
111
|
"react-dom": "^16.8.0",
|
|
112
112
|
"react-intl-next": "npm:react-intl@^5.18.1",
|
|
113
113
|
"react-test-renderer": "^16.8.0",
|
|
114
|
+
"ts-jest": "24.3.0",
|
|
114
115
|
"typescript": "3.9.6",
|
|
115
116
|
"xhr-mock": "^2.4.0"
|
|
116
117
|
},
|
|
@@ -119,6 +120,7 @@
|
|
|
119
120
|
"./in-product": "./src/in-product.ts",
|
|
120
121
|
"./client": "./src/client/index.ts",
|
|
121
122
|
"./types": "./src/types.ts",
|
|
123
|
+
"./hooks": "./src/hooks.ts",
|
|
122
124
|
".": "./src/index.ts"
|
|
123
125
|
},
|
|
124
126
|
"prettier": "@atlassian/atlassian-frontend-prettier-config-1.0.1"
|