@atlaskit/react-ufo 2.14.2 → 2.15.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 (71) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/cjs/create-payload/index.js +11 -0
  3. package/dist/cjs/experience-trace-id-context/index.js +5 -1
  4. package/dist/cjs/segment/segment.js +7 -1
  5. package/dist/cjs/vc/vc-observer/heatmap/heatmap.js +275 -0
  6. package/dist/cjs/vc/vc-observer/index.js +133 -29
  7. package/dist/cjs/vc/vc-observer/observers/ssr-placeholders/index.js +16 -27
  8. package/dist/cjs/vc/vc-observer/revisions/ViewportUpdateClassifier.js +52 -0
  9. package/dist/cjs/vc/vc-observer/revisions/fy24_01.js +39 -0
  10. package/dist/cjs/vc/vc-observer/revisions/fy25_01.js +39 -0
  11. package/dist/cjs/vc/vc-observer/revisions/revisions.js +23 -0
  12. package/dist/cjs/vc/vc-observer/revisions/types.js +5 -0
  13. package/dist/es2019/create-payload/index.js +11 -0
  14. package/dist/es2019/experience-trace-id-context/index.js +4 -0
  15. package/dist/es2019/segment/segment.js +11 -3
  16. package/dist/es2019/vc/vc-observer/heatmap/heatmap.js +238 -0
  17. package/dist/es2019/vc/vc-observer/index.js +115 -7
  18. package/dist/es2019/vc/vc-observer/observers/ssr-placeholders/index.js +16 -27
  19. package/dist/es2019/vc/vc-observer/revisions/ViewportUpdateClassifier.js +35 -0
  20. package/dist/es2019/vc/vc-observer/revisions/fy24_01.js +21 -0
  21. package/dist/es2019/vc/vc-observer/revisions/fy25_01.js +21 -0
  22. package/dist/es2019/vc/vc-observer/revisions/revisions.js +19 -0
  23. package/dist/es2019/vc/vc-observer/revisions/types.js +1 -0
  24. package/dist/esm/create-payload/index.js +11 -0
  25. package/dist/esm/experience-trace-id-context/index.js +4 -0
  26. package/dist/esm/segment/segment.js +7 -1
  27. package/dist/esm/vc/vc-observer/heatmap/heatmap.js +268 -0
  28. package/dist/esm/vc/vc-observer/index.js +133 -29
  29. package/dist/esm/vc/vc-observer/observers/ssr-placeholders/index.js +16 -27
  30. package/dist/esm/vc/vc-observer/revisions/ViewportUpdateClassifier.js +45 -0
  31. package/dist/esm/vc/vc-observer/revisions/fy24_01.js +32 -0
  32. package/dist/esm/vc/vc-observer/revisions/fy25_01.js +32 -0
  33. package/dist/esm/vc/vc-observer/revisions/revisions.js +17 -0
  34. package/dist/esm/vc/vc-observer/revisions/types.js +1 -0
  35. package/dist/types/common/vc/types.d.ts +28 -9
  36. package/dist/types/create-payload/index.d.ts +16 -0
  37. package/dist/types/experience-trace-id-context/index.d.ts +1 -0
  38. package/dist/types/interaction-ignore/ufo-interaction-ignore.d.ts +2 -2
  39. package/dist/types/label/UFOLabel.d.ts +2 -2
  40. package/dist/types/load-hold/UFOLoadHold.d.ts +2 -2
  41. package/dist/types/placeholder/Placeholder.d.ts +2 -2
  42. package/dist/types/placeholder/loosely-lazy/lazy-suspense.d.ts +2 -2
  43. package/dist/types/segment/segment-highlight.d.ts +2 -2
  44. package/dist/types/segment/segment.d.ts +2 -2
  45. package/dist/types/vc/vc-observer/heatmap/heatmap.d.ts +75 -0
  46. package/dist/types/vc/vc-observer/index.d.ts +6 -1
  47. package/dist/types/vc/vc-observer/media-wrapper/MediaWrapper.d.ts +1 -1
  48. package/dist/types/vc/vc-observer/revisions/ViewportUpdateClassifier.d.ts +25 -0
  49. package/dist/types/vc/vc-observer/revisions/fy24_01.d.ts +11 -0
  50. package/dist/types/vc/vc-observer/revisions/fy25_01.d.ts +13 -0
  51. package/dist/types/vc/vc-observer/revisions/revisions.d.ts +2 -0
  52. package/dist/types/vc/vc-observer/revisions/types.d.ts +5 -0
  53. package/dist/types-ts4.5/common/vc/types.d.ts +28 -9
  54. package/dist/types-ts4.5/create-payload/index.d.ts +16 -0
  55. package/dist/types-ts4.5/experience-trace-id-context/index.d.ts +1 -0
  56. package/dist/types-ts4.5/interaction-ignore/ufo-interaction-ignore.d.ts +2 -2
  57. package/dist/types-ts4.5/label/UFOLabel.d.ts +2 -2
  58. package/dist/types-ts4.5/load-hold/UFOLoadHold.d.ts +2 -2
  59. package/dist/types-ts4.5/placeholder/Placeholder.d.ts +2 -2
  60. package/dist/types-ts4.5/placeholder/loosely-lazy/lazy-suspense.d.ts +2 -2
  61. package/dist/types-ts4.5/segment/segment-highlight.d.ts +2 -2
  62. package/dist/types-ts4.5/segment/segment.d.ts +2 -2
  63. package/dist/types-ts4.5/vc/vc-observer/heatmap/heatmap.d.ts +75 -0
  64. package/dist/types-ts4.5/vc/vc-observer/index.d.ts +16 -1
  65. package/dist/types-ts4.5/vc/vc-observer/media-wrapper/MediaWrapper.d.ts +1 -1
  66. package/dist/types-ts4.5/vc/vc-observer/revisions/ViewportUpdateClassifier.d.ts +25 -0
  67. package/dist/types-ts4.5/vc/vc-observer/revisions/fy24_01.d.ts +11 -0
  68. package/dist/types-ts4.5/vc/vc-observer/revisions/fy25_01.d.ts +13 -0
  69. package/dist/types-ts4.5/vc/vc-observer/revisions/revisions.d.ts +2 -0
  70. package/dist/types-ts4.5/vc/vc-observer/revisions/types.d.ts +5 -0
  71. package/package.json +17 -6
@@ -0,0 +1,268 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import _objectDestructuringEmpty from "@babel/runtime/helpers/objectDestructuringEmpty";
3
+ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
4
+ import _createClass from "@babel/runtime/helpers/createClass";
5
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
6
+ var UNUSED_SECTOR = 0;
7
+ export var MultiRevisionHeatmap = /*#__PURE__*/function () {
8
+ function MultiRevisionHeatmap(_ref) {
9
+ var _this = this;
10
+ var viewport = _ref.viewport,
11
+ revisions = _ref.revisions,
12
+ arraySize = _ref.arraySize,
13
+ devToolsEnabled = _ref.devToolsEnabled;
14
+ _classCallCheck(this, MultiRevisionHeatmap);
15
+ _defineProperty(this, "arraySize", {
16
+ w: 200,
17
+ h: 200
18
+ });
19
+ _defineProperty(this, "mapPixelsToHeatmap", function (left, top, width, height) {
20
+ var _this$viewport = _this.viewport,
21
+ w = _this$viewport.w,
22
+ h = _this$viewport.h;
23
+ var l = Math.floor(left / w * _this.arraySize.w);
24
+ var t = Math.floor(top / h * _this.arraySize.h);
25
+ var r = Math.ceil((left + width) / w * _this.arraySize.w);
26
+ var b = Math.ceil((top + height) / h * _this.arraySize.h);
27
+
28
+ // correct values to min - 0, max - arraySize
29
+ var result = {
30
+ l: Math.max(0, l),
31
+ t: Math.max(0, t),
32
+ r: Math.min(_this.arraySize.w, r),
33
+ b: Math.min(_this.arraySize.h, b)
34
+ };
35
+ return result;
36
+ });
37
+ _defineProperty(this, "getElementRatio", function (mappedValues) {
38
+ var r = mappedValues.r,
39
+ l = mappedValues.l,
40
+ b = mappedValues.b,
41
+ t = mappedValues.t;
42
+ return (r - l) * (b - t) / (_this.arraySize.w * _this.arraySize.h);
43
+ });
44
+ this.viewport = viewport;
45
+ this.revisions = revisions;
46
+ if (arraySize) {
47
+ this.arraySize = arraySize;
48
+ }
49
+ this.heatmaps = new Array(revisions.length);
50
+ this.componentsLogs = new Array(revisions.length);
51
+ this.vcRatios = new Array(revisions.length);
52
+ this.devToolsEnabled = devToolsEnabled || false;
53
+ revisions.forEach(function (_ref2, i) {
54
+ _objectDestructuringEmpty(_ref2);
55
+ _this.heatmaps[i] = _this.getCleanHeatmap();
56
+ _this.componentsLogs[i] = {};
57
+ _this.vcRatios[i] = {};
58
+ });
59
+ }
60
+ return _createClass(MultiRevisionHeatmap, [{
61
+ key: "handleUpdate",
62
+ value: function handleUpdate(_ref3) {
63
+ var _this2 = this;
64
+ var time = _ref3.time,
65
+ type = _ref3.type,
66
+ classification = _ref3.classification,
67
+ intersectionRect = _ref3.intersectionRect,
68
+ element = _ref3.element,
69
+ targetName = _ref3.targetName,
70
+ ignoreReason = _ref3.ignoreReason,
71
+ onError = _ref3.onError;
72
+ var mappedValues = this.mapPixelsToHeatmap(intersectionRect.left, intersectionRect.top, intersectionRect.width, intersectionRect.height);
73
+ var result = this.applyChangesToHeatMap(mappedValues, time, classification);
74
+ if (result !== true) {
75
+ onError(result);
76
+ }
77
+ var componentRatio = this.getElementRatio(mappedValues);
78
+ this.revisions.forEach(function (_, i) {
79
+ if (classification[i]) {
80
+ _this2.vcRatios[i][targetName] = componentRatio;
81
+ }
82
+ if (!_this2.componentsLogs[i][time]) {
83
+ _this2.componentsLogs[i][time] = [];
84
+ }
85
+ _this2.componentsLogs[i][time].push({
86
+ __debug__element: _this2.devToolsEnabled ? new WeakRef(element) : null,
87
+ intersectionRect: intersectionRect,
88
+ targetName: targetName,
89
+ ignoreReason: ignoreReason
90
+ });
91
+ });
92
+ }
93
+ }, {
94
+ key: "getData",
95
+ value: function getData() {
96
+ return {
97
+ heatmaps: this.heatmaps
98
+ };
99
+ }
100
+ }, {
101
+ key: "getPayloadShapedData",
102
+ value: function getPayloadShapedData(args) {
103
+ var result = this.processData(args);
104
+ var payload = this.revisions.map(function (rev, i) {
105
+ var vcDetails = {};
106
+ args.VCParts.forEach(function (VCPart) {
107
+ vcDetails[VCPart] = {
108
+ t: result[i].VC[VCPart] || 0,
109
+ e: Array.from(result[i].VCBox[VCPart] || [])
110
+ };
111
+ });
112
+ return {
113
+ revision: rev.name,
114
+ vcDetails: vcDetails,
115
+ clean: args.clean,
116
+ 'metric:vc90': null // will be set or not in the payload generator
117
+ };
118
+ });
119
+ return payload;
120
+ }
121
+ }, {
122
+ key: "processData",
123
+ value: function processData(_ref4) {
124
+ var _this3 = this;
125
+ var VCParts = _ref4.VCParts,
126
+ _ref4$ssr = _ref4.ssr,
127
+ ssr = _ref4$ssr === void 0 ? UNUSED_SECTOR : _ref4$ssr;
128
+ return this.heatmaps.map(function (heatmap, i) {
129
+ var lastUpdate = {};
130
+ var totalPainted = 0;
131
+ var componentsLog = _this3.componentsLogs[i];
132
+ if (ssr !== UNUSED_SECTOR) {
133
+ var _window$document;
134
+ var element = {
135
+ __debug__element: new WeakRef((_window$document = window.document) === null || _window$document === void 0 ? void 0 : _window$document.body),
136
+ intersectionRect: {
137
+ top: 0,
138
+ left: 0,
139
+ right: 0,
140
+ bottom: 0,
141
+ x: 0,
142
+ y: 0,
143
+ width: _this3.viewport.w,
144
+ height: _this3.viewport.h,
145
+ toJSON: function toJSON() {
146
+ return {};
147
+ }
148
+ },
149
+ targetName: 'SSR'
150
+ };
151
+ if (!componentsLog[ssr]) {
152
+ componentsLog[ssr] = [];
153
+ }
154
+ componentsLog[ssr].push(element);
155
+ }
156
+ for (var _i = 0; _i < heatmap.length; _i++) {
157
+ var rounded = Math.floor(heatmap[_i] === UNUSED_SECTOR && ssr !== UNUSED_SECTOR ? ssr : heatmap[_i]);
158
+ totalPainted += rounded !== UNUSED_SECTOR ? 1 : 0;
159
+ if (rounded !== UNUSED_SECTOR) {
160
+ lastUpdate[rounded] = lastUpdate[rounded] ? lastUpdate[rounded] + 1 : 1;
161
+ }
162
+ }
163
+ var entries = Object.entries(lastUpdate).map(function (a) {
164
+ return [parseInt(a[0], 10), a[1]];
165
+ }).sort(function (a, b) {
166
+ return a[0] > b[0] ? 1 : -1;
167
+ });
168
+ var VC = MultiRevisionHeatmap.makeVCReturnObj(VCParts);
169
+ var VCBox = MultiRevisionHeatmap.makeVCReturnObj(VCParts);
170
+ entries.reduce(function () {
171
+ var acc = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
172
+ var v = arguments.length > 1 ? arguments[1] : undefined;
173
+ var VCRatio = v[1] / totalPainted + acc;
174
+ var time = v[0];
175
+ VCParts.forEach(function (value) {
176
+ if ((VC[value] === null || VC[value] === undefined) && VCRatio >= value / 100) {
177
+ var _componentsLog$time;
178
+ VC[value] = time;
179
+ VCBox[value] = new Set();
180
+ (_componentsLog$time = componentsLog[time]) === null || _componentsLog$time === void 0 || _componentsLog$time.forEach(function (v) {
181
+ var _VCBox$value;
182
+ return (_VCBox$value = VCBox[value]) === null || _VCBox$value === void 0 ? void 0 : _VCBox$value.add(v.targetName);
183
+ });
184
+ }
185
+ });
186
+ return VCRatio;
187
+ }, 0);
188
+ var VCEntries = entries.reduce(function (acc, _ref5, i) {
189
+ var _acc$abs, _componentsLog$timest;
190
+ var _ref6 = _slicedToArray(_ref5, 2),
191
+ timestamp = _ref6[0],
192
+ entryPainted = _ref6[1];
193
+ var currentlyPainted = entryPainted + (((_acc$abs = acc.abs[i - 1]) === null || _acc$abs === void 0 ? void 0 : _acc$abs[1]) || 0);
194
+ var currentlyPaintedRatio = Math.round(currentlyPainted / totalPainted * 1000) / 10;
195
+ var logEntry = (_componentsLog$timest = componentsLog[timestamp]) === null || _componentsLog$timest === void 0 ? void 0 : _componentsLog$timest.map(function (v) {
196
+ return v.targetName;
197
+ });
198
+ acc.abs.push([timestamp, currentlyPainted]);
199
+ acc.rel.push({
200
+ time: timestamp,
201
+ vc: currentlyPaintedRatio,
202
+ elements: logEntry
203
+ });
204
+ return acc;
205
+ }, {
206
+ abs: [],
207
+ rel: []
208
+ });
209
+ return {
210
+ VC: VC,
211
+ VCBox: VCBox,
212
+ VCEntries: VCEntries,
213
+ totalPainted: totalPainted
214
+ };
215
+ });
216
+ }
217
+ }, {
218
+ key: "applyChangesToHeatMap",
219
+ value: function applyChangesToHeatMap(a, time, classification) {
220
+ var l = a.l,
221
+ t = a.t,
222
+ r = a.r,
223
+ b = a.b;
224
+ var size = classification.length;
225
+ for (var row = t; row < b; row++) {
226
+ if (this.heatmaps[0][row] === undefined) {
227
+ try {
228
+ return {
229
+ error: "index - ".concat(row),
230
+ time: time
231
+ };
232
+ } catch (e) {
233
+ return {
234
+ error: 'row error',
235
+ time: time
236
+ };
237
+ }
238
+ } else {
239
+ for (var heatmapIndex = 0; heatmapIndex < size; heatmapIndex++) {
240
+ if (classification[heatmapIndex]) {
241
+ this.heatmaps[heatmapIndex].fill(time, this.getIndex(l, row), this.getIndex(r, row));
242
+ }
243
+ }
244
+ }
245
+ }
246
+ return true;
247
+ }
248
+ }, {
249
+ key: "getIndex",
250
+ value: function getIndex(x, y) {
251
+ return x + this.arraySize.w * y;
252
+ }
253
+ }, {
254
+ key: "getCleanHeatmap",
255
+ value: function getCleanHeatmap() {
256
+ return new Uint32Array(this.arraySize.w * this.arraySize.h);
257
+ }
258
+ }], [{
259
+ key: "makeVCReturnObj",
260
+ value: function makeVCReturnObj(VCParts) {
261
+ var vc = {};
262
+ VCParts.forEach(function (v) {
263
+ vc[v] = null;
264
+ });
265
+ return vc;
266
+ }
267
+ }]);
268
+ }();
@@ -9,7 +9,9 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
9
9
  import { fg } from '@atlaskit/platform-feature-flags';
10
10
  import { attachAbortListeners } from './attachAbortListeners';
11
11
  import { getViewportHeight, getViewportWidth } from './getViewport';
12
+ import { MultiRevisionHeatmap } from './heatmap/heatmap';
12
13
  import { Observers } from './observers';
14
+ import { getRevisions } from './revisions/revisions';
13
15
  var abortReason = {
14
16
  scroll: 'scroll',
15
17
  keypress: 'keypress',
@@ -47,6 +49,7 @@ export var VCObserver = /*#__PURE__*/function () {
47
49
  });
48
50
  /* heatmap */
49
51
  _defineProperty(this, "arraySize", 0);
52
+ _defineProperty(this, "multiHeatmap", null);
50
53
  _defineProperty(this, "componentsLog", {});
51
54
  _defineProperty(this, "vcRatios", {});
52
55
  _defineProperty(this, "active", false);
@@ -78,6 +81,7 @@ export var VCObserver = /*#__PURE__*/function () {
78
81
  abortReason: _objectSpread({}, _this.abortReason),
79
82
  heatmap: _this.heatmap,
80
83
  heatmapNext: _this.heatmapNext,
84
+ multiHeatmap: _this.multiHeatmap,
81
85
  outOfBoundaryInfo: _this.outOfBoundaryInfo,
82
86
  totalTime: Math.round(_this.totalTime + _this.observers.getTotalTime()),
83
87
  componentsLog: _objectSpread({}, _this.componentsLog),
@@ -110,7 +114,8 @@ export var VCObserver = /*#__PURE__*/function () {
110
114
  componentsLog = rawData.componentsLog,
111
115
  viewport = rawData.viewport,
112
116
  devToolsEnabled = rawData.devToolsEnabled,
113
- ratios = rawData.ratios;
117
+ ratios = rawData.ratios,
118
+ multiHeatmap = rawData.multiHeatmap;
114
119
  if (abortReasonInfo !== null && abortReason.blocking) {
115
120
  // exposing data to devtools
116
121
  try {
@@ -146,6 +151,7 @@ export var VCObserver = /*#__PURE__*/function () {
146
151
  /* empty */
147
152
  }
148
153
  var _componentsLog = {};
154
+ // eslint-disable-next-line @atlaskit/platform/ensure-feature-flag-prefix
149
155
  if (fg('ufo-remove-vc-component-observations-after-ttai')) {
150
156
  Object.entries(_this.componentsLog).forEach(function (_ref5) {
151
157
  var _ref6 = _slicedToArray(_ref5, 2),
@@ -202,9 +208,30 @@ export var VCObserver = /*#__PURE__*/function () {
202
208
  tti: tti,
203
209
  ttai: stop - start
204
210
  },
211
+ start: start,
212
+ stop: stop,
205
213
  heatmap: heatmap,
206
214
  ratios: ratios
207
215
  };
216
+ window.__vcNext = {
217
+ entries: vcNext.VCEntries.rel,
218
+ log: componentsLog,
219
+ metrics: {
220
+ '75': vcNext.VC['75'],
221
+ '80': vcNext.VC['80'],
222
+ '85': vcNext.VC['85'],
223
+ '90': vcNext.VC['90'],
224
+ '95': vcNext.VC['95'],
225
+ '98': vcNext.VC['98'],
226
+ '99': vcNext.VC['99'],
227
+ tti: tti,
228
+ ttai: stop - start
229
+ },
230
+ start: start,
231
+ stop: stop,
232
+ heatmap: heatmapNext,
233
+ ratios: ratios
234
+ };
208
235
 
209
236
  // Emitting a custom event to make it available in the Chrome extension
210
237
  window.dispatchEvent(new CustomEvent('vcReady', {
@@ -217,12 +244,36 @@ export var VCObserver = /*#__PURE__*/function () {
217
244
  } catch (e) {
218
245
  /* do nothing */
219
246
  }
220
- return _objectSpread(_objectSpread(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty({
247
+ var isMultiHeatmapEnabled = fg('ufo_vc_multiheatmap');
248
+ var revisionsData = isMultiHeatmapEnabled && multiHeatmap !== null ? _defineProperty({}, "".concat(fullPrefix, "vc:rev"), multiHeatmap.getPayloadShapedData({
249
+ VCParts: VCObserver.VCParts.map(function (v) {
250
+ return parseInt(v);
251
+ }),
252
+ ssr: ssr,
253
+ clean: !abortReasonInfo
254
+ })) : null;
255
+ // eslint-disable-next-line @atlaskit/platform/ensure-feature-flag-prefix
256
+ var isCalcSpeedIndexEnabled = fg('ufo-calc-speed-index');
257
+ return _objectSpread(_objectSpread(_objectSpread(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty({
221
258
  'metrics:vc': VC
222
- }, "".concat(fullPrefix, "vc:state"), true), "".concat(fullPrefix, "vc:clean"), !abortReasonInfo), "".concat(fullPrefix, "vc:dom"), VCBox), "".concat(fullPrefix, "vc:updates"), VCEntries.rel.slice(0, 50)), "".concat(fullPrefix, "vc:size"), viewport), "".concat(fullPrefix, "vc:time"), Math.round(totalTime + (stopTime - startTime))), "".concat(fullPrefix, "vc:total"), totalPainted), "".concat(fullPrefix, "vc:ratios"), ratios), outOfBoundary), {}, _defineProperty(_defineProperty(_defineProperty(_defineProperty({}, "".concat(fullPrefix, "vc:next"), vcNext.VC), "".concat(fullPrefix, "vc:next:updates"), vcNext.VCEntries.rel.slice(0, 50)), "".concat(fullPrefix, "vc:next:dom"), vcNext.VCBox), "".concat(fullPrefix, "vc:ignored"), _this.getIgnoredElements(componentsLog)));
259
+ }, "".concat(fullPrefix, "vc:state"), true), "".concat(fullPrefix, "vc:clean"), !abortReasonInfo), "".concat(fullPrefix, "vc:dom"), VCBox), "".concat(fullPrefix, "vc:updates"), VCEntries.rel.slice(0, 50)), "".concat(fullPrefix, "vc:size"), viewport), "".concat(fullPrefix, "vc:time"), Math.round(totalTime + (stopTime - startTime))), "".concat(fullPrefix, "vc:total"), totalPainted), "".concat(fullPrefix, "vc:ratios"), ratios), outOfBoundary), {}, _defineProperty(_defineProperty(_defineProperty(_defineProperty({}, "".concat(fullPrefix, "vc:next"), vcNext.VC), "".concat(fullPrefix, "vc:next:updates"), vcNext.VCEntries.rel.slice(0, 50)), "".concat(fullPrefix, "vc:next:dom"), vcNext.VCBox), "".concat(fullPrefix, "vc:ignored"), _this.getIgnoredElements(componentsLog)), revisionsData), {}, _defineProperty(_defineProperty({}, "ufo:speedIndex", isCalcSpeedIndexEnabled ? VCEntries.speedIndex : undefined), "ufo:next:speedIndex", isCalcSpeedIndexEnabled ? vcNext.VCEntries.speedIndex : undefined));
223
260
  });
224
261
  _defineProperty(this, "handleUpdate", function (rawTime, intersectionRect, targetName, element, type, ignoreReason) {
225
262
  _this.measureStart();
263
+ _this.legacyHandleUpdate(rawTime, intersectionRect, targetName, element, type, ignoreReason);
264
+ if (fg('ufo_vc_multiheatmap')) {
265
+ _this.onViewportChangeDetected({
266
+ timestamp: rawTime,
267
+ intersectionRect: intersectionRect,
268
+ targetName: targetName,
269
+ element: element,
270
+ type: type,
271
+ ignoreReason: ignoreReason
272
+ });
273
+ }
274
+ _this.measureStop();
275
+ });
276
+ _defineProperty(this, "legacyHandleUpdate", function (rawTime, intersectionRect, targetName, element, type, ignoreReason) {
226
277
  if (_this.abortReason.reason === null || _this.abortReason.blocking === false) {
227
278
  var time = Math.round(rawTime - _this.startTime);
228
279
  var mappedValues = _this.mapPixelsToHeatmap(intersectionRect.left, intersectionRect.top, intersectionRect.width, intersectionRect.height);
@@ -243,8 +294,38 @@ export var VCObserver = /*#__PURE__*/function () {
243
294
  ignoreReason: ignoreReason
244
295
  });
245
296
  }
246
- // devtools export
247
- _this.measureStop();
297
+ });
298
+ _defineProperty(this, "onViewportChangeDetected", function (_ref9) {
299
+ var element = _ref9.element,
300
+ type = _ref9.type,
301
+ ignoreReason = _ref9.ignoreReason,
302
+ timestamp = _ref9.timestamp,
303
+ targetName = _ref9.targetName,
304
+ intersectionRect = _ref9.intersectionRect;
305
+ if (_this.multiHeatmap === null) {
306
+ return;
307
+ }
308
+ // @todo add abort reason handling
309
+ var time = Math.round(timestamp - _this.startTime);
310
+ var revisions = getRevisions();
311
+ var revisionsClassification = revisions.map(function (revision) {
312
+ return revision.classifier.classifyUpdate({
313
+ element: element,
314
+ type: type,
315
+ ignoreReason: ignoreReason
316
+ });
317
+ }, []);
318
+ _this.multiHeatmap.handleUpdate({
319
+ time: time,
320
+ targetName: targetName,
321
+ intersectionRect: intersectionRect,
322
+ type: type,
323
+ element: element,
324
+ classification: revisionsClassification,
325
+ onError: function onError(error) {
326
+ _this.setAbortReason(abortReason.error, error.time, error.error);
327
+ }
328
+ });
248
329
  });
249
330
  _defineProperty(this, "mapPixelsToHeatmap", function (left, top, width, height) {
250
331
  var _this$viewport = _this.viewport,
@@ -302,10 +383,10 @@ export var VCObserver = /*#__PURE__*/function () {
302
383
  var unbinds = attachAbortListeners(window, _this.viewport, _this.abortReasonCallback);
303
384
  if ((_window = window) !== null && _window !== void 0 && _window.__SSR_ABORT_LISTENERS__) {
304
385
  var _window2;
305
- Object.entries(window.__SSR_ABORT_LISTENERS__.aborts).forEach(function (_ref8) {
306
- var _ref9 = _slicedToArray(_ref8, 2),
307
- key = _ref9[0],
308
- time = _ref9[1];
386
+ Object.entries(window.__SSR_ABORT_LISTENERS__.aborts).forEach(function (_ref10) {
387
+ var _ref11 = _slicedToArray(_ref10, 2),
388
+ key = _ref11[0],
389
+ time = _ref11[1];
309
390
  if (time) {
310
391
  _this.abortReasonCallback(key, time);
311
392
  }
@@ -329,12 +410,19 @@ export var VCObserver = /*#__PURE__*/function () {
329
410
  });
330
411
  this.heatmap = this.getCleanHeatmap();
331
412
  this.heatmapNext = this.getCleanHeatmap();
413
+ if (fg('ufo_vc_multiheatmap')) {
414
+ this.multiHeatmap = new MultiRevisionHeatmap({
415
+ viewport: this.viewport,
416
+ revisions: getRevisions(),
417
+ devToolsEnabled: this.devToolsEnabled
418
+ });
419
+ }
332
420
  this.isPostInteraction = options.isPostInteraction || false;
333
421
  }
334
422
  return _createClass(VCObserver, [{
335
423
  key: "start",
336
- value: function start(_ref10) {
337
- var startTime = _ref10.startTime;
424
+ value: function start(_ref12) {
425
+ var startTime = _ref12.startTime;
338
426
  this.active = true;
339
427
  if (this.observers.isBrowserSupported()) {
340
428
  this.setViewportSize();
@@ -356,12 +444,12 @@ export var VCObserver = /*#__PURE__*/function () {
356
444
  }, {
357
445
  key: "getIgnoredElements",
358
446
  value: function getIgnoredElements(componentsLog) {
359
- return Object.values(componentsLog).flat().filter(function (_ref11) {
360
- var ignoreReason = _ref11.ignoreReason;
447
+ return Object.values(componentsLog).flat().filter(function (_ref13) {
448
+ var ignoreReason = _ref13.ignoreReason;
361
449
  return Boolean(ignoreReason);
362
- }).map(function (_ref12) {
363
- var targetName = _ref12.targetName,
364
- ignoreReason = _ref12.ignoreReason;
450
+ }).map(function (_ref14) {
451
+ var targetName = _ref14.targetName,
452
+ ignoreReason = _ref14.ignoreReason;
365
453
  return {
366
454
  targetName: targetName,
367
455
  ignoreReason: ignoreReason
@@ -482,12 +570,12 @@ export var VCObserver = /*#__PURE__*/function () {
482
570
  }
483
571
  }], [{
484
572
  key: "calculateVC",
485
- value: function calculateVC(_ref13) {
486
- var heatmap = _ref13.heatmap,
487
- _ref13$ssr = _ref13.ssr,
488
- ssr = _ref13$ssr === void 0 ? UNUSED_SECTOR : _ref13$ssr,
489
- componentsLog = _ref13.componentsLog,
490
- viewport = _ref13.viewport;
573
+ value: function calculateVC(_ref15) {
574
+ var heatmap = _ref15.heatmap,
575
+ _ref15$ssr = _ref15.ssr,
576
+ ssr = _ref15$ssr === void 0 ? UNUSED_SECTOR : _ref15$ssr,
577
+ componentsLog = _ref15.componentsLog,
578
+ viewport = _ref15.viewport;
491
579
  var lastUpdate = {};
492
580
  var totalPainted = 0;
493
581
  if (ssr !== UNUSED_SECTOR) {
@@ -530,10 +618,19 @@ export var VCObserver = /*#__PURE__*/function () {
530
618
  });
531
619
  var VC = VCObserver.makeVCReturnObj();
532
620
  var VCBox = VCObserver.makeVCReturnObj();
621
+
622
+ // eslint-disable-next-line @atlaskit/platform/ensure-feature-flag-prefix
623
+ var isCalcSpeedIndexEnabled = fg('ufo-calc-speed-index');
533
624
  entries.reduce(function () {
534
625
  var acc = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
535
626
  var v = arguments.length > 1 ? arguments[1] : undefined;
536
- var VCRatio = v[1] / totalPainted + acc;
627
+ var currRatio = v[1] / totalPainted;
628
+ var VCRatio = currRatio + acc;
629
+ if (fg('platform_ufo_fix_vc_observer_rounding_error')) {
630
+ var preciseCurrRatio = Math.round(100 * (v[1] / totalPainted));
631
+ var preciseAccRatio = Math.round(acc * 100);
632
+ VCRatio = (preciseCurrRatio + preciseAccRatio) / 100;
633
+ }
537
634
  var time = v[0];
538
635
  VCObserver.VCParts.forEach(function (key) {
539
636
  var value = parseInt(key, 10);
@@ -547,16 +644,21 @@ export var VCObserver = /*#__PURE__*/function () {
547
644
  });
548
645
  return VCRatio;
549
646
  }, 0);
550
- var VCEntries = entries.reduce(function (acc, _ref14, i) {
551
- var _acc$abs, _componentsLog$timest;
552
- var _ref15 = _slicedToArray(_ref14, 2),
553
- timestamp = _ref15[0],
554
- entryPainted = _ref15[1];
647
+ var VCEntries = entries.reduce(function (acc, _ref16, i) {
648
+ var _acc$abs, _componentsLog$timest, _acc$rel$vc, _acc$rel;
649
+ var _ref17 = _slicedToArray(_ref16, 2),
650
+ timestamp = _ref17[0],
651
+ entryPainted = _ref17[1];
555
652
  var currentlyPainted = entryPainted + (((_acc$abs = acc.abs[i - 1]) === null || _acc$abs === void 0 ? void 0 : _acc$abs[1]) || 0);
556
653
  var currentlyPaintedRatio = Math.round(currentlyPainted / totalPainted * 1000) / 10;
557
654
  var logEntry = (_componentsLog$timest = componentsLog[timestamp]) === null || _componentsLog$timest === void 0 ? void 0 : _componentsLog$timest.map(function (v) {
558
655
  return v.targetName;
559
656
  });
657
+ var ratioDelta = (currentlyPaintedRatio - ((_acc$rel$vc = (_acc$rel = acc.rel[i - 1]) === null || _acc$rel === void 0 ? void 0 : _acc$rel.vc) !== null && _acc$rel$vc !== void 0 ? _acc$rel$vc : 0)) / 100;
658
+ if (isCalcSpeedIndexEnabled) {
659
+ var speedIndex = timestamp * ratioDelta;
660
+ acc.speedIndex += speedIndex;
661
+ }
560
662
  acc.abs.push([timestamp, currentlyPainted]);
561
663
  acc.rel.push({
562
664
  time: timestamp,
@@ -566,8 +668,10 @@ export var VCObserver = /*#__PURE__*/function () {
566
668
  return acc;
567
669
  }, {
568
670
  abs: [],
569
- rel: []
671
+ rel: [],
672
+ speedIndex: 0
570
673
  });
674
+ VCEntries.speedIndex = Math.round(VCEntries.speedIndex);
571
675
  return {
572
676
  VC: VC,
573
677
  VCBox: VCBox,
@@ -1,7 +1,6 @@
1
1
  import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
2
2
  import _createClass from "@babel/runtime/helpers/createClass";
3
3
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
4
- import { fg } from '@atlaskit/platform-feature-flags';
5
4
  var EQUALITY_THRESHOLD = 0.1;
6
5
  var ANCESTOR_LOOKUP_LIMIT = 10;
7
6
  export var SSRPlaceholderHandlers = /*#__PURE__*/function () {
@@ -29,20 +28,15 @@ export var SSRPlaceholderHandlers = /*#__PURE__*/function () {
29
28
  return;
30
29
  }
31
30
  var rect = _this.staticPlaceholders.get(staticKey);
32
- if (fg('platform_ufo_ssr_ttvc_use_target_rect')) {
33
- var hasSameSizePosition = _this.hasSameSizePosition(rect, boundingClientRect);
34
- if (hasSameSizePosition || _this.isDummyRect(rect)) {
35
- _resolve(hasSameSizePosition);
36
- } else {
37
- requestAnimationFrame(function () {
38
- var targetRect = target.getBoundingClientRect();
39
- var hasSameSizePosition = _this.hasSameSizePosition(rect, targetRect);
40
- _resolve(hasSameSizePosition);
41
- });
42
- }
31
+ var hasSameSizePosition = _this.hasSameSizePosition(rect, boundingClientRect);
32
+ if (hasSameSizePosition || _this.isDummyRect(rect)) {
33
+ _resolve(hasSameSizePosition);
43
34
  } else {
44
- var _hasSameSizePosition = _this.hasSameSizePosition(rect, boundingClientRect);
45
- _resolve(_hasSameSizePosition);
35
+ requestAnimationFrame(function () {
36
+ var targetRect = target.getBoundingClientRect();
37
+ var hasSameSizePosition = _this.hasSameSizePosition(rect, targetRect);
38
+ _resolve(hasSameSizePosition);
39
+ });
46
40
  }
47
41
  _this.callbacks.delete(staticKey);
48
42
  }
@@ -53,20 +47,15 @@ export var SSRPlaceholderHandlers = /*#__PURE__*/function () {
53
47
  return;
54
48
  }
55
49
  var _rect = _this.staticPlaceholders.get(key);
56
- if (fg('platform_ufo_ssr_ttvc_use_target_rect')) {
57
- var _hasSameSizePosition2 = _this.hasSameSizePosition(_rect, boundingClientRect);
58
- if (_hasSameSizePosition2 || _this.isDummyRect(_rect)) {
59
- _resolve2(_hasSameSizePosition2);
60
- } else {
61
- requestAnimationFrame(function () {
62
- var targetRect = target.getBoundingClientRect();
63
- var hasSameSizePosition = _this.hasSameSizePosition(_rect, targetRect);
64
- _resolve2(hasSameSizePosition);
65
- });
66
- }
50
+ var _hasSameSizePosition = _this.hasSameSizePosition(_rect, boundingClientRect);
51
+ if (_hasSameSizePosition || _this.isDummyRect(_rect)) {
52
+ _resolve2(_hasSameSizePosition);
67
53
  } else {
68
- var _hasSameSizePosition3 = _this.hasSameSizePosition(_rect, boundingClientRect);
69
- _resolve2(_hasSameSizePosition3);
54
+ requestAnimationFrame(function () {
55
+ var targetRect = target.getBoundingClientRect();
56
+ var hasSameSizePosition = _this.hasSameSizePosition(_rect, targetRect);
57
+ _resolve2(hasSameSizePosition);
58
+ });
70
59
  }
71
60
  _this.staticPlaceholders.delete(staticKey);
72
61
  _this.reactValidateCallbacks.delete(staticKey);
@@ -0,0 +1,45 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
3
+ import _createClass from "@babel/runtime/helpers/createClass";
4
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
5
+ export var ViewportUpdateClassifier = /*#__PURE__*/function () {
6
+ function ViewportUpdateClassifier() {
7
+ _classCallCheck(this, ViewportUpdateClassifier);
8
+ _defineProperty(this, "types", []);
9
+ _defineProperty(this, "filters", []);
10
+ _defineProperty(this, "removedFilters", []);
11
+ _defineProperty(this, "__combinedTypes", []);
12
+ _defineProperty(this, "__combinedFilters", []);
13
+ }
14
+ return _createClass(ViewportUpdateClassifier, [{
15
+ key: "mergeConfig",
16
+ value: function mergeConfig() {
17
+ var _this = this;
18
+ this.__combinedTypes = [].concat(_toConsumableArray(this.types), _toConsumableArray((this === null || this === void 0 ? void 0 : this.__combinedTypes) || []));
19
+ var previousFilters = this.removedFilters.length === 0 ? this.__combinedFilters : this.__combinedFilters.filter(function (filter) {
20
+ return !_this.removedFilters.includes(filter.name);
21
+ });
22
+ this.__combinedFilters = [].concat(_toConsumableArray(this.filters), _toConsumableArray(previousFilters));
23
+ }
24
+ }, {
25
+ key: "classifyUpdate",
26
+ value: function classifyUpdate(_ref) {
27
+ var element = _ref.element,
28
+ type = _ref.type,
29
+ tags = _ref.tags,
30
+ ignoreReason = _ref.ignoreReason;
31
+ if (!this.__combinedTypes.includes(type)) {
32
+ return false;
33
+ }
34
+ return this.__combinedFilters.every(function (_ref2) {
35
+ var filter = _ref2.filter,
36
+ name = _ref2.name;
37
+ return filter({
38
+ type: type,
39
+ tags: tags,
40
+ ignoreReason: ignoreReason
41
+ });
42
+ });
43
+ }
44
+ }]);
45
+ }();