@atlaskit/smart-card 43.11.3 → 43.12.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 (33) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/analytics.spec.yaml +7 -1
  3. package/dist/cjs/view/CardWithUrl/component.js +327 -3
  4. package/dist/cjs/view/EmbedCard/components/ExpandedFrame.js +93 -2
  5. package/dist/cjs/view/EmbedCard/components/Frame.js +121 -3
  6. package/dist/cjs/view/EmbedCard/components/IframeDwellTracker.js +25 -4
  7. package/dist/cjs/view/EmbedCard/index.js +204 -1
  8. package/dist/cjs/view/EmbedCard/views/ResolvedView.js +95 -2
  9. package/dist/es2019/view/CardWithUrl/component.js +324 -2
  10. package/dist/es2019/view/EmbedCard/components/ExpandedFrame.js +87 -2
  11. package/dist/es2019/view/EmbedCard/components/Frame.js +112 -2
  12. package/dist/es2019/view/EmbedCard/components/IframeDwellTracker.js +25 -4
  13. package/dist/es2019/view/EmbedCard/index.js +208 -0
  14. package/dist/es2019/view/EmbedCard/views/ResolvedView.js +91 -3
  15. package/dist/esm/view/CardWithUrl/component.js +326 -2
  16. package/dist/esm/view/EmbedCard/components/ExpandedFrame.js +95 -2
  17. package/dist/esm/view/EmbedCard/components/Frame.js +122 -2
  18. package/dist/esm/view/EmbedCard/components/IframeDwellTracker.js +25 -4
  19. package/dist/esm/view/EmbedCard/index.js +203 -0
  20. package/dist/esm/view/EmbedCard/views/ResolvedView.js +97 -3
  21. package/dist/types/common/analytics/generated/analytics.types.d.ts +1 -0
  22. package/dist/types/view/EmbedCard/components/ExpandedFrame.d.ts +8 -1
  23. package/dist/types/view/EmbedCard/components/Frame.d.ts +6 -0
  24. package/dist/types/view/EmbedCard/index.d.ts +4 -0
  25. package/dist/types/view/EmbedCard/types.d.ts +4 -0
  26. package/dist/types/view/EmbedCard/views/ResolvedView.d.ts +6 -1
  27. package/dist/types-ts4.5/common/analytics/generated/analytics.types.d.ts +1 -0
  28. package/dist/types-ts4.5/view/EmbedCard/components/ExpandedFrame.d.ts +8 -1
  29. package/dist/types-ts4.5/view/EmbedCard/components/Frame.d.ts +6 -0
  30. package/dist/types-ts4.5/view/EmbedCard/index.d.ts +4 -0
  31. package/dist/types-ts4.5/view/EmbedCard/types.d.ts +4 -0
  32. package/dist/types-ts4.5/view/EmbedCard/views/ResolvedView.d.ts +6 -1
  33. package/package.json +5 -1
@@ -3,12 +3,15 @@ import _extends from "@babel/runtime/helpers/extends";
3
3
  import "./ExpandedFrame.compiled.css";
4
4
  import * as React from 'react';
5
5
  import { ax, ix } from "@compiled/react/runtime";
6
+ // eslint-disable-next-line no-unused-vars
7
+
6
8
  import { fg } from '@atlaskit/platform-feature-flags';
9
+ import { componentWithFG } from '@atlaskit/platform-feature-flags-react';
7
10
  import Tooltip from '@atlaskit/tooltip';
8
11
  import { useMouseDownEvent } from '../../../state/analytics/useLinkClicked';
9
12
  import { handleClickCommon } from '../../common/utils';
10
13
  import { className } from './styled';
11
- export var ExpandedFrame = function ExpandedFrame(_ref) {
14
+ var ExpandedFrame = function ExpandedFrame(_ref) {
12
15
  var _ref$isPlaceholder = _ref.isPlaceholder,
13
16
  isPlaceholder = _ref$isPlaceholder === void 0 ? false : _ref$isPlaceholder,
14
17
  children = _ref.children,
@@ -104,4 +107,94 @@ var styles = {
104
107
  contentStyle: "_19itdlqj _2rko12b0 _1reo15vq _18m915vq _v56414au _bfhkhp5a _16jlkb7n _4t3i1osq _1pbykb7n",
105
108
  contentInteractiveActiveBorder: "_1jhm1tt7",
106
109
  contentOverflowAuto: "_1reo1wug _18m91wug"
107
- };
110
+ };
111
+ var ExpandedFrameUpdated = function ExpandedFrameUpdated(_ref2) {
112
+ var _ref2$isPlaceholder = _ref2.isPlaceholder,
113
+ isPlaceholder = _ref2$isPlaceholder === void 0 ? false : _ref2$isPlaceholder,
114
+ children = _ref2.children,
115
+ onClick = _ref2.onClick,
116
+ icon = _ref2.icon,
117
+ text = _ref2.text,
118
+ isSelected = _ref2.isSelected,
119
+ _ref2$frameStyle = _ref2.frameStyle,
120
+ frameStyle = _ref2$frameStyle === void 0 ? 'showOnHover' : _ref2$frameStyle,
121
+ href = _ref2.href,
122
+ minWidth = _ref2.minWidth,
123
+ maxWidth = _ref2.maxWidth,
124
+ _ref2$testId = _ref2.testId,
125
+ testId = _ref2$testId === void 0 ? 'expanded-frame' : _ref2$testId,
126
+ inheritDimensions = _ref2.inheritDimensions,
127
+ _ref2$allowScrollBar = _ref2.allowScrollBar,
128
+ allowScrollBar = _ref2$allowScrollBar === void 0 ? false : _ref2$allowScrollBar,
129
+ _ref2$setOverflow = _ref2.setOverflow,
130
+ setOverflow = _ref2$setOverflow === void 0 ? true : _ref2$setOverflow,
131
+ CompetitorPrompt = _ref2.CompetitorPrompt,
132
+ onContentMouseEnter = _ref2.onContentMouseEnter,
133
+ onContentMouseLeave = _ref2.onContentMouseLeave;
134
+ var isInteractive = function isInteractive() {
135
+ return !isPlaceholder && (Boolean(href) || Boolean(onClick));
136
+ };
137
+ var handleClick = function handleClick(event) {
138
+ return handleClickCommon(event, onClick);
139
+ };
140
+ var handleMouseDown = useMouseDownEvent();
141
+
142
+ // Note: cleanup fg based on results of prompt_whiteboard_competitor_link experiment
143
+ var CompetitorPromptComponent = CompetitorPrompt && href && fg('prompt_whiteboard_competitor_link_gate') ? /*#__PURE__*/React.createElement(CompetitorPrompt, {
144
+ sourceUrl: href,
145
+ linkType: "embed"
146
+ }) : null;
147
+ var renderHeader = function renderHeader() {
148
+ return frameStyle !== 'hide' && /*#__PURE__*/React.createElement("div", {
149
+ className: ax([styles.header, "embed-header"])
150
+ }, /*#__PURE__*/React.createElement("div", {
151
+ className: ax([styles.leftSection])
152
+ }, /*#__PURE__*/React.createElement("div", {
153
+ className: ax([styles.headerIcon])
154
+ }, icon), /*#__PURE__*/React.createElement("div", {
155
+ className: ax([styles.tooltipWrapper])
156
+ }, !isPlaceholder && /*#__PURE__*/React.createElement(Tooltip, {
157
+ content: text,
158
+ hideTooltipOnMouseDown: true
159
+ }, /*#__PURE__*/React.createElement("a", {
160
+ href: href,
161
+ onClick: handleClick,
162
+ onMouseDown: handleMouseDown,
163
+ className: ax([styles.headerAnchor])
164
+ }, text)))), CompetitorPromptComponent);
165
+ };
166
+ var interactive = isInteractive();
167
+ var showBackgroundAlways = frameStyle === 'show' || isSelected && frameStyle !== 'hide';
168
+ var showBackgroundOnHover = interactive && frameStyle !== 'hide';
169
+ var renderContent = function renderContent() {
170
+ return /*#__PURE__*/React.createElement("div", {
171
+ "data-testid": "embed-content-wrapper",
172
+ // This fixes an issue with input fields in cross domain iframes (ie. databases and jira fields from different domains)
173
+ // See: HOT-107830
174
+ contentEditable: false,
175
+ onMouseEnter: onContentMouseEnter,
176
+ onMouseLeave: onContentMouseLeave,
177
+ onFocus: onContentMouseEnter,
178
+ onBlur: onContentMouseLeave,
179
+ className: ax([styles.contentStyle, setOverflow && allowScrollBar && styles.contentOverflowAuto, interactive && !showBackgroundAlways && !showBackgroundOnHover && styles.contentInteractiveActiveBorder])
180
+ }, children);
181
+ };
182
+ return /*#__PURE__*/React.createElement("div", _extends({
183
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
184
+ className: ax([styles.linkWrapper, inheritDimensions && styles.linkWrapperInheritDimensions, isSelected && frameStyle !== 'hide' && styles.linkWrapperSelected, showBackgroundAlways && styles.linkWrapperBorderAndBackground, showBackgroundOnHover && !showBackgroundAlways && styles.linkWrapperInteractiveNotHidden, className]),
185
+ style: {
186
+ minWidth: minWidth ? "".concat(minWidth, "px") : '',
187
+ maxWidth: maxWidth ? "".concat(maxWidth, "px") : ''
188
+ },
189
+ "data-testid": testId,
190
+ "data-trello-do-not-use-override": testId
191
+ // Due to limitations of testing library, we can't assert ::after
192
+ ,
193
+ "data-is-selected": isSelected
194
+ }, (isPlaceholder || !href) && {
195
+ 'data-wrapper-type': 'default',
196
+ 'data-is-interactive': isInteractive()
197
+ }), renderHeader(), renderContent());
198
+ };
199
+ var ExpandedFrameWithFG = componentWithFG('rovo_chat_embed_card_dwell_and_hover_metrics', ExpandedFrameUpdated, ExpandedFrame);
200
+ export { ExpandedFrameWithFG as ExpandedFrame };
@@ -3,6 +3,9 @@ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
3
  import "./Frame.compiled.css";
4
4
  import { ax, ix } from "@compiled/react/runtime";
5
5
  import React, { useEffect, useRef, useState } from 'react';
6
+
7
+ // eslint-disable-next-line no-unused-vars
8
+
6
9
  import { di } from 'react-magnetic-di';
7
10
  import { getIframeSandboxAttribute } from '../../../utils';
8
11
  import { IFrame } from './IFrame';
@@ -103,10 +106,127 @@ export var Frame = /*#__PURE__*/React.forwardRef(function (_ref, iframeRef) {
103
106
  "data-testid": "".concat(testId, "-frame"),
104
107
  "data-iframe-loaded": isIframeLoaded,
105
108
  onMouseEnter: function onMouseEnter() {
106
- return setMouseOver(true);
109
+ setMouseOver(true);
110
+ },
111
+ onMouseLeave: function onMouseLeave() {
112
+ setMouseOver(false);
113
+ },
114
+ allowFullScreen: true,
115
+ scrolling: "yes",
116
+ allow: "autoplay; encrypted-media; clipboard-write",
117
+ onLoad: function onLoad() {
118
+ setIframeLoaded(true);
119
+ },
120
+ sandbox: getIframeSandboxAttribute(isTrusted),
121
+ title: title,
122
+ extensionKey: extensionKey,
123
+ className: ax(["_19itidpf _1reo15vq _18m915vq _2rkofajl _154iidpf _1ltvidpf _1bsb1osq _4t3i1osq _kqswh2mm"])
124
+ }));
125
+ });
126
+ export var FrameUpdated = /*#__PURE__*/React.forwardRef(function (_ref2, iframeRef) {
127
+ var url = _ref2.url,
128
+ _ref2$isTrusted = _ref2.isTrusted,
129
+ isTrusted = _ref2$isTrusted === void 0 ? false : _ref2$isTrusted,
130
+ testId = _ref2.testId,
131
+ onIframeDwell = _ref2.onIframeDwell,
132
+ onIframeFocus = _ref2.onIframeFocus,
133
+ onIframeMouseEnter = _ref2.onIframeMouseEnter,
134
+ onIframeMouseLeave = _ref2.onIframeMouseLeave,
135
+ isMouseOverProp = _ref2.isMouseOver,
136
+ title = _ref2.title,
137
+ extensionKey = _ref2.extensionKey;
138
+ var _useState1 = useState(false),
139
+ _useState10 = _slicedToArray(_useState1, 2),
140
+ isIframeLoaded = _useState10[0],
141
+ setIframeLoaded = _useState10[1];
142
+ var _useState11 = useState(false),
143
+ _useState12 = _slicedToArray(_useState11, 2),
144
+ isMouseOver = _useState12[0],
145
+ setMouseOver = _useState12[1];
146
+ var _useState13 = useState(document.hasFocus()),
147
+ _useState14 = _slicedToArray(_useState13, 2),
148
+ isWindowFocused = _useState14[0],
149
+ setWindowFocused = _useState14[1];
150
+
151
+ // Use prop if provided (from wrapper), otherwise use local state (for backward compatibility)
152
+ var effectiveMouseOver = isMouseOverProp !== undefined ? isMouseOverProp : isMouseOver;
153
+ var ref = useRef();
154
+ var mergedRef = mergeRefs([iframeRef, ref]);
155
+ var _useState15 = useState(0),
156
+ _useState16 = _slicedToArray(_useState15, 2),
157
+ percentVisible = _useState16[0],
158
+ setPercentVisible = _useState16[1];
159
+
160
+ /**
161
+ * These are the 'percent visible' thresholds at which the intersectionObserver will
162
+ * trigger a state change. Eg. when the user scrolls and moves from 74% to 76%, or
163
+ * vice versa. It's in a state object so that its static for the useEffect
164
+ */
165
+ var _useState17 = useState([0.75, 0.8, 0.85, 0.9, 0.95, 1]),
166
+ _useState18 = _slicedToArray(_useState17, 1),
167
+ threshold = _useState18[0];
168
+ useEffect(function () {
169
+ if (!ref || !ref.current) {
170
+ return;
171
+ }
172
+ var observer = new IntersectionObserver(function (entries) {
173
+ entries.forEach(function (entry) {
174
+ setPercentVisible(entry === null || entry === void 0 ? void 0 : entry.intersectionRatio);
175
+ });
176
+ }, {
177
+ threshold: threshold
178
+ });
179
+ observer.observe(ref.current);
180
+ return function () {
181
+ observer.disconnect();
182
+ };
183
+ }, [threshold, mergedRef]);
184
+ useEffect(function () {
185
+ // Initialize with current focus state
186
+ setWindowFocused(document.hasFocus());
187
+ var onBlur = function onBlur() {
188
+ setWindowFocused(false);
189
+ if (document.activeElement === ref.current) {
190
+ onIframeFocus && onIframeFocus();
191
+ }
192
+ };
193
+ var onFocus = function onFocus() {
194
+ setWindowFocused(true);
195
+ };
196
+ window.addEventListener('blur', onBlur);
197
+ window.addEventListener('focus', onFocus);
198
+ return function () {
199
+ window.removeEventListener('blur', onBlur);
200
+ window.removeEventListener('focus', onFocus);
201
+ };
202
+ }, [ref, onIframeFocus]);
203
+ if (!url) {
204
+ return null;
205
+ }
206
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(IframeDwellTracker, {
207
+ isIframeLoaded: isIframeLoaded,
208
+ isMouseOver: effectiveMouseOver,
209
+ isWindowFocused: isWindowFocused,
210
+ iframePercentVisible: percentVisible,
211
+ onIframeDwell: onIframeDwell
212
+ }), /*#__PURE__*/React.createElement(IFrame, {
213
+ childRef: mergedRef,
214
+ src: url,
215
+ "data-testid": "".concat(testId, "-frame"),
216
+ "data-iframe-loaded": isIframeLoaded,
217
+ onMouseEnter: function onMouseEnter() {
218
+ onIframeMouseEnter === null || onIframeMouseEnter === void 0 || onIframeMouseEnter();
219
+ // Use local state if prop not provided, otherwise prop takes precedence
220
+ if (isMouseOverProp === undefined) {
221
+ setMouseOver(true);
222
+ }
107
223
  },
108
224
  onMouseLeave: function onMouseLeave() {
109
- return setMouseOver(false);
225
+ onIframeMouseLeave === null || onIframeMouseLeave === void 0 || onIframeMouseLeave();
226
+ // Use local state if prop not provided, otherwise prop takes precedence
227
+ if (isMouseOverProp === undefined) {
228
+ setMouseOver(false);
229
+ }
110
230
  },
111
231
  allowFullScreen: true,
112
232
  scrolling: "yes",
@@ -4,6 +4,7 @@ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
4
4
  * @jsx jsx
5
5
  */
6
6
  import { useEffect, useRef, useState } from 'react';
7
+ import { fg } from '@atlaskit/platform-feature-flags';
7
8
  /**
8
9
  * A kind of cheap logarithmic backoff. Fire analytics after the user has
9
10
  * dwelled for 5 seconds, then 10 seconds, and so on.
@@ -44,11 +45,31 @@ export var IframeDwellTracker = function IframeDwellTracker(_ref) {
44
45
  };
45
46
  });
46
47
  };
47
- if (isIframeLoaded && isMouseOver && isWindowFocused && iframePercentVisible > 0.75) {
48
- if (dwellTimeoutId.current) {
49
- clearInterval(dwellTimeoutId.current);
48
+
49
+ // Require: iframe loaded, mouse over, and >75% visible
50
+ var isDwellAndHoverMetricsEnabled = fg('rovo_chat_embed_card_dwell_and_hover_metrics');
51
+ if (isDwellAndHoverMetricsEnabled) {
52
+ // Note: Removed isWindowFocused requirement as it's unreliable and prevents tracking
53
+ // The mouse over check is sufficient to indicate user engagement
54
+ var shouldTrack = isIframeLoaded && isMouseOver && iframePercentVisible > 0.75;
55
+ if (shouldTrack) {
56
+ if (dwellTimeoutId.current) {
57
+ clearInterval(dwellTimeoutId.current);
58
+ }
59
+ dwellTimeoutId.current = setInterval(incrementDwellTime, 1000);
60
+ } else {
61
+ if (dwellTimeoutId.current) {
62
+ clearInterval(dwellTimeoutId.current);
63
+ dwellTimeoutId.current = undefined;
64
+ }
65
+ }
66
+ } else {
67
+ if (isIframeLoaded && isMouseOver && isWindowFocused && iframePercentVisible > 0.75) {
68
+ if (dwellTimeoutId.current) {
69
+ clearInterval(dwellTimeoutId.current);
70
+ }
71
+ dwellTimeoutId.current = setInterval(incrementDwellTime, 1000);
50
72
  }
51
- dwellTimeoutId.current = setInterval(incrementDwellTime, 1000);
52
73
  }
53
74
  return function () {
54
75
  if (dwellTimeoutId.current) {
@@ -226,4 +226,207 @@ export var EmbedCard = /*#__PURE__*/React.forwardRef(function (_ref2, iframeRef)
226
226
  isSelected: isSelected
227
227
  });
228
228
  }
229
+ });
230
+ export var EmbedCardUpdated = /*#__PURE__*/React.forwardRef(function (_ref3, iframeRef) {
231
+ var _details$meta4, _forbiddenViewProps$c3, _forbiddenViewProps$c4, _notFoundViewProps$co3, _notFoundViewProps$co4;
232
+ var url = _ref3.url,
233
+ cardState = _ref3.cardState,
234
+ handleAuthorize = _ref3.handleAuthorize,
235
+ handleErrorRetry = _ref3.handleErrorRetry,
236
+ handleFrameClick = _ref3.handleFrameClick,
237
+ isSelected = _ref3.isSelected,
238
+ frameStyle = _ref3.frameStyle,
239
+ platform = _ref3.platform,
240
+ onResolve = _ref3.onResolve,
241
+ onError = _ref3.onError,
242
+ testId = _ref3.testId,
243
+ inheritDimensions = _ref3.inheritDimensions,
244
+ onIframeDwell = _ref3.onIframeDwell,
245
+ onIframeFocus = _ref3.onIframeFocus,
246
+ onIframeMouseEnter = _ref3.onIframeMouseEnter,
247
+ onIframeMouseLeave = _ref3.onIframeMouseLeave,
248
+ iframeUrlType = _ref3.iframeUrlType,
249
+ actionOptions = _ref3.actionOptions,
250
+ renderers = _ref3.renderers,
251
+ CompetitorPrompt = _ref3.CompetitorPrompt,
252
+ hideIconLoadingSkeleton = _ref3.hideIconLoadingSkeleton;
253
+ var _useAnalyticsEvents2 = useAnalyticsEvents(),
254
+ createAnalyticsEvent = _useAnalyticsEvents2.createAnalyticsEvent;
255
+ var status = cardState.status,
256
+ details = cardState.details;
257
+ var extensionKey = getExtensionKey(details);
258
+ var isProductIntegrationSupported = hasAuthScopeOverrides(details);
259
+ var _useControlDataExport3 = useControlDataExportConfig(),
260
+ _useControlDataExport4 = _useControlDataExport3.shouldControlDataExport,
261
+ shouldControlDataExport = _useControlDataExport4 === void 0 ? false : _useControlDataExport4;
262
+ switch (status) {
263
+ case 'pending':
264
+ case 'resolving':
265
+ return /*#__PURE__*/React.createElement(UFOLoadHoldWrapper, null, /*#__PURE__*/React.createElement(BlockCardResolvedView, {
266
+ url: url,
267
+ cardState: cardState,
268
+ onClick: handleFrameClick,
269
+ onError: onError,
270
+ onResolve: onResolve,
271
+ renderers: renderers,
272
+ actionOptions: actionOptions,
273
+ testId: testId ? "".concat(testId, "-resolving-view") : 'embed-card-resolving-view'
274
+ }));
275
+ case 'resolved':
276
+ var resolvedViewProps = extractEmbedProps(details, platform, iframeUrlType);
277
+ if (onResolve) {
278
+ var _resolvedViewProps$pr2, _details$meta3;
279
+ onResolve(_objectSpread({
280
+ title: resolvedViewProps.title,
281
+ url: url,
282
+ aspectRatio: (_resolvedViewProps$pr2 = resolvedViewProps.preview) === null || _resolvedViewProps$pr2 === void 0 ? void 0 : _resolvedViewProps$pr2.aspectRatio
283
+ }, fg('expose-product-details-from-smart-card') && {
284
+ extensionKey: details === null || details === void 0 || (_details$meta3 = details.meta) === null || _details$meta3 === void 0 ? void 0 : _details$meta3.key
285
+ }));
286
+ }
287
+ if (getIsDataExportEnabled(shouldControlDataExport, cardState.details)) {
288
+ var unauthViewProps = extractEmbedProps(details, platform);
289
+ return /*#__PURE__*/React.createElement(UnauthorizedView, {
290
+ context: unauthViewProps.context,
291
+ extensionKey: extensionKey,
292
+ frameStyle: frameStyle,
293
+ isProductIntegrationSupported: isProductIntegrationSupported,
294
+ inheritDimensions: inheritDimensions,
295
+ isSelected: isSelected,
296
+ onAuthorize: handleAuthorize,
297
+ onClick: handleFrameClick,
298
+ testId: testId,
299
+ url: unauthViewProps.link
300
+ });
301
+ }
302
+ if (resolvedViewProps.preview) {
303
+ return /*#__PURE__*/React.createElement(EmbedCardResolvedView, _extends({}, resolvedViewProps, {
304
+ isSelected: isSelected,
305
+ frameStyle: frameStyle,
306
+ inheritDimensions: inheritDimensions,
307
+ onClick: handleFrameClick,
308
+ ref: iframeRef,
309
+ onIframeDwell: onIframeDwell,
310
+ onIframeFocus: onIframeFocus,
311
+ onIframeMouseEnter: onIframeMouseEnter,
312
+ onIframeMouseLeave: onIframeMouseLeave,
313
+ testId: testId,
314
+ CompetitorPrompt: CompetitorPrompt,
315
+ hideIconLoadingSkeleton: hideIconLoadingSkeleton,
316
+ extensionKey: extensionKey
317
+ }));
318
+ } else {
319
+ if (platform === 'mobile') {
320
+ var resolvedInlineViewProps = extractInlineProps(details);
321
+ return /*#__PURE__*/React.createElement(InlineCardResolvedView, _extends({}, resolvedInlineViewProps, {
322
+ isSelected: isSelected,
323
+ testId: testId,
324
+ onClick: handleFrameClick
325
+ }));
326
+ }
327
+ return /*#__PURE__*/React.createElement(BlockCardResolvedView, {
328
+ url: url,
329
+ cardState: cardState,
330
+ onClick: handleFrameClick,
331
+ onError: onError,
332
+ onResolve: onResolve,
333
+ renderers: renderers,
334
+ actionOptions: actionOptions,
335
+ testId: testId
336
+ });
337
+ }
338
+ case 'unauthorized':
339
+ if (onError) {
340
+ onError({
341
+ url: url,
342
+ status: status
343
+ });
344
+ }
345
+ var unauthorisedViewProps = extractEmbedProps(details, platform);
346
+ return /*#__PURE__*/React.createElement(UnauthorizedView, {
347
+ context: unauthorisedViewProps.context,
348
+ extensionKey: extensionKey,
349
+ frameStyle: frameStyle,
350
+ isProductIntegrationSupported: isProductIntegrationSupported,
351
+ inheritDimensions: inheritDimensions,
352
+ isSelected: isSelected,
353
+ onAuthorize: handleAuthorize,
354
+ onClick: handleFrameClick,
355
+ testId: testId,
356
+ url: unauthorisedViewProps.link
357
+ });
358
+ case 'forbidden':
359
+ if (onError) {
360
+ onError({
361
+ url: url,
362
+ status: status
363
+ });
364
+ }
365
+ var forbiddenViewProps = extractEmbedProps(details, platform);
366
+ var cardMetadata = (_details$meta4 = details === null || details === void 0 ? void 0 : details.meta) !== null && _details$meta4 !== void 0 ? _details$meta4 : getForbiddenJsonLd().meta;
367
+ if (forbiddenViewProps.preview) {
368
+ return /*#__PURE__*/React.createElement(EmbedCardResolvedView, _extends({}, forbiddenViewProps, {
369
+ title: forbiddenViewProps.link,
370
+ frameStyle: frameStyle,
371
+ isSelected: isSelected,
372
+ inheritDimensions: inheritDimensions,
373
+ onClick: handleFrameClick,
374
+ ref: iframeRef,
375
+ extensionKey: extensionKey
376
+ }));
377
+ }
378
+ var forbiddenAccessContext = extractRequestAccessContextImproved({
379
+ jsonLd: cardMetadata,
380
+ url: url,
381
+ product: (_forbiddenViewProps$c3 = (_forbiddenViewProps$c4 = forbiddenViewProps.context) === null || _forbiddenViewProps$c4 === void 0 ? void 0 : _forbiddenViewProps$c4.text) !== null && _forbiddenViewProps$c3 !== void 0 ? _forbiddenViewProps$c3 : '',
382
+ createAnalyticsEvent: createAnalyticsEvent
383
+ });
384
+ return /*#__PURE__*/React.createElement(ForbiddenView, {
385
+ context: forbiddenViewProps.context,
386
+ frameStyle: frameStyle,
387
+ inheritDimensions: inheritDimensions,
388
+ isSelected: isSelected,
389
+ onAuthorize: handleAuthorize,
390
+ onClick: handleFrameClick,
391
+ accessContext: forbiddenAccessContext,
392
+ url: forbiddenViewProps.link
393
+ });
394
+ case 'not_found':
395
+ if (onError) {
396
+ onError({
397
+ url: url,
398
+ status: status
399
+ });
400
+ }
401
+ var notFoundViewProps = extractEmbedProps(details, platform);
402
+ var notFoundAccessContext = details !== null && details !== void 0 && details.meta ? extractRequestAccessContextImproved({
403
+ jsonLd: details === null || details === void 0 ? void 0 : details.meta,
404
+ url: url,
405
+ product: (_notFoundViewProps$co3 = (_notFoundViewProps$co4 = notFoundViewProps.context) === null || _notFoundViewProps$co4 === void 0 ? void 0 : _notFoundViewProps$co4.text) !== null && _notFoundViewProps$co3 !== void 0 ? _notFoundViewProps$co3 : '',
406
+ createAnalyticsEvent: createAnalyticsEvent
407
+ }) : undefined;
408
+ return /*#__PURE__*/React.createElement(NotFoundView, {
409
+ context: notFoundViewProps.context,
410
+ frameStyle: frameStyle,
411
+ inheritDimensions: inheritDimensions,
412
+ isSelected: isSelected,
413
+ onClick: handleFrameClick,
414
+ accessContext: notFoundAccessContext,
415
+ url: notFoundViewProps.link
416
+ });
417
+ case 'fallback':
418
+ case 'errored':
419
+ default:
420
+ if (onError) {
421
+ onError({
422
+ url: url,
423
+ status: status
424
+ });
425
+ }
426
+ return /*#__PURE__*/React.createElement(EmbedCardErroredView, {
427
+ onRetry: handleErrorRetry,
428
+ inheritDimensions: inheritDimensions,
429
+ isSelected: isSelected
430
+ });
431
+ }
229
432
  });
@@ -1,12 +1,15 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
1
2
  import React from 'react';
2
3
  import LinkGlyph from '@atlaskit/icon/core/migration/link';
4
+ import { componentWithFG } from '@atlaskit/platform-feature-flags-react';
3
5
  import { useThemeObserver } from '@atlaskit/tokens';
4
6
  import { getPreviewUrlWithTheme, isProfileType } from '../../../utils';
5
7
  import { ExpandedFrame } from '../components/ExpandedFrame';
6
- import { Frame } from '../components/Frame';
8
+ import { Frame, FrameUpdated } from '../components/Frame';
7
9
  import { ImageIcon } from '../components/ImageIcon';
8
10
  import { useEmbedResolvePostMessageListener } from '../useEmbedResolvePostMessageListener';
9
- export var EmbedCardResolvedView = /*#__PURE__*/React.forwardRef(function (_ref, embedIframeRef) {
11
+ var FrameComponent = componentWithFG('rovo_chat_embed_card_dwell_and_hover_metrics', FrameUpdated, Frame);
12
+ var EmbedCardResolvedViewOld = /*#__PURE__*/React.forwardRef(function (_ref, embedIframeRef) {
10
13
  var link = _ref.link,
11
14
  context = _ref.context,
12
15
  onClick = _ref.onClick,
@@ -77,4 +80,95 @@ export var EmbedCardResolvedView = /*#__PURE__*/React.forwardRef(function (_ref,
77
80
  title: text,
78
81
  extensionKey: extensionKey
79
82
  }));
80
- });
83
+ });
84
+ var EmbedCardResolvedViewUpdated = /*#__PURE__*/React.forwardRef(function (_ref2, embedIframeRef) {
85
+ var link = _ref2.link,
86
+ context = _ref2.context,
87
+ onClick = _ref2.onClick,
88
+ isSelected = _ref2.isSelected,
89
+ frameStyle = _ref2.frameStyle,
90
+ preview = _ref2.preview,
91
+ title = _ref2.title,
92
+ isTrusted = _ref2.isTrusted,
93
+ _ref2$testId = _ref2.testId,
94
+ testId = _ref2$testId === void 0 ? 'embed-card-resolved-view' : _ref2$testId,
95
+ inheritDimensions = _ref2.inheritDimensions,
96
+ onIframeDwell = _ref2.onIframeDwell,
97
+ onIframeFocus = _ref2.onIframeFocus,
98
+ onIframeMouseEnter = _ref2.onIframeMouseEnter,
99
+ onIframeMouseLeave = _ref2.onIframeMouseLeave,
100
+ isSupportTheming = _ref2.isSupportTheming,
101
+ type = _ref2.type,
102
+ CompetitorPrompt = _ref2.CompetitorPrompt,
103
+ hideIconLoadingSkeleton = _ref2.hideIconLoadingSkeleton,
104
+ extensionKey = _ref2.extensionKey;
105
+ var iconFromContext = context === null || context === void 0 ? void 0 : context.icon;
106
+ var src = typeof iconFromContext === 'string' ? iconFromContext : undefined;
107
+ var text = title || (context === null || context === void 0 ? void 0 : context.text);
108
+ var linkGlyph = React.useMemo(function () {
109
+ return /*#__PURE__*/React.createElement(LinkGlyph, {
110
+ label: "icon",
111
+ LEGACY_size: "small",
112
+ testId: "embed-card-fallback-icon",
113
+ color: "currentColor"
114
+ });
115
+ }, []);
116
+ var icon = React.useMemo(function () {
117
+ if ( /*#__PURE__*/React.isValidElement(iconFromContext)) {
118
+ return iconFromContext;
119
+ }
120
+ return /*#__PURE__*/React.createElement(ImageIcon, {
121
+ src: src,
122
+ default: linkGlyph,
123
+ appearance: isProfileType(type) ? 'round' : 'square',
124
+ hideLoadingSkeleton: hideIconLoadingSkeleton
125
+ });
126
+ }, [iconFromContext, src, linkGlyph, type, hideIconLoadingSkeleton]);
127
+ useEmbedResolvePostMessageListener({
128
+ url: link,
129
+ embedIframeRef: embedIframeRef
130
+ });
131
+ var themeState = useThemeObserver();
132
+ var previewUrl = preview === null || preview === void 0 ? void 0 : preview.src;
133
+ if (previewUrl && isSupportTheming) {
134
+ previewUrl = getPreviewUrlWithTheme(previewUrl, themeState);
135
+ }
136
+ var _React$useState = React.useState(false),
137
+ _React$useState2 = _slicedToArray(_React$useState, 2),
138
+ isMouseOver = _React$useState2[0],
139
+ setMouseOver = _React$useState2[1];
140
+ return /*#__PURE__*/React.createElement(ExpandedFrame, {
141
+ isSelected: isSelected,
142
+ frameStyle: frameStyle,
143
+ href: link,
144
+ testId: testId,
145
+ icon: icon,
146
+ text: text,
147
+ onClick: onClick,
148
+ inheritDimensions: inheritDimensions,
149
+ setOverflow: false,
150
+ CompetitorPrompt: CompetitorPrompt,
151
+ onContentMouseEnter: function onContentMouseEnter() {
152
+ setMouseOver(true);
153
+ onIframeMouseEnter === null || onIframeMouseEnter === void 0 || onIframeMouseEnter();
154
+ },
155
+ onContentMouseLeave: function onContentMouseLeave() {
156
+ setMouseOver(false);
157
+ onIframeMouseLeave === null || onIframeMouseLeave === void 0 || onIframeMouseLeave();
158
+ }
159
+ }, /*#__PURE__*/React.createElement(FrameComponent, {
160
+ url: previewUrl,
161
+ isTrusted: isTrusted,
162
+ testId: testId,
163
+ ref: embedIframeRef,
164
+ onIframeDwell: onIframeDwell,
165
+ onIframeFocus: onIframeFocus,
166
+ onIframeMouseEnter: onIframeMouseEnter,
167
+ onIframeMouseLeave: onIframeMouseLeave,
168
+ isMouseOver: isMouseOver,
169
+ title: text,
170
+ extensionKey: extensionKey
171
+ }));
172
+ });
173
+ var EmbedCardResolvedViewWithFG = componentWithFG('rovo_chat_embed_card_dwell_and_hover_metrics', EmbedCardResolvedViewUpdated, EmbedCardResolvedViewOld);
174
+ export { EmbedCardResolvedViewWithFG as EmbedCardResolvedView };
@@ -108,6 +108,7 @@ export type SmartLinkIframeFocusedAttributesType = {
108
108
  id: string;
109
109
  display: 'inline' | 'block' | 'embed' | 'embedPreview' | 'flexible' | 'hoverCardPreview' | 'url';
110
110
  definitionId: string | null;
111
+ interactionType?: 'mouseenter' | 'mouseleave' | 'focus';
111
112
  };
112
113
  export type ApplicationAccountConnectedAttributesType = {
113
114
  definitionId: string | null;
@@ -41,4 +41,11 @@ export interface ExpandedFrameProps {
41
41
  testId?: string;
42
42
  text?: React.ReactNode;
43
43
  }
44
- export declare const ExpandedFrame: ({ isPlaceholder, children, onClick, icon, text, isSelected, frameStyle, href, minWidth, maxWidth, testId, inheritDimensions, allowScrollBar, setOverflow, CompetitorPrompt, }: ExpandedFrameProps) => JSX.Element;
44
+ export interface ExpandedFrameUpdatedProps extends ExpandedFrameProps {
45
+ /** Callback for when mouse enters the content wrapper - for dwell tracking */
46
+ onContentMouseEnter?: () => void;
47
+ /** Callback for when mouse leaves the content wrapper - for dwell tracking */
48
+ onContentMouseLeave?: () => void;
49
+ }
50
+ declare const ExpandedFrameWithFG: import("react").FC<ExpandedFrameUpdatedProps & ExpandedFrameProps>;
51
+ export { ExpandedFrameWithFG as ExpandedFrame };
@@ -12,4 +12,10 @@ export interface FrameProps {
12
12
  title?: string;
13
13
  url?: string;
14
14
  }
15
+ export interface FrameUpdatedProps extends FrameProps {
16
+ isMouseOver?: boolean;
17
+ onIframeMouseEnter?: () => void;
18
+ onIframeMouseLeave?: () => void;
19
+ }
15
20
  export declare const Frame: React.ForwardRefExoticComponent<FrameProps & React.RefAttributes<HTMLIFrameElement>>;
21
+ export declare const FrameUpdated: React.ForwardRefExoticComponent<FrameUpdatedProps & React.RefAttributes<HTMLIFrameElement>>;
@@ -1,3 +1,7 @@
1
1
  import React from 'react';
2
2
  import { type EmbedCardProps } from './types';
3
3
  export declare const EmbedCard: React.ForwardRefExoticComponent<EmbedCardProps & React.RefAttributes<HTMLIFrameElement>>;
4
+ export declare const EmbedCardUpdated: React.ForwardRefExoticComponent<EmbedCardProps & {
5
+ onIframeMouseEnter?: () => void;
6
+ onIframeMouseLeave?: () => void;
7
+ } & React.RefAttributes<HTMLIFrameElement>>;
@@ -30,6 +30,10 @@ export type EmbedCardProps = {
30
30
  testId?: string;
31
31
  url: string;
32
32
  };
33
+ export type EmbedCardUpdatedProps = EmbedCardProps & {
34
+ onIframeMouseEnter?: () => void;
35
+ onIframeMouseLeave?: () => void;
36
+ };
33
37
  export interface WithShowControlMethodProp {
34
38
  showControls?: () => void;
35
39
  }