@atlaskit/react-ufo 4.11.0 → 4.11.2

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 (48) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/create-post-interaction-log-payload/index.js +12 -3
  3. package/dist/cjs/interaction-metrics/index.js +4 -0
  4. package/dist/cjs/interaction-metrics/post-interaction-log.js +13 -1
  5. package/dist/cjs/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.js +8 -18
  6. package/dist/cjs/vc/vc-observer-new/metric-calculator/fy25_03/index.js +5 -0
  7. package/dist/cjs/vc/vc-observer-new/metric-calculator/vcnext/index.js +4 -1
  8. package/dist/cjs/vc/vc-observer-new/viewport-observer/index.js +26 -40
  9. package/dist/cjs/vc/vc-observer-new/viewport-observer/utils/is-element-visible.js +23 -0
  10. package/dist/cjs/vc/vc-observer-new/viewport-observer/utils/is-same-rect-dimensions.js +13 -0
  11. package/dist/cjs/vc/vc-observer-new/viewport-observer/utils/is-same-rect-size.js +13 -0
  12. package/dist/es2019/create-post-interaction-log-payload/index.js +9 -2
  13. package/dist/es2019/interaction-metrics/index.js +4 -0
  14. package/dist/es2019/interaction-metrics/post-interaction-log.js +11 -1
  15. package/dist/es2019/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.js +8 -18
  16. package/dist/es2019/vc/vc-observer-new/metric-calculator/fy25_03/index.js +5 -0
  17. package/dist/es2019/vc/vc-observer-new/metric-calculator/vcnext/index.js +4 -1
  18. package/dist/es2019/vc/vc-observer-new/viewport-observer/index.js +25 -39
  19. package/dist/es2019/vc/vc-observer-new/viewport-observer/utils/is-element-visible.js +17 -0
  20. package/dist/es2019/vc/vc-observer-new/viewport-observer/utils/is-same-rect-dimensions.js +7 -0
  21. package/dist/es2019/vc/vc-observer-new/viewport-observer/utils/is-same-rect-size.js +7 -0
  22. package/dist/esm/create-post-interaction-log-payload/index.js +12 -3
  23. package/dist/esm/interaction-metrics/index.js +4 -0
  24. package/dist/esm/interaction-metrics/post-interaction-log.js +13 -1
  25. package/dist/esm/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.js +8 -18
  26. package/dist/esm/vc/vc-observer-new/metric-calculator/fy25_03/index.js +5 -0
  27. package/dist/esm/vc/vc-observer-new/metric-calculator/vcnext/index.js +4 -1
  28. package/dist/esm/vc/vc-observer-new/viewport-observer/index.js +25 -39
  29. package/dist/esm/vc/vc-observer-new/viewport-observer/utils/is-element-visible.js +17 -0
  30. package/dist/esm/vc/vc-observer-new/viewport-observer/utils/is-same-rect-dimensions.js +7 -0
  31. package/dist/esm/vc/vc-observer-new/viewport-observer/utils/is-same-rect-size.js +7 -0
  32. package/dist/types/common/common/types.d.ts +1 -0
  33. package/dist/types/common/react-ufo-payload-schema.d.ts +1 -0
  34. package/dist/types/create-post-interaction-log-payload/index.d.ts +7 -1
  35. package/dist/types/interaction-metrics/post-interaction-log.d.ts +3 -1
  36. package/dist/types/vc/vc-observer-new/types.d.ts +1 -1
  37. package/dist/types/vc/vc-observer-new/viewport-observer/utils/is-element-visible.d.ts +1 -0
  38. package/dist/types/vc/vc-observer-new/viewport-observer/utils/is-same-rect-dimensions.d.ts +1 -0
  39. package/dist/types/vc/vc-observer-new/viewport-observer/utils/is-same-rect-size.d.ts +1 -0
  40. package/dist/types-ts4.5/common/common/types.d.ts +1 -0
  41. package/dist/types-ts4.5/common/react-ufo-payload-schema.d.ts +1 -0
  42. package/dist/types-ts4.5/create-post-interaction-log-payload/index.d.ts +7 -1
  43. package/dist/types-ts4.5/interaction-metrics/post-interaction-log.d.ts +3 -1
  44. package/dist/types-ts4.5/vc/vc-observer-new/types.d.ts +1 -1
  45. package/dist/types-ts4.5/vc/vc-observer-new/viewport-observer/utils/is-element-visible.d.ts +1 -0
  46. package/dist/types-ts4.5/vc/vc-observer-new/viewport-observer/utils/is-same-rect-dimensions.d.ts +1 -0
  47. package/dist/types-ts4.5/vc/vc-observer-new/viewport-observer/utils/is-same-rect-size.d.ts +1 -0
  48. package/package.json +7 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @atlaskit/ufo-interaction-ignore
2
2
 
3
+ ## 4.11.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [`2237400c3b932`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/2237400c3b932) -
8
+ FG cleanup - platform_ufo_unify_abort_status_in_ttvc_debug_data
9
+
10
+ ## 4.11.1
11
+
12
+ ### Patch Changes
13
+
14
+ - [`89aa5e2bb9363`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/89aa5e2bb9363) -
15
+ Mark layout-shift entries with same-rect in VC observer
16
+
3
17
  ## 4.11.0
4
18
 
5
19
  ### Minor Changes
@@ -125,7 +125,8 @@ function createPostInteractionLogPayload(_ref2) {
125
125
  var lastInteractionFinish = _ref2.lastInteractionFinish,
126
126
  reactProfilerTimings = _ref2.reactProfilerTimings,
127
127
  lastInteractionFinishVCResult = _ref2.lastInteractionFinishVCResult,
128
- postInteractionFinishVCResult = _ref2.postInteractionFinishVCResult;
128
+ postInteractionFinishVCResult = _ref2.postInteractionFinishVCResult,
129
+ postInteractionHoldInfo = _ref2.postInteractionHoldInfo;
129
130
  var config = (0, _config.getConfig)();
130
131
  if (!config) {
131
132
  throw Error('UFO Configuration not provided');
@@ -213,7 +214,7 @@ function createPostInteractionLogPayload(_ref2) {
213
214
  },
214
215
  'event:region': config.region || 'unknown',
215
216
  'experience:key': 'custom.post-interaction-logs',
216
- postInteractionLog: {
217
+ postInteractionLog: _objectSpread({
217
218
  lastInteractionFinish: _objectSpread(_objectSpread({}, lastInteractionFinish), {}, {
218
219
  ufoName: ufoName,
219
220
  start: lastInteractionFinishStart,
@@ -228,7 +229,15 @@ function createPostInteractionLogPayload(_ref2) {
228
229
  vcClean: postInteractionFinishVCClean,
229
230
  lateMutations: lateMutations,
230
231
  reactProfilerTimings: transformReactProfilerTimings(reactProfilerTimings)
231
- }
232
+ }, (0, _platformFeatureFlags.fg)('platform_ufo_enable_late_holds_post_interaction') ? {
233
+ postInteractionHoldInfo: postInteractionHoldInfo === null || postInteractionHoldInfo === void 0 ? void 0 : postInteractionHoldInfo.map(function (hold) {
234
+ return _objectSpread(_objectSpread({}, hold), {}, {
235
+ labelStack: hold.labelStack.map(function (label) {
236
+ return label.name;
237
+ }).join('/')
238
+ });
239
+ })
240
+ } : {})
232
241
  }
233
242
  }
234
243
  };
@@ -385,6 +385,10 @@ function removeHoldCriterion(id) {
385
385
  function addHold(interactionId, labelStack, name, experimental) {
386
386
  var interaction = _constants.interactions.get(interactionId);
387
387
  var id = (0, _uuid.v4)();
388
+ if (!interaction && (0, _platformFeatureFlags.fg)('platform_ufo_enable_late_holds_post_interaction')) {
389
+ // add hold timestamp to post interaction log if interaction is complete
390
+ postInteractionLog.addHoldInfo(labelStack, name, performance.now());
391
+ }
388
392
  if (interaction != null) {
389
393
  var start = performance.now();
390
394
  var holdActive = {
@@ -32,6 +32,7 @@ var PostInteractionLog = exports.default = /*#__PURE__*/function () {
32
32
  * Store the scheduled sink timeout Id so that it can be cancelled when needed
33
33
  */
34
34
  (0, _defineProperty2.default)(this, "sinkTimeoutId", null);
35
+ (0, _defineProperty2.default)(this, "holdInfo", []);
35
36
  /**
36
37
  * independent VC observer, that observes until `custom.post-interaction-logs` event is sent
37
38
  */
@@ -98,6 +99,7 @@ var PostInteractionLog = exports.default = /*#__PURE__*/function () {
98
99
  value: function reset() {
99
100
  this.lastInteractionFinish = null;
100
101
  this.reactProfilerTimings = [];
102
+ this.holdInfo = [];
101
103
  if (this.sinkTimeoutId != null) {
102
104
  clearTimeout(this.sinkTimeoutId);
103
105
  this.sinkTimeoutId = null;
@@ -162,7 +164,8 @@ var PostInteractionLog = exports.default = /*#__PURE__*/function () {
162
164
  lastInteractionFinish: this.lastInteractionFinish,
163
165
  reactProfilerTimings: this.reactProfilerTimings,
164
166
  postInteractionFinishVCResult: postInteractionFinishVCResult,
165
- lastInteractionFinishVCResult: this.lastInteractionFinishVCResult
167
+ lastInteractionFinishVCResult: this.lastInteractionFinishVCResult,
168
+ postInteractionHoldInfo: this.holdInfo
166
169
  });
167
170
  this.reset();
168
171
  case 13:
@@ -243,5 +246,14 @@ var PostInteractionLog = exports.default = /*#__PURE__*/function () {
243
246
  });
244
247
  }
245
248
  }
249
+ }, {
250
+ key: "addHoldInfo",
251
+ value: function addHoldInfo(labelStack, name, start) {
252
+ this.holdInfo.push({
253
+ name: name,
254
+ labelStack: labelStack,
255
+ start: start
256
+ });
257
+ }
246
258
  }]);
247
259
  }();
@@ -310,24 +310,14 @@ var AbstractVCCalculatorBase = exports.default = /*#__PURE__*/function () {
310
310
  // Only create debug details if callbacks exist
311
311
  v3RevisionDebugDetails = null;
312
312
  if (shouldCalculateDebugDetails) {
313
- if ((0, _platformFeatureFlags.fg)('platform_ufo_unify_abort_status_in_ttvc_debug_data')) {
314
- v3RevisionDebugDetails = {
315
- revision: this.revisionNo,
316
- isClean: isVCClean && !interactionAbortReason && isPageVisible,
317
- abortReason: !isPageVisible ? 'browser_backgrounded' : dirtyReason !== null && dirtyReason !== void 0 ? dirtyReason : interactionAbortReason,
318
- vcLogs: enhancedVcLogs,
319
- interactionId: interactionId,
320
- interactionType: interactionType
321
- };
322
- } else {
323
- v3RevisionDebugDetails = {
324
- revision: this.revisionNo,
325
- isClean: isVCClean,
326
- abortReason: dirtyReason,
327
- vcLogs: enhancedVcLogs,
328
- interactionId: interactionId
329
- };
330
- }
313
+ v3RevisionDebugDetails = {
314
+ revision: this.revisionNo,
315
+ isClean: isVCClean && !interactionAbortReason && isPageVisible,
316
+ abortReason: !isPageVisible ? 'browser_backgrounded' : dirtyReason !== null && dirtyReason !== void 0 ? dirtyReason : interactionAbortReason,
317
+ vcLogs: enhancedVcLogs,
318
+ interactionId: interactionId,
319
+ interactionType: interactionType
320
+ };
331
321
  }
332
322
 
333
323
  // Handle devtool callback
@@ -21,6 +21,11 @@ var REVISION_NO = 'fy25.03';
21
21
  var getConsideredEntryTypes = function getConsideredEntryTypes(include3p) {
22
22
  var entryTypes = ['mutation:child-element', 'mutation:element', 'mutation:attribute', 'layout-shift', 'window:event'];
23
23
 
24
+ // in rolling this out, still include it in TTVC v3
25
+ if ((0, _platformFeatureFlags.fg)('platform_ufo_vc_next_filter_ls_entries_same_rect')) {
26
+ entryTypes.push('layout-shift:same-rect');
27
+ }
28
+
24
29
  // If not exclude 3p elements from ttvc,
25
30
  // including the tags into the ConsideredEntryTypes so that it won't be ignored for TTVC calculation
26
31
  if (!(0, _platformFeatureFlags.fg)('platform_ufo_exclude_3p_elements_from_ttvc') || include3p) {
@@ -20,6 +20,9 @@ var REVISION_NO = 'next';
20
20
  var getConsideredEntryTypes = function getConsideredEntryTypes() {
21
21
  return ['mutation:display-contents-children-element'];
22
22
  };
23
+ var getExcludedEntryTypes = function getExcludedEntryTypes() {
24
+ return ['layout-shift:same-rect'];
25
+ };
23
26
 
24
27
  // NOTE: `VCNext` to be renamed `FY26_04` once stable
25
28
  var VCNextCalculator = exports.default = /*#__PURE__*/function (_VCCalculator_FY25_) {
@@ -32,7 +35,7 @@ var VCNextCalculator = exports.default = /*#__PURE__*/function (_VCCalculator_FY
32
35
  key: "isEntryIncluded",
33
36
  value: function isEntryIncluded(entry, include3p) {
34
37
  var isEntryIncludedInV3 = _superPropGet(VCNextCalculator, "isEntryIncluded", this, 3)([entry, include3p]);
35
- if (isEntryIncludedInV3) {
38
+ if (isEntryIncludedInV3 && !getExcludedEntryTypes().includes(entry.data.type)) {
36
39
  return true;
37
40
  }
38
41
  return getConsideredEntryTypes().includes(entry.data.type);
@@ -22,41 +22,15 @@ var _performanceObserver = _interopRequireDefault(require("./performance-observe
22
22
  var _checkDisplayContent = _interopRequireDefault(require("./utils/check-display-content"));
23
23
  var _checkWithinComponent2 = _interopRequireWildcard(require("./utils/check-within-component"));
24
24
  var _getMutatedElements = require("./utils/get-mutated-elements");
25
+ var _isElementVisible = require("./utils/is-element-visible");
25
26
  var _isInVcIgnoreIfNoLayoutShiftMarker = _interopRequireDefault(require("./utils/is-in-vc-ignore-if-no-layout-shift-marker"));
27
+ var _isSameRectDimensions = require("./utils/is-same-rect-dimensions");
28
+ var _isSameRectSize = require("./utils/is-same-rect-size");
26
29
  var _trackDisplayContentOccurrence = _interopRequireDefault(require("./utils/track-display-content-occurrence"));
27
30
  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); }
28
31
  function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
29
32
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
30
33
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
31
- function isElementVisible(element) {
32
- if (!(element instanceof HTMLElement)) {
33
- return true;
34
- }
35
- try {
36
- var visible = element.checkVisibility({
37
- // @ts-ignore - visibilityProperty may not exist in all TS environments
38
- visibilityProperty: true,
39
- contentVisibilityAuto: true,
40
- opacityProperty: true
41
- });
42
- return visible;
43
- } catch (e) {
44
- // there is no support for checkVisibility
45
- return true;
46
- }
47
- }
48
- function sameRectSize(a, b) {
49
- if (!a || !b) {
50
- return false;
51
- }
52
- return a.width === b.width && a.height === b.height;
53
- }
54
- function sameRectDimensions(a, b) {
55
- if (!a || !b) {
56
- return false;
57
- }
58
- return a.width === b.width && a.height === b.height && a.x === b.x && a.y === b.y;
59
- }
60
34
  var createElementMutationsWatcher = function createElementMutationsWatcher(removedNodeRects) {
61
35
  return function (_ref) {
62
36
  var target = _ref.target,
@@ -70,7 +44,7 @@ var createElementMutationsWatcher = function createElementMutationsWatcher(remov
70
44
  return 'mutation:rll-placeholder';
71
45
  }
72
46
  var wasDeleted = removedNodeRects.some(function (nr) {
73
- return sameRectDimensions(nr, rect);
47
+ return (0, _isSameRectDimensions.isSameRectDimensions)(nr, rect);
74
48
  });
75
49
  if (wasDeleted && isInIgnoreLsMarker) {
76
50
  return 'mutation:element-replacement';
@@ -96,7 +70,7 @@ var ViewportObserver = exports.default = /*#__PURE__*/function () {
96
70
  if (!target) {
97
71
  return;
98
72
  }
99
- var visible = isElementVisible(target);
73
+ var visible = (0, _isElementVisible.isElementVisible)(target);
100
74
  var lastElementRect = _this.mapVisibleNodeRects.get(target);
101
75
  _this.mapVisibleNodeRects.set(target, rect);
102
76
  _this.onChange({
@@ -381,7 +355,7 @@ var ViewportObserver = exports.default = /*#__PURE__*/function () {
381
355
  };
382
356
  }
383
357
  var lastElementRect = _this.mapVisibleNodeRects.get(target);
384
- if (lastElementRect && sameRectSize(rect, lastElementRect)) {
358
+ if (lastElementRect && (0, _isSameRectSize.isSameRectSize)(rect, lastElementRect)) {
385
359
  return {
386
360
  type: 'mutation:attribute:no-layout-shift',
387
361
  mutationData: {
@@ -411,14 +385,26 @@ var ViewportObserver = exports.default = /*#__PURE__*/function () {
411
385
  var changedRect = _step4.value;
412
386
  var target = changedRect.node;
413
387
  if (target) {
414
- _this.onChange({
415
- time: time,
416
- elementRef: new WeakRef(target),
417
- visible: true,
418
- rect: changedRect.rect,
419
- previousRect: changedRect.previousRect,
420
- type: 'layout-shift'
421
- });
388
+ if ((0, _platformFeatureFlags.fg)('platform_ufo_vc_next_filter_ls_entries_same_rect')) {
389
+ var isSameCurrentAndPreviousRects = (0, _isSameRectDimensions.isSameRectDimensions)(changedRect.rect, changedRect.previousRect);
390
+ _this.onChange({
391
+ time: time,
392
+ elementRef: new WeakRef(target),
393
+ visible: true,
394
+ rect: changedRect.rect,
395
+ previousRect: changedRect.previousRect,
396
+ type: isSameCurrentAndPreviousRects ? 'layout-shift:same-rect' : 'layout-shift'
397
+ });
398
+ } else {
399
+ _this.onChange({
400
+ time: time,
401
+ elementRef: new WeakRef(target),
402
+ visible: true,
403
+ rect: changedRect.rect,
404
+ previousRect: changedRect.previousRect,
405
+ type: 'layout-shift'
406
+ });
407
+ }
422
408
  }
423
409
  }
424
410
  } catch (err) {
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isElementVisible = isElementVisible;
7
+ function isElementVisible(element) {
8
+ if (!(element instanceof HTMLElement)) {
9
+ return true;
10
+ }
11
+ try {
12
+ var visible = element.checkVisibility({
13
+ // @ts-ignore - visibilityProperty may not exist in all TS environments
14
+ visibilityProperty: true,
15
+ contentVisibilityAuto: true,
16
+ opacityProperty: true
17
+ });
18
+ return visible;
19
+ } catch (e) {
20
+ // there is no support for checkVisibility
21
+ return true;
22
+ }
23
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isSameRectDimensions = isSameRectDimensions;
7
+ var DIMENSIONS_CHECK_TOLERANCE_MARGIN_IN_PX = 1;
8
+ function isSameRectDimensions(a, b) {
9
+ if (!a || !b) {
10
+ return false;
11
+ }
12
+ return Math.abs(a.width - b.width) <= DIMENSIONS_CHECK_TOLERANCE_MARGIN_IN_PX && Math.abs(a.height - b.height) <= DIMENSIONS_CHECK_TOLERANCE_MARGIN_IN_PX && Math.abs(a.x - b.x) <= DIMENSIONS_CHECK_TOLERANCE_MARGIN_IN_PX && Math.abs(a.y - b.y) <= DIMENSIONS_CHECK_TOLERANCE_MARGIN_IN_PX;
13
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isSameRectSize = isSameRectSize;
7
+ var SIZE_CHECK_TOLERANCE_MARGIN_IN_PX = 1;
8
+ function isSameRectSize(a, b) {
9
+ if (!a || !b) {
10
+ return false;
11
+ }
12
+ return Math.abs(a.width - b.width) <= SIZE_CHECK_TOLERANCE_MARGIN_IN_PX && Math.abs(a.height - b.height) <= SIZE_CHECK_TOLERANCE_MARGIN_IN_PX;
13
+ }
@@ -110,7 +110,8 @@ function createPostInteractionLogPayload({
110
110
  lastInteractionFinish,
111
111
  reactProfilerTimings,
112
112
  lastInteractionFinishVCResult,
113
- postInteractionFinishVCResult
113
+ postInteractionFinishVCResult,
114
+ postInteractionHoldInfo
114
115
  }) {
115
116
  var _getMostRecentVCRevis, _window$location;
116
117
  const config = getConfig();
@@ -211,7 +212,13 @@ function createPostInteractionLogPayload({
211
212
  revisedVC90,
212
213
  vcClean: postInteractionFinishVCClean,
213
214
  lateMutations,
214
- reactProfilerTimings: transformReactProfilerTimings(reactProfilerTimings)
215
+ reactProfilerTimings: transformReactProfilerTimings(reactProfilerTimings),
216
+ ...(fg('platform_ufo_enable_late_holds_post_interaction') ? {
217
+ postInteractionHoldInfo: postInteractionHoldInfo === null || postInteractionHoldInfo === void 0 ? void 0 : postInteractionHoldInfo.map(hold => ({
218
+ ...hold,
219
+ labelStack: hold.labelStack.map(label => label.name).join('/')
220
+ }))
221
+ } : {})
215
222
  }
216
223
  }
217
224
  }
@@ -299,6 +299,10 @@ function removeHoldCriterion(id) {
299
299
  export function addHold(interactionId, labelStack, name, experimental) {
300
300
  const interaction = interactions.get(interactionId);
301
301
  const id = createUUID();
302
+ if (!interaction && fg('platform_ufo_enable_late_holds_post_interaction')) {
303
+ // add hold timestamp to post interaction log if interaction is complete
304
+ postInteractionLog.addHoldInfo(labelStack, name, performance.now());
305
+ }
302
306
  if (interaction != null) {
303
307
  const start = performance.now();
304
308
  const holdActive = {
@@ -18,6 +18,7 @@ export default class PostInteractionLog {
18
18
  * Store the scheduled sink timeout Id so that it can be cancelled when needed
19
19
  */
20
20
  _defineProperty(this, "sinkTimeoutId", null);
21
+ _defineProperty(this, "holdInfo", []);
21
22
  /**
22
23
  * independent VC observer, that observes until `custom.post-interaction-logs` event is sent
23
24
  */
@@ -71,6 +72,7 @@ export default class PostInteractionLog {
71
72
  reset() {
72
73
  this.lastInteractionFinish = null;
73
74
  this.reactProfilerTimings = [];
75
+ this.holdInfo = [];
74
76
  if (this.sinkTimeoutId != null) {
75
77
  clearTimeout(this.sinkTimeoutId);
76
78
  this.sinkTimeoutId = null;
@@ -121,7 +123,8 @@ export default class PostInteractionLog {
121
123
  lastInteractionFinish: this.lastInteractionFinish,
122
124
  reactProfilerTimings: this.reactProfilerTimings,
123
125
  postInteractionFinishVCResult,
124
- lastInteractionFinishVCResult: this.lastInteractionFinishVCResult
126
+ lastInteractionFinishVCResult: this.lastInteractionFinishVCResult,
127
+ postInteractionHoldInfo: this.holdInfo
125
128
  });
126
129
  this.reset();
127
130
  }
@@ -179,4 +182,11 @@ export default class PostInteractionLog {
179
182
  });
180
183
  }
181
184
  }
185
+ addHoldInfo(labelStack, name, start) {
186
+ this.holdInfo.push({
187
+ name,
188
+ labelStack,
189
+ start
190
+ });
191
+ }
182
192
  }
@@ -208,24 +208,14 @@ export default class AbstractVCCalculatorBase {
208
208
  // Only create debug details if callbacks exist
209
209
  let v3RevisionDebugDetails = null;
210
210
  if (shouldCalculateDebugDetails) {
211
- if (fg('platform_ufo_unify_abort_status_in_ttvc_debug_data')) {
212
- v3RevisionDebugDetails = {
213
- revision: this.revisionNo,
214
- isClean: isVCClean && !interactionAbortReason && isPageVisible,
215
- abortReason: !isPageVisible ? 'browser_backgrounded' : dirtyReason !== null && dirtyReason !== void 0 ? dirtyReason : interactionAbortReason,
216
- vcLogs: enhancedVcLogs,
217
- interactionId,
218
- interactionType
219
- };
220
- } else {
221
- v3RevisionDebugDetails = {
222
- revision: this.revisionNo,
223
- isClean: isVCClean,
224
- abortReason: dirtyReason,
225
- vcLogs: enhancedVcLogs,
226
- interactionId
227
- };
228
- }
211
+ v3RevisionDebugDetails = {
212
+ revision: this.revisionNo,
213
+ isClean: isVCClean && !interactionAbortReason && isPageVisible,
214
+ abortReason: !isPageVisible ? 'browser_backgrounded' : dirtyReason !== null && dirtyReason !== void 0 ? dirtyReason : interactionAbortReason,
215
+ vcLogs: enhancedVcLogs,
216
+ interactionId,
217
+ interactionType
218
+ };
229
219
  }
230
220
 
231
221
  // Handle devtool callback
@@ -7,6 +7,11 @@ const REVISION_NO = 'fy25.03';
7
7
  const getConsideredEntryTypes = include3p => {
8
8
  const entryTypes = ['mutation:child-element', 'mutation:element', 'mutation:attribute', 'layout-shift', 'window:event'];
9
9
 
10
+ // in rolling this out, still include it in TTVC v3
11
+ if (fg('platform_ufo_vc_next_filter_ls_entries_same_rect')) {
12
+ entryTypes.push('layout-shift:same-rect');
13
+ }
14
+
10
15
  // If not exclude 3p elements from ttvc,
11
16
  // including the tags into the ConsideredEntryTypes so that it won't be ignored for TTVC calculation
12
17
  if (!fg('platform_ufo_exclude_3p_elements_from_ttvc') || include3p) {
@@ -5,6 +5,9 @@ const REVISION_NO = 'next';
5
5
  const getConsideredEntryTypes = () => {
6
6
  return ['mutation:display-contents-children-element'];
7
7
  };
8
+ const getExcludedEntryTypes = () => {
9
+ return ['layout-shift:same-rect'];
10
+ };
8
11
 
9
12
  // NOTE: `VCNext` to be renamed `FY26_04` once stable
10
13
  export default class VCNextCalculator extends VCCalculator_FY25_03 {
@@ -13,7 +16,7 @@ export default class VCNextCalculator extends VCCalculator_FY25_03 {
13
16
  }
14
17
  isEntryIncluded(entry, include3p) {
15
18
  const isEntryIncludedInV3 = super.isEntryIncluded(entry, include3p);
16
- if (isEntryIncludedInV3) {
19
+ if (isEntryIncludedInV3 && !getExcludedEntryTypes().includes(entry.data.type)) {
17
20
  return true;
18
21
  }
19
22
  return getConsideredEntryTypes().includes(entry.data.type);
@@ -10,37 +10,11 @@ import createPerformanceObserver from './performance-observer';
10
10
  import checkCssProperty from './utils/check-display-content';
11
11
  import checkWithinComponent, { cleanupCaches } from './utils/check-within-component';
12
12
  import { getMutatedElements } from './utils/get-mutated-elements';
13
+ import { isElementVisible } from './utils/is-element-visible';
13
14
  import isInVCIgnoreIfNoLayoutShiftMarker from './utils/is-in-vc-ignore-if-no-layout-shift-marker';
15
+ import { isSameRectDimensions } from './utils/is-same-rect-dimensions';
16
+ import { isSameRectSize } from './utils/is-same-rect-size';
14
17
  import trackDisplayContentsOccurrence from './utils/track-display-content-occurrence';
15
- function isElementVisible(element) {
16
- if (!(element instanceof HTMLElement)) {
17
- return true;
18
- }
19
- try {
20
- const visible = element.checkVisibility({
21
- // @ts-ignore - visibilityProperty may not exist in all TS environments
22
- visibilityProperty: true,
23
- contentVisibilityAuto: true,
24
- opacityProperty: true
25
- });
26
- return visible;
27
- } catch (e) {
28
- // there is no support for checkVisibility
29
- return true;
30
- }
31
- }
32
- function sameRectSize(a, b) {
33
- if (!a || !b) {
34
- return false;
35
- }
36
- return a.width === b.width && a.height === b.height;
37
- }
38
- function sameRectDimensions(a, b) {
39
- if (!a || !b) {
40
- return false;
41
- }
42
- return a.width === b.width && a.height === b.height && a.x === b.x && a.y === b.y;
43
- }
44
18
  const createElementMutationsWatcher = removedNodeRects => ({
45
19
  target,
46
20
  rect
@@ -53,7 +27,7 @@ const createElementMutationsWatcher = removedNodeRects => ({
53
27
  if (isRLLPlaceholder && isInIgnoreLsMarker) {
54
28
  return 'mutation:rll-placeholder';
55
29
  }
56
- const wasDeleted = removedNodeRects.some(nr => sameRectDimensions(nr, rect));
30
+ const wasDeleted = removedNodeRects.some(nr => isSameRectDimensions(nr, rect));
57
31
  if (wasDeleted && isInIgnoreLsMarker) {
58
32
  return 'mutation:element-replacement';
59
33
  }
@@ -281,7 +255,7 @@ export default class ViewportObserver {
281
255
  };
282
256
  }
283
257
  const lastElementRect = this.mapVisibleNodeRects.get(target);
284
- if (lastElementRect && sameRectSize(rect, lastElementRect)) {
258
+ if (lastElementRect && isSameRectSize(rect, lastElementRect)) {
285
259
  return {
286
260
  type: 'mutation:attribute:no-layout-shift',
287
261
  mutationData: {
@@ -308,14 +282,26 @@ export default class ViewportObserver {
308
282
  for (const changedRect of changedRects) {
309
283
  const target = changedRect.node;
310
284
  if (target) {
311
- this.onChange({
312
- time,
313
- elementRef: new WeakRef(target),
314
- visible: true,
315
- rect: changedRect.rect,
316
- previousRect: changedRect.previousRect,
317
- type: 'layout-shift'
318
- });
285
+ if (fg('platform_ufo_vc_next_filter_ls_entries_same_rect')) {
286
+ const isSameCurrentAndPreviousRects = isSameRectDimensions(changedRect.rect, changedRect.previousRect);
287
+ this.onChange({
288
+ time,
289
+ elementRef: new WeakRef(target),
290
+ visible: true,
291
+ rect: changedRect.rect,
292
+ previousRect: changedRect.previousRect,
293
+ type: isSameCurrentAndPreviousRects ? 'layout-shift:same-rect' : 'layout-shift'
294
+ });
295
+ } else {
296
+ this.onChange({
297
+ time,
298
+ elementRef: new WeakRef(target),
299
+ visible: true,
300
+ rect: changedRect.rect,
301
+ previousRect: changedRect.previousRect,
302
+ type: 'layout-shift'
303
+ });
304
+ }
319
305
  }
320
306
  }
321
307
  });
@@ -0,0 +1,17 @@
1
+ export function isElementVisible(element) {
2
+ if (!(element instanceof HTMLElement)) {
3
+ return true;
4
+ }
5
+ try {
6
+ const visible = element.checkVisibility({
7
+ // @ts-ignore - visibilityProperty may not exist in all TS environments
8
+ visibilityProperty: true,
9
+ contentVisibilityAuto: true,
10
+ opacityProperty: true
11
+ });
12
+ return visible;
13
+ } catch (e) {
14
+ // there is no support for checkVisibility
15
+ return true;
16
+ }
17
+ }
@@ -0,0 +1,7 @@
1
+ const DIMENSIONS_CHECK_TOLERANCE_MARGIN_IN_PX = 1;
2
+ export function isSameRectDimensions(a, b) {
3
+ if (!a || !b) {
4
+ return false;
5
+ }
6
+ return Math.abs(a.width - b.width) <= DIMENSIONS_CHECK_TOLERANCE_MARGIN_IN_PX && Math.abs(a.height - b.height) <= DIMENSIONS_CHECK_TOLERANCE_MARGIN_IN_PX && Math.abs(a.x - b.x) <= DIMENSIONS_CHECK_TOLERANCE_MARGIN_IN_PX && Math.abs(a.y - b.y) <= DIMENSIONS_CHECK_TOLERANCE_MARGIN_IN_PX;
7
+ }
@@ -0,0 +1,7 @@
1
+ const SIZE_CHECK_TOLERANCE_MARGIN_IN_PX = 1;
2
+ export function isSameRectSize(a, b) {
3
+ if (!a || !b) {
4
+ return false;
5
+ }
6
+ return Math.abs(a.width - b.width) <= SIZE_CHECK_TOLERANCE_MARGIN_IN_PX && Math.abs(a.height - b.height) <= SIZE_CHECK_TOLERANCE_MARGIN_IN_PX;
7
+ }
@@ -118,7 +118,8 @@ function createPostInteractionLogPayload(_ref2) {
118
118
  var lastInteractionFinish = _ref2.lastInteractionFinish,
119
119
  reactProfilerTimings = _ref2.reactProfilerTimings,
120
120
  lastInteractionFinishVCResult = _ref2.lastInteractionFinishVCResult,
121
- postInteractionFinishVCResult = _ref2.postInteractionFinishVCResult;
121
+ postInteractionFinishVCResult = _ref2.postInteractionFinishVCResult,
122
+ postInteractionHoldInfo = _ref2.postInteractionHoldInfo;
122
123
  var config = getConfig();
123
124
  if (!config) {
124
125
  throw Error('UFO Configuration not provided');
@@ -206,7 +207,7 @@ function createPostInteractionLogPayload(_ref2) {
206
207
  },
207
208
  'event:region': config.region || 'unknown',
208
209
  'experience:key': 'custom.post-interaction-logs',
209
- postInteractionLog: {
210
+ postInteractionLog: _objectSpread({
210
211
  lastInteractionFinish: _objectSpread(_objectSpread({}, lastInteractionFinish), {}, {
211
212
  ufoName: ufoName,
212
213
  start: lastInteractionFinishStart,
@@ -221,7 +222,15 @@ function createPostInteractionLogPayload(_ref2) {
221
222
  vcClean: postInteractionFinishVCClean,
222
223
  lateMutations: lateMutations,
223
224
  reactProfilerTimings: transformReactProfilerTimings(reactProfilerTimings)
224
- }
225
+ }, fg('platform_ufo_enable_late_holds_post_interaction') ? {
226
+ postInteractionHoldInfo: postInteractionHoldInfo === null || postInteractionHoldInfo === void 0 ? void 0 : postInteractionHoldInfo.map(function (hold) {
227
+ return _objectSpread(_objectSpread({}, hold), {}, {
228
+ labelStack: hold.labelStack.map(function (label) {
229
+ return label.name;
230
+ }).join('/')
231
+ });
232
+ })
233
+ } : {})
225
234
  }
226
235
  }
227
236
  };
@@ -339,6 +339,10 @@ function removeHoldCriterion(id) {
339
339
  export function addHold(interactionId, labelStack, name, experimental) {
340
340
  var interaction = interactions.get(interactionId);
341
341
  var id = createUUID();
342
+ if (!interaction && fg('platform_ufo_enable_late_holds_post_interaction')) {
343
+ // add hold timestamp to post interaction log if interaction is complete
344
+ postInteractionLog.addHoldInfo(labelStack, name, performance.now());
345
+ }
342
346
  if (interaction != null) {
343
347
  var start = performance.now();
344
348
  var holdActive = {
@@ -25,6 +25,7 @@ var PostInteractionLog = /*#__PURE__*/function () {
25
25
  * Store the scheduled sink timeout Id so that it can be cancelled when needed
26
26
  */
27
27
  _defineProperty(this, "sinkTimeoutId", null);
28
+ _defineProperty(this, "holdInfo", []);
28
29
  /**
29
30
  * independent VC observer, that observes until `custom.post-interaction-logs` event is sent
30
31
  */
@@ -91,6 +92,7 @@ var PostInteractionLog = /*#__PURE__*/function () {
91
92
  value: function reset() {
92
93
  this.lastInteractionFinish = null;
93
94
  this.reactProfilerTimings = [];
95
+ this.holdInfo = [];
94
96
  if (this.sinkTimeoutId != null) {
95
97
  clearTimeout(this.sinkTimeoutId);
96
98
  this.sinkTimeoutId = null;
@@ -155,7 +157,8 @@ var PostInteractionLog = /*#__PURE__*/function () {
155
157
  lastInteractionFinish: this.lastInteractionFinish,
156
158
  reactProfilerTimings: this.reactProfilerTimings,
157
159
  postInteractionFinishVCResult: postInteractionFinishVCResult,
158
- lastInteractionFinishVCResult: this.lastInteractionFinishVCResult
160
+ lastInteractionFinishVCResult: this.lastInteractionFinishVCResult,
161
+ postInteractionHoldInfo: this.holdInfo
159
162
  });
160
163
  this.reset();
161
164
  case 13:
@@ -236,6 +239,15 @@ var PostInteractionLog = /*#__PURE__*/function () {
236
239
  });
237
240
  }
238
241
  }
242
+ }, {
243
+ key: "addHoldInfo",
244
+ value: function addHoldInfo(labelStack, name, start) {
245
+ this.holdInfo.push({
246
+ name: name,
247
+ labelStack: labelStack,
248
+ start: start
249
+ });
250
+ }
239
251
  }]);
240
252
  }();
241
253
  export { PostInteractionLog as default };
@@ -304,24 +304,14 @@ var AbstractVCCalculatorBase = /*#__PURE__*/function () {
304
304
  // Only create debug details if callbacks exist
305
305
  v3RevisionDebugDetails = null;
306
306
  if (shouldCalculateDebugDetails) {
307
- if (fg('platform_ufo_unify_abort_status_in_ttvc_debug_data')) {
308
- v3RevisionDebugDetails = {
309
- revision: this.revisionNo,
310
- isClean: isVCClean && !interactionAbortReason && isPageVisible,
311
- abortReason: !isPageVisible ? 'browser_backgrounded' : dirtyReason !== null && dirtyReason !== void 0 ? dirtyReason : interactionAbortReason,
312
- vcLogs: enhancedVcLogs,
313
- interactionId: interactionId,
314
- interactionType: interactionType
315
- };
316
- } else {
317
- v3RevisionDebugDetails = {
318
- revision: this.revisionNo,
319
- isClean: isVCClean,
320
- abortReason: dirtyReason,
321
- vcLogs: enhancedVcLogs,
322
- interactionId: interactionId
323
- };
324
- }
307
+ v3RevisionDebugDetails = {
308
+ revision: this.revisionNo,
309
+ isClean: isVCClean && !interactionAbortReason && isPageVisible,
310
+ abortReason: !isPageVisible ? 'browser_backgrounded' : dirtyReason !== null && dirtyReason !== void 0 ? dirtyReason : interactionAbortReason,
311
+ vcLogs: enhancedVcLogs,
312
+ interactionId: interactionId,
313
+ interactionType: interactionType
314
+ };
325
315
  }
326
316
 
327
317
  // Handle devtool callback
@@ -14,6 +14,11 @@ var REVISION_NO = 'fy25.03';
14
14
  var getConsideredEntryTypes = function getConsideredEntryTypes(include3p) {
15
15
  var entryTypes = ['mutation:child-element', 'mutation:element', 'mutation:attribute', 'layout-shift', 'window:event'];
16
16
 
17
+ // in rolling this out, still include it in TTVC v3
18
+ if (fg('platform_ufo_vc_next_filter_ls_entries_same_rect')) {
19
+ entryTypes.push('layout-shift:same-rect');
20
+ }
21
+
17
22
  // If not exclude 3p elements from ttvc,
18
23
  // including the tags into the ConsideredEntryTypes so that it won't be ignored for TTVC calculation
19
24
  if (!fg('platform_ufo_exclude_3p_elements_from_ttvc') || include3p) {
@@ -14,6 +14,9 @@ var REVISION_NO = 'next';
14
14
  var getConsideredEntryTypes = function getConsideredEntryTypes() {
15
15
  return ['mutation:display-contents-children-element'];
16
16
  };
17
+ var getExcludedEntryTypes = function getExcludedEntryTypes() {
18
+ return ['layout-shift:same-rect'];
19
+ };
17
20
 
18
21
  // NOTE: `VCNext` to be renamed `FY26_04` once stable
19
22
  var VCNextCalculator = /*#__PURE__*/function (_VCCalculator_FY25_) {
@@ -26,7 +29,7 @@ var VCNextCalculator = /*#__PURE__*/function (_VCCalculator_FY25_) {
26
29
  key: "isEntryIncluded",
27
30
  value: function isEntryIncluded(entry, include3p) {
28
31
  var isEntryIncludedInV3 = _superPropGet(VCNextCalculator, "isEntryIncluded", this, 3)([entry, include3p]);
29
- if (isEntryIncludedInV3) {
32
+ if (isEntryIncludedInV3 && !getExcludedEntryTypes().includes(entry.data.type)) {
30
33
  return true;
31
34
  }
32
35
  return getConsideredEntryTypes().includes(entry.data.type);
@@ -17,37 +17,11 @@ import createPerformanceObserver from './performance-observer';
17
17
  import checkCssProperty from './utils/check-display-content';
18
18
  import checkWithinComponent, { cleanupCaches } from './utils/check-within-component';
19
19
  import { getMutatedElements } from './utils/get-mutated-elements';
20
+ import { isElementVisible } from './utils/is-element-visible';
20
21
  import isInVCIgnoreIfNoLayoutShiftMarker from './utils/is-in-vc-ignore-if-no-layout-shift-marker';
22
+ import { isSameRectDimensions } from './utils/is-same-rect-dimensions';
23
+ import { isSameRectSize } from './utils/is-same-rect-size';
21
24
  import trackDisplayContentsOccurrence from './utils/track-display-content-occurrence';
22
- function isElementVisible(element) {
23
- if (!(element instanceof HTMLElement)) {
24
- return true;
25
- }
26
- try {
27
- var visible = element.checkVisibility({
28
- // @ts-ignore - visibilityProperty may not exist in all TS environments
29
- visibilityProperty: true,
30
- contentVisibilityAuto: true,
31
- opacityProperty: true
32
- });
33
- return visible;
34
- } catch (e) {
35
- // there is no support for checkVisibility
36
- return true;
37
- }
38
- }
39
- function sameRectSize(a, b) {
40
- if (!a || !b) {
41
- return false;
42
- }
43
- return a.width === b.width && a.height === b.height;
44
- }
45
- function sameRectDimensions(a, b) {
46
- if (!a || !b) {
47
- return false;
48
- }
49
- return a.width === b.width && a.height === b.height && a.x === b.x && a.y === b.y;
50
- }
51
25
  var createElementMutationsWatcher = function createElementMutationsWatcher(removedNodeRects) {
52
26
  return function (_ref) {
53
27
  var target = _ref.target,
@@ -61,7 +35,7 @@ var createElementMutationsWatcher = function createElementMutationsWatcher(remov
61
35
  return 'mutation:rll-placeholder';
62
36
  }
63
37
  var wasDeleted = removedNodeRects.some(function (nr) {
64
- return sameRectDimensions(nr, rect);
38
+ return isSameRectDimensions(nr, rect);
65
39
  });
66
40
  if (wasDeleted && isInIgnoreLsMarker) {
67
41
  return 'mutation:element-replacement';
@@ -372,7 +346,7 @@ var ViewportObserver = /*#__PURE__*/function () {
372
346
  };
373
347
  }
374
348
  var lastElementRect = _this.mapVisibleNodeRects.get(target);
375
- if (lastElementRect && sameRectSize(rect, lastElementRect)) {
349
+ if (lastElementRect && isSameRectSize(rect, lastElementRect)) {
376
350
  return {
377
351
  type: 'mutation:attribute:no-layout-shift',
378
352
  mutationData: {
@@ -402,14 +376,26 @@ var ViewportObserver = /*#__PURE__*/function () {
402
376
  var changedRect = _step4.value;
403
377
  var target = changedRect.node;
404
378
  if (target) {
405
- _this.onChange({
406
- time: time,
407
- elementRef: new WeakRef(target),
408
- visible: true,
409
- rect: changedRect.rect,
410
- previousRect: changedRect.previousRect,
411
- type: 'layout-shift'
412
- });
379
+ if (fg('platform_ufo_vc_next_filter_ls_entries_same_rect')) {
380
+ var isSameCurrentAndPreviousRects = isSameRectDimensions(changedRect.rect, changedRect.previousRect);
381
+ _this.onChange({
382
+ time: time,
383
+ elementRef: new WeakRef(target),
384
+ visible: true,
385
+ rect: changedRect.rect,
386
+ previousRect: changedRect.previousRect,
387
+ type: isSameCurrentAndPreviousRects ? 'layout-shift:same-rect' : 'layout-shift'
388
+ });
389
+ } else {
390
+ _this.onChange({
391
+ time: time,
392
+ elementRef: new WeakRef(target),
393
+ visible: true,
394
+ rect: changedRect.rect,
395
+ previousRect: changedRect.previousRect,
396
+ type: 'layout-shift'
397
+ });
398
+ }
413
399
  }
414
400
  }
415
401
  } catch (err) {
@@ -0,0 +1,17 @@
1
+ export function isElementVisible(element) {
2
+ if (!(element instanceof HTMLElement)) {
3
+ return true;
4
+ }
5
+ try {
6
+ var visible = element.checkVisibility({
7
+ // @ts-ignore - visibilityProperty may not exist in all TS environments
8
+ visibilityProperty: true,
9
+ contentVisibilityAuto: true,
10
+ opacityProperty: true
11
+ });
12
+ return visible;
13
+ } catch (e) {
14
+ // there is no support for checkVisibility
15
+ return true;
16
+ }
17
+ }
@@ -0,0 +1,7 @@
1
+ var DIMENSIONS_CHECK_TOLERANCE_MARGIN_IN_PX = 1;
2
+ export function isSameRectDimensions(a, b) {
3
+ if (!a || !b) {
4
+ return false;
5
+ }
6
+ return Math.abs(a.width - b.width) <= DIMENSIONS_CHECK_TOLERANCE_MARGIN_IN_PX && Math.abs(a.height - b.height) <= DIMENSIONS_CHECK_TOLERANCE_MARGIN_IN_PX && Math.abs(a.x - b.x) <= DIMENSIONS_CHECK_TOLERANCE_MARGIN_IN_PX && Math.abs(a.y - b.y) <= DIMENSIONS_CHECK_TOLERANCE_MARGIN_IN_PX;
7
+ }
@@ -0,0 +1,7 @@
1
+ var SIZE_CHECK_TOLERANCE_MARGIN_IN_PX = 1;
2
+ export function isSameRectSize(a, b) {
3
+ if (!a || !b) {
4
+ return false;
5
+ }
6
+ return Math.abs(a.width - b.width) <= SIZE_CHECK_TOLERANCE_MARGIN_IN_PX && Math.abs(a.height - b.height) <= SIZE_CHECK_TOLERANCE_MARGIN_IN_PX;
7
+ }
@@ -224,5 +224,6 @@ export type PostInteractionLogOutput = {
224
224
  reactProfilerTimings?: ReactProfilerTiming[];
225
225
  postInteractionFinishVCResult?: VCResult;
226
226
  lastInteractionFinishVCResult?: VCResult;
227
+ postInteractionHoldInfo?: HoldActive[];
227
228
  };
228
229
  export {};
@@ -240,6 +240,7 @@ export type PostInteractionLogPayload = {
240
240
  vcClean: boolean;
241
241
  lateMutations: LateMutation[];
242
242
  reactProfilerTimings: ReactProfilerTiming[];
243
+ postInteractionHoldInfo?: HoldActive[];
243
244
  };
244
245
  };
245
246
  };
@@ -1,6 +1,6 @@
1
1
  import { type PostInteractionLogOutput } from '../common';
2
2
  import type { LateMutation } from '../common/react-ufo-payload-schema';
3
- declare function createPostInteractionLogPayload({ lastInteractionFinish, reactProfilerTimings, lastInteractionFinishVCResult, postInteractionFinishVCResult, }: PostInteractionLogOutput): {
3
+ declare function createPostInteractionLogPayload({ lastInteractionFinish, reactProfilerTimings, lastInteractionFinishVCResult, postInteractionFinishVCResult, postInteractionHoldInfo, }: PostInteractionLogOutput): {
4
4
  actionSubject: string;
5
5
  action: string;
6
6
  eventType: string;
@@ -18,6 +18,12 @@ declare function createPostInteractionLogPayload({ lastInteractionFinish, reactP
18
18
  'event:region': string;
19
19
  'experience:key': string;
20
20
  postInteractionLog: {
21
+ postInteractionHoldInfo?: {
22
+ labelStack: string;
23
+ name: string;
24
+ start: number;
25
+ ignoreOnSubmit?: boolean;
26
+ }[] | undefined;
21
27
  lastInteractionFinish: {
22
28
  ufoName: string;
23
29
  start: number;
@@ -1,4 +1,4 @@
1
- import { type LastInteractionFinishInfo, type PostInteractionLogOutput, type ReactProfilerTiming } from '../common/common/types';
1
+ import { type HoldActive, type LastInteractionFinishInfo, type PostInteractionLogOutput, type ReactProfilerTiming } from '../common/common/types';
2
2
  import type { VCResult } from '../common/vc/types';
3
3
  import type { LabelStack } from '../interaction-context';
4
4
  import type { VCObserverInterface, VCObserverOptions } from '../vc/types';
@@ -15,6 +15,7 @@ export default class PostInteractionLog {
15
15
  * Store the scheduled sink timeout Id so that it can be cancelled when needed
16
16
  */
17
17
  sinkTimeoutId: number | null;
18
+ holdInfo: HoldActive[];
18
19
  /**
19
20
  * independent VC observer, that observes until `custom.post-interaction-logs` event is sent
20
21
  */
@@ -67,4 +68,5 @@ export default class PostInteractionLog {
67
68
  * This fn should be invoked when a React render happens after interaction has finished
68
69
  */
69
70
  addProfilerTimings(labelStack: LabelStack, type: 'mount' | 'update' | 'nested-update', actualDuration: number, baseDuration: number, startTime: number, commitTime: number): void;
71
+ addHoldInfo(labelStack: LabelStack, name: string, start: number): void;
70
72
  }
@@ -1,6 +1,6 @@
1
1
  import type { AbortReasonType, InteractionType } from '../../common/common/types';
2
2
  import type { ObservedWindowEvent } from './window-event-observer';
3
- export type VCObserverEntryType = 'mutation:child-element' | 'mutation:remount' | 'mutation:element' | 'mutation:element-replacement' | 'mutation:display-contents-children-element' | 'mutation:attribute:no-layout-shift' | 'mutation:attribute:non-visual-style' | 'mutation:attribute' | 'mutation:media' | 'mutation:rll-placeholder' | 'mutation:third-party-element' | 'mutation:ssr-placeholder' | 'layout-shift' | 'window:event' | 'ssr-hydration' | 'unknown';
3
+ export type VCObserverEntryType = 'mutation:child-element' | 'mutation:remount' | 'mutation:element' | 'mutation:element-replacement' | 'mutation:display-contents-children-element' | 'mutation:attribute:no-layout-shift' | 'mutation:attribute:non-visual-style' | 'mutation:attribute' | 'mutation:media' | 'mutation:rll-placeholder' | 'mutation:third-party-element' | 'mutation:ssr-placeholder' | 'layout-shift' | 'layout-shift:same-rect' | 'window:event' | 'ssr-hydration' | 'unknown';
4
4
  export type ViewportEntryData = {
5
5
  readonly type: VCObserverEntryType;
6
6
  readonly elementName: string;
@@ -0,0 +1 @@
1
+ export declare function isElementVisible(element: Element): boolean;
@@ -0,0 +1 @@
1
+ export declare function isSameRectDimensions(a: DOMRect | null | undefined, b: DOMRect | null | undefined): boolean;
@@ -0,0 +1 @@
1
+ export declare function isSameRectSize(a: DOMRect | null | undefined, b: DOMRect | null | undefined): boolean;
@@ -224,5 +224,6 @@ export type PostInteractionLogOutput = {
224
224
  reactProfilerTimings?: ReactProfilerTiming[];
225
225
  postInteractionFinishVCResult?: VCResult;
226
226
  lastInteractionFinishVCResult?: VCResult;
227
+ postInteractionHoldInfo?: HoldActive[];
227
228
  };
228
229
  export {};
@@ -244,6 +244,7 @@ export type PostInteractionLogPayload = {
244
244
  vcClean: boolean;
245
245
  lateMutations: LateMutation[];
246
246
  reactProfilerTimings: ReactProfilerTiming[];
247
+ postInteractionHoldInfo?: HoldActive[];
247
248
  };
248
249
  };
249
250
  };
@@ -1,6 +1,6 @@
1
1
  import { type PostInteractionLogOutput } from '../common';
2
2
  import type { LateMutation } from '../common/react-ufo-payload-schema';
3
- declare function createPostInteractionLogPayload({ lastInteractionFinish, reactProfilerTimings, lastInteractionFinishVCResult, postInteractionFinishVCResult, }: PostInteractionLogOutput): {
3
+ declare function createPostInteractionLogPayload({ lastInteractionFinish, reactProfilerTimings, lastInteractionFinishVCResult, postInteractionFinishVCResult, postInteractionHoldInfo, }: PostInteractionLogOutput): {
4
4
  actionSubject: string;
5
5
  action: string;
6
6
  eventType: string;
@@ -18,6 +18,12 @@ declare function createPostInteractionLogPayload({ lastInteractionFinish, reactP
18
18
  'event:region': string;
19
19
  'experience:key': string;
20
20
  postInteractionLog: {
21
+ postInteractionHoldInfo?: {
22
+ labelStack: string;
23
+ name: string;
24
+ start: number;
25
+ ignoreOnSubmit?: boolean;
26
+ }[] | undefined;
21
27
  lastInteractionFinish: {
22
28
  ufoName: string;
23
29
  start: number;
@@ -1,4 +1,4 @@
1
- import { type LastInteractionFinishInfo, type PostInteractionLogOutput, type ReactProfilerTiming } from '../common/common/types';
1
+ import { type HoldActive, type LastInteractionFinishInfo, type PostInteractionLogOutput, type ReactProfilerTiming } from '../common/common/types';
2
2
  import type { VCResult } from '../common/vc/types';
3
3
  import type { LabelStack } from '../interaction-context';
4
4
  import type { VCObserverInterface, VCObserverOptions } from '../vc/types';
@@ -15,6 +15,7 @@ export default class PostInteractionLog {
15
15
  * Store the scheduled sink timeout Id so that it can be cancelled when needed
16
16
  */
17
17
  sinkTimeoutId: number | null;
18
+ holdInfo: HoldActive[];
18
19
  /**
19
20
  * independent VC observer, that observes until `custom.post-interaction-logs` event is sent
20
21
  */
@@ -67,4 +68,5 @@ export default class PostInteractionLog {
67
68
  * This fn should be invoked when a React render happens after interaction has finished
68
69
  */
69
70
  addProfilerTimings(labelStack: LabelStack, type: 'mount' | 'update' | 'nested-update', actualDuration: number, baseDuration: number, startTime: number, commitTime: number): void;
71
+ addHoldInfo(labelStack: LabelStack, name: string, start: number): void;
70
72
  }
@@ -1,6 +1,6 @@
1
1
  import type { AbortReasonType, InteractionType } from '../../common/common/types';
2
2
  import type { ObservedWindowEvent } from './window-event-observer';
3
- export type VCObserverEntryType = 'mutation:child-element' | 'mutation:remount' | 'mutation:element' | 'mutation:element-replacement' | 'mutation:display-contents-children-element' | 'mutation:attribute:no-layout-shift' | 'mutation:attribute:non-visual-style' | 'mutation:attribute' | 'mutation:media' | 'mutation:rll-placeholder' | 'mutation:third-party-element' | 'mutation:ssr-placeholder' | 'layout-shift' | 'window:event' | 'ssr-hydration' | 'unknown';
3
+ export type VCObserverEntryType = 'mutation:child-element' | 'mutation:remount' | 'mutation:element' | 'mutation:element-replacement' | 'mutation:display-contents-children-element' | 'mutation:attribute:no-layout-shift' | 'mutation:attribute:non-visual-style' | 'mutation:attribute' | 'mutation:media' | 'mutation:rll-placeholder' | 'mutation:third-party-element' | 'mutation:ssr-placeholder' | 'layout-shift' | 'layout-shift:same-rect' | 'window:event' | 'ssr-hydration' | 'unknown';
4
4
  export type ViewportEntryData = {
5
5
  readonly type: VCObserverEntryType;
6
6
  readonly elementName: string;
@@ -0,0 +1 @@
1
+ export declare function isElementVisible(element: Element): boolean;
@@ -0,0 +1 @@
1
+ export declare function isSameRectDimensions(a: DOMRect | null | undefined, b: DOMRect | null | undefined): boolean;
@@ -0,0 +1 @@
1
+ export declare function isSameRectSize(a: DOMRect | null | undefined, b: DOMRect | null | undefined): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/react-ufo",
3
- "version": "4.11.0",
3
+ "version": "4.11.2",
4
4
  "description": "Parts of React UFO that are publicly available",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -88,6 +88,9 @@
88
88
  "platform_ufo_vcnext_v4_enabled": {
89
89
  "type": "boolean"
90
90
  },
91
+ "platform_ufo_vc_next_filter_ls_entries_same_rect": {
92
+ "type": "boolean"
93
+ },
91
94
  "platform_ufo_enable_minor_interactions": {
92
95
  "type": "boolean"
93
96
  },
@@ -121,9 +124,6 @@
121
124
  "platform_ufo_enable_interactivity_jsm": {
122
125
  "type": "boolean"
123
126
  },
124
- "platform_ufo_unify_abort_status_in_ttvc_debug_data": {
125
- "type": "boolean"
126
- },
127
127
  "platform_ufo_exclude_3p_elements_from_ttai": {
128
128
  "type": "boolean"
129
129
  },
@@ -148,6 +148,9 @@
148
148
  "platform_ufo_exclude_3p_extensions_from_ttvc": {
149
149
  "type": "boolean"
150
150
  },
151
+ "platform_ufo_enable_late_holds_post_interaction": {
152
+ "type": "boolean"
153
+ },
151
154
  "platform_ufo_display_content_track_occurrence": {
152
155
  "type": "boolean"
153
156
  },