@atlaskit/smart-card 44.9.9 → 44.9.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/analytics.spec.yaml +0 -8
  3. package/dist/cjs/__tests__/vr-tests/__snapshots__/inline-card/inline-card-with-all-card-examples-in-text--default--jfp-magma-platform-lozenge-jump-fix-false.png +0 -0
  4. package/dist/cjs/__tests__/vr-tests/__snapshots__/inline-card/inline-card-with-all-card-examples-in-text--default--jfp-magma-platform-lozenge-jump-fix-true.png +0 -0
  5. package/dist/cjs/__tests__/vr-tests/__snapshots__/link-url-connect-button/linkurl-default-state--default.png +0 -0
  6. package/dist/cjs/state/hooks/use-intersection-observer/index.js +2 -1
  7. package/dist/cjs/state/hooks/use-smart-link-seen-event/index.js +66 -0
  8. package/dist/cjs/state/hooks/use-social-proof-experiment/index.js +3 -41
  9. package/dist/cjs/utils/analytics/SmartLinkAnalyticsContext.js +31 -8
  10. package/dist/cjs/view/BlockCard/views/UnauthorisedView.js +9 -18
  11. package/dist/cjs/view/CardWithUrl/card-intersection-observer/index.js +25 -20
  12. package/dist/cjs/view/CardWithUrl/component-lazy/LazyIntersectionObserverCard.js +24 -4
  13. package/dist/cjs/view/CardWithUrl/component.js +4 -47
  14. package/dist/cjs/view/InlineCard/Frame/index.js +3 -2
  15. package/dist/cjs/view/LinkUrl/HyperlinkResolver/index.js +0 -41
  16. package/dist/es2019/__tests__/vr-tests/__snapshots__/inline-card/inline-card-with-all-card-examples-in-text--default--jfp-magma-platform-lozenge-jump-fix-false.png +0 -0
  17. package/dist/es2019/__tests__/vr-tests/__snapshots__/inline-card/inline-card-with-all-card-examples-in-text--default--jfp-magma-platform-lozenge-jump-fix-true.png +0 -0
  18. package/dist/es2019/__tests__/vr-tests/__snapshots__/link-url-connect-button/linkurl-default-state--default.png +0 -0
  19. package/dist/es2019/state/hooks/use-intersection-observer/index.js +2 -1
  20. package/dist/es2019/state/hooks/use-smart-link-seen-event/index.js +60 -0
  21. package/dist/es2019/state/hooks/use-social-proof-experiment/index.js +2 -38
  22. package/dist/es2019/utils/analytics/SmartLinkAnalyticsContext.js +28 -6
  23. package/dist/es2019/view/BlockCard/views/UnauthorisedView.js +9 -18
  24. package/dist/es2019/view/CardWithUrl/card-intersection-observer/index.js +28 -11
  25. package/dist/es2019/view/CardWithUrl/component-lazy/LazyIntersectionObserverCard.js +25 -4
  26. package/dist/es2019/view/CardWithUrl/component.js +3 -48
  27. package/dist/es2019/view/InlineCard/Frame/index.js +3 -2
  28. package/dist/es2019/view/LinkUrl/HyperlinkResolver/index.js +1 -40
  29. package/dist/esm/__tests__/vr-tests/__snapshots__/inline-card/inline-card-with-all-card-examples-in-text--default--jfp-magma-platform-lozenge-jump-fix-false.png +0 -0
  30. package/dist/esm/__tests__/vr-tests/__snapshots__/inline-card/inline-card-with-all-card-examples-in-text--default--jfp-magma-platform-lozenge-jump-fix-true.png +0 -0
  31. package/dist/esm/__tests__/vr-tests/__snapshots__/link-url-connect-button/linkurl-default-state--default.png +0 -0
  32. package/dist/esm/state/hooks/use-intersection-observer/index.js +2 -1
  33. package/dist/esm/state/hooks/use-smart-link-seen-event/index.js +60 -0
  34. package/dist/esm/state/hooks/use-social-proof-experiment/index.js +2 -40
  35. package/dist/esm/utils/analytics/SmartLinkAnalyticsContext.js +31 -8
  36. package/dist/esm/view/BlockCard/views/UnauthorisedView.js +9 -18
  37. package/dist/esm/view/CardWithUrl/card-intersection-observer/index.js +26 -21
  38. package/dist/esm/view/CardWithUrl/component-lazy/LazyIntersectionObserverCard.js +24 -4
  39. package/dist/esm/view/CardWithUrl/component.js +5 -48
  40. package/dist/esm/view/InlineCard/Frame/index.js +3 -2
  41. package/dist/esm/view/LinkUrl/HyperlinkResolver/index.js +1 -42
  42. package/dist/types/common/analytics/generated/analytics.types.d.ts +0 -1
  43. package/dist/types/state/hooks/use-smart-link-seen-event/index.d.ts +14 -0
  44. package/dist/types/state/hooks/use-social-proof-experiment/index.d.ts +0 -22
  45. package/dist/types/utils/analytics/SmartLinkAnalyticsContext.d.ts +10 -0
  46. package/dist/types/view/CardWithUrl/card-intersection-observer/index.d.ts +3 -5
  47. package/dist/types/view/CardWithUrl/types.d.ts +0 -1
  48. package/dist/types-ts4.5/common/analytics/generated/analytics.types.d.ts +0 -1
  49. package/dist/types-ts4.5/state/hooks/use-smart-link-seen-event/index.d.ts +14 -0
  50. package/dist/types-ts4.5/state/hooks/use-social-proof-experiment/index.d.ts +0 -22
  51. package/dist/types-ts4.5/utils/analytics/SmartLinkAnalyticsContext.d.ts +10 -0
  52. package/dist/types-ts4.5/view/CardWithUrl/card-intersection-observer/index.d.ts +3 -5
  53. package/dist/types-ts4.5/view/CardWithUrl/types.d.ts +0 -1
  54. package/package.json +8 -5
  55. package/dist/cjs/__tests__/vr-tests/__snapshots__/link-url-connect-button/linkurl-default-state-without-connect-button-functionality--default.png +0 -0
  56. package/dist/cjs/__tests__/vr-tests/__snapshots__/link-url-connect-button/linkurl-resolved-state-with-feature-flag-enabled-should-show-no-connect-button---default--platform-editor-resolve-hyperlinks-killswitch-false.png +0 -0
  57. package/dist/cjs/__tests__/vr-tests/__snapshots__/link-url-connect-button/linkurl-resolved-state-with-feature-flag-enabled-should-show-no-connect-button---default--platform-editor-resolve-hyperlinks-killswitch-true.png +0 -0
  58. package/dist/cjs/__tests__/vr-tests/__snapshots__/link-url-connect-button/linkurl-unauthorized-state-with-connect-button-direct-render---always-visible---default.png +0 -0
  59. package/dist/cjs/view/CardWithUrl/experiment-meta-event-attributes/index.js +0 -39
  60. package/dist/cjs/view/LinkUrl/HyperlinkResolver/unauthorize-view.js +0 -30
  61. package/dist/es2019/__tests__/vr-tests/__snapshots__/link-url-connect-button/linkurl-default-state-without-connect-button-functionality--default.png +0 -0
  62. package/dist/es2019/__tests__/vr-tests/__snapshots__/link-url-connect-button/linkurl-resolved-state-with-feature-flag-enabled-should-show-no-connect-button---default--platform-editor-resolve-hyperlinks-killswitch-false.png +0 -0
  63. package/dist/es2019/__tests__/vr-tests/__snapshots__/link-url-connect-button/linkurl-resolved-state-with-feature-flag-enabled-should-show-no-connect-button---default--platform-editor-resolve-hyperlinks-killswitch-true.png +0 -0
  64. package/dist/es2019/__tests__/vr-tests/__snapshots__/link-url-connect-button/linkurl-unauthorized-state-with-connect-button-direct-render---always-visible---default.png +0 -0
  65. package/dist/es2019/view/CardWithUrl/experiment-meta-event-attributes/index.js +0 -40
  66. package/dist/es2019/view/LinkUrl/HyperlinkResolver/unauthorize-view.js +0 -22
  67. package/dist/esm/__tests__/vr-tests/__snapshots__/link-url-connect-button/linkurl-default-state-without-connect-button-functionality--default.png +0 -0
  68. package/dist/esm/__tests__/vr-tests/__snapshots__/link-url-connect-button/linkurl-resolved-state-with-feature-flag-enabled-should-show-no-connect-button---default--platform-editor-resolve-hyperlinks-killswitch-false.png +0 -0
  69. package/dist/esm/__tests__/vr-tests/__snapshots__/link-url-connect-button/linkurl-resolved-state-with-feature-flag-enabled-should-show-no-connect-button---default--platform-editor-resolve-hyperlinks-killswitch-true.png +0 -0
  70. package/dist/esm/__tests__/vr-tests/__snapshots__/link-url-connect-button/linkurl-unauthorized-state-with-connect-button-direct-render---always-visible---default.png +0 -0
  71. package/dist/esm/view/CardWithUrl/experiment-meta-event-attributes/index.js +0 -32
  72. package/dist/esm/view/LinkUrl/HyperlinkResolver/unauthorize-view.js +0 -23
  73. package/dist/types/view/CardWithUrl/experiment-meta-event-attributes/index.d.ts +0 -9
  74. package/dist/types/view/LinkUrl/HyperlinkResolver/unauthorize-view.d.ts +0 -10
  75. package/dist/types-ts4.5/view/CardWithUrl/experiment-meta-event-attributes/index.d.ts +0 -9
  76. package/dist/types-ts4.5/view/LinkUrl/HyperlinkResolver/unauthorize-view.d.ts +0 -10
@@ -11,8 +11,6 @@ var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/h
11
11
  var _react = _interopRequireWildcard(require("react"));
12
12
  var _reactErrorBoundary = require("react-error-boundary");
13
13
  var _reactIntl = require("react-intl");
14
- var _featureGateJsClient = _interopRequireDefault(require("@atlaskit/feature-gate-js-client"));
15
- var _linkExtractors = require("@atlaskit/link-extractors");
16
14
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
17
15
  var _helpers = require("../../../state/helpers");
18
16
  var _useResolveHyperlink2 = _interopRequireDefault(require("../../../state/hooks/use-resolve-hyperlink"));
@@ -21,7 +19,6 @@ var _SmartLinkAnalyticsContext = require("../../../utils/analytics/SmartLinkAnal
21
19
  var _intlProvider = _interopRequireDefault(require("../../common/intl-provider"));
22
20
  var _useSmartLinkEvents = require("../../SmartLinkEvents/useSmartLinkEvents");
23
21
  var _Hyperlink = _interopRequireDefault(require("../Hyperlink"));
24
- var _unauthorizeView = _interopRequireDefault(require("./unauthorize-view"));
25
22
  var _excluded = ["onClick"];
26
23
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
27
24
  var HyperlinkFallbackComponent = function HyperlinkFallbackComponent() {
@@ -42,9 +39,7 @@ var HyperlinkWithSmartLinkResolverInner = function HyperlinkWithSmartLinkResolve
42
39
  var _useResolveHyperlink = (0, _useResolveHyperlink2.default)({
43
40
  href: props.href || ''
44
41
  }),
45
- actions = _useResolveHyperlink.actions,
46
42
  state = _useResolveHyperlink.state;
47
- var services = (0, _helpers.getServices)(state === null || state === void 0 ? void 0 : state.details);
48
43
  var thirdPartyARI = (0, _helpers.getThirdPartyARI)(state === null || state === void 0 ? void 0 : state.details);
49
44
  var firstPartyIdentifier = (0, _helpers.getFirstPartyIdentifier)();
50
45
  var fire3PClickEvent = (0, _platformFeatureFlags.fg)('platform_smartlink_3pclick_analytics') ?
@@ -59,42 +54,6 @@ var HyperlinkWithSmartLinkResolverInner = function HyperlinkWithSmartLinkResolve
59
54
  }
60
55
  onClickCallback === null || onClickCallback === void 0 || onClickCallback(e);
61
56
  }, [onClickCallback, fire3PClickEvent, state === null || state === void 0 ? void 0 : state.status]);
62
- var onAuthorize = (0, _react.useCallback)(function () {
63
- return actions.authorize('url');
64
- }, [actions]);
65
- var shouldRenderConnectBtn = function shouldRenderConnectBtn() {
66
- if (!props.children || !Array.isArray(props.children) || props.children.length === 0) {
67
- return false;
68
- }
69
- var firstChild = props.children[0];
70
- try {
71
- var _firstChild$props;
72
- // Check if first child has a string matching href
73
- if (typeof firstChild === 'string') {
74
- return props.href === firstChild;
75
- }
76
-
77
- // Check if first child has another child object containing matching href. This aligns with the behavior of the TextWrapper component used by editor to render link nodes
78
- if (firstChild !== null && firstChild !== void 0 && (_firstChild$props = firstChild.props) !== null && _firstChild$props !== void 0 && _firstChild$props.children && typeof firstChild.props.children === 'string') {
79
- return props.href === firstChild.props.children;
80
- }
81
- } catch (_) {
82
- return false;
83
- }
84
- };
85
- if ((state === null || state === void 0 ? void 0 : state.status) === 'unauthorized' && shouldRenderConnectBtn() && (
86
- // eslint-disable-next-line @atlaskit/platform/use-recommended-utils -- Statsig migration pending for Bluelink connect experiments
87
- _featureGateJsClient.default.getExperimentValue('platform_linking_bluelink_connect_confluence', 'isEnabled', false) ||
88
- // eslint-disable-next-line @atlaskit/platform/use-recommended-utils -- Statsig migration pending for Bluelink connect experiments
89
- _featureGateJsClient.default.getExperimentValue('platform_linking_bluelink_connect_jira', 'isEnabled', false))) {
90
- var provider = (0, _linkExtractors.extractSmartLinkProvider)(state === null || state === void 0 ? void 0 : state.details);
91
- return /*#__PURE__*/_react.default.createElement(_unauthorizeView.default, (0, _extends2.default)({}, props, {
92
- onAuthorize: services !== null && services !== void 0 && services.length ? onAuthorize : undefined,
93
- onClick: onClick,
94
- showConnectBtn: (services === null || services === void 0 ? void 0 : services.length) > 0,
95
- provider: provider
96
- }));
97
- }
98
57
  return /*#__PURE__*/_react.default.createElement(_Hyperlink.default, (0, _extends2.default)({}, props, {
99
58
  onClick: onClick
100
59
  }));
@@ -1,4 +1,5 @@
1
1
  import { useCallback, useEffect, useRef } from 'react';
2
+ import { isIntersectionObserverSupported } from '../../../utils';
2
3
 
3
4
  // This property enables the intersection observer to be run once the
4
5
  // HTML element being observed is within `X` px of the target container it is
@@ -27,7 +28,7 @@ const useIntersectionObserver = ({
27
28
  }
28
29
  }, []);
29
30
  useEffect(() => {
30
- if (!ref.current) {
31
+ if (!isIntersectionObserverSupported() || !ref.current) {
31
32
  return;
32
33
  }
33
34
  const intersectionObserver = new IntersectionObserver(onIntersection, {
@@ -0,0 +1,60 @@
1
+ import { useCallback, useEffect, useMemo, useRef } from 'react';
2
+ import { useAnalyticsEvents } from '../../../common/analytics/generated/use-analytics-events';
3
+ import { useSmartLinkAnalyticsUtils } from '../../../utils/analytics/SmartLinkAnalyticsContext';
4
+ import { isFlexibleUiCard } from '../../../utils/flexible';
5
+ /**
6
+ * Fires `ui.smartLink.seen` once when a smart link with status `unauthorized`
7
+ * enters the viewport. Uses refs internally so it never causes re-renders,
8
+ * which is important for SSR.
9
+ */
10
+ export function useSmartLinkSeenEvent({
11
+ appearance,
12
+ children,
13
+ id,
14
+ ui,
15
+ url = ''
16
+ }) {
17
+ const {
18
+ fireEvent
19
+ } = useAnalyticsEvents();
20
+ const {
21
+ getByUrl
22
+ } = useSmartLinkAnalyticsUtils();
23
+ const getAnalyticsProps = useCallback(() => {
24
+ const isFlexibleUi = isFlexibleUiCard(children, ui);
25
+ const display = isFlexibleUi ? 'flexible' : appearance;
26
+ return {
27
+ display,
28
+ id
29
+ };
30
+ }, [appearance, children, id, ui]);
31
+ const statusRef = useRef();
32
+ const analyticsPropsRef = useRef(null);
33
+ const hasIntersectedRef = useRef(false);
34
+ const hasFiredSeenRef = useRef(false);
35
+ useEffect(() => {
36
+ analyticsPropsRef.current = getAnalyticsProps();
37
+ }, [getAnalyticsProps]);
38
+ const maybeFireSeenEvent = useCallback(() => {
39
+ if (!hasFiredSeenRef.current && hasIntersectedRef.current && statusRef.current === 'unauthorized') {
40
+ const payload = getByUrl(url, analyticsPropsRef.current);
41
+ fireEvent('ui.smartLink.seen', payload === null || payload === void 0 ? void 0 : payload.attributes);
42
+ hasFiredSeenRef.current = true;
43
+ }
44
+ }, [fireEvent, getByUrl, url]);
45
+ const onIntersecting = useCallback(() => {
46
+ if (hasIntersectedRef.current) {
47
+ return;
48
+ }
49
+ hasIntersectedRef.current = true;
50
+ maybeFireSeenEvent();
51
+ }, [maybeFireSeenEvent]);
52
+ const onStatusSettled = useCallback(status => {
53
+ statusRef.current = status;
54
+ maybeFireSeenEvent();
55
+ }, [maybeFireSeenEvent]);
56
+ return useMemo(() => ({
57
+ onIntersecting,
58
+ onStatusSettled
59
+ }), [onIntersecting, onStatusSettled]);
60
+ }
@@ -1,42 +1,7 @@
1
1
  import { useMemo } from 'react';
2
2
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
3
- import { getCurrentSiteCloudIdSync } from '../../services/current-site-cloud-id';
4
- import { getProviderPctMapSync, SOCIAL_PROOF_TRAIT_NAME } from '../../services/personalization';
5
3
  import useSocialProof from '../use-social-proof';
6
- export const SOCIAL_PROOF_3P_UNAUTH_BLOCK_EXPERIMENT_KEY = 'social_proof_3p_unauth_block_exp';
7
- export const INLINE_SOCIAL_PROOF_EXPERIMENT_KEY = 'platform_sl_3p_preauth_social_proof_inline_cta';
8
- export const SOCIAL_PROOF_TIER_THRESHOLD = 30;
9
- export const getSocialProofTier = connectedPct => {
10
- if (connectedPct === undefined) {
11
- return undefined;
12
- }
13
- return connectedPct >= SOCIAL_PROOF_TIER_THRESHOLD ? 'not-low' : 'low';
14
- };
15
- const getSocialProofExperimentMetadata = ({
16
- extensionKey,
17
- baseUriWithNoTrailingSlash = ''
18
- }) => {
19
- if (!extensionKey) {
20
- return {
21
- isEligible: false
22
- };
23
- }
24
- const cloudId = getCurrentSiteCloudIdSync(baseUriWithNoTrailingSlash);
25
- const providerPctMap = getProviderPctMapSync(cloudId, SOCIAL_PROOF_TRAIT_NAME);
26
- const tier = getSocialProofTier(providerPctMap === null || providerPctMap === void 0 ? void 0 : providerPctMap[extensionKey]);
27
- return {
28
- isEligible: tier !== undefined,
29
- ...(tier ? {
30
- tier
31
- } : {})
32
- };
33
- };
34
- export const getSocialProofExperimentMeta = params => ({
35
- [SOCIAL_PROOF_3P_UNAUTH_BLOCK_EXPERIMENT_KEY]: getSocialProofExperimentMetadata(params)
36
- });
37
- export const getInlineSocialProofExperimentMeta = params => ({
38
- [INLINE_SOCIAL_PROOF_EXPERIMENT_KEY]: getSocialProofExperimentMetadata(params)
39
- });
4
+ const TIER_THRESHOLD = 30;
40
5
 
41
6
  /**
42
7
  * Returns enrollment and treatment state for the social proof unauth block card experiment.
@@ -60,12 +25,11 @@ const useSocialProofExperiment = (extensionKey, baseUriWithNoTrailingSlash = '')
60
25
  isLoading
61
26
  } = useSocialProof(extensionKey, true, baseUriWithNoTrailingSlash);
62
27
  return useMemo(() => {
63
- var _getSocialProofTier;
64
28
  const hasSocialProofData = connectedPct !== undefined;
65
29
 
66
30
  // Only fire exposure when data has loaded (prevents exposure inflation)
67
31
  const isTreatment = isEnabled && !isLoading && hasSocialProofData ? editorExperiment('social_proof_3p_unauth_block_exp', true) : false;
68
- const tier = (_getSocialProofTier = getSocialProofTier(connectedPct)) !== null && _getSocialProofTier !== void 0 ? _getSocialProofTier : 'low';
32
+ const tier = connectedPct !== undefined && connectedPct >= TIER_THRESHOLD ? 'not-low' : 'low';
69
33
  return {
70
34
  isTreatment,
71
35
  tier,
@@ -1,6 +1,5 @@
1
- import React, { useMemo } from 'react';
1
+ import React, { useCallback, useMemo } from 'react';
2
2
  import { AnalyticsContext } from '@atlaskit/analytics-next';
3
- import FeatureGates from '@atlaskit/feature-gate-js-client';
4
3
  import { getResolvedAttributes } from '@atlaskit/link-analytics/resolved-attributes';
5
4
  import { useSmartLinkContext } from '@atlaskit/link-provider';
6
5
  import { getUrl } from '@atlaskit/linking-common';
@@ -24,12 +23,9 @@ const getSmartLinkAnalyticsContext = ({
24
23
  url,
25
24
  error
26
25
  }) => {
27
- const isHyperlinkConnectExperimentEnabled = FeatureGates.getExperimentValue('platform_linking_bluelink_connect_confluence', 'isEnabled', false) || FeatureGates.getExperimentValue('platform_linking_bluelink_connect_jira', 'isEnabled', false);
28
- const resolvedAttributes = isHyperlinkConnectExperimentEnabled ? getExtendedResolvedAttributes({
26
+ const resolvedAttributes = getExtendedResolvedAttributes({
29
27
  url,
30
28
  displayCategory: display === 'url' ? 'link' : 'smartLink'
31
- }, response, status, error) : getExtendedResolvedAttributes({
32
- url
33
29
  }, response, status, error);
34
30
  return {
35
31
  source,
@@ -45,6 +41,32 @@ const getSmartLinkAnalyticsContext = ({
45
41
  * Provides an analytics context data to supply attributes to events based on a URL
46
42
  * and the link state in the store
47
43
  */
44
+ export const useSmartLinkAnalyticsUtils = () => {
45
+ const {
46
+ store
47
+ } = useSmartLinkContext();
48
+ const getByUrl = useCallback((url, props) => {
49
+ const state = store ? getUrl(store, url) : undefined;
50
+ return getSmartLinkAnalyticsContext({
51
+ display: props === null || props === void 0 ? void 0 : props.display,
52
+ id: props === null || props === void 0 ? void 0 : props.id,
53
+ response: state === null || state === void 0 ? void 0 : state.details,
54
+ source: props === null || props === void 0 ? void 0 : props.source,
55
+ status: state === null || state === void 0 ? void 0 : state.status,
56
+ url,
57
+ error: state === null || state === void 0 ? void 0 : state.error
58
+ });
59
+ }, [store]);
60
+ return useMemo(() => ({
61
+ getByUrl
62
+ }), [getByUrl]);
63
+ };
64
+
65
+ /**
66
+ * Provides an analytics context data to supply attributes to events based on a URL
67
+ * and the link state in the store
68
+ * @deprecated Use useSmartLinkAnalyticsUtils instead
69
+ */
48
70
  export const useSmartLinkAnalyticsContext = ({
49
71
  display,
50
72
  id,
@@ -16,7 +16,7 @@ import { ElementName, SmartLinkDirection, SmartLinkSize, SmartLinkWidth } from '
16
16
  import { messages } from '../../../messages';
17
17
  import { useFlexibleCardContext } from '../../../state/flexible-ui-context';
18
18
  import { hasAuthScopeOverrides } from '../../../state/helpers';
19
- import useSocialProofExperiment, { getSocialProofExperimentMeta } from '../../../state/hooks/use-social-proof-experiment';
19
+ import useSocialProofExperiment from '../../../state/hooks/use-social-proof-experiment';
20
20
  import UnauthorisedViewContent from '../../common/UnauthorisedViewContent';
21
21
  import FlexibleCard from '../../FlexibleCard';
22
22
  import ActionGroup from '../../FlexibleCard/components/blocks/action-group';
@@ -251,28 +251,19 @@ const UnauthorisedViewWithExperiment = ({
251
251
  tier,
252
252
  connectedPct
253
253
  } = useSocialProofExperiment(providerName ? extensionKey : undefined, connections.client.baseUrlOverride);
254
- const socialProofExperimentMeta = getSocialProofExperimentMeta({
255
- extensionKey,
256
- baseUriWithNoTrailingSlash: connections.client.baseUrlOverride
257
- });
258
- const analyticsContextData = {
259
- attributes: {
260
- experiment: 'social_proof_3p_unauth_block_exp',
261
- cohort: isTreatment ? 'treatment' : 'control',
262
- tier,
263
- experimentMeta: socialProofExperimentMeta
264
- }
265
- };
266
254
  if (!isTreatment || !providerName) {
267
- const fallbackView = /*#__PURE__*/React.createElement(UnauthorisedViewBase, _extends({}, props, {
255
+ return /*#__PURE__*/React.createElement(UnauthorisedViewBase, _extends({}, props, {
268
256
  testId: testId
269
257
  }));
270
- return connectedPct !== undefined ? /*#__PURE__*/React.createElement(AnalyticsContext, {
271
- data: analyticsContextData
272
- }, fallbackView) : fallbackView;
273
258
  }
274
259
  return /*#__PURE__*/React.createElement(AnalyticsContext, {
275
- data: analyticsContextData
260
+ data: {
261
+ attributes: {
262
+ experiment: 'social_proof_3p_unauth_block_exp',
263
+ cohort: 'treatment',
264
+ tier
265
+ }
266
+ }
276
267
  }, /*#__PURE__*/React.createElement(UnauthorisedViewFrame, _extends({}, props, {
277
268
  content: /*#__PURE__*/React.createElement(SocialProofMessage, {
278
269
  tier: tier,
@@ -1,14 +1,34 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
- import React, { useCallback, useState } from 'react';
2
+ import React, { useCallback } from 'react';
3
3
  import useIntersectionObserver from '../../../state/hooks/use-intersection-observer';
4
- import { isIntersectionObserverSupported } from '../../../utils';
4
+ import { useSmartLinkSeenEvent } from '../../../state/hooks/use-smart-link-seen-event';
5
5
  import CardLoaderWrapper from '../card-loader-wrapper';
6
6
  const withCardIntersectionObserver = Component => props => {
7
7
  // TODO: NAVX-4682: Add feature parity to LazyIntersectionObserverCard for no lazy loading
8
- const [isIntersected, setIsIntersected] = useState(false);
9
- const onIntersecting = useCallback(() => {
10
- setIsIntersected(true);
11
- }, []);
8
+ const {
9
+ appearance,
10
+ children,
11
+ id,
12
+ onError: onErrorCallback,
13
+ ui,
14
+ url = ''
15
+ } = props;
16
+ const {
17
+ onIntersecting,
18
+ onStatusSettled
19
+ } = useSmartLinkSeenEvent({
20
+ appearance,
21
+ children,
22
+ id,
23
+ ui,
24
+ url
25
+ });
26
+ const onError = useCallback(data => {
27
+ if (data !== null && data !== void 0 && data.status) {
28
+ onStatusSettled(data.status);
29
+ }
30
+ onErrorCallback === null || onErrorCallback === void 0 ? void 0 : onErrorCallback(data);
31
+ }, [onStatusSettled, onErrorCallback]);
12
32
  const ref = useIntersectionObserver({
13
33
  onIntersecting
14
34
  });
@@ -16,10 +36,7 @@ const withCardIntersectionObserver = Component => props => {
16
36
  appearance: props.appearance,
17
37
  ref: ref
18
38
  }, /*#__PURE__*/React.createElement(Component, _extends({}, props, {
19
- isIntersected: isIntersected
39
+ onError: onError
20
40
  })));
21
41
  };
22
- const withCardIntersectionObserverFallback = Component => props => /*#__PURE__*/React.createElement(CardLoaderWrapper, {
23
- appearance: props.appearance
24
- }, /*#__PURE__*/React.createElement(Component, props));
25
- export default (Component => isIntersectionObserverSupported() ? withCardIntersectionObserver(Component) : withCardIntersectionObserverFallback(Component));
42
+ export default withCardIntersectionObserver;
@@ -4,6 +4,7 @@ import { componentWithFG } from '@atlaskit/platform-feature-flags-react';
4
4
  import { usePrefetch } from '../../../state';
5
5
  import { startUfoExperience } from '../../../state/analytics/ufoExperiences';
6
6
  import useIntersectionObserver from '../../../state/hooks/use-intersection-observer';
7
+ import { useSmartLinkSeenEvent } from '../../../state/hooks/use-smart-link-seen-event';
7
8
  import { shouldSample } from '../../../utils/shouldSample';
8
9
  import CardLoaderWrapper from '../card-loader-wrapper';
9
10
  import { CardWithUrlContent } from '../component';
@@ -62,26 +63,46 @@ const LazyIntersectionObserverCardNew = props => {
62
63
  const [shouldSendRenderedUFOEvent] = useState(shouldSample());
63
64
  const {
64
65
  appearance,
65
- url,
66
- id
66
+ children,
67
+ id,
68
+ onError: onErrorCallback,
69
+ ui,
70
+ url
67
71
  } = props;
68
72
  const prefetch = usePrefetch(url);
69
73
  const ComponentObserver = appearance === 'inline' ? 'span' : 'div';
74
+ const {
75
+ onIntersecting: onSeenIntersecting,
76
+ onStatusSettled
77
+ } = useSmartLinkSeenEvent({
78
+ appearance,
79
+ children,
80
+ id,
81
+ ui,
82
+ url
83
+ });
84
+ const onError = useCallback(data => {
85
+ if (data !== null && data !== void 0 && data.status) {
86
+ onStatusSettled(data.status);
87
+ }
88
+ onErrorCallback === null || onErrorCallback === void 0 ? void 0 : onErrorCallback(data);
89
+ }, [onStatusSettled, onErrorCallback]);
70
90
  const onIntersection = useCallback(isIntersecting => {
71
91
  if (isIntersecting) {
72
92
  if (shouldSendRenderedUFOEvent) {
73
93
  startUfoExperience('smart-link-rendered', id);
74
94
  }
95
+ onSeenIntersecting();
75
96
  setIsIntersected(true);
76
97
  } else {
77
98
  prefetch();
78
99
  }
79
- }, [id, prefetch, shouldSendRenderedUFOEvent]);
100
+ }, [id, onSeenIntersecting, prefetch, shouldSendRenderedUFOEvent]);
80
101
  const ref = useIntersectionObserver({
81
102
  onIntersection
82
103
  });
83
104
  const content = isIntersected ? /*#__PURE__*/React.createElement(CardWithUrlContent, _extends({}, props, {
84
- isIntersected: true
105
+ onError: onError
85
106
  })) : /*#__PURE__*/React.createElement(ComponentObserver, {
86
107
  ref: ref
87
108
  }, /*#__PURE__*/React.createElement(LoadingCardLink, props));
@@ -1,4 +1,4 @@
1
- import React, { useCallback, useEffect, useMemo, useRef } from 'react';
1
+ import React, { useCallback, useEffect, useMemo } from 'react';
2
2
  import { useAnalyticsEvents as useAnalyticsEventsNext } from '@atlaskit/analytics-next';
3
3
  import { extractSmartLinkEmbed } from '@atlaskit/link-extractors';
4
4
  import { fg } from '@atlaskit/platform-feature-flags';
@@ -24,7 +24,6 @@ import FlexibleCard from '../FlexibleCard';
24
24
  import { InlineCard } from '../InlineCard';
25
25
  import { useFire3PWorkflowsClickEvent } from '../SmartLinkEvents/useSmartLinkEvents';
26
26
  import withCardIntersectionObserver from './card-intersection-observer';
27
- import useExperimentMetaEventAttributes from './experiment-meta-event-attributes';
28
27
  const thirdPartyARIPrefix = 'ari:third-party';
29
28
  const EmbedCardComponent = componentWithFG('rovo_chat_embed_card_dwell_and_hover_metrics', EmbedCardUpdated, EmbedCard);
30
29
  function Component({
@@ -32,7 +31,6 @@ function Component({
32
31
  url,
33
32
  isSelected,
34
33
  isHovered,
35
- isIntersected,
36
34
  frameStyle,
37
35
  platform,
38
36
  onClick,
@@ -63,7 +61,6 @@ function Component({
63
61
  const {
64
62
  fireEvent
65
63
  } = useAnalyticsEvents();
66
- const hasFiredSeenRef = useRef(false);
67
64
  let isFlexibleUi = useMemo(() => isFlexibleUiCard(children, ui), [children, ui]);
68
65
 
69
66
  // Get state, actions for this card.
@@ -167,10 +164,6 @@ function Component({
167
164
  actions.reload();
168
165
  }, [actions]);
169
166
  const handleInvoke = useCallback(opts => actions.invoke(opts, appearance), [actions, appearance]);
170
- const experimentMetaEventAttributes = useExperimentMetaEventAttributes({
171
- appearance,
172
- state
173
- });
174
167
 
175
168
  // NB: for each status change in a Smart Link, a performance mark is created.
176
169
  // Measures are sent relative to the first mark, matching what a user sees.
@@ -218,26 +211,10 @@ function Component({
218
211
  display: isFlexibleUi ? 'flexible' : appearance,
219
212
  ...(appearance === 'inline' && {
220
213
  rovoActionsCtaShown
221
- }),
222
- ...(experimentMetaEventAttributes && {
223
- experimentMeta: experimentMetaEventAttributes
224
214
  })
225
215
  });
226
216
  }
227
- }, [appearance, extensionKey, fireEvent, id, isFlexibleUi, rovoActionsCtaShown, state.status, experimentMetaEventAttributes]);
228
-
229
- // Fire smartLink seen event once on a successful render card is in the viewport
230
- useEffect(() => {
231
- if (fg('platform_sl_event_ui_seen')) {
232
- if (state.status !== 'unauthorized') return;
233
- if (isIntersected && !hasFiredSeenRef.current) {
234
- fireEvent('ui.smartLink.seen', {
235
- display: appearance
236
- });
237
- hasFiredSeenRef.current = true;
238
- }
239
- }
240
- }, [state.status, isIntersected, fireEvent, appearance]);
217
+ }, [appearance, extensionKey, fireEvent, id, isFlexibleUi, rovoActionsCtaShown, state.status]);
241
218
  const onIframeDwell = useCallback((dwellTime, dwellPercentVisible) => {
242
219
  fireEvent('ui.smartLinkIframe.dwelled', {
243
220
  id,
@@ -360,7 +337,6 @@ function ComponentUpdated({
360
337
  url,
361
338
  isSelected,
362
339
  isHovered,
363
- isIntersected,
364
340
  frameStyle,
365
341
  platform,
366
342
  onClick,
@@ -391,7 +367,6 @@ function ComponentUpdated({
391
367
  const {
392
368
  fireEvent
393
369
  } = useAnalyticsEvents();
394
- const hasFiredSeenRef = useRef(false);
395
370
  let isFlexibleUi = useMemo(() => isFlexibleUiCard(children, ui), [children, ui]);
396
371
 
397
372
  // Get state, actions for this card.
@@ -495,10 +470,6 @@ function ComponentUpdated({
495
470
  actions.reload();
496
471
  }, [actions]);
497
472
  const handleInvoke = useCallback(opts => actions.invoke(opts, appearance), [actions, appearance]);
498
- const experimentMetaEventAttributes = useExperimentMetaEventAttributes({
499
- appearance,
500
- state
501
- });
502
473
 
503
474
  // NB: for each status change in a Smart Link, a performance mark is created.
504
475
  // Measures are sent relative to the first mark, matching what a user sees.
@@ -546,26 +517,10 @@ function ComponentUpdated({
546
517
  display: isFlexibleUi ? 'flexible' : appearance,
547
518
  ...(appearance === 'inline' && {
548
519
  rovoActionsCtaShown
549
- }),
550
- ...(experimentMetaEventAttributes && {
551
- experimentMeta: experimentMetaEventAttributes
552
520
  })
553
521
  });
554
522
  }
555
- }, [appearance, extensionKey, fireEvent, id, isFlexibleUi, rovoActionsCtaShown, state.status, experimentMetaEventAttributes]);
556
-
557
- // Fire smartLink seen event once on a successful render card is in the viewport
558
- useEffect(() => {
559
- if (fg('platform_sl_event_ui_seen')) {
560
- if (state.status !== 'unauthorized') return;
561
- if (isIntersected && !hasFiredSeenRef.current) {
562
- fireEvent('ui.smartLink.seen', {
563
- display: appearance
564
- });
565
- hasFiredSeenRef.current = true;
566
- }
567
- }
568
- }, [state.status, isIntersected, fireEvent, appearance]);
523
+ }, [appearance, extensionKey, fireEvent, id, isFlexibleUi, rovoActionsCtaShown, state.status]);
569
524
  const onIframeDwell = useCallback((dwellTime, dwellPercentVisible) => {
570
525
  fireEvent('ui.smartLinkIframe.dwelled', {
571
526
  id,
@@ -1,4 +1,5 @@
1
1
  import React, { forwardRef, useCallback } from 'react';
2
+ import { fg } from '@atlaskit/platform-feature-flags';
2
3
  import { useMouseDownEvent } from '../../../state/analytics/useLinkClicked';
3
4
  import { WrapperAnchor, WrapperSpan } from './styled';
4
5
  export const Frame = /*#__PURE__*/forwardRef((props, ref) => {
@@ -42,8 +43,8 @@ export const Frame = /*#__PURE__*/forwardRef((props, ref) => {
42
43
  withoutBackground: withoutBackground,
43
44
  isSelected: isSelected,
44
45
  isInteractive: isInteractive,
45
- tabIndex: isInteractive ? 0 : undefined,
46
- role: isInteractive ? 'button' : undefined,
46
+ tabIndex: isInteractive && (fg('navx-3611-inline-card-a11y-role-fix') ? !link : true) ? 0 : undefined,
47
+ role: isInteractive && (fg('navx-3611-inline-card-a11y-role-fix') ? !link : true) ? 'button' : undefined,
47
48
  onClick: handleClick,
48
49
  onMouseDown: handleMouseDown,
49
50
  onKeyPress: handleKeyPress,
@@ -2,17 +2,14 @@ import _extends from "@babel/runtime/helpers/extends";
2
2
  import React, { useCallback } from 'react';
3
3
  import { withErrorBoundary as withReactErrorBoundary } from 'react-error-boundary';
4
4
  import { injectIntl } from 'react-intl';
5
- import FeatureGates from '@atlaskit/feature-gate-js-client';
6
- import { extractSmartLinkProvider } from '@atlaskit/link-extractors';
7
5
  import { fg } from '@atlaskit/platform-feature-flags';
8
- import { getFirstPartyIdentifier, getServices, getThirdPartyARI } from '../../../state/helpers';
6
+ import { getFirstPartyIdentifier, getThirdPartyARI } from '../../../state/helpers';
9
7
  import useResolveHyperlink from '../../../state/hooks/use-resolve-hyperlink';
10
8
  import useResolveHyperlinkValidator from '../../../state/hooks/use-resolve-hyperlink/useResolveHyperlinkValidator';
11
9
  import { SmartLinkAnalyticsContext } from '../../../utils/analytics/SmartLinkAnalyticsContext';
12
10
  import withIntlProvider from '../../common/intl-provider';
13
11
  import { useFire3PWorkflowsClickEvent } from '../../SmartLinkEvents/useSmartLinkEvents';
14
12
  import Hyperlink from '../Hyperlink';
15
- import HyperlinkUnauthorizedView from './unauthorize-view';
16
13
  const HyperlinkFallbackComponent = () => null;
17
14
  const withValidator = (Component, DefaultComponent) => props => {
18
15
  const shouldResolveHyperlink = useResolveHyperlinkValidator(props === null || props === void 0 ? void 0 : props.href);
@@ -26,12 +23,10 @@ const HyperlinkWithSmartLinkResolverInner = ({
26
23
  ...props
27
24
  }) => {
28
25
  const {
29
- actions,
30
26
  state
31
27
  } = useResolveHyperlink({
32
28
  href: props.href || ''
33
29
  });
34
- const services = getServices(state === null || state === void 0 ? void 0 : state.details);
35
30
  const thirdPartyARI = getThirdPartyARI(state === null || state === void 0 ? void 0 : state.details);
36
31
  const firstPartyIdentifier = getFirstPartyIdentifier();
37
32
  const fire3PClickEvent = fg('platform_smartlink_3pclick_analytics') ?
@@ -46,40 +41,6 @@ const HyperlinkWithSmartLinkResolverInner = ({
46
41
  }
47
42
  onClickCallback === null || onClickCallback === void 0 ? void 0 : onClickCallback(e);
48
43
  }, [onClickCallback, fire3PClickEvent, state === null || state === void 0 ? void 0 : state.status]);
49
- const onAuthorize = useCallback(() => actions.authorize('url'), [actions]);
50
- const shouldRenderConnectBtn = () => {
51
- if (!props.children || !Array.isArray(props.children) || props.children.length === 0) {
52
- return false;
53
- }
54
- const firstChild = props.children[0];
55
- try {
56
- var _firstChild$props;
57
- // Check if first child has a string matching href
58
- if (typeof firstChild === 'string') {
59
- return props.href === firstChild;
60
- }
61
-
62
- // Check if first child has another child object containing matching href. This aligns with the behavior of the TextWrapper component used by editor to render link nodes
63
- if (firstChild !== null && firstChild !== void 0 && (_firstChild$props = firstChild.props) !== null && _firstChild$props !== void 0 && _firstChild$props.children && typeof firstChild.props.children === 'string') {
64
- return props.href === firstChild.props.children;
65
- }
66
- } catch (_) {
67
- return false;
68
- }
69
- };
70
- if ((state === null || state === void 0 ? void 0 : state.status) === 'unauthorized' && shouldRenderConnectBtn() && (
71
- // eslint-disable-next-line @atlaskit/platform/use-recommended-utils -- Statsig migration pending for Bluelink connect experiments
72
- FeatureGates.getExperimentValue('platform_linking_bluelink_connect_confluence', 'isEnabled', false) ||
73
- // eslint-disable-next-line @atlaskit/platform/use-recommended-utils -- Statsig migration pending for Bluelink connect experiments
74
- FeatureGates.getExperimentValue('platform_linking_bluelink_connect_jira', 'isEnabled', false))) {
75
- const provider = extractSmartLinkProvider(state === null || state === void 0 ? void 0 : state.details);
76
- return /*#__PURE__*/React.createElement(HyperlinkUnauthorizedView, _extends({}, props, {
77
- onAuthorize: services !== null && services !== void 0 && services.length ? onAuthorize : undefined,
78
- onClick: onClick,
79
- showConnectBtn: (services === null || services === void 0 ? void 0 : services.length) > 0,
80
- provider: provider
81
- }));
82
- }
83
44
  return /*#__PURE__*/React.createElement(Hyperlink, _extends({}, props, {
84
45
  onClick: onClick
85
46
  }));
@@ -1,4 +1,5 @@
1
1
  import { useCallback, useEffect, useRef } from 'react';
2
+ import { isIntersectionObserverSupported } from '../../../utils';
2
3
 
3
4
  // This property enables the intersection observer to be run once the
4
5
  // HTML element being observed is within `X` px of the target container it is
@@ -28,7 +29,7 @@ var useIntersectionObserver = function useIntersectionObserver(_ref) {
28
29
  }
29
30
  }, []);
30
31
  useEffect(function () {
31
- if (!ref.current) {
32
+ if (!isIntersectionObserverSupported() || !ref.current) {
32
33
  return;
33
34
  }
34
35
  var intersectionObserver = new IntersectionObserver(onIntersection, {