@atlaskit/react-ufo 5.2.9 → 5.2.10

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 (51) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/cjs/interaction-metrics/index.js +1 -0
  3. package/dist/cjs/interaction-metrics-init/index.js +2 -1
  4. package/dist/cjs/vc/index.js +4 -2
  5. package/dist/cjs/vc/vc-observer-new/index.js +10 -4
  6. package/dist/cjs/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.js +84 -29
  7. package/dist/cjs/vc/vc-observer-new/metric-calculator/utils/detect-layout-shift-cause.js +164 -0
  8. package/dist/cjs/vc/vc-observer-new/viewport-observer/index.js +173 -34
  9. package/dist/cjs/vc/vc-observer-new/viewport-observer/intersection-observer/index.js +1 -1
  10. package/dist/cjs/vc/vc-observer-new/viewport-observer/mutation-observer/index.js +2 -1
  11. package/dist/es2019/interaction-metrics/index.js +1 -0
  12. package/dist/es2019/interaction-metrics-init/index.js +2 -1
  13. package/dist/es2019/vc/index.js +4 -2
  14. package/dist/es2019/vc/vc-observer-new/index.js +10 -5
  15. package/dist/es2019/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.js +61 -7
  16. package/dist/es2019/vc/vc-observer-new/metric-calculator/utils/detect-layout-shift-cause.js +138 -0
  17. package/dist/es2019/vc/vc-observer-new/viewport-observer/index.js +145 -10
  18. package/dist/es2019/vc/vc-observer-new/viewport-observer/intersection-observer/index.js +1 -1
  19. package/dist/es2019/vc/vc-observer-new/viewport-observer/mutation-observer/index.js +2 -1
  20. package/dist/esm/interaction-metrics/index.js +1 -0
  21. package/dist/esm/interaction-metrics-init/index.js +2 -1
  22. package/dist/esm/vc/index.js +4 -2
  23. package/dist/esm/vc/vc-observer-new/index.js +10 -4
  24. package/dist/esm/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.js +84 -29
  25. package/dist/esm/vc/vc-observer-new/metric-calculator/utils/detect-layout-shift-cause.js +158 -0
  26. package/dist/esm/vc/vc-observer-new/viewport-observer/index.js +173 -34
  27. package/dist/esm/vc/vc-observer-new/viewport-observer/intersection-observer/index.js +1 -1
  28. package/dist/esm/vc/vc-observer-new/viewport-observer/mutation-observer/index.js +2 -1
  29. package/dist/types/common/vc/types.d.ts +55 -0
  30. package/dist/types/config/index.d.ts +1 -0
  31. package/dist/types/vc/types.d.ts +2 -0
  32. package/dist/types/vc/vc-observer-new/index.d.ts +2 -0
  33. package/dist/types/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.d.ts +1 -1
  34. package/dist/types/vc/vc-observer-new/metric-calculator/types.d.ts +1 -0
  35. package/dist/types/vc/vc-observer-new/metric-calculator/utils/detect-layout-shift-cause.d.ts +31 -0
  36. package/dist/types/vc/vc-observer-new/types.d.ts +2 -0
  37. package/dist/types/vc/vc-observer-new/viewport-observer/index.d.ts +3 -1
  38. package/dist/types/vc/vc-observer-new/viewport-observer/mutation-observer/index.d.ts +1 -0
  39. package/dist/types/vc/vc-observer-new/viewport-observer/types.d.ts +5 -2
  40. package/dist/types-ts4.5/common/vc/types.d.ts +55 -0
  41. package/dist/types-ts4.5/config/index.d.ts +1 -0
  42. package/dist/types-ts4.5/vc/types.d.ts +2 -0
  43. package/dist/types-ts4.5/vc/vc-observer-new/index.d.ts +2 -0
  44. package/dist/types-ts4.5/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.d.ts +1 -1
  45. package/dist/types-ts4.5/vc/vc-observer-new/metric-calculator/types.d.ts +1 -0
  46. package/dist/types-ts4.5/vc/vc-observer-new/metric-calculator/utils/detect-layout-shift-cause.d.ts +31 -0
  47. package/dist/types-ts4.5/vc/vc-observer-new/types.d.ts +2 -0
  48. package/dist/types-ts4.5/vc/vc-observer-new/viewport-observer/index.d.ts +3 -1
  49. package/dist/types-ts4.5/vc/vc-observer-new/viewport-observer/mutation-observer/index.d.ts +1 -0
  50. package/dist/types-ts4.5/vc/vc-observer-new/viewport-observer/types.d.ts +5 -2
  51. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # @atlaskit/ufo-interaction-ignore
2
2
 
3
+ ## 5.2.10
4
+
5
+ ### Patch Changes
6
+
7
+ - [`06d7af199b6c7`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/06d7af199b6c7) -
8
+ Added experimental API to track VC offenders
9
+
3
10
  ## 5.2.9
4
11
 
5
12
  ### Patch Changes
@@ -1194,6 +1194,7 @@ function addNewInteraction(interactionId, ufoName, type, startTime, rate, labelS
1194
1194
  devToolsEnabled: config.vc.devToolsEnabled,
1195
1195
  selectorConfig: config.vc.selectorConfig,
1196
1196
  ssrEnablePageLayoutPlaceholder: config.vc.ssrEnablePageLayoutPlaceholder,
1197
+ trackLayoutShiftOffenders: config.vc.trackLayoutShiftOffenders,
1197
1198
  searchPageConfig: searchPageConfig
1198
1199
  };
1199
1200
  vcObserver = (0, _vc.newVCObserver)(vcOptions);
@@ -182,7 +182,8 @@ function init(analyticsWebClientAsync, config) {
182
182
  oldDomUpdates: config.vc.oldDomUpdates,
183
183
  devToolsEnabled: config.vc.devToolsEnabled,
184
184
  selectorConfig: config.vc.selectorConfig,
185
- ssrEnablePageLayoutPlaceholder: config.vc.ssrEnablePageLayoutPlaceholder
185
+ ssrEnablePageLayoutPlaceholder: config.vc.ssrEnablePageLayoutPlaceholder,
186
+ trackLayoutShiftOffenders: config.vc.trackLayoutShiftOffenders
186
187
  };
187
188
  _interactionMetrics.postInteractionLog.initializeVCObserver(vcOptions);
188
189
  if (config !== null && config !== void 0 && (_config$experimentalI = config.experimentalInteractionMetrics) !== null && _config$experimentalI !== void 0 && _config$experimentalI.enabled) {
@@ -36,7 +36,7 @@ var VCObserverWrapper = exports.VCObserverWrapper = /*#__PURE__*/function () {
36
36
  enablePageLayoutPlaceholder: (_opts$ssrEnablePageLa = opts.ssrEnablePageLayoutPlaceholder) !== null && _opts$ssrEnablePageLa !== void 0 ? _opts$ssrEnablePageLa : false
37
37
  });
38
38
  if ((0, _config.isVCRevisionEnabled)('fy25.03') || (0, _config.isVCRevisionEnabled)('fy26.04')) {
39
- var _opts$ssrEnablePageLa2;
39
+ var _opts$ssrEnablePageLa2, _opts$trackLayoutShif;
40
40
  this.newVCObserver = new _vcObserverNew.default({
41
41
  selectorConfig: opts.selectorConfig,
42
42
  isPostInteraction: opts.isPostInteraction,
@@ -44,6 +44,7 @@ var VCObserverWrapper = exports.VCObserverWrapper = /*#__PURE__*/function () {
44
44
  enablePageLayoutPlaceholder: (_opts$ssrEnablePageLa2 = opts.ssrEnablePageLayoutPlaceholder) !== null && _opts$ssrEnablePageLa2 !== void 0 ? _opts$ssrEnablePageLa2 : false
45
45
  },
46
46
  ssrPlaceholderHandler: this.ssrPlaceholderHandler,
47
+ trackLayoutShiftOffenders: (_opts$trackLayoutShif = opts.trackLayoutShiftOffenders) !== null && _opts$trackLayoutShif !== void 0 ? _opts$trackLayoutShif : false,
47
48
  searchPageConfig: opts.searchPageConfig
48
49
  });
49
50
  }
@@ -160,7 +161,8 @@ var VCObserverWrapper = exports.VCObserverWrapper = /*#__PURE__*/function () {
160
161
  interactionAbortReason: param.interactionAbortReason,
161
162
  includeRawData: includeRawData,
162
163
  includeSSRInV3: param.includeSSRInV3,
163
- rawDataStopTime: param.rawDataStopTime
164
+ rawDataStopTime: param.rawDataStopTime,
165
+ reportLayoutShiftOffenders: param.reportLayoutShiftOffenders
164
166
  });
165
167
  case 12:
166
168
  _context.t1 = _context.sent;
@@ -47,6 +47,7 @@ var VCObserverNew = exports.default = /*#__PURE__*/function () {
47
47
  function VCObserverNew(config) {
48
48
  var _config$isPostInterac,
49
49
  _config$selectorConfi,
50
+ _config$trackLayoutSh,
50
51
  _this = this;
51
52
  (0, _classCallCheck2.default)(this, VCObserverNew);
52
53
  (0, _defineProperty2.default)(this, "viewportObserver", null);
@@ -72,6 +73,7 @@ var VCObserverNew = exports.default = /*#__PURE__*/function () {
72
73
  enablePageLayoutPlaceholder: (_config$SSRConfig$ena = (_config$SSRConfig = config.SSRConfig) === null || _config$SSRConfig === void 0 ? void 0 : _config$SSRConfig.enablePageLayoutPlaceholder) !== null && _config$SSRConfig$ena !== void 0 ? _config$SSRConfig$ena : false
73
74
  });
74
75
  }
76
+ this.trackLayoutShiftOffenders = (_config$trackLayoutSh = config.trackLayoutShiftOffenders) !== null && _config$trackLayoutSh !== void 0 ? _config$trackLayoutSh : false;
75
77
  this.viewportObserver = new _viewportObserver.default({
76
78
  onChange: function onChange(onChangeArg) {
77
79
  var time = onChangeArg.time,
@@ -94,7 +96,8 @@ var VCObserverNew = exports.default = /*#__PURE__*/function () {
94
96
  visible: visible,
95
97
  attributeName: mutationData === null || mutationData === void 0 ? void 0 : mutationData.attributeName,
96
98
  oldValue: mutationData === null || mutationData === void 0 ? void 0 : mutationData.oldValue,
97
- newValue: mutationData === null || mutationData === void 0 ? void 0 : mutationData.newValue
99
+ newValue: mutationData === null || mutationData === void 0 ? void 0 : mutationData.newValue,
100
+ originalMutationTimestamp: mutationData === null || mutationData === void 0 ? void 0 : mutationData.timestamp
98
101
  };
99
102
  if (element) {
100
103
  var labelStacks = getLabelStacks(element);
@@ -116,7 +119,8 @@ var VCObserverNew = exports.default = /*#__PURE__*/function () {
116
119
  getSSRPlaceholderHandler: function getSSRPlaceholderHandler() {
117
120
  return _this.getSSRPlaceholderHandler();
118
121
  },
119
- searchPageConfig: config.searchPageConfig
122
+ searchPageConfig: config.searchPageConfig,
123
+ trackLayoutShiftOffenders: this.trackLayoutShiftOffenders
120
124
  });
121
125
  this.windowEventObserver = new _windowEventObserver.default({
122
126
  onEvent: function onEvent(_ref) {
@@ -316,7 +320,8 @@ var VCObserverNew = exports.default = /*#__PURE__*/function () {
316
320
  excludeSmartAnswersInSearch: excludeSmartAnswersInSearch,
317
321
  includeSSRRatio: includeSSRRatio,
318
322
  isPageVisible: isPageVisible,
319
- interactionAbortReason: interactionAbortReason
323
+ interactionAbortReason: interactionAbortReason,
324
+ reportLayoutShiftOffenders: this.trackLayoutShiftOffenders
320
325
  });
321
326
  case 10:
322
327
  _context.t0 = _context.sent;
@@ -347,7 +352,8 @@ var VCObserverNew = exports.default = /*#__PURE__*/function () {
347
352
  excludeSmartAnswersInSearch: excludeSmartAnswersInSearch,
348
353
  includeSSRRatio: includeSSRRatio,
349
354
  isPageVisible: isPageVisible,
350
- interactionAbortReason: interactionAbortReason
355
+ interactionAbortReason: interactionAbortReason,
356
+ reportLayoutShiftOffenders: this.trackLayoutShiftOffenders
351
357
  };
352
358
  _context.next = 22;
353
359
  return Promise.all([(0, _config.isVCRevisionEnabled)('fy26.04') ? calculator_fy26_04.calculate(calculatorParams) : null, (0, _config.isVCRevisionEnabled)('next') ? calculator_next.calculate(calculatorParams) : null]);
@@ -14,6 +14,7 @@ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/cl
14
14
  var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
15
15
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
16
16
  var _percentileCalc = require("./percentile-calc");
17
+ var _detectLayoutShiftCause = require("./utils/detect-layout-shift-cause");
17
18
  var _getViewportHeight = _interopRequireDefault(require("./utils/get-viewport-height"));
18
19
  var _getViewportWidth = _interopRequireDefault(require("./utils/get-viewport-width"));
19
20
  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; }
@@ -118,9 +119,9 @@ var AbstractVCCalculatorBase = exports.default = /*#__PURE__*/function () {
118
119
  }, {
119
120
  key: "calculateWithDebugInfo",
120
121
  value: function () {
121
- var _calculateWithDebugInfo = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(filteredEntries, startTime, stopTime, isPostInteraction, isVCClean, interactionType, isPageVisible, interactionId, dirtyReason, allEntries, include3p, excludeSmartAnswersInSearch, interactionAbortReason, includeSSRRatio) {
122
+ var _calculateWithDebugInfo = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(filteredEntries, startTime, stopTime, isPostInteraction, isVCClean, interactionType, isPageVisible, interactionId, dirtyReason, allEntries, include3p, excludeSmartAnswersInSearch, interactionAbortReason, includeSSRRatio, reportLayoutShiftOffenders) {
122
123
  var _window, _window2, _window3, _window4, _window6;
123
- var percentiles, viewportEntries, _yield$calculateTTVCP, vcLogs, speedIndex, vcDetails, percentileIndex, entryDataBuffer, ssrRatio, _iterator4, _step4, _entry3, time, viewportPercentage, entries, elementNames, previousResult, i, percentile, enhancedVcLogs, shouldCalculate3p, shouldCalculateDebugDetails, sortedVcLogs, maxViewportPercentageAtTime, maxSoFar, _iterator5, _step5, log, getBiggestPreviousViewportPercentage, ignoredEntriesByTime, _iterator6, _step6, _entry4, _ignoredEntriesByTime, _viewportData$rect, _viewportData$previou, viewportData, timestamp, additionalVcLogs, _iterator7, _step7, _step7$value, _timestamp, ignoredEntries, _viewportPercentage, v3RevisionDebugDetails, _window5, _window5$__ufo_devtoo, _window7, _window7$__on_ufo_vc_;
124
+ var percentiles, viewportEntries, _yield$calculateTTVCP, vcLogs, speedIndex, vcDetails, percentileIndex, entryDataBuffer, ssrRatio, layoutShiftInsights, previousViewportPercentage, _iterator4, _step4, _entry3, time, viewportPercentage, entries, elementNames, layoutShiftEntries, previousResult, i, percentile, enhancedVcLogs, shouldCalculate3p, shouldCalculateDebugDetails, sortedVcLogs, maxViewportPercentageAtTime, maxSoFar, _iterator5, _step5, log, getBiggestPreviousViewportPercentage, ignoredEntriesByTime, _iterator6, _step6, _entry4, _ignoredEntriesByTime, _viewportData$rect, _viewportData$previou, viewportData, timestamp, additionalVcLogs, _iterator7, _step7, _step7$value, _timestamp, ignoredEntries, _viewportPercentage, v3RevisionDebugDetails, _window5, _window5$__ufo_devtoo, _window7, _window7$__on_ufo_vc_;
124
125
  return _regenerator.default.wrap(function _callee$(_context) {
125
126
  while (1) switch (_context.prev = _context.next) {
126
127
  case 0:
@@ -144,16 +145,18 @@ var AbstractVCCalculatorBase = exports.default = /*#__PURE__*/function () {
144
145
  percentileIndex = 0;
145
146
  entryDataBuffer = new Set();
146
147
  ssrRatio = -1;
148
+ layoutShiftInsights = null;
149
+ previousViewportPercentage = 0;
147
150
  if (!vcLogs) {
148
- _context.next = 32;
151
+ _context.next = 35;
149
152
  break;
150
153
  }
151
154
  _iterator4 = _createForOfIteratorHelper(vcLogs);
152
- _context.prev = 13;
155
+ _context.prev = 15;
153
156
  _iterator4.s();
154
- case 15:
157
+ case 17:
155
158
  if ((_step4 = _iterator4.n()).done) {
156
- _context.next = 24;
159
+ _context.next = 27;
157
160
  break;
158
161
  }
159
162
  _entry3 = _step4.value;
@@ -166,11 +169,11 @@ var AbstractVCCalculatorBase = exports.default = /*#__PURE__*/function () {
166
169
 
167
170
  // Only process entries if we haven't reached all percentiles
168
171
  if (!(percentileIndex >= percentiles.length)) {
169
- _context.next = 21;
172
+ _context.next = 23;
170
173
  break;
171
174
  }
172
- return _context.abrupt("break", 24);
173
- case 21:
175
+ return _context.abrupt("break", 27);
176
+ case 23:
174
177
  // Check if this entry matches any checkpoint percentiles
175
178
  if (viewportPercentage >= percentiles[percentileIndex]) {
176
179
  elementNames = (0, _toConsumableArray2.default)(new Set(entries.map(function (e) {
@@ -181,6 +184,23 @@ var AbstractVCCalculatorBase = exports.default = /*#__PURE__*/function () {
181
184
  t: Math.round(time),
182
185
  e: elementNames
183
186
  };
187
+ if (reportLayoutShiftOffenders && percentiles[percentileIndex] === 90 && entries.some(function (e) {
188
+ return e.type === 'layout-shift';
189
+ })) {
190
+ layoutShiftEntries = entries.filter(function (e) {
191
+ return e.type === 'layout-shift';
192
+ });
193
+ layoutShiftInsights = {
194
+ layoutShiftOffendersResult: (0, _detectLayoutShiftCause.detectLayoutShiftCause)({
195
+ viewportEntries: viewportEntries,
196
+ layoutShiftEntries: layoutShiftEntries,
197
+ time: time,
198
+ startTime: startTime
199
+ }),
200
+ layoutShiftEntriesCount: layoutShiftEntries.length,
201
+ layoutShiftImpact: viewportPercentage - previousViewportPercentage
202
+ };
203
+ }
184
204
  percentileIndex++;
185
205
  }
186
206
 
@@ -192,21 +212,22 @@ var AbstractVCCalculatorBase = exports.default = /*#__PURE__*/function () {
192
212
  return entryDataBuffer.add(e);
193
213
  });
194
214
  }
195
- case 22:
196
- _context.next = 15;
215
+ previousViewportPercentage = viewportPercentage;
216
+ case 25:
217
+ _context.next = 17;
197
218
  break;
198
- case 24:
199
- _context.next = 29;
219
+ case 27:
220
+ _context.next = 32;
200
221
  break;
201
- case 26:
202
- _context.prev = 26;
203
- _context.t0 = _context["catch"](13);
204
- _iterator4.e(_context.t0);
205
222
  case 29:
206
223
  _context.prev = 29;
207
- _iterator4.f();
208
- return _context.finish(29);
224
+ _context.t0 = _context["catch"](15);
225
+ _iterator4.e(_context.t0);
209
226
  case 32:
227
+ _context.prev = 32;
228
+ _iterator4.f();
229
+ return _context.finish(32);
230
+ case 35:
210
231
  // Fill in any missing percentiles with the last known values
211
232
  previousResult = {
212
233
  t: 0,
@@ -367,15 +388,16 @@ var AbstractVCCalculatorBase = exports.default = /*#__PURE__*/function () {
367
388
  return _context.abrupt("return", {
368
389
  vcDetails: vcDetails,
369
390
  ssrRatio: ssrRatio,
370
- speedIndex: speedIndex
391
+ speedIndex: speedIndex,
392
+ VC90layoutShiftInsights: layoutShiftInsights
371
393
  });
372
- case 44:
394
+ case 47:
373
395
  case "end":
374
396
  return _context.stop();
375
397
  }
376
- }, _callee, this, [[13, 26, 29, 32]]);
398
+ }, _callee, this, [[15, 29, 32, 35]]);
377
399
  }));
378
- function calculateWithDebugInfo(_x, _x2, _x3, _x4, _x5, _x6, _x7, _x8, _x9, _x0, _x1, _x10, _x11, _x12) {
400
+ function calculateWithDebugInfo(_x, _x2, _x3, _x4, _x5, _x6, _x7, _x8, _x9, _x0, _x1, _x10, _x11, _x12, _x13) {
379
401
  return _calculateWithDebugInfo.apply(this, arguments);
380
402
  }
381
403
  return calculateWithDebugInfo;
@@ -387,11 +409,11 @@ var AbstractVCCalculatorBase = exports.default = /*#__PURE__*/function () {
387
409
  var _this = this,
388
410
  _vcDetails$90$t,
389
411
  _vcDetails$;
390
- var startTime, stopTime, orderedEntries, interactionId, isPostInteraction, include3p, excludeSmartAnswersInSearch, includeSSRRatio, interactionType, isPageVisible, interactionAbortReason, filteredEntries, isVCClean, dirtyReason, getVCCleanStatusResult, _yield$this$calculate, vcDetails, ssrRatio, speedIndex, result;
412
+ var startTime, stopTime, orderedEntries, interactionId, isPostInteraction, include3p, excludeSmartAnswersInSearch, includeSSRRatio, interactionType, isPageVisible, interactionAbortReason, reportLayoutShiftOffenders, filteredEntries, isVCClean, dirtyReason, getVCCleanStatusResult, _yield$this$calculate, vcDetails, ssrRatio, speedIndex, VC90layoutShiftInsights, layoutShiftInsightsPayload, _layoutShiftOffenders, _layoutShiftOffenders2, _layoutShiftOffenders3, layoutShiftOffendersResult, layoutShiftEntriesCount, layoutShiftImpact, result;
391
413
  return _regenerator.default.wrap(function _callee2$(_context2) {
392
414
  while (1) switch (_context2.prev = _context2.next) {
393
415
  case 0:
394
- startTime = _ref.startTime, stopTime = _ref.stopTime, orderedEntries = _ref.orderedEntries, interactionId = _ref.interactionId, isPostInteraction = _ref.isPostInteraction, include3p = _ref.include3p, excludeSmartAnswersInSearch = _ref.excludeSmartAnswersInSearch, includeSSRRatio = _ref.includeSSRRatio, interactionType = _ref.interactionType, isPageVisible = _ref.isPageVisible, interactionAbortReason = _ref.interactionAbortReason;
416
+ startTime = _ref.startTime, stopTime = _ref.stopTime, orderedEntries = _ref.orderedEntries, interactionId = _ref.interactionId, isPostInteraction = _ref.isPostInteraction, include3p = _ref.include3p, excludeSmartAnswersInSearch = _ref.excludeSmartAnswersInSearch, includeSSRRatio = _ref.includeSSRRatio, interactionType = _ref.interactionType, isPageVisible = _ref.isPageVisible, interactionAbortReason = _ref.interactionAbortReason, reportLayoutShiftOffenders = _ref.reportLayoutShiftOffenders;
395
417
  filteredEntries = orderedEntries.filter(function (entry) {
396
418
  return _this.isEntryIncluded(entry, include3p, excludeSmartAnswersInSearch);
397
419
  });
@@ -411,17 +433,50 @@ var AbstractVCCalculatorBase = exports.default = /*#__PURE__*/function () {
411
433
  });
412
434
  case 7:
413
435
  _context2.next = 9;
414
- return this.calculateWithDebugInfo(filteredEntries, startTime, stopTime, isPostInteraction, isVCClean, interactionType, isPageVisible, interactionId, dirtyReason, orderedEntries, include3p, excludeSmartAnswersInSearch, interactionAbortReason, includeSSRRatio);
436
+ return this.calculateWithDebugInfo(filteredEntries, startTime, stopTime, isPostInteraction, isVCClean, interactionType, isPageVisible, interactionId, dirtyReason, orderedEntries, include3p, excludeSmartAnswersInSearch, interactionAbortReason, includeSSRRatio, reportLayoutShiftOffenders);
415
437
  case 9:
416
438
  _yield$this$calculate = _context2.sent;
417
439
  vcDetails = _yield$this$calculate.vcDetails;
418
440
  ssrRatio = _yield$this$calculate.ssrRatio;
419
441
  speedIndex = _yield$this$calculate.speedIndex;
442
+ VC90layoutShiftInsights = _yield$this$calculate.VC90layoutShiftInsights;
443
+ if (VC90layoutShiftInsights !== null && reportLayoutShiftOffenders) {
444
+ layoutShiftOffendersResult = VC90layoutShiftInsights.layoutShiftOffendersResult, layoutShiftEntriesCount = VC90layoutShiftInsights.layoutShiftEntriesCount, layoutShiftImpact = VC90layoutShiftInsights.layoutShiftImpact;
445
+ layoutShiftInsightsPayload = {
446
+ impact: layoutShiftImpact,
447
+ sources: layoutShiftEntriesCount !== null && layoutShiftEntriesCount !== void 0 ? layoutShiftEntriesCount : 0,
448
+ same: {
449
+ dir: (_layoutShiftOffenders = layoutShiftOffendersResult === null || layoutShiftOffendersResult === void 0 ? void 0 : layoutShiftOffendersResult.layoutShiftVariables.allMovedSameWay) !== null && _layoutShiftOffenders !== void 0 ? _layoutShiftOffenders : false,
450
+ dist: (_layoutShiftOffenders2 = layoutShiftOffendersResult === null || layoutShiftOffendersResult === void 0 ? void 0 : layoutShiftOffendersResult.layoutShiftVariables.allMovedSameAmount) !== null && _layoutShiftOffenders2 !== void 0 ? _layoutShiftOffenders2 : false
451
+ },
452
+ total_mut: (_layoutShiftOffenders3 = layoutShiftOffendersResult === null || layoutShiftOffendersResult === void 0 ? void 0 : layoutShiftOffendersResult.layoutShiftOffenders.length) !== null && _layoutShiftOffenders3 !== void 0 ? _layoutShiftOffenders3 : 0,
453
+ mut: layoutShiftOffendersResult === null || layoutShiftOffendersResult === void 0 ? void 0 : layoutShiftOffendersResult.layoutShiftOffenders.sort(function (a, b) {
454
+ return Math.abs(a.distanceToLS) - Math.abs(b.distanceToLS);
455
+ }).slice(0, 5).map(function (offender) {
456
+ return {
457
+ e: offender.offender,
458
+ size: -1,
459
+ // @todo: calculate size
460
+ attr: {
461
+ t_before: offender.happenedBefore,
462
+ t_distance: offender.distanceToLS,
463
+ p_above: offender.isAbove,
464
+ p_left: offender.isLeft,
465
+ p_right: offender.isRight,
466
+ p_h_overlap: offender.hasHorizontalOverlap,
467
+ p_v_overlap: offender.hasVerticalOverlap,
468
+ p_same_offset: offender.matchesLayoutShiftDelta ? 'all' : 'none'
469
+ }
470
+ };
471
+ })
472
+ };
473
+ }
420
474
  result = {
421
475
  revision: this.revisionNo,
422
476
  clean: true,
423
477
  'metric:vc90': (_vcDetails$90$t = vcDetails === null || vcDetails === void 0 || (_vcDetails$ = vcDetails['90']) === null || _vcDetails$ === void 0 ? void 0 : _vcDetails$.t) !== null && _vcDetails$90$t !== void 0 ? _vcDetails$90$t : null,
424
- vcDetails: vcDetails !== null && vcDetails !== void 0 ? vcDetails : undefined
478
+ vcDetails: vcDetails !== null && vcDetails !== void 0 ? vcDetails : undefined,
479
+ 'vc90:ls': layoutShiftInsightsPayload !== null && layoutShiftInsightsPayload !== void 0 ? layoutShiftInsightsPayload : undefined
425
480
  };
426
481
  result.ratios = this.calculateRatios(filteredEntries);
427
482
  if (ssrRatio !== -1) {
@@ -434,13 +489,13 @@ var AbstractVCCalculatorBase = exports.default = /*#__PURE__*/function () {
434
489
  }
435
490
  result.labelStacks = this.getLabelStacks(filteredEntries, isPostInteraction);
436
491
  return _context2.abrupt("return", result);
437
- case 19:
492
+ case 21:
438
493
  case "end":
439
494
  return _context2.stop();
440
495
  }
441
496
  }, _callee2, this);
442
497
  }));
443
- function calculate(_x13) {
498
+ function calculate(_x14) {
444
499
  return _calculate.apply(this, arguments);
445
500
  }
446
501
  return calculate;
@@ -0,0 +1,164 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.detectLayoutShiftCause = void 0;
7
+ 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; } } }; }
8
+ 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; } }
9
+ 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; }
10
+ var calculateOffenderState = function calculateOffenderState(current, matchesCurrentEntry) {
11
+ // Once we know it's mixed across entries, we can short-circuit.
12
+ if (current === 'some') {
13
+ return 'some';
14
+ }
15
+ var entryState = matchesCurrentEntry ? 'all' : 'none';
16
+ if (current == null) {
17
+ return entryState;
18
+ }
19
+
20
+ // If the state flips between entries (all <-> none), it's "some".
21
+ if (current !== entryState) {
22
+ return 'some';
23
+ }
24
+ return current;
25
+ };
26
+ var calculateLayoutShiftMovement = function calculateLayoutShiftMovement(layoutShiftEntries) {
27
+ var movements = layoutShiftEntries.map(function (lsEntry) {
28
+ var rect = lsEntry.rect;
29
+ var previousRect = lsEntry.previousRect;
30
+ if (!rect || !previousRect) {
31
+ return null;
32
+ }
33
+ var dx = rect.x - previousRect.x;
34
+ var dy = rect.y - previousRect.y;
35
+ return {
36
+ dx: dx,
37
+ dy: dy,
38
+ movedX: dx !== 0,
39
+ movedY: dy !== 0,
40
+ dirX: Math.sign(dx),
41
+ dirY: Math.sign(dy),
42
+ absDx: Math.abs(dx),
43
+ absDy: Math.abs(dy)
44
+ };
45
+ });
46
+ var hasMovement = function hasMovement(m) {
47
+ return m !== null;
48
+ };
49
+ var validMovements = movements.filter(hasMovement);
50
+ var allHaveRects = layoutShiftEntries.length > 0 && validMovements.length === layoutShiftEntries.length;
51
+ if (!allHaveRects) {
52
+ return {
53
+ allHaveRects: allHaveRects,
54
+ allMovedSameWay: false,
55
+ allMovedSameAmount: false
56
+ };
57
+ }
58
+ var first = validMovements[0];
59
+ var allMovedSameWay = validMovements.every(function (m) {
60
+ return m.movedX === first.movedX && m.movedY === first.movedY && m.dirX === first.dirX && m.dirY === first.dirY;
61
+ });
62
+ var allMovedSameAmount = allMovedSameWay && validMovements.every(function (m) {
63
+ return m.absDx === first.absDx && m.absDy === first.absDy;
64
+ });
65
+ return {
66
+ allHaveRects: allHaveRects,
67
+ allMovedSameWay: allMovedSameWay,
68
+ allMovedSameAmount: allMovedSameAmount,
69
+ deltaX: first.dx,
70
+ deltaY: first.dy
71
+ };
72
+ };
73
+ var detectLayoutShiftCause = exports.detectLayoutShiftCause = function detectLayoutShiftCause(_ref) {
74
+ var viewportEntries = _ref.viewportEntries,
75
+ layoutShiftEntries = _ref.layoutShiftEntries,
76
+ time = _ref.time,
77
+ startTime = _ref.startTime,
78
+ _ref$offenderWindowMs = _ref.offenderWindowMs,
79
+ offenderWindowMs = _ref$offenderWindowMs === void 0 ? 250 : _ref$offenderWindowMs;
80
+ var checkpointTimestamp = startTime + time;
81
+ var filteredLSPotentialOffenders = viewportEntries.filter(function (viewportEntry) {
82
+ return (viewportEntry.time < checkpointTimestamp && viewportEntry.time > checkpointTimestamp - offenderWindowMs || viewportEntry.time > checkpointTimestamp && viewportEntry.time < checkpointTimestamp + offenderWindowMs) && viewportEntry.data.type !== 'layout-shift';
83
+ });
84
+
85
+ // Summarize whether all layout-shift entries moved in a consistent direction and by the same amount.
86
+ var layoutShiftVariables = calculateLayoutShiftMovement(layoutShiftEntries);
87
+
88
+ // Classify each offender against *all* layout-shift entries when the layout shift is consistently moving in a
89
+ // single axis (pure X or pure Y) so we can reason about whether an offender could have caused the movement.
90
+ var layoutShiftOffenders = filteredLSPotentialOffenders.reduce(function (acc, offender) {
91
+ var _offenderData$origina;
92
+ var offenderData = offender.data;
93
+ var offenderRect = offenderData.rect;
94
+ if (!offenderRect) {
95
+ return acc;
96
+ }
97
+ var offenderTimestamp = (_offenderData$origina = offenderData.originalMutationTimestamp) !== null && _offenderData$origina !== void 0 ? _offenderData$origina : offender.time;
98
+ var happenedBefore = offenderTimestamp <= checkpointTimestamp;
99
+ var offenderLeft = offenderRect.x;
100
+ var offenderRight = offenderRect.x + offenderRect.width;
101
+ var offenderTop = offenderRect.y;
102
+ var offenderBottom = offenderRect.y + offenderRect.height;
103
+ var shouldClassifyAgainstAllEntries = layoutShiftVariables.allMovedSameWay && 'deltaX' in layoutShiftVariables && 'deltaY' in layoutShiftVariables && layoutShiftVariables.deltaX === 0 !== (layoutShiftVariables.deltaY === 0);
104
+ var isAbove = null;
105
+ var isLeft = null;
106
+ var isRight = null;
107
+ var hasHorizontalOverlap = null;
108
+ var hasVerticalOverlap = null;
109
+ if (shouldClassifyAgainstAllEntries) {
110
+ var _iterator = _createForOfIteratorHelper(layoutShiftEntries),
111
+ _step;
112
+ try {
113
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
114
+ var lsEntry = _step.value;
115
+ var lsRect = lsEntry.rect;
116
+ if (!lsRect) {
117
+ continue;
118
+ }
119
+ var lsLeft = lsRect.x;
120
+ var lsRight = lsRect.x + lsRect.width;
121
+ var lsTop = lsRect.y;
122
+ var lsBottom = lsRect.y + lsRect.height;
123
+ isAbove = calculateOffenderState(isAbove, offenderBottom <= lsTop);
124
+ isLeft = calculateOffenderState(isLeft, offenderRight <= lsLeft);
125
+ isRight = calculateOffenderState(isRight, offenderLeft >= lsRight);
126
+ hasHorizontalOverlap = calculateOffenderState(hasHorizontalOverlap, offenderLeft < lsRight && offenderRight > lsLeft);
127
+ hasVerticalOverlap = calculateOffenderState(hasVerticalOverlap, offenderTop < lsBottom && offenderBottom > lsTop);
128
+ }
129
+ } catch (err) {
130
+ _iterator.e(err);
131
+ } finally {
132
+ _iterator.f();
133
+ }
134
+ }
135
+ var matchesLayoutShiftDelta = false;
136
+ if (shouldClassifyAgainstAllEntries && layoutShiftVariables.allMovedSameAmount && offenderData.previousRect) {
137
+ var dx = offenderRect.x - offenderData.previousRect.x;
138
+ var dy = offenderRect.y - offenderData.previousRect.y;
139
+ var isPureX = layoutShiftVariables.deltaX !== 0 && layoutShiftVariables.deltaY === 0;
140
+ var isPureY = layoutShiftVariables.deltaY !== 0 && layoutShiftVariables.deltaX === 0;
141
+ if (isPureX) {
142
+ matchesLayoutShiftDelta = dx === layoutShiftVariables.deltaX && dy === 0;
143
+ } else if (isPureY) {
144
+ matchesLayoutShiftDelta = dy === layoutShiftVariables.deltaY && dx === 0;
145
+ }
146
+ }
147
+ acc.push({
148
+ offender: offenderData.elementName,
149
+ happenedBefore: happenedBefore,
150
+ distanceToLS: Math.round(offenderTimestamp - checkpointTimestamp),
151
+ isAbove: isAbove !== null && isAbove !== void 0 ? isAbove : 'none',
152
+ isLeft: isLeft !== null && isLeft !== void 0 ? isLeft : 'none',
153
+ isRight: isRight !== null && isRight !== void 0 ? isRight : 'none',
154
+ hasHorizontalOverlap: hasHorizontalOverlap !== null && hasHorizontalOverlap !== void 0 ? hasHorizontalOverlap : 'none',
155
+ hasVerticalOverlap: hasVerticalOverlap !== null && hasVerticalOverlap !== void 0 ? hasVerticalOverlap : 'none',
156
+ matchesLayoutShiftDelta: matchesLayoutShiftDelta
157
+ });
158
+ return acc;
159
+ }, []);
160
+ return {
161
+ layoutShiftVariables: layoutShiftVariables,
162
+ layoutShiftOffenders: layoutShiftOffenders
163
+ };
164
+ };