@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.
- package/CHANGELOG.md +14 -0
- package/dist/cjs/create-post-interaction-log-payload/index.js +12 -3
- package/dist/cjs/interaction-metrics/index.js +4 -0
- package/dist/cjs/interaction-metrics/post-interaction-log.js +13 -1
- package/dist/cjs/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.js +8 -18
- package/dist/cjs/vc/vc-observer-new/metric-calculator/fy25_03/index.js +5 -0
- package/dist/cjs/vc/vc-observer-new/metric-calculator/vcnext/index.js +4 -1
- package/dist/cjs/vc/vc-observer-new/viewport-observer/index.js +26 -40
- package/dist/cjs/vc/vc-observer-new/viewport-observer/utils/is-element-visible.js +23 -0
- package/dist/cjs/vc/vc-observer-new/viewport-observer/utils/is-same-rect-dimensions.js +13 -0
- package/dist/cjs/vc/vc-observer-new/viewport-observer/utils/is-same-rect-size.js +13 -0
- package/dist/es2019/create-post-interaction-log-payload/index.js +9 -2
- package/dist/es2019/interaction-metrics/index.js +4 -0
- package/dist/es2019/interaction-metrics/post-interaction-log.js +11 -1
- package/dist/es2019/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.js +8 -18
- package/dist/es2019/vc/vc-observer-new/metric-calculator/fy25_03/index.js +5 -0
- package/dist/es2019/vc/vc-observer-new/metric-calculator/vcnext/index.js +4 -1
- package/dist/es2019/vc/vc-observer-new/viewport-observer/index.js +25 -39
- package/dist/es2019/vc/vc-observer-new/viewport-observer/utils/is-element-visible.js +17 -0
- package/dist/es2019/vc/vc-observer-new/viewport-observer/utils/is-same-rect-dimensions.js +7 -0
- package/dist/es2019/vc/vc-observer-new/viewport-observer/utils/is-same-rect-size.js +7 -0
- package/dist/esm/create-post-interaction-log-payload/index.js +12 -3
- package/dist/esm/interaction-metrics/index.js +4 -0
- package/dist/esm/interaction-metrics/post-interaction-log.js +13 -1
- package/dist/esm/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.js +8 -18
- package/dist/esm/vc/vc-observer-new/metric-calculator/fy25_03/index.js +5 -0
- package/dist/esm/vc/vc-observer-new/metric-calculator/vcnext/index.js +4 -1
- package/dist/esm/vc/vc-observer-new/viewport-observer/index.js +25 -39
- package/dist/esm/vc/vc-observer-new/viewport-observer/utils/is-element-visible.js +17 -0
- package/dist/esm/vc/vc-observer-new/viewport-observer/utils/is-same-rect-dimensions.js +7 -0
- package/dist/esm/vc/vc-observer-new/viewport-observer/utils/is-same-rect-size.js +7 -0
- package/dist/types/common/common/types.d.ts +1 -0
- package/dist/types/common/react-ufo-payload-schema.d.ts +1 -0
- package/dist/types/create-post-interaction-log-payload/index.d.ts +7 -1
- package/dist/types/interaction-metrics/post-interaction-log.d.ts +3 -1
- package/dist/types/vc/vc-observer-new/types.d.ts +1 -1
- package/dist/types/vc/vc-observer-new/viewport-observer/utils/is-element-visible.d.ts +1 -0
- package/dist/types/vc/vc-observer-new/viewport-observer/utils/is-same-rect-dimensions.d.ts +1 -0
- package/dist/types/vc/vc-observer-new/viewport-observer/utils/is-same-rect-size.d.ts +1 -0
- package/dist/types-ts4.5/common/common/types.d.ts +1 -0
- package/dist/types-ts4.5/common/react-ufo-payload-schema.d.ts +1 -0
- package/dist/types-ts4.5/create-post-interaction-log-payload/index.d.ts +7 -1
- package/dist/types-ts4.5/interaction-metrics/post-interaction-log.d.ts +3 -1
- package/dist/types-ts4.5/vc/vc-observer-new/types.d.ts +1 -1
- package/dist/types-ts4.5/vc/vc-observer-new/viewport-observer/utils/is-element-visible.d.ts +1 -0
- package/dist/types-ts4.5/vc/vc-observer-new/viewport-observer/utils/is-same-rect-dimensions.d.ts +1 -0
- package/dist/types-ts4.5/vc/vc-observer-new/viewport-observer/utils/is-same-rect-size.d.ts +1 -0
- 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
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
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
|
|
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 &&
|
|
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
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
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
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
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 =>
|
|
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 &&
|
|
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
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
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
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
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
|
|
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 &&
|
|
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
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
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
|
+
}
|
|
@@ -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;
|
|
@@ -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;
|
package/dist/types-ts4.5/vc/vc-observer-new/viewport-observer/utils/is-same-rect-dimensions.d.ts
ADDED
|
@@ -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.
|
|
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
|
},
|