@atlaskit/smart-card 45.21.0 → 45.21.1
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 +24 -0
- package/dist/cjs/extractors/action/extract-invoke-view-action.js +2 -8
- package/dist/cjs/extractors/flexible/actions/index.js +2 -3
- package/dist/cjs/extractors/flexible/extract-state.js +3 -4
- package/dist/cjs/extractors/flexible/index.js +3 -4
- package/dist/cjs/state/hooks/use-destination-url/index.js +6 -11
- package/dist/cjs/state/hooks/use-smart-link-cross-product-url-wrapper/index.js +49 -10
- package/dist/cjs/state/hooks-external/useSmartLinkActions.js +5 -6
- package/dist/cjs/utils/analytics/analytics.js +1 -1
- package/dist/cjs/view/CardWithUrl/component.js +62 -111
- package/dist/cjs/view/FlexibleCard/index.js +2 -3
- package/dist/cjs/view/HoverCard/components/HoverCardContent.js +16 -23
- package/dist/cjs/view/LinkUrl/index.js +1 -1
- package/dist/es2019/extractors/action/extract-invoke-view-action.js +3 -7
- package/dist/es2019/extractors/flexible/actions/index.js +1 -3
- package/dist/es2019/extractors/flexible/extract-state.js +2 -4
- package/dist/es2019/extractors/flexible/index.js +2 -4
- package/dist/es2019/state/hooks/use-destination-url/index.js +4 -7
- package/dist/es2019/state/hooks/use-smart-link-cross-product-url-wrapper/index.js +47 -5
- package/dist/es2019/state/hooks-external/useSmartLinkActions.js +5 -7
- package/dist/es2019/utils/analytics/analytics.js +1 -1
- package/dist/es2019/view/CardWithUrl/component.js +64 -113
- package/dist/es2019/view/FlexibleCard/index.js +3 -4
- package/dist/es2019/view/HoverCard/components/HoverCardContent.js +16 -20
- package/dist/es2019/view/LinkUrl/index.js +1 -1
- package/dist/esm/extractors/action/extract-invoke-view-action.js +2 -8
- package/dist/esm/extractors/flexible/actions/index.js +2 -3
- package/dist/esm/extractors/flexible/extract-state.js +3 -4
- package/dist/esm/extractors/flexible/index.js +3 -4
- package/dist/esm/state/hooks/use-destination-url/index.js +4 -9
- package/dist/esm/state/hooks/use-smart-link-cross-product-url-wrapper/index.js +47 -9
- package/dist/esm/state/hooks-external/useSmartLinkActions.js +6 -7
- package/dist/esm/utils/analytics/analytics.js +1 -1
- package/dist/esm/view/CardWithUrl/component.js +63 -112
- package/dist/esm/view/FlexibleCard/index.js +3 -4
- package/dist/esm/view/HoverCard/components/HoverCardContent.js +17 -24
- package/dist/esm/view/LinkUrl/index.js +1 -1
- package/dist/types/state/hooks/use-destination-url/index.d.ts +18 -1
- package/dist/types/state/hooks/use-smart-link-cross-product-url-wrapper/index.d.ts +5 -2
- package/package.json +3 -5
- package/dist/cjs/state/hooks/use-smart-link-cross-product-url-wrapper/useSmartLinkCrossProductUrlWrapper.js +0 -54
- package/dist/es2019/state/hooks/use-smart-link-cross-product-url-wrapper/useSmartLinkCrossProductUrlWrapper.js +0 -47
- package/dist/esm/state/hooks/use-smart-link-cross-product-url-wrapper/useSmartLinkCrossProductUrlWrapper.js +0 -47
- package/dist/types/state/hooks/use-smart-link-cross-product-url-wrapper/useSmartLinkCrossProductUrlWrapper.d.ts +0 -5
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { getClickUrl } from '../../getClickUrl';
|
|
1
|
+
import { getClickUrl } from '../../helpers';
|
|
3
2
|
import { useSmartCardState } from '../../store';
|
|
4
|
-
import { useSmartLinkCrossProductUrlWrapper } from '../use-smart-link-cross-product-url-wrapper
|
|
3
|
+
import { useSmartLinkCrossProductUrlWrapper } from '../use-smart-link-cross-product-url-wrapper';
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Returns the resolved destination URL for a Smart Link, with cross-product analytics
|
|
8
|
-
* parameters appended when
|
|
7
|
+
* parameters appended when applicable.
|
|
9
8
|
*
|
|
10
9
|
* This is the same URL that SmartCard would navigate to when clicked. Use this as an `href`
|
|
11
10
|
* wherever you render a link to a Smart Link URL outside of the SmartCard component itself
|
|
@@ -13,7 +12,6 @@ import { useSmartLinkCrossProductUrlWrapper } from '../use-smart-link-cross-prod
|
|
|
13
12
|
*
|
|
14
13
|
* Falls back to the raw `url` when:
|
|
15
14
|
* - The link has not yet resolved
|
|
16
|
-
* - The feature gate is disabled
|
|
17
15
|
* - The link is not a first-party Atlassian link
|
|
18
16
|
*
|
|
19
17
|
* @example
|
|
@@ -21,7 +19,7 @@ import { useSmartLinkCrossProductUrlWrapper } from '../use-smart-link-cross-prod
|
|
|
21
19
|
*
|
|
22
20
|
* Use as <a href={href} target="_blank">Open link</a>
|
|
23
21
|
*/
|
|
24
|
-
var
|
|
22
|
+
var useDestinationUrl = function useDestinationUrl(url) {
|
|
25
23
|
var state = useSmartCardState(url);
|
|
26
24
|
var appendCrossProductAnalyticsParams = useSmartLinkCrossProductUrlWrapper({
|
|
27
25
|
details: state.details
|
|
@@ -29,9 +27,6 @@ var useDestinationUrlImplementation = function useDestinationUrlImplementation(u
|
|
|
29
27
|
var resolvedUrl = getClickUrl(url, state.details);
|
|
30
28
|
return appendCrossProductAnalyticsParams(resolvedUrl);
|
|
31
29
|
};
|
|
32
|
-
export var useDestinationUrl = functionWithFG('platform_smartlink_xpc_url_wrapping', useDestinationUrlImplementation, function (url) {
|
|
33
|
-
return url;
|
|
34
|
-
});
|
|
35
30
|
|
|
36
31
|
// Public API aliases preserved from an eliminated entry-point (volt-migrate-package).
|
|
37
32
|
export { useDestinationUrl as useSmartLinkDestinationUrl };
|
|
@@ -1,9 +1,47 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
var
|
|
4
|
-
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
};
|
|
9
|
-
export var
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
import { useCallback } from 'react';
|
|
5
|
+
import { useCrossProductUrlWrapper } from '@atlaskit/analytics-cross-product/useCrossProductUrlWrapper';
|
|
6
|
+
import { useSmartLinkContext } from '@atlaskit/link-provider';
|
|
7
|
+
import { XPC_CONSTANTS } from './constants';
|
|
8
|
+
import { getIsFirstPartyLink } from './getIsFirstPartyLink';
|
|
9
|
+
export var useSmartLinkCrossProductUrlWrapper = function useSmartLinkCrossProductUrlWrapper(_ref) {
|
|
10
|
+
var _effectiveProduct$toL;
|
|
11
|
+
var details = _ref.details;
|
|
12
|
+
var _useSmartLinkContext = useSmartLinkContext(),
|
|
13
|
+
product = _useSmartLinkContext.product,
|
|
14
|
+
bridgeProduct = _useSmartLinkContext.bridgeProduct,
|
|
15
|
+
xpcProduct = _useSmartLinkContext.xpcProduct,
|
|
16
|
+
xpcSubProduct = _useSmartLinkContext.xpcSubProduct;
|
|
17
|
+
// xpcProduct takes precedence over product — it identifies the host product for XPC analytics
|
|
18
|
+
// without affecting link resolution (which uses the `product` prop separately).
|
|
19
|
+
var effectiveProduct = xpcProduct !== null && xpcProduct !== void 0 ? xpcProduct : product;
|
|
20
|
+
var effectiveBridge = bridgeProduct !== null && bridgeProduct !== void 0 ? bridgeProduct : XPC_CONSTANTS.SMART_LINKS_XPC_BRIDGE;
|
|
21
|
+
var effectiveProductForWrapper = (_effectiveProduct$toL = effectiveProduct === null || effectiveProduct === void 0 ? void 0 : effectiveProduct.toLowerCase()) !== null && _effectiveProduct$toL !== void 0 ? _effectiveProduct$toL : 'unknown';
|
|
22
|
+
var wrapUrl = useCrossProductUrlWrapper(_objectSpread({
|
|
23
|
+
bridge: effectiveBridge,
|
|
24
|
+
product: effectiveProductForWrapper
|
|
25
|
+
}, xpcSubProduct ? {
|
|
26
|
+
subProduct: xpcSubProduct
|
|
27
|
+
} : {}));
|
|
28
|
+
return useCallback(function (url) {
|
|
29
|
+
if (typeof window === 'undefined' || !getIsFirstPartyLink(details) || !effectiveProduct) {
|
|
30
|
+
return url;
|
|
31
|
+
}
|
|
32
|
+
var parsedUrl;
|
|
33
|
+
try {
|
|
34
|
+
parsedUrl = new URL(url);
|
|
35
|
+
} catch (_unused) {
|
|
36
|
+
return url;
|
|
37
|
+
}
|
|
38
|
+
if (parsedUrl.searchParams.has(XPC_CONSTANTS.QUERY_PARAM)) {
|
|
39
|
+
return url;
|
|
40
|
+
}
|
|
41
|
+
return wrapUrl(url);
|
|
42
|
+
},
|
|
43
|
+
// Keep bridge/subproduct in the dependency array so consumers that memoize this callback
|
|
44
|
+
// refresh when mini-modal context updates from smartLinks to rovo-chat.
|
|
45
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
46
|
+
[details, effectiveBridge, effectiveProduct, wrapUrl, xpcSubProduct]);
|
|
47
|
+
};
|
|
@@ -16,7 +16,7 @@ import { messages } from '../../messages';
|
|
|
16
16
|
import { toAction } from '../../utils/actions/to-action';
|
|
17
17
|
import useInvokeClientAction from '../hooks/use-invoke-client-action';
|
|
18
18
|
import useResolve from '../hooks/use-resolve';
|
|
19
|
-
import {
|
|
19
|
+
import { useSmartLinkCrossProductUrlWrapper } from '../hooks/use-smart-link-cross-product-url-wrapper';
|
|
20
20
|
import { useSmartCardState as useLinkState } from '../store';
|
|
21
21
|
export function useSmartLinkActions(_ref) {
|
|
22
22
|
var url = _ref.url,
|
|
@@ -39,7 +39,7 @@ export function useSmartLinkActions(_ref) {
|
|
|
39
39
|
fireEvent: fireEvent
|
|
40
40
|
});
|
|
41
41
|
var resolve = useResolve();
|
|
42
|
-
var appendCrossProductAnalyticsParams =
|
|
42
|
+
var appendCrossProductAnalyticsParams = useSmartLinkCrossProductUrlWrapper({
|
|
43
43
|
details: linkState.details
|
|
44
44
|
});
|
|
45
45
|
if (expValEquals('platform_hover_card_preview_panel', 'cohort', 'test') && prefetch && !linkState.details) {
|
|
@@ -59,12 +59,12 @@ export function useSmartLinkActions(_ref) {
|
|
|
59
59
|
if (downloadActionProps) {
|
|
60
60
|
actions.push(toAction(downloadActionProps, invokeClientAction, messages.download, 'download-content'));
|
|
61
61
|
}
|
|
62
|
-
var viewActionProps =
|
|
62
|
+
var viewActionProps = extractInvokeViewAction(_objectSpread(_objectSpread({}, invokeParam), {}, {
|
|
63
63
|
transformUrl: function transformUrl() {
|
|
64
64
|
var destinationUrl = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : url;
|
|
65
65
|
return appendCrossProductAnalyticsParams(destinationUrl);
|
|
66
66
|
}
|
|
67
|
-
}))
|
|
67
|
+
}));
|
|
68
68
|
if (viewActionProps) {
|
|
69
69
|
actions.push(toAction(viewActionProps, invokeClientAction, messages.view, 'view-content'));
|
|
70
70
|
}
|
|
@@ -75,13 +75,12 @@ export function useSmartLinkActions(_ref) {
|
|
|
75
75
|
}, fg('preview_panel_unit_check') ? {
|
|
76
76
|
isPreviewRestricted: isPreviewRestricted
|
|
77
77
|
} : undefined), {}, {
|
|
78
|
-
openPreviewPanel: openPreviewPanel
|
|
79
|
-
}, fg('platform_smartlink_xpc_url_wrapping') ? {
|
|
78
|
+
openPreviewPanel: openPreviewPanel,
|
|
80
79
|
transformUrl: function transformUrl() {
|
|
81
80
|
var destinationUrl = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : url;
|
|
82
81
|
return appendCrossProductAnalyticsParams(destinationUrl);
|
|
83
82
|
}
|
|
84
|
-
}
|
|
83
|
+
}));
|
|
85
84
|
if (previewActionProps) {
|
|
86
85
|
actions.push(toAction(previewActionProps.invokeAction, invokeClientAction, messages.preview_improved, 'preview-content'));
|
|
87
86
|
}
|
|
@@ -3,7 +3,7 @@ export var ANALYTICS_CHANNEL = 'media';
|
|
|
3
3
|
export var context = {
|
|
4
4
|
componentName: 'smart-cards',
|
|
5
5
|
packageName: "@atlaskit/smart-card" || '',
|
|
6
|
-
packageVersion: "45.
|
|
6
|
+
packageVersion: "45.21.0" || ''
|
|
7
7
|
};
|
|
8
8
|
export var TrackQuickActionType = /*#__PURE__*/function (TrackQuickActionType) {
|
|
9
9
|
TrackQuickActionType["StatusUpdate"] = "StatusUpdate";
|
|
@@ -19,7 +19,7 @@ import { getObjectName } from '../../state/getObjectName';
|
|
|
19
19
|
import { getResourceType } from '../../state/getResourceType';
|
|
20
20
|
import { getServices } from '../../state/getServices';
|
|
21
21
|
import { getThirdPartyARI } from '../../state/getThirdPartyARI';
|
|
22
|
-
import {
|
|
22
|
+
import { useSmartLinkCrossProductUrlWrapper } from '../../state/hooks/use-smart-link-cross-product-url-wrapper';
|
|
23
23
|
import { useSmartLink } from '../../state/hooks/useSmartLink';
|
|
24
24
|
import { isFinalState } from '../../state/isFinalState';
|
|
25
25
|
import { SmartLinkModalProvider } from '../../state/modal/SmartLinkModalProvider';
|
|
@@ -101,7 +101,7 @@ function Component(_ref) {
|
|
|
101
101
|
var services = getServices(state.details);
|
|
102
102
|
var thirdPartyARI = getThirdPartyARI(state.details);
|
|
103
103
|
var firstPartyIdentifier = getFirstPartyIdentifier();
|
|
104
|
-
var appendCrossProductAnalyticsParams =
|
|
104
|
+
var appendCrossProductAnalyticsParams = useSmartLinkCrossProductUrlWrapper({
|
|
105
105
|
details: state.details
|
|
106
106
|
});
|
|
107
107
|
var actionOptions = combineActionOptions({
|
|
@@ -138,126 +138,79 @@ function Component(_ref) {
|
|
|
138
138
|
// please reach out to the 3P Workflows Team via Slack in #help-3p-connector-workflow
|
|
139
139
|
fire3PClickEvent === null || fire3PClickEvent === void 0 || fire3PClickEvent();
|
|
140
140
|
}
|
|
141
|
-
if (fg('platform_smartlink_xpc_url_wrapping')) {
|
|
142
|
-
// FIXME: InlineCard, BlockCard and EmbedCard call event.preventDefault() internally
|
|
143
|
-
// before the event bubbles up to this handler. This forces us to snapshot
|
|
144
|
-
// event.defaultPrevented before calling onClick to detect whether the consumer
|
|
145
|
-
// specifically prevented navigation. Ideally those components should not call
|
|
146
|
-
// preventDefault so this workaround can be removed.
|
|
147
|
-
var isEventDefaultPrevented = event.defaultPrevented;
|
|
148
|
-
var canOpenPreviewPanel = !isModifierKeyPressed && ari && name && openPreviewPanel && (isPreviewPanelAvailable === null || isPreviewPanelAvailable === void 0 ? void 0 : isPreviewPanelAvailable({
|
|
149
|
-
ari: ari
|
|
150
|
-
})) && !disablePreviewPanel;
|
|
151
141
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
iconUrl: getObjectIconUrl(state.details),
|
|
162
|
-
panelData: {
|
|
163
|
-
embedUrl: expValEquals('platform_hover_card_preview_panel', 'cohort', 'test') ? (_extractSmartLinkEmbe = extractSmartLinkEmbed(state.details)) === null || _extractSmartLinkEmbe === void 0 ? void 0 : _extractSmartLinkEmbe.src : undefined
|
|
164
|
-
}
|
|
165
|
-
});
|
|
166
|
-
fireLinkClickedEvent(createAnalyticsEvent)(event, {
|
|
167
|
-
attributes: {
|
|
168
|
-
clickOutcome: 'previewPanel'
|
|
169
|
-
}
|
|
170
|
-
});
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
var destinationUrl = getDestinationUrl();
|
|
174
|
-
updateAnchorHref(event, destinationUrl);
|
|
142
|
+
// FIXME: InlineCard, BlockCard and EmbedCard call event.preventDefault() internally
|
|
143
|
+
// before the event bubbles up to this handler. This forces us to snapshot
|
|
144
|
+
// event.defaultPrevented before calling onClick to detect whether the consumer
|
|
145
|
+
// specifically prevented navigation. Ideally those components should not call
|
|
146
|
+
// preventDefault so this workaround can be removed.
|
|
147
|
+
var isEventDefaultPrevented = event.defaultPrevented;
|
|
148
|
+
var canOpenPreviewPanel = !isModifierKeyPressed && ari && name && openPreviewPanel && (isPreviewPanelAvailable === null || isPreviewPanelAvailable === void 0 ? void 0 : isPreviewPanelAvailable({
|
|
149
|
+
ari: ari
|
|
150
|
+
})) && !disablePreviewPanel;
|
|
175
151
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
var
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
152
|
+
// Preview panel takes priority over link navigation when available.
|
|
153
|
+
if (canOpenPreviewPanel) {
|
|
154
|
+
var _extractSmartLinkEmbe;
|
|
155
|
+
event.preventDefault();
|
|
156
|
+
event.stopPropagation();
|
|
157
|
+
openPreviewPanel({
|
|
182
158
|
url: url,
|
|
183
|
-
|
|
159
|
+
ari: ari,
|
|
160
|
+
name: name,
|
|
161
|
+
iconUrl: getObjectIconUrl(state.details),
|
|
162
|
+
panelData: {
|
|
163
|
+
embedUrl: expValEquals('platform_hover_card_preview_panel', 'cohort', 'test') ? (_extractSmartLinkEmbe = extractSmartLinkEmbed(state.details)) === null || _extractSmartLinkEmbe === void 0 ? void 0 : _extractSmartLinkEmbe.src : undefined
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
fireLinkClickedEvent(createAnalyticsEvent)(event, {
|
|
167
|
+
attributes: {
|
|
168
|
+
clickOutcome: 'previewPanel'
|
|
169
|
+
}
|
|
184
170
|
});
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
var destinationUrl = getDestinationUrl();
|
|
174
|
+
updateAnchorHref(event, destinationUrl);
|
|
185
175
|
|
|
186
|
-
|
|
187
|
-
|
|
176
|
+
// For FlexibleCard, read target from the clicked anchor element (e.g. _blank for links
|
|
177
|
+
// rendered with explicit target). For classic cards, default to _self
|
|
178
|
+
var _getAnchorAttributesF = getAnchorAttributesFromEvent(event),
|
|
179
|
+
anchorTarget = _getAnchorAttributesF.target;
|
|
180
|
+
var target = isSpecialEvent(event) ? '_blank' : isFlexibleUi ? anchorTarget : '_self';
|
|
181
|
+
onClick === null || onClick === void 0 || onClick(event, {
|
|
182
|
+
url: url,
|
|
183
|
+
destinationUrl: destinationUrl
|
|
184
|
+
});
|
|
188
185
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
// FlexibleCard's anchor is prevented from native navigation, so this handler always
|
|
192
|
-
// opens the link for FlexibleCard unless the consumer's onClick called preventDefault.
|
|
193
|
-
var shouldOpenLink = isFlexibleUi || !onClick;
|
|
194
|
-
var doOpenLink = shouldOpenLink && !consumerPreventedNavigation;
|
|
195
|
-
if (doOpenLink) {
|
|
196
|
-
event.preventDefault();
|
|
197
|
-
window.open(destinationUrl, target);
|
|
198
|
-
}
|
|
186
|
+
// Check if the event is prevented via onClick callback
|
|
187
|
+
var consumerPreventedNavigation = event.defaultPrevented && !isEventDefaultPrevented;
|
|
199
188
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
if (!isModifierKeyPressed && ari && name && openPreviewPanel && isPreviewPanelAvailable !== null && isPreviewPanelAvailable !== void 0 && isPreviewPanelAvailable({
|
|
211
|
-
ari: ari
|
|
212
|
-
}) && !disablePreviewPanel) {
|
|
213
|
-
var _extractSmartLinkEmbe2;
|
|
214
|
-
event.preventDefault();
|
|
215
|
-
event.stopPropagation();
|
|
216
|
-
openPreviewPanel({
|
|
217
|
-
url: url,
|
|
218
|
-
ari: ari,
|
|
219
|
-
name: name,
|
|
220
|
-
iconUrl: getObjectIconUrl(state.details),
|
|
221
|
-
panelData: {
|
|
222
|
-
embedUrl: expValEquals('platform_hover_card_preview_panel', 'cohort', 'test') ? (_extractSmartLinkEmbe2 = extractSmartLinkEmbed(state.details)) === null || _extractSmartLinkEmbe2 === void 0 ? void 0 : _extractSmartLinkEmbe2.src : undefined
|
|
223
|
-
}
|
|
224
|
-
});
|
|
225
|
-
fireLinkClickedEvent(createAnalyticsEvent)(event, {
|
|
226
|
-
attributes: {
|
|
227
|
-
clickOutcome: 'previewPanel'
|
|
228
|
-
}
|
|
229
|
-
});
|
|
230
|
-
return;
|
|
231
|
-
} else if (!onClick && !isFlexibleUi) {
|
|
232
|
-
var clickUrl = getClickUrl(url, state.details);
|
|
189
|
+
// Classic cards (InlineCard, BlockCard, EmbedCard) rely on their own anchor navigation
|
|
190
|
+
// when onClick is provided, so this handler should not open the link for them.
|
|
191
|
+
// FlexibleCard's anchor is prevented from native navigation, so this handler always
|
|
192
|
+
// opens the link for FlexibleCard unless the consumer's onClick called preventDefault.
|
|
193
|
+
var shouldOpenLink = isFlexibleUi || !onClick;
|
|
194
|
+
var doOpenLink = shouldOpenLink && !consumerPreventedNavigation;
|
|
195
|
+
if (doOpenLink) {
|
|
196
|
+
event.preventDefault();
|
|
197
|
+
window.open(destinationUrl, target);
|
|
198
|
+
}
|
|
233
199
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
window.open(clickUrl, _target);
|
|
240
|
-
fireLinkClickedEvent(createAnalyticsEvent)(event, {
|
|
241
|
-
attributes: {
|
|
242
|
-
clickOutcome: _target === '_blank' ? 'clickThroughNewTabOrWindow' : 'clickThrough'
|
|
243
|
-
}
|
|
244
|
-
});
|
|
245
|
-
} else {
|
|
246
|
-
if (onClick) {
|
|
247
|
-
onClick(event);
|
|
248
|
-
}
|
|
249
|
-
fireLinkClickedEvent(createAnalyticsEvent)(event);
|
|
200
|
+
// Only set clickOutcome when this handler actually opened the link.
|
|
201
|
+
// If a parent onClick handled navigation, fire a generic click event instead.
|
|
202
|
+
fireLinkClickedEvent(createAnalyticsEvent)(event, doOpenLink ? {
|
|
203
|
+
attributes: {
|
|
204
|
+
clickOutcome: target === '_blank' ? 'clickThroughNewTabOrWindow' : 'clickThrough'
|
|
250
205
|
}
|
|
251
|
-
}
|
|
206
|
+
} : undefined);
|
|
252
207
|
}, [fireEvent, id, isFlexibleUi, appearance, definitionId, getDestinationUrl, onClick, url, state.details, ari, name, fire3PClickEvent, shouldFire3PClickEvent, isPreviewPanelAvailable, openPreviewPanel, createAnalyticsEvent, disablePreviewPanel]);
|
|
253
208
|
|
|
254
209
|
// Middle-click handler to trigger fire3PClickEvent on middle-clicks.
|
|
255
210
|
// Scope is limited to 3P click analytics.
|
|
256
211
|
var handleFrameAuxClick = useCallback(function (event) {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
updateAnchorHref(event, destinationUrl);
|
|
260
|
-
}
|
|
212
|
+
var destinationUrl = getDestinationUrl();
|
|
213
|
+
updateAnchorHref(event, destinationUrl);
|
|
261
214
|
|
|
262
215
|
// isAuxClick filters Windows right-clicks (button === 2) that also fire onAuxClick.
|
|
263
216
|
if (isAuxClick(event) && shouldFire3PClickEvent) {
|
|
@@ -270,10 +223,8 @@ function Component(_ref) {
|
|
|
270
223
|
// Right-click handler to trigger fire3PClickEvent on right-clicks.
|
|
271
224
|
// Scope is limited to 3P click analytics.
|
|
272
225
|
var handleFrameContextMenu = useCallback(function (event) {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
updateAnchorHref(event, destinationUrl);
|
|
276
|
-
}
|
|
226
|
+
var destinationUrl = getDestinationUrl();
|
|
227
|
+
updateAnchorHref(event, destinationUrl);
|
|
277
228
|
if (shouldFire3PClickEvent) {
|
|
278
229
|
fire3PClickEvent === null || fire3PClickEvent === void 0 || fire3PClickEvent({
|
|
279
230
|
isContextMenu: true
|
|
@@ -13,7 +13,7 @@ import { FlexibleCardContext } from '../../state/flexible-ui-context';
|
|
|
13
13
|
import { useAISummaryConfig } from '../../state/hooks/use-ai-summary-config';
|
|
14
14
|
import useResolve from '../../state/hooks/use-resolve';
|
|
15
15
|
import useRovoConfig from '../../state/hooks/use-rovo-config';
|
|
16
|
-
import {
|
|
16
|
+
import { useSmartLinkCrossProductUrlWrapper } from '../../state/hooks/use-smart-link-cross-product-url-wrapper';
|
|
17
17
|
import Container from './components/container';
|
|
18
18
|
import { getContextByStatus } from './getContextByStatus';
|
|
19
19
|
var PENDING_LINK_STATUSES = [SmartLinkStatus.Pending, SmartLinkStatus.Resolving];
|
|
@@ -60,14 +60,13 @@ var FlexibleCard = function FlexibleCard(_ref) {
|
|
|
60
60
|
var cardType = cardState.status,
|
|
61
61
|
details = cardState.details;
|
|
62
62
|
var status = cardType;
|
|
63
|
-
var appendCrossProductAnalyticsParams =
|
|
63
|
+
var appendCrossProductAnalyticsParams = useSmartLinkCrossProductUrlWrapper({
|
|
64
64
|
details: details
|
|
65
65
|
});
|
|
66
|
-
var
|
|
66
|
+
var transformUrl = useCallback(function () {
|
|
67
67
|
var destinationUrl = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : url;
|
|
68
68
|
return appendCrossProductAnalyticsParams(destinationUrl);
|
|
69
69
|
}, [appendCrossProductAnalyticsParams, url]);
|
|
70
|
-
var transformUrl = fg('platform_smartlink_xpc_url_wrapping') ? transformUrlCallback : undefined;
|
|
71
70
|
|
|
72
71
|
// if we have placeholder state it means we can internally use it
|
|
73
72
|
// as temporary resolved data until the actual data comes back as one of the final statuses
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
-
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
-
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
1
|
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
|
|
5
2
|
import AnalyticsContext from '@atlaskit/analytics-next/AnalyticsContext';
|
|
6
3
|
import { useAnalyticsEvents as useAnalyticsEventsNext } from '@atlaskit/analytics-next/useAnalyticsEvents';
|
|
@@ -16,7 +13,7 @@ import { getDefinitionId } from '../../../state/getDefinitionId';
|
|
|
16
13
|
import { getExtensionKey } from '../../../state/getExtensionKey';
|
|
17
14
|
import { getServices } from '../../../state/getServices';
|
|
18
15
|
import useRovoConfig from '../../../state/hooks/use-rovo-config';
|
|
19
|
-
import {
|
|
16
|
+
import { useSmartLinkCrossProductUrlWrapper } from '../../../state/hooks/use-smart-link-cross-product-url-wrapper';
|
|
20
17
|
import { useSmartCardState } from '../../../state/store';
|
|
21
18
|
import { isSpecialEvent } from '../../../utils/is-special-event';
|
|
22
19
|
import { fireLinkClickedEvent } from '../../../utils/analytics/fireLinkClickedEvent';
|
|
@@ -90,7 +87,7 @@ var HoverCardContent = function HoverCardContent(_ref4) {
|
|
|
90
87
|
product = _useSmartLinkContext.product;
|
|
91
88
|
var isAISummaryEnabled = getIsAISummaryEnabled(isAdminHubAIEnabled, cardState.details);
|
|
92
89
|
var services = getServices(linkState.details);
|
|
93
|
-
var appendCrossProductAnalyticsParams =
|
|
90
|
+
var appendCrossProductAnalyticsParams = useSmartLinkCrossProductUrlWrapper({
|
|
94
91
|
details: linkState.details
|
|
95
92
|
});
|
|
96
93
|
var statusRef = useRef(linkStatus);
|
|
@@ -154,19 +151,17 @@ var HoverCardContent = function HoverCardContent(_ref4) {
|
|
|
154
151
|
updateAnchorHref(event, destinationUrl);
|
|
155
152
|
}, [getDestinationUrl]);
|
|
156
153
|
var onClick = useCallback(function (event) {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
window.open(destinationUrl, target);
|
|
169
|
-
}
|
|
154
|
+
// Prevent the anchor's native navigation so we can open the destination URL
|
|
155
|
+
// with cross-product analytics query parameters appended.
|
|
156
|
+
// The cross-product params are client-only and cannot be rendered
|
|
157
|
+
// server-side. Falls back to the original `url` prop if the event target is
|
|
158
|
+
// not an anchor element.
|
|
159
|
+
event.preventDefault();
|
|
160
|
+
var _getAnchorAttributesF = getAnchorAttributesFromEvent(event),
|
|
161
|
+
target = _getAnchorAttributesF.target;
|
|
162
|
+
var destinationUrl = getDestinationUrl();
|
|
163
|
+
updateAnchorHref(event, destinationUrl);
|
|
164
|
+
window.open(destinationUrl, target);
|
|
170
165
|
var isModifierKeyPressed = isSpecialEvent(event);
|
|
171
166
|
fireEvent('ui.smartLink.clicked.titleGoToLink', {
|
|
172
167
|
id: id,
|
|
@@ -189,14 +184,12 @@ var HoverCardContent = function HoverCardContent(_ref4) {
|
|
|
189
184
|
};
|
|
190
185
|
var uiOptions = flexibleUiOptions;
|
|
191
186
|
uiOptions.enableSnippetRenderer = true;
|
|
192
|
-
var flexibleCardProps =
|
|
187
|
+
var flexibleCardProps = {
|
|
193
188
|
appearance: CardDisplay.HoverCardPreview,
|
|
194
189
|
cardState: cardState,
|
|
195
|
-
onClick: onClick
|
|
196
|
-
}, fg('platform_smartlink_xpc_url_wrapping') ? {
|
|
190
|
+
onClick: onClick,
|
|
197
191
|
onAuxClick: onAuxClick,
|
|
198
|
-
onContextMenu: onContextMenu
|
|
199
|
-
} : undefined), {}, {
|
|
192
|
+
onContextMenu: onContextMenu,
|
|
200
193
|
onResolve: onResolve,
|
|
201
194
|
origin: 'smartLinkPreviewHoverCard',
|
|
202
195
|
renderers: renderers,
|
|
@@ -204,7 +197,7 @@ var HoverCardContent = function HoverCardContent(_ref4) {
|
|
|
204
197
|
ui: uiOptions,
|
|
205
198
|
url: url,
|
|
206
199
|
children: null
|
|
207
|
-
}
|
|
200
|
+
};
|
|
208
201
|
var onClickStopPropagation = useCallback(function (e) {
|
|
209
202
|
return e.stopPropagation();
|
|
210
203
|
}, []);
|
|
@@ -12,7 +12,7 @@ import LinkWarningModal from './LinkWarningModal';
|
|
|
12
12
|
import { useLinkWarningModal } from './LinkWarningModal/hooks/use-link-warning-modal';
|
|
13
13
|
var PACKAGE_DATA = {
|
|
14
14
|
packageName: "@atlaskit/smart-card",
|
|
15
|
-
packageVersion: "45.
|
|
15
|
+
packageVersion: "45.21.0",
|
|
16
16
|
componentName: 'linkUrl'
|
|
17
17
|
};
|
|
18
18
|
var LinkUrl = function LinkUrl(_ref) {
|
|
@@ -1,2 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Returns the resolved destination URL for a Smart Link, with cross-product analytics
|
|
3
|
+
* parameters appended when applicable.
|
|
4
|
+
*
|
|
5
|
+
* This is the same URL that SmartCard would navigate to when clicked. Use this as an `href`
|
|
6
|
+
* wherever you render a link to a Smart Link URL outside of the SmartCard component itself
|
|
7
|
+
* (e.g. toolbar buttons, overlays).
|
|
8
|
+
*
|
|
9
|
+
* Falls back to the raw `url` when:
|
|
10
|
+
* - The link has not yet resolved
|
|
11
|
+
* - The link is not a first-party Atlassian link
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const href = useSmartLinkDestinationUrl(url);
|
|
15
|
+
*
|
|
16
|
+
* Use as <a href={href} target="_blank">Open link</a>
|
|
17
|
+
*/
|
|
18
|
+
declare const useDestinationUrl: (url: string) => string;
|
|
2
19
|
export { useDestinationUrl as useSmartLinkDestinationUrl };
|
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export
|
|
1
|
+
import type { SmartLinkResponse } from '@atlaskit/linking-types/smart-link';
|
|
2
|
+
export type UseSmartLinkCrossProductUrlWrapperArgs = {
|
|
3
|
+
details?: SmartLinkResponse;
|
|
4
|
+
};
|
|
5
|
+
export declare const useSmartLinkCrossProductUrlWrapper: ({ details, }: UseSmartLinkCrossProductUrlWrapperArgs) => ((url: string) => string);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/smart-card",
|
|
3
|
-
"version": "45.21.
|
|
3
|
+
"version": "45.21.1",
|
|
4
4
|
"description": "Smart card component",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"@atlaskit/textfield": "^10.2.0",
|
|
91
91
|
"@atlaskit/theme": "^28.2.0",
|
|
92
92
|
"@atlaskit/tile": "^4.1.0",
|
|
93
|
-
"@atlaskit/tmp-editor-statsig": "^
|
|
93
|
+
"@atlaskit/tmp-editor-statsig": "^180.0.0",
|
|
94
94
|
"@atlaskit/tokens": "^16.11.0",
|
|
95
95
|
"@atlaskit/tooltip": "^24.3.0",
|
|
96
96
|
"@atlaskit/ufo": "^1.2.0",
|
|
@@ -142,6 +142,7 @@
|
|
|
142
142
|
"@types/lorem-ipsum": "^1.0.2",
|
|
143
143
|
"@types/react": "^18.2.0",
|
|
144
144
|
"@types/react-loadable": "^5.4.1",
|
|
145
|
+
"@types/react-test-renderer": "^18.0.6",
|
|
145
146
|
"@types/use-sync-external-store": "^1",
|
|
146
147
|
"abortcontroller-polyfill": "^1.1.9",
|
|
147
148
|
"brace": "^0.11.1",
|
|
@@ -181,9 +182,6 @@
|
|
|
181
182
|
"platform_smartlink_3pclick_analytics": {
|
|
182
183
|
"type": "boolean"
|
|
183
184
|
},
|
|
184
|
-
"platform_smartlink_xpc_url_wrapping": {
|
|
185
|
-
"type": "boolean"
|
|
186
|
-
},
|
|
187
185
|
"rovogrowth-635-pre-auth-cta-preview-fg": {
|
|
188
186
|
"type": "boolean"
|
|
189
187
|
},
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
-
Object.defineProperty(exports, "__esModule", {
|
|
5
|
-
value: true
|
|
6
|
-
});
|
|
7
|
-
exports.useSmartLinkCrossProductUrlWrapper = void 0;
|
|
8
|
-
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
|
-
var _react = require("react");
|
|
10
|
-
var _useCrossProductUrlWrapper = require("@atlaskit/analytics-cross-product/useCrossProductUrlWrapper");
|
|
11
|
-
var _linkProvider = require("@atlaskit/link-provider");
|
|
12
|
-
var _constants = require("./constants");
|
|
13
|
-
var _getIsFirstPartyLink = require("./getIsFirstPartyLink");
|
|
14
|
-
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
15
|
-
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
16
|
-
var useSmartLinkCrossProductUrlWrapper = exports.useSmartLinkCrossProductUrlWrapper = function useSmartLinkCrossProductUrlWrapper(_ref) {
|
|
17
|
-
var _effectiveProduct$toL;
|
|
18
|
-
var details = _ref.details;
|
|
19
|
-
var _useSmartLinkContext = (0, _linkProvider.useSmartLinkContext)(),
|
|
20
|
-
product = _useSmartLinkContext.product,
|
|
21
|
-
bridgeProduct = _useSmartLinkContext.bridgeProduct,
|
|
22
|
-
xpcProduct = _useSmartLinkContext.xpcProduct,
|
|
23
|
-
xpcSubProduct = _useSmartLinkContext.xpcSubProduct;
|
|
24
|
-
// xpcProduct takes precedence over product — it identifies the host product for XPC analytics
|
|
25
|
-
// without affecting link resolution (which uses the `product` prop separately).
|
|
26
|
-
var effectiveProduct = xpcProduct !== null && xpcProduct !== void 0 ? xpcProduct : product;
|
|
27
|
-
var effectiveBridge = bridgeProduct !== null && bridgeProduct !== void 0 ? bridgeProduct : _constants.XPC_CONSTANTS.SMART_LINKS_XPC_BRIDGE;
|
|
28
|
-
var effectiveProductForWrapper = (_effectiveProduct$toL = effectiveProduct === null || effectiveProduct === void 0 ? void 0 : effectiveProduct.toLowerCase()) !== null && _effectiveProduct$toL !== void 0 ? _effectiveProduct$toL : 'unknown';
|
|
29
|
-
var wrapUrl = (0, _useCrossProductUrlWrapper.useCrossProductUrlWrapper)(_objectSpread({
|
|
30
|
-
bridge: effectiveBridge,
|
|
31
|
-
product: effectiveProductForWrapper
|
|
32
|
-
}, xpcSubProduct ? {
|
|
33
|
-
subProduct: xpcSubProduct
|
|
34
|
-
} : {}));
|
|
35
|
-
return (0, _react.useCallback)(function (url) {
|
|
36
|
-
if (typeof window === 'undefined' || !(0, _getIsFirstPartyLink.getIsFirstPartyLink)(details) || !effectiveProduct) {
|
|
37
|
-
return url;
|
|
38
|
-
}
|
|
39
|
-
var parsedUrl;
|
|
40
|
-
try {
|
|
41
|
-
parsedUrl = new URL(url);
|
|
42
|
-
} catch (_unused) {
|
|
43
|
-
return url;
|
|
44
|
-
}
|
|
45
|
-
if (parsedUrl.searchParams.has(_constants.XPC_CONSTANTS.QUERY_PARAM)) {
|
|
46
|
-
return url;
|
|
47
|
-
}
|
|
48
|
-
return wrapUrl(url);
|
|
49
|
-
},
|
|
50
|
-
// Keep bridge/subproduct in the dependency array so consumers that memoize this callback
|
|
51
|
-
// refresh when mini-modal context updates from smartLinks to rovo-chat.
|
|
52
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
53
|
-
[details, effectiveBridge, effectiveProduct, wrapUrl, xpcSubProduct]);
|
|
54
|
-
};
|