@atlaskit/smart-card 40.7.2 → 40.8.0

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 (27) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/analytics.spec.yaml +129 -112
  3. package/dist/cjs/utils/analytics/analytics.js +1 -1
  4. package/dist/cjs/view/CardWithUrl/component-lazy/LazyIntersectionObserverCard.js +24 -8
  5. package/dist/cjs/view/CardWithUrl/component.js +23 -0
  6. package/dist/cjs/view/FlexibleCard/components/elements/common/base-avatar-group-element/index.compiled.css +1 -3
  7. package/dist/cjs/view/FlexibleCard/components/elements/common/base-avatar-group-element/index.js +1 -10
  8. package/dist/cjs/view/LinkUrl/index.js +1 -1
  9. package/dist/es2019/utils/analytics/analytics.js +1 -1
  10. package/dist/es2019/view/CardWithUrl/component-lazy/LazyIntersectionObserverCard.js +24 -8
  11. package/dist/es2019/view/CardWithUrl/component.js +23 -0
  12. package/dist/es2019/view/FlexibleCard/components/elements/common/base-avatar-group-element/index.compiled.css +1 -3
  13. package/dist/es2019/view/FlexibleCard/components/elements/common/base-avatar-group-element/index.js +2 -10
  14. package/dist/es2019/view/LinkUrl/index.js +1 -1
  15. package/dist/esm/utils/analytics/analytics.js +1 -1
  16. package/dist/esm/view/CardWithUrl/component-lazy/LazyIntersectionObserverCard.js +25 -9
  17. package/dist/esm/view/CardWithUrl/component.js +23 -0
  18. package/dist/esm/view/FlexibleCard/components/elements/common/base-avatar-group-element/index.compiled.css +1 -3
  19. package/dist/esm/view/FlexibleCard/components/elements/common/base-avatar-group-element/index.js +2 -11
  20. package/dist/esm/view/LinkUrl/index.js +1 -1
  21. package/dist/types/common/analytics/generated/analytics.types.d.ts +8 -1
  22. package/dist/types/view/CardWithUrl/component-lazy/LazyIntersectionObserverCard.d.ts +5 -0
  23. package/dist/types/view/FlexibleCard/components/elements/common/base-avatar-group-element/index.d.ts +1 -1
  24. package/dist/types-ts4.5/common/analytics/generated/analytics.types.d.ts +8 -1
  25. package/dist/types-ts4.5/view/CardWithUrl/component-lazy/LazyIntersectionObserverCard.d.ts +5 -0
  26. package/dist/types-ts4.5/view/FlexibleCard/components/elements/common/base-avatar-group-element/index.d.ts +1 -1
  27. package/package.json +7 -7
@@ -10,6 +10,7 @@ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/sli
10
10
  var _react = _interopRequireWildcard(require("react"));
11
11
  var _state = require("../../../state");
12
12
  var _ufoExperiences = require("../../../state/analytics/ufoExperiences");
13
+ var _store = require("../../../state/store");
13
14
  var _shouldSample = require("../../../utils/shouldSample");
14
15
  var _component = require("../component");
15
16
  var _LoadingCardLink = require("./LoadingCardLink");
@@ -19,18 +20,25 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
19
20
  // being compared to. Since the default container is the `document`, we set this
20
21
  // up to check once a Smart Link is within `X` px from the bottom of the viewport.
21
22
  var ROOT_MARGIN_VERTICAL = '360px';
23
+ // Returns true on SSR and SPA if page was SSR'd
24
+ var isPageSSRd = function isPageSSRd() {
25
+ return Boolean(process.env.REACT_SSR || window.__SSR_RENDERED__);
26
+ };
22
27
  function LazyIntersectionObserverCard(props) {
28
+ var appearance = props.appearance,
29
+ url = props.url,
30
+ id = props.id;
23
31
  var ref = (0, _react.useRef)(null);
24
- var _useState = (0, _react.useState)(false),
32
+ var state = (0, _store.useSmartCardState)(url);
33
+ // If page was SSR we don't need to enable intersection for already resolved cards,
34
+ // to avoid flickering.
35
+ var _useState = (0, _react.useState)(isPageSSRd() && state.status === 'resolved'),
25
36
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
26
37
  isIntersecting = _useState2[0],
27
38
  setIsIntersecting = _useState2[1];
28
39
  var _useState3 = (0, _react.useState)((0, _shouldSample.shouldSample)()),
29
40
  _useState4 = (0, _slicedToArray2.default)(_useState3, 1),
30
41
  shouldSendRenderedUFOEvent = _useState4[0];
31
- var appearance = props.appearance,
32
- url = props.url,
33
- id = props.id;
34
42
  var prefetch = (0, _state.usePrefetch)(url);
35
43
  var Component = appearance === 'inline' ? 'span' : 'div';
36
44
  var ComponentObserver = Component;
@@ -39,15 +47,23 @@ function LazyIntersectionObserverCard(props) {
39
47
  return entry.isIntersecting;
40
48
  });
41
49
  if (isVisible) {
42
- if (shouldSendRenderedUFOEvent) {
43
- (0, _ufoExperiences.startUfoExperience)('smart-link-rendered', id);
44
- }
45
50
  setIsIntersecting(true);
46
51
  observer.disconnect();
47
52
  } else {
48
53
  prefetch();
49
54
  }
50
- }, [id, prefetch, shouldSendRenderedUFOEvent]);
55
+ }, [prefetch]);
56
+ var isSartUfoExperienceSend = (0, _react.useRef)(false);
57
+ // We need to use `useLayoutEffect` here to ensure that the UFO start event is sent
58
+ // before another component is rendered.
59
+ (0, _react.useLayoutEffect)(function () {
60
+ if (isIntersecting && !isSartUfoExperienceSend.current) {
61
+ isSartUfoExperienceSend.current = true;
62
+ if (shouldSendRenderedUFOEvent) {
63
+ (0, _ufoExperiences.startUfoExperience)('smart-link-rendered', id);
64
+ }
65
+ }
66
+ }, [id, isIntersecting, shouldSendRenderedUFOEvent]);
51
67
  (0, _react.useEffect)(function () {
52
68
  if (!ref.current) {
53
69
  return;
@@ -26,6 +26,7 @@ var _EmbedCard = require("../EmbedCard");
26
26
  var _FlexibleCard = _interopRequireDefault(require("../FlexibleCard"));
27
27
  var _InlineCard = require("../InlineCard");
28
28
  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); }
29
+ var thirdPartyARIPrefix = 'ari:third-party';
29
30
  function Component(_ref) {
30
31
  var id = _ref.id,
31
32
  url = _ref.url,
@@ -89,6 +90,28 @@ function Component(_ref) {
89
90
  definitionId: definitionId !== null && definitionId !== void 0 ? definitionId : null,
90
91
  isModifierKeyPressed: isModifierKeyPressed
91
92
  });
93
+ if ((0, _platformFeatureFlags.fg)('platform_smartlink_3pclick_analytics')) {
94
+ if (ari && ari.startsWith(thirdPartyARIPrefix)) {
95
+ var sourceURL = window.location.href;
96
+ var clickURL = (0, _helpers.getClickUrl)(url, state.details);
97
+ if (clickURL === url) {
98
+ // For questions or concerns about this event,
99
+ // please reach out to the 3P Workflows Team via Slack in #help-3p-connector-workflow
100
+ var smartlinkClickAnalyticsEvent = createAnalyticsEvent({
101
+ action: 'clicked',
102
+ actionSubject: 'smartLink',
103
+ actionSubjectId: 'smartlinkClickAnalyticsWorkflows',
104
+ eventType: 'ui',
105
+ attributes: {},
106
+ nonPrivacySafeAttributes: {
107
+ sourceURL: sourceURL,
108
+ thirdPartyARI: ari
109
+ }
110
+ });
111
+ smartlinkClickAnalyticsEvent.fire();
112
+ }
113
+ }
114
+ }
92
115
 
93
116
  // If preview panel is available and the user clicked on the link,
94
117
  // delegate the click to the preview panel handler
@@ -1,6 +1,4 @@
1
1
  ._102oidpf ul{margin-top:0}
2
2
  ._1e0c116y{display:inline-flex}
3
3
  ._1kvxu2gc ul{margin-right:var(--ds-space-100,8px)}
4
- ._1ul91ns9{min-width:-moz-fit-content;min-width:fit-content}
5
- ._6fu61k92 li span, ._1rrq1k92 li svg{max-height:1.25rem}
6
- ._udwj1k92 li span, ._10pr1k92 li svg{max-width:1.25rem}
4
+ ._1ul91ns9{min-width:-moz-fit-content;min-width:fit-content}
@@ -22,14 +22,7 @@ var _utils = require("../../../utils");
22
22
  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); }
23
23
  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; }
24
24
  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; }
25
- var stylesOld = null;
26
25
  var styles = null;
27
- var stylesMap = {
28
- xlarge: "_1e0c116y _1kvxu2gc _102oidpf",
29
- large: "_1e0c116y _1kvxu2gc _102oidpf",
30
- medium: "_1e0c116y _1kvxu2gc _102oidpf _6fu61k92 _1rrq1k92 _udwj1k92 _10pr1k92",
31
- small: "_1e0c116y _1kvxu2gc _102oidpf _6fu61k92 _1rrq1k92 _udwj1k92 _10pr1k92"
32
- };
33
26
  var getPersonNameWithPrefix = function getPersonNameWithPrefix(elementName, personName, intl) {
34
27
  switch (elementName) {
35
28
  case _constants.ElementName.AssignedToGroup:
@@ -56,8 +49,6 @@ var BaseAvatarGroup = function BaseAvatarGroup(_ref) {
56
49
  maxCount = _ref$maxCount === void 0 ? 4 : _ref$maxCount,
57
50
  name = _ref.name,
58
51
  className = _ref.className,
59
- _ref$size = _ref.size,
60
- size = _ref$size === void 0 ? _constants.SmartLinkSize.Medium : _ref$size,
61
52
  _ref$testId = _ref.testId,
62
53
  testId = _ref$testId === void 0 ? 'smart-element-avatar-group' : _ref$testId,
63
54
  _ref$showNamePrefix = _ref.showNamePrefix,
@@ -96,7 +87,7 @@ var BaseAvatarGroup = function BaseAvatarGroup(_ref) {
96
87
  "data-testid": testId
97
88
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop
98
89
  ,
99
- className: (0, _runtime.ax)([!(0, _platformFeatureFlags.fg)('platform-linking-fix-smart-card-avatar-overrides') && stylesMap[size], (0, _platformFeatureFlags.fg)('platform-linking-fix-smart-card-avatar-overrides') ? "_1ul91ns9 _1e0c116y _1kvxu2gc _102oidpf" : "_1ul91ns9", className])
90
+ className: (0, _runtime.ax)(["_1ul91ns9 _1e0c116y _1kvxu2gc _102oidpf", className])
100
91
  }), /*#__PURE__*/React.createElement(_avatarGroup.default, {
101
92
  maxCount: maxCount,
102
93
  appearance: "stack",
@@ -19,7 +19,7 @@ var _excluded = ["href", "children", "checkSafety", "onClick", "testId", "isLink
19
19
  _excluded2 = ["isLinkSafe", "showSafetyWarningModal"];
20
20
  var PACKAGE_DATA = {
21
21
  packageName: "@atlaskit/smart-card",
22
- packageVersion: "40.7.1",
22
+ packageVersion: "40.7.3",
23
23
  componentName: 'linkUrl'
24
24
  };
25
25
  var Anchor = (0, _click.withLinkClickedEvent)('a');
@@ -2,7 +2,7 @@ export const ANALYTICS_CHANNEL = 'media';
2
2
  export const context = {
3
3
  componentName: 'smart-cards',
4
4
  packageName: "@atlaskit/smart-card",
5
- packageVersion: "40.7.1"
5
+ packageVersion: "40.7.3"
6
6
  };
7
7
  export let TrackQuickActionType = /*#__PURE__*/function (TrackQuickActionType) {
8
8
  TrackQuickActionType["StatusUpdate"] = "StatusUpdate";
@@ -1,6 +1,7 @@
1
- import React, { useCallback, useEffect, useRef, useState } from 'react';
1
+ import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
2
2
  import { usePrefetch } from '../../../state';
3
3
  import { startUfoExperience } from '../../../state/analytics/ufoExperiences';
4
+ import { useSmartCardState } from '../../../state/store';
4
5
  import { shouldSample } from '../../../utils/shouldSample';
5
6
  import { CardWithUrlContent } from '../component';
6
7
  import { LoadingCardLink } from './LoadingCardLink';
@@ -10,30 +11,45 @@ import { LoadingCardLink } from './LoadingCardLink';
10
11
  // being compared to. Since the default container is the `document`, we set this
11
12
  // up to check once a Smart Link is within `X` px from the bottom of the viewport.
12
13
  const ROOT_MARGIN_VERTICAL = '360px';
14
+ // Returns true on SSR and SPA if page was SSR'd
15
+ const isPageSSRd = () => {
16
+ return Boolean(process.env.REACT_SSR || window.__SSR_RENDERED__);
17
+ };
13
18
  export function LazyIntersectionObserverCard(props) {
14
- const ref = useRef(null);
15
- const [isIntersecting, setIsIntersecting] = useState(false);
16
- const [shouldSendRenderedUFOEvent] = useState(shouldSample());
17
19
  const {
18
20
  appearance,
19
21
  url,
20
22
  id
21
23
  } = props;
24
+ const ref = useRef(null);
25
+ const state = useSmartCardState(url);
26
+ // If page was SSR we don't need to enable intersection for already resolved cards,
27
+ // to avoid flickering.
28
+ const [isIntersecting, setIsIntersecting] = useState(isPageSSRd() && state.status === 'resolved');
29
+ const [shouldSendRenderedUFOEvent] = useState(shouldSample());
22
30
  const prefetch = usePrefetch(url);
23
31
  const Component = appearance === 'inline' ? 'span' : 'div';
24
32
  const ComponentObserver = Component;
25
33
  const onIntersection = useCallback((entries, observer) => {
26
34
  const isVisible = entries.some(entry => entry.isIntersecting);
27
35
  if (isVisible) {
28
- if (shouldSendRenderedUFOEvent) {
29
- startUfoExperience('smart-link-rendered', id);
30
- }
31
36
  setIsIntersecting(true);
32
37
  observer.disconnect();
33
38
  } else {
34
39
  prefetch();
35
40
  }
36
- }, [id, prefetch, shouldSendRenderedUFOEvent]);
41
+ }, [prefetch]);
42
+ const isSartUfoExperienceSend = useRef(false);
43
+ // We need to use `useLayoutEffect` here to ensure that the UFO start event is sent
44
+ // before another component is rendered.
45
+ useLayoutEffect(() => {
46
+ if (isIntersecting && !isSartUfoExperienceSend.current) {
47
+ isSartUfoExperienceSend.current = true;
48
+ if (shouldSendRenderedUFOEvent) {
49
+ startUfoExperience('smart-link-rendered', id);
50
+ }
51
+ }
52
+ }, [id, isIntersecting, shouldSendRenderedUFOEvent]);
37
53
  useEffect(() => {
38
54
  if (!ref.current) {
39
55
  return;
@@ -17,6 +17,7 @@ import { BlockCard } from '../BlockCard';
17
17
  import { EmbedCard } from '../EmbedCard';
18
18
  import FlexibleCard from '../FlexibleCard';
19
19
  import { InlineCard } from '../InlineCard';
20
+ const thirdPartyARIPrefix = 'ari:third-party';
20
21
  function Component({
21
22
  id,
22
23
  url,
@@ -82,6 +83,28 @@ function Component({
82
83
  definitionId: definitionId !== null && definitionId !== void 0 ? definitionId : null,
83
84
  isModifierKeyPressed
84
85
  });
86
+ if (fg('platform_smartlink_3pclick_analytics')) {
87
+ if (ari && ari.startsWith(thirdPartyARIPrefix)) {
88
+ const sourceURL = window.location.href;
89
+ const clickURL = getClickUrl(url, state.details);
90
+ if (clickURL === url) {
91
+ // For questions or concerns about this event,
92
+ // please reach out to the 3P Workflows Team via Slack in #help-3p-connector-workflow
93
+ const smartlinkClickAnalyticsEvent = createAnalyticsEvent({
94
+ action: 'clicked',
95
+ actionSubject: 'smartLink',
96
+ actionSubjectId: 'smartlinkClickAnalyticsWorkflows',
97
+ eventType: 'ui',
98
+ attributes: {},
99
+ nonPrivacySafeAttributes: {
100
+ sourceURL: sourceURL,
101
+ thirdPartyARI: ari
102
+ }
103
+ });
104
+ smartlinkClickAnalyticsEvent.fire();
105
+ }
106
+ }
107
+ }
85
108
 
86
109
  // If preview panel is available and the user clicked on the link,
87
110
  // delegate the click to the preview panel handler
@@ -1,6 +1,4 @@
1
1
  ._102oidpf ul{margin-top:0}
2
2
  ._1e0c116y{display:inline-flex}
3
3
  ._1kvxu2gc ul{margin-right:var(--ds-space-100,8px)}
4
- ._1ul91ns9{min-width:-moz-fit-content;min-width:fit-content}
5
- ._6fu61k92 li span, ._1rrq1k92 li svg{max-height:1.25rem}
6
- ._udwj1k92 li span, ._10pr1k92 li svg{max-width:1.25rem}
4
+ ._1ul91ns9{min-width:-moz-fit-content;min-width:fit-content}
@@ -7,17 +7,10 @@ import { useMemo } from 'react';
7
7
  import { useIntl } from 'react-intl-next';
8
8
  import AtlaskitAvatarGroup from '@atlaskit/avatar-group';
9
9
  import { fg } from '@atlaskit/platform-feature-flags';
10
- import { ElementName, SmartLinkSize } from '../../../../../../constants';
10
+ import { ElementName } from '../../../../../../constants';
11
11
  import { messages } from '../../../../../../messages';
12
12
  import { getFormattedMessageAsString } from '../../../utils';
13
- const stylesOld = null;
14
13
  const styles = null;
15
- const stylesMap = {
16
- xlarge: "_1e0c116y _1kvxu2gc _102oidpf",
17
- large: "_1e0c116y _1kvxu2gc _102oidpf",
18
- medium: "_1e0c116y _1kvxu2gc _102oidpf _6fu61k92 _1rrq1k92 _udwj1k92 _10pr1k92",
19
- small: "_1e0c116y _1kvxu2gc _102oidpf _6fu61k92 _1rrq1k92 _udwj1k92 _10pr1k92"
20
- };
21
14
  const getPersonNameWithPrefix = (elementName, personName, intl) => {
22
15
  switch (elementName) {
23
16
  case ElementName.AssignedToGroup:
@@ -42,7 +35,6 @@ const BaseAvatarGroup = ({
42
35
  maxCount = 4,
43
36
  name,
44
37
  className,
45
- size = SmartLinkSize.Medium,
46
38
  testId = 'smart-element-avatar-group',
47
39
  showNamePrefix = false,
48
40
  showFallbackAvatar = true
@@ -82,7 +74,7 @@ const BaseAvatarGroup = ({
82
74
  "data-testid": testId
83
75
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop
84
76
  ,
85
- className: ax([!fg('platform-linking-fix-smart-card-avatar-overrides') && stylesMap[size], fg('platform-linking-fix-smart-card-avatar-overrides') ? "_1ul91ns9 _1e0c116y _1kvxu2gc _102oidpf" : "_1ul91ns9", className])
77
+ className: ax(["_1ul91ns9 _1e0c116y _1kvxu2gc _102oidpf", className])
86
78
  }), /*#__PURE__*/React.createElement(AtlaskitAvatarGroup, {
87
79
  maxCount: maxCount,
88
80
  appearance: "stack",
@@ -9,7 +9,7 @@ import LinkWarningModal from './LinkWarningModal';
9
9
  import { useLinkWarningModal } from './LinkWarningModal/hooks/use-link-warning-modal';
10
10
  const PACKAGE_DATA = {
11
11
  packageName: "@atlaskit/smart-card",
12
- packageVersion: "40.7.1",
12
+ packageVersion: "40.7.3",
13
13
  componentName: 'linkUrl'
14
14
  };
15
15
  const Anchor = withLinkClickedEvent('a');
@@ -4,7 +4,7 @@ export var ANALYTICS_CHANNEL = 'media';
4
4
  export var context = {
5
5
  componentName: 'smart-cards',
6
6
  packageName: "@atlaskit/smart-card",
7
- packageVersion: "40.7.1"
7
+ packageVersion: "40.7.3"
8
8
  };
9
9
  export var TrackQuickActionType = /*#__PURE__*/function (TrackQuickActionType) {
10
10
  TrackQuickActionType["StatusUpdate"] = "StatusUpdate";
@@ -1,7 +1,8 @@
1
1
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
- import React, { useCallback, useEffect, useRef, useState } from 'react';
2
+ import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
3
3
  import { usePrefetch } from '../../../state';
4
4
  import { startUfoExperience } from '../../../state/analytics/ufoExperiences';
5
+ import { useSmartCardState } from '../../../state/store';
5
6
  import { shouldSample } from '../../../utils/shouldSample';
6
7
  import { CardWithUrlContent } from '../component';
7
8
  import { LoadingCardLink } from './LoadingCardLink';
@@ -11,18 +12,25 @@ import { LoadingCardLink } from './LoadingCardLink';
11
12
  // being compared to. Since the default container is the `document`, we set this
12
13
  // up to check once a Smart Link is within `X` px from the bottom of the viewport.
13
14
  var ROOT_MARGIN_VERTICAL = '360px';
15
+ // Returns true on SSR and SPA if page was SSR'd
16
+ var isPageSSRd = function isPageSSRd() {
17
+ return Boolean(process.env.REACT_SSR || window.__SSR_RENDERED__);
18
+ };
14
19
  export function LazyIntersectionObserverCard(props) {
20
+ var appearance = props.appearance,
21
+ url = props.url,
22
+ id = props.id;
15
23
  var ref = useRef(null);
16
- var _useState = useState(false),
24
+ var state = useSmartCardState(url);
25
+ // If page was SSR we don't need to enable intersection for already resolved cards,
26
+ // to avoid flickering.
27
+ var _useState = useState(isPageSSRd() && state.status === 'resolved'),
17
28
  _useState2 = _slicedToArray(_useState, 2),
18
29
  isIntersecting = _useState2[0],
19
30
  setIsIntersecting = _useState2[1];
20
31
  var _useState3 = useState(shouldSample()),
21
32
  _useState4 = _slicedToArray(_useState3, 1),
22
33
  shouldSendRenderedUFOEvent = _useState4[0];
23
- var appearance = props.appearance,
24
- url = props.url,
25
- id = props.id;
26
34
  var prefetch = usePrefetch(url);
27
35
  var Component = appearance === 'inline' ? 'span' : 'div';
28
36
  var ComponentObserver = Component;
@@ -31,15 +39,23 @@ export function LazyIntersectionObserverCard(props) {
31
39
  return entry.isIntersecting;
32
40
  });
33
41
  if (isVisible) {
34
- if (shouldSendRenderedUFOEvent) {
35
- startUfoExperience('smart-link-rendered', id);
36
- }
37
42
  setIsIntersecting(true);
38
43
  observer.disconnect();
39
44
  } else {
40
45
  prefetch();
41
46
  }
42
- }, [id, prefetch, shouldSendRenderedUFOEvent]);
47
+ }, [prefetch]);
48
+ var isSartUfoExperienceSend = useRef(false);
49
+ // We need to use `useLayoutEffect` here to ensure that the UFO start event is sent
50
+ // before another component is rendered.
51
+ useLayoutEffect(function () {
52
+ if (isIntersecting && !isSartUfoExperienceSend.current) {
53
+ isSartUfoExperienceSend.current = true;
54
+ if (shouldSendRenderedUFOEvent) {
55
+ startUfoExperience('smart-link-rendered', id);
56
+ }
57
+ }
58
+ }, [id, isIntersecting, shouldSendRenderedUFOEvent]);
43
59
  useEffect(function () {
44
60
  if (!ref.current) {
45
61
  return;
@@ -17,6 +17,7 @@ import { BlockCard } from '../BlockCard';
17
17
  import { EmbedCard } from '../EmbedCard';
18
18
  import FlexibleCard from '../FlexibleCard';
19
19
  import { InlineCard } from '../InlineCard';
20
+ var thirdPartyARIPrefix = 'ari:third-party';
20
21
  function Component(_ref) {
21
22
  var id = _ref.id,
22
23
  url = _ref.url,
@@ -80,6 +81,28 @@ function Component(_ref) {
80
81
  definitionId: definitionId !== null && definitionId !== void 0 ? definitionId : null,
81
82
  isModifierKeyPressed: isModifierKeyPressed
82
83
  });
84
+ if (fg('platform_smartlink_3pclick_analytics')) {
85
+ if (ari && ari.startsWith(thirdPartyARIPrefix)) {
86
+ var sourceURL = window.location.href;
87
+ var clickURL = getClickUrl(url, state.details);
88
+ if (clickURL === url) {
89
+ // For questions or concerns about this event,
90
+ // please reach out to the 3P Workflows Team via Slack in #help-3p-connector-workflow
91
+ var smartlinkClickAnalyticsEvent = createAnalyticsEvent({
92
+ action: 'clicked',
93
+ actionSubject: 'smartLink',
94
+ actionSubjectId: 'smartlinkClickAnalyticsWorkflows',
95
+ eventType: 'ui',
96
+ attributes: {},
97
+ nonPrivacySafeAttributes: {
98
+ sourceURL: sourceURL,
99
+ thirdPartyARI: ari
100
+ }
101
+ });
102
+ smartlinkClickAnalyticsEvent.fire();
103
+ }
104
+ }
105
+ }
83
106
 
84
107
  // If preview panel is available and the user clicked on the link,
85
108
  // delegate the click to the preview panel handler
@@ -1,6 +1,4 @@
1
1
  ._102oidpf ul{margin-top:0}
2
2
  ._1e0c116y{display:inline-flex}
3
3
  ._1kvxu2gc ul{margin-right:var(--ds-space-100,8px)}
4
- ._1ul91ns9{min-width:-moz-fit-content;min-width:fit-content}
5
- ._6fu61k92 li span, ._1rrq1k92 li svg{max-height:1.25rem}
6
- ._udwj1k92 li span, ._10pr1k92 li svg{max-width:1.25rem}
4
+ ._1ul91ns9{min-width:-moz-fit-content;min-width:fit-content}
@@ -10,17 +10,10 @@ import { useMemo } from 'react';
10
10
  import { useIntl } from 'react-intl-next';
11
11
  import AtlaskitAvatarGroup from '@atlaskit/avatar-group';
12
12
  import { fg } from '@atlaskit/platform-feature-flags';
13
- import { ElementName, SmartLinkSize } from '../../../../../../constants';
13
+ import { ElementName } from '../../../../../../constants';
14
14
  import { messages } from '../../../../../../messages';
15
15
  import { getFormattedMessageAsString } from '../../../utils';
16
- var stylesOld = null;
17
16
  var styles = null;
18
- var stylesMap = {
19
- xlarge: "_1e0c116y _1kvxu2gc _102oidpf",
20
- large: "_1e0c116y _1kvxu2gc _102oidpf",
21
- medium: "_1e0c116y _1kvxu2gc _102oidpf _6fu61k92 _1rrq1k92 _udwj1k92 _10pr1k92",
22
- small: "_1e0c116y _1kvxu2gc _102oidpf _6fu61k92 _1rrq1k92 _udwj1k92 _10pr1k92"
23
- };
24
17
  var getPersonNameWithPrefix = function getPersonNameWithPrefix(elementName, personName, intl) {
25
18
  switch (elementName) {
26
19
  case ElementName.AssignedToGroup:
@@ -47,8 +40,6 @@ var BaseAvatarGroup = function BaseAvatarGroup(_ref) {
47
40
  maxCount = _ref$maxCount === void 0 ? 4 : _ref$maxCount,
48
41
  name = _ref.name,
49
42
  className = _ref.className,
50
- _ref$size = _ref.size,
51
- size = _ref$size === void 0 ? SmartLinkSize.Medium : _ref$size,
52
43
  _ref$testId = _ref.testId,
53
44
  testId = _ref$testId === void 0 ? 'smart-element-avatar-group' : _ref$testId,
54
45
  _ref$showNamePrefix = _ref.showNamePrefix,
@@ -87,7 +78,7 @@ var BaseAvatarGroup = function BaseAvatarGroup(_ref) {
87
78
  "data-testid": testId
88
79
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop
89
80
  ,
90
- className: ax([!fg('platform-linking-fix-smart-card-avatar-overrides') && stylesMap[size], fg('platform-linking-fix-smart-card-avatar-overrides') ? "_1ul91ns9 _1e0c116y _1kvxu2gc _102oidpf" : "_1ul91ns9", className])
81
+ className: ax(["_1ul91ns9 _1e0c116y _1kvxu2gc _102oidpf", className])
91
82
  }), /*#__PURE__*/React.createElement(AtlaskitAvatarGroup, {
92
83
  maxCount: maxCount,
93
84
  appearance: "stack",
@@ -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: "40.7.1",
15
+ packageVersion: "40.7.3",
16
16
  componentName: 'linkUrl'
17
17
  };
18
18
  var Anchor = withLinkClickedEvent('a');
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Generates Typescript types for analytics events from analytics.spec.yaml
5
5
  *
6
- * @codegen <<SignedSource::84c7074821df29c52dd13557dab19219>>
6
+ * @codegen <<SignedSource::18e5687cdc42ba3ac58b306a03a60d9d>>
7
7
  * @codegenCommand yarn workspace @atlassian/analytics-tooling run analytics:codegen smart-card
8
8
  */
9
9
  export type PackageMetaDataContextType = {
@@ -230,6 +230,10 @@ export type SmartLinkRenderFailedAttributesType = {
230
230
  errorInfo: Record<string, unknown>;
231
231
  id: string | null;
232
232
  };
233
+ export type SmartLinkClickedSmartlinkClickAnalyticsWorkflowsAttributesType = {
234
+ sourceURL: string;
235
+ thirdPartyARI: string;
236
+ };
233
237
  export type AnalyticsEventAttributes = {
234
238
  /**
235
239
  * Fired when an copy link is clicked */
@@ -385,5 +389,8 @@ export type AnalyticsEventAttributes = {
385
389
  /**
386
390
  * fires an event that represents when a Smart Link renders unsuccessfully. */
387
391
  'ui.smartLink.renderFailed': SmartLinkRenderFailedAttributesType;
392
+ /**
393
+ * fires an event that represents when a user clicks on a Smart Link to track analytics for the 3P Workflows team */
394
+ 'ui.smartLink.clicked.smartlinkClickAnalyticsWorkflows': SmartLinkClickedSmartlinkClickAnalyticsWorkflowsAttributesType;
388
395
  };
389
396
  export type EventKey = keyof AnalyticsEventAttributes;
@@ -1,3 +1,8 @@
1
1
  import React from 'react';
2
2
  import { type CardWithUrlContentProps } from '../types';
3
+ declare global {
4
+ interface Window {
5
+ __SSR_RENDERED__?: boolean;
6
+ }
7
+ }
3
8
  export declare function LazyIntersectionObserverCard(props: CardWithUrlContentProps): React.JSX.Element;
@@ -35,6 +35,6 @@ export type BaseAvatarGroupElementProps = ElementProps & {
35
35
  * @see AuthorGroup
36
36
  * @see CollaboratorGroup
37
37
  */
38
- declare const BaseAvatarGroup: ({ items, maxCount, name, className, size, testId, showNamePrefix, showFallbackAvatar, }: BaseAvatarGroupElementProps) => JSX.Element | null;
38
+ declare const BaseAvatarGroup: ({ items, maxCount, name, className, testId, showNamePrefix, showFallbackAvatar, }: BaseAvatarGroupElementProps) => JSX.Element | null;
39
39
  export default BaseAvatarGroup;
40
40
  export declare const toAvatarGroupProps: (items?: BaseAvatarItemProps[], showFallbackAvatar?: boolean) => Partial<BaseAvatarGroupElementProps> | undefined;
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Generates Typescript types for analytics events from analytics.spec.yaml
5
5
  *
6
- * @codegen <<SignedSource::84c7074821df29c52dd13557dab19219>>
6
+ * @codegen <<SignedSource::18e5687cdc42ba3ac58b306a03a60d9d>>
7
7
  * @codegenCommand yarn workspace @atlassian/analytics-tooling run analytics:codegen smart-card
8
8
  */
9
9
  export type PackageMetaDataContextType = {
@@ -230,6 +230,10 @@ export type SmartLinkRenderFailedAttributesType = {
230
230
  errorInfo: Record<string, unknown>;
231
231
  id: string | null;
232
232
  };
233
+ export type SmartLinkClickedSmartlinkClickAnalyticsWorkflowsAttributesType = {
234
+ sourceURL: string;
235
+ thirdPartyARI: string;
236
+ };
233
237
  export type AnalyticsEventAttributes = {
234
238
  /**
235
239
  * Fired when an copy link is clicked */
@@ -385,5 +389,8 @@ export type AnalyticsEventAttributes = {
385
389
  /**
386
390
  * fires an event that represents when a Smart Link renders unsuccessfully. */
387
391
  'ui.smartLink.renderFailed': SmartLinkRenderFailedAttributesType;
392
+ /**
393
+ * fires an event that represents when a user clicks on a Smart Link to track analytics for the 3P Workflows team */
394
+ 'ui.smartLink.clicked.smartlinkClickAnalyticsWorkflows': SmartLinkClickedSmartlinkClickAnalyticsWorkflowsAttributesType;
388
395
  };
389
396
  export type EventKey = keyof AnalyticsEventAttributes;
@@ -1,3 +1,8 @@
1
1
  import React from 'react';
2
2
  import { type CardWithUrlContentProps } from '../types';
3
+ declare global {
4
+ interface Window {
5
+ __SSR_RENDERED__?: boolean;
6
+ }
7
+ }
3
8
  export declare function LazyIntersectionObserverCard(props: CardWithUrlContentProps): React.JSX.Element;
@@ -35,6 +35,6 @@ export type BaseAvatarGroupElementProps = ElementProps & {
35
35
  * @see AuthorGroup
36
36
  * @see CollaboratorGroup
37
37
  */
38
- declare const BaseAvatarGroup: ({ items, maxCount, name, className, size, testId, showNamePrefix, showFallbackAvatar, }: BaseAvatarGroupElementProps) => JSX.Element | null;
38
+ declare const BaseAvatarGroup: ({ items, maxCount, name, className, testId, showNamePrefix, showFallbackAvatar, }: BaseAvatarGroupElementProps) => JSX.Element | null;
39
39
  export default BaseAvatarGroup;
40
40
  export declare const toAvatarGroupProps: (items?: BaseAvatarItemProps[], showFallbackAvatar?: boolean) => Partial<BaseAvatarGroupElementProps> | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/smart-card",
3
- "version": "40.7.2",
3
+ "version": "40.8.0",
4
4
  "description": "Smart card component",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -29,7 +29,7 @@
29
29
  "@atlaskit/analytics-gas-types": "^5.1.0",
30
30
  "@atlaskit/analytics-next": "^11.1.0",
31
31
  "@atlaskit/avatar": "^25.1.0",
32
- "@atlaskit/avatar-group": "^12.1.0",
32
+ "@atlaskit/avatar-group": "^12.2.0",
33
33
  "@atlaskit/badge": "^18.1.0",
34
34
  "@atlaskit/button": "^23.3.0",
35
35
  "@atlaskit/checkbox": "^17.1.0",
@@ -38,9 +38,9 @@
38
38
  "@atlaskit/form": "^12.0.0",
39
39
  "@atlaskit/frontend-utilities": "^3.1.0",
40
40
  "@atlaskit/heading": "^5.2.0",
41
- "@atlaskit/icon": "^27.9.0",
41
+ "@atlaskit/icon": "^27.10.0",
42
42
  "@atlaskit/icon-file-type": "^7.0.0",
43
- "@atlaskit/icon-lab": "^5.3.0",
43
+ "@atlaskit/icon-lab": "^5.4.0",
44
44
  "@atlaskit/icon-object": "^7.2.0",
45
45
  "@atlaskit/icon-priority": "^6.3.0",
46
46
  "@atlaskit/image": "^3.0.0",
@@ -231,9 +231,6 @@
231
231
  "platform_editor_inline_card_selected_state_fix": {
232
232
  "type": "boolean"
233
233
  },
234
- "platform-linking-fix-smart-card-avatar-overrides": {
235
- "type": "boolean"
236
- },
237
234
  "platform-linking-slack-entity-support": {
238
235
  "type": "boolean"
239
236
  },
@@ -242,6 +239,9 @@
242
239
  },
243
240
  "navx-1304-related-links-remove-false-autofocus": {
244
241
  "type": "boolean"
242
+ },
243
+ "platform_smartlink_3pclick_analytics": {
244
+ "type": "boolean"
245
245
  }
246
246
  },
247
247
  "compassUnitTestMetricSourceId": "ari:cloud:compass:a436116f-02ce-4520-8fbb-7301462a1674:metric-source/c5751cc6-3513-4070-9deb-af31e86aed34/f74ef1bc-7240-4aac-9dc8-9dc43b502089"