@atlaskit/react-ufo 5.2.9 → 5.3.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.
- package/CHANGELOG.md +16 -0
- package/dist/cjs/create-payload/index.js +6 -5
- package/dist/cjs/hidden-timing/index.js +52 -0
- package/dist/cjs/interaction-metrics/index.js +1 -0
- package/dist/cjs/interaction-metrics-init/index.js +2 -1
- package/dist/cjs/vc/index.js +4 -2
- package/dist/cjs/vc/vc-observer-new/index.js +10 -4
- package/dist/cjs/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.js +84 -29
- package/dist/cjs/vc/vc-observer-new/metric-calculator/utils/detect-layout-shift-cause.js +164 -0
- package/dist/cjs/vc/vc-observer-new/viewport-observer/index.js +173 -34
- package/dist/cjs/vc/vc-observer-new/viewport-observer/intersection-observer/index.js +1 -1
- package/dist/cjs/vc/vc-observer-new/viewport-observer/mutation-observer/index.js +2 -1
- package/dist/es2019/create-payload/index.js +5 -3
- package/dist/es2019/hidden-timing/index.js +51 -0
- package/dist/es2019/interaction-metrics/index.js +1 -0
- package/dist/es2019/interaction-metrics-init/index.js +2 -1
- package/dist/es2019/vc/index.js +4 -2
- package/dist/es2019/vc/vc-observer-new/index.js +10 -5
- package/dist/es2019/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.js +61 -7
- package/dist/es2019/vc/vc-observer-new/metric-calculator/utils/detect-layout-shift-cause.js +138 -0
- package/dist/es2019/vc/vc-observer-new/viewport-observer/index.js +145 -10
- package/dist/es2019/vc/vc-observer-new/viewport-observer/intersection-observer/index.js +1 -1
- package/dist/es2019/vc/vc-observer-new/viewport-observer/mutation-observer/index.js +2 -1
- package/dist/esm/create-payload/index.js +7 -6
- package/dist/esm/hidden-timing/index.js +51 -0
- package/dist/esm/interaction-metrics/index.js +1 -0
- package/dist/esm/interaction-metrics-init/index.js +2 -1
- package/dist/esm/vc/index.js +4 -2
- package/dist/esm/vc/vc-observer-new/index.js +10 -4
- package/dist/esm/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.js +84 -29
- package/dist/esm/vc/vc-observer-new/metric-calculator/utils/detect-layout-shift-cause.js +158 -0
- package/dist/esm/vc/vc-observer-new/viewport-observer/index.js +173 -34
- package/dist/esm/vc/vc-observer-new/viewport-observer/intersection-observer/index.js +1 -1
- package/dist/esm/vc/vc-observer-new/viewport-observer/mutation-observer/index.js +2 -1
- package/dist/types/common/react-ufo-payload-schema.d.ts +2 -0
- package/dist/types/common/vc/types.d.ts +55 -0
- package/dist/types/config/index.d.ts +1 -0
- package/dist/types/hidden-timing/index.d.ts +9 -0
- package/dist/types/vc/types.d.ts +2 -0
- package/dist/types/vc/vc-observer-new/index.d.ts +2 -0
- package/dist/types/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.d.ts +1 -1
- package/dist/types/vc/vc-observer-new/metric-calculator/types.d.ts +1 -0
- package/dist/types/vc/vc-observer-new/metric-calculator/utils/detect-layout-shift-cause.d.ts +31 -0
- package/dist/types/vc/vc-observer-new/types.d.ts +2 -0
- package/dist/types/vc/vc-observer-new/viewport-observer/index.d.ts +3 -1
- package/dist/types/vc/vc-observer-new/viewport-observer/mutation-observer/index.d.ts +1 -0
- package/dist/types/vc/vc-observer-new/viewport-observer/types.d.ts +5 -2
- package/dist/types-ts4.5/common/react-ufo-payload-schema.d.ts +2 -0
- package/dist/types-ts4.5/common/vc/types.d.ts +55 -0
- package/dist/types-ts4.5/config/index.d.ts +1 -0
- package/dist/types-ts4.5/hidden-timing/index.d.ts +9 -0
- package/dist/types-ts4.5/vc/types.d.ts +2 -0
- package/dist/types-ts4.5/vc/vc-observer-new/index.d.ts +2 -0
- package/dist/types-ts4.5/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.d.ts +1 -1
- package/dist/types-ts4.5/vc/vc-observer-new/metric-calculator/types.d.ts +1 -0
- package/dist/types-ts4.5/vc/vc-observer-new/metric-calculator/utils/detect-layout-shift-cause.d.ts +31 -0
- package/dist/types-ts4.5/vc/vc-observer-new/types.d.ts +2 -0
- package/dist/types-ts4.5/vc/vc-observer-new/viewport-observer/index.d.ts +3 -1
- package/dist/types-ts4.5/vc/vc-observer-new/viewport-observer/mutation-observer/index.d.ts +1 -0
- package/dist/types-ts4.5/vc/vc-observer-new/viewport-observer/types.d.ts +5 -2
- package/package.json +4 -1
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
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; } } }; }
|
|
2
|
+
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; } }
|
|
3
|
+
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; }
|
|
4
|
+
var calculateOffenderState = function calculateOffenderState(current, matchesCurrentEntry) {
|
|
5
|
+
// Once we know it's mixed across entries, we can short-circuit.
|
|
6
|
+
if (current === 'some') {
|
|
7
|
+
return 'some';
|
|
8
|
+
}
|
|
9
|
+
var entryState = matchesCurrentEntry ? 'all' : 'none';
|
|
10
|
+
if (current == null) {
|
|
11
|
+
return entryState;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// If the state flips between entries (all <-> none), it's "some".
|
|
15
|
+
if (current !== entryState) {
|
|
16
|
+
return 'some';
|
|
17
|
+
}
|
|
18
|
+
return current;
|
|
19
|
+
};
|
|
20
|
+
var calculateLayoutShiftMovement = function calculateLayoutShiftMovement(layoutShiftEntries) {
|
|
21
|
+
var movements = layoutShiftEntries.map(function (lsEntry) {
|
|
22
|
+
var rect = lsEntry.rect;
|
|
23
|
+
var previousRect = lsEntry.previousRect;
|
|
24
|
+
if (!rect || !previousRect) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
var dx = rect.x - previousRect.x;
|
|
28
|
+
var dy = rect.y - previousRect.y;
|
|
29
|
+
return {
|
|
30
|
+
dx: dx,
|
|
31
|
+
dy: dy,
|
|
32
|
+
movedX: dx !== 0,
|
|
33
|
+
movedY: dy !== 0,
|
|
34
|
+
dirX: Math.sign(dx),
|
|
35
|
+
dirY: Math.sign(dy),
|
|
36
|
+
absDx: Math.abs(dx),
|
|
37
|
+
absDy: Math.abs(dy)
|
|
38
|
+
};
|
|
39
|
+
});
|
|
40
|
+
var hasMovement = function hasMovement(m) {
|
|
41
|
+
return m !== null;
|
|
42
|
+
};
|
|
43
|
+
var validMovements = movements.filter(hasMovement);
|
|
44
|
+
var allHaveRects = layoutShiftEntries.length > 0 && validMovements.length === layoutShiftEntries.length;
|
|
45
|
+
if (!allHaveRects) {
|
|
46
|
+
return {
|
|
47
|
+
allHaveRects: allHaveRects,
|
|
48
|
+
allMovedSameWay: false,
|
|
49
|
+
allMovedSameAmount: false
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
var first = validMovements[0];
|
|
53
|
+
var allMovedSameWay = validMovements.every(function (m) {
|
|
54
|
+
return m.movedX === first.movedX && m.movedY === first.movedY && m.dirX === first.dirX && m.dirY === first.dirY;
|
|
55
|
+
});
|
|
56
|
+
var allMovedSameAmount = allMovedSameWay && validMovements.every(function (m) {
|
|
57
|
+
return m.absDx === first.absDx && m.absDy === first.absDy;
|
|
58
|
+
});
|
|
59
|
+
return {
|
|
60
|
+
allHaveRects: allHaveRects,
|
|
61
|
+
allMovedSameWay: allMovedSameWay,
|
|
62
|
+
allMovedSameAmount: allMovedSameAmount,
|
|
63
|
+
deltaX: first.dx,
|
|
64
|
+
deltaY: first.dy
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
export var detectLayoutShiftCause = function detectLayoutShiftCause(_ref) {
|
|
68
|
+
var viewportEntries = _ref.viewportEntries,
|
|
69
|
+
layoutShiftEntries = _ref.layoutShiftEntries,
|
|
70
|
+
time = _ref.time,
|
|
71
|
+
startTime = _ref.startTime,
|
|
72
|
+
_ref$offenderWindowMs = _ref.offenderWindowMs,
|
|
73
|
+
offenderWindowMs = _ref$offenderWindowMs === void 0 ? 250 : _ref$offenderWindowMs;
|
|
74
|
+
var checkpointTimestamp = startTime + time;
|
|
75
|
+
var filteredLSPotentialOffenders = viewportEntries.filter(function (viewportEntry) {
|
|
76
|
+
return (viewportEntry.time < checkpointTimestamp && viewportEntry.time > checkpointTimestamp - offenderWindowMs || viewportEntry.time > checkpointTimestamp && viewportEntry.time < checkpointTimestamp + offenderWindowMs) && viewportEntry.data.type !== 'layout-shift';
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Summarize whether all layout-shift entries moved in a consistent direction and by the same amount.
|
|
80
|
+
var layoutShiftVariables = calculateLayoutShiftMovement(layoutShiftEntries);
|
|
81
|
+
|
|
82
|
+
// Classify each offender against *all* layout-shift entries when the layout shift is consistently moving in a
|
|
83
|
+
// single axis (pure X or pure Y) so we can reason about whether an offender could have caused the movement.
|
|
84
|
+
var layoutShiftOffenders = filteredLSPotentialOffenders.reduce(function (acc, offender) {
|
|
85
|
+
var _offenderData$origina;
|
|
86
|
+
var offenderData = offender.data;
|
|
87
|
+
var offenderRect = offenderData.rect;
|
|
88
|
+
if (!offenderRect) {
|
|
89
|
+
return acc;
|
|
90
|
+
}
|
|
91
|
+
var offenderTimestamp = (_offenderData$origina = offenderData.originalMutationTimestamp) !== null && _offenderData$origina !== void 0 ? _offenderData$origina : offender.time;
|
|
92
|
+
var happenedBefore = offenderTimestamp <= checkpointTimestamp;
|
|
93
|
+
var offenderLeft = offenderRect.x;
|
|
94
|
+
var offenderRight = offenderRect.x + offenderRect.width;
|
|
95
|
+
var offenderTop = offenderRect.y;
|
|
96
|
+
var offenderBottom = offenderRect.y + offenderRect.height;
|
|
97
|
+
var shouldClassifyAgainstAllEntries = layoutShiftVariables.allMovedSameWay && 'deltaX' in layoutShiftVariables && 'deltaY' in layoutShiftVariables && layoutShiftVariables.deltaX === 0 !== (layoutShiftVariables.deltaY === 0);
|
|
98
|
+
var isAbove = null;
|
|
99
|
+
var isLeft = null;
|
|
100
|
+
var isRight = null;
|
|
101
|
+
var hasHorizontalOverlap = null;
|
|
102
|
+
var hasVerticalOverlap = null;
|
|
103
|
+
if (shouldClassifyAgainstAllEntries) {
|
|
104
|
+
var _iterator = _createForOfIteratorHelper(layoutShiftEntries),
|
|
105
|
+
_step;
|
|
106
|
+
try {
|
|
107
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
108
|
+
var lsEntry = _step.value;
|
|
109
|
+
var lsRect = lsEntry.rect;
|
|
110
|
+
if (!lsRect) {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
var lsLeft = lsRect.x;
|
|
114
|
+
var lsRight = lsRect.x + lsRect.width;
|
|
115
|
+
var lsTop = lsRect.y;
|
|
116
|
+
var lsBottom = lsRect.y + lsRect.height;
|
|
117
|
+
isAbove = calculateOffenderState(isAbove, offenderBottom <= lsTop);
|
|
118
|
+
isLeft = calculateOffenderState(isLeft, offenderRight <= lsLeft);
|
|
119
|
+
isRight = calculateOffenderState(isRight, offenderLeft >= lsRight);
|
|
120
|
+
hasHorizontalOverlap = calculateOffenderState(hasHorizontalOverlap, offenderLeft < lsRight && offenderRight > lsLeft);
|
|
121
|
+
hasVerticalOverlap = calculateOffenderState(hasVerticalOverlap, offenderTop < lsBottom && offenderBottom > lsTop);
|
|
122
|
+
}
|
|
123
|
+
} catch (err) {
|
|
124
|
+
_iterator.e(err);
|
|
125
|
+
} finally {
|
|
126
|
+
_iterator.f();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
var matchesLayoutShiftDelta = false;
|
|
130
|
+
if (shouldClassifyAgainstAllEntries && layoutShiftVariables.allMovedSameAmount && offenderData.previousRect) {
|
|
131
|
+
var dx = offenderRect.x - offenderData.previousRect.x;
|
|
132
|
+
var dy = offenderRect.y - offenderData.previousRect.y;
|
|
133
|
+
var isPureX = layoutShiftVariables.deltaX !== 0 && layoutShiftVariables.deltaY === 0;
|
|
134
|
+
var isPureY = layoutShiftVariables.deltaY !== 0 && layoutShiftVariables.deltaX === 0;
|
|
135
|
+
if (isPureX) {
|
|
136
|
+
matchesLayoutShiftDelta = dx === layoutShiftVariables.deltaX && dy === 0;
|
|
137
|
+
} else if (isPureY) {
|
|
138
|
+
matchesLayoutShiftDelta = dy === layoutShiftVariables.deltaY && dx === 0;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
acc.push({
|
|
142
|
+
offender: offenderData.elementName,
|
|
143
|
+
happenedBefore: happenedBefore,
|
|
144
|
+
distanceToLS: Math.round(offenderTimestamp - checkpointTimestamp),
|
|
145
|
+
isAbove: isAbove !== null && isAbove !== void 0 ? isAbove : 'none',
|
|
146
|
+
isLeft: isLeft !== null && isLeft !== void 0 ? isLeft : 'none',
|
|
147
|
+
isRight: isRight !== null && isRight !== void 0 ? isRight : 'none',
|
|
148
|
+
hasHorizontalOverlap: hasHorizontalOverlap !== null && hasHorizontalOverlap !== void 0 ? hasHorizontalOverlap : 'none',
|
|
149
|
+
hasVerticalOverlap: hasVerticalOverlap !== null && hasVerticalOverlap !== void 0 ? hasVerticalOverlap : 'none',
|
|
150
|
+
matchesLayoutShiftDelta: matchesLayoutShiftDelta
|
|
151
|
+
});
|
|
152
|
+
return acc;
|
|
153
|
+
}, []);
|
|
154
|
+
return {
|
|
155
|
+
layoutShiftVariables: layoutShiftVariables,
|
|
156
|
+
layoutShiftOffenders: layoutShiftOffenders
|
|
157
|
+
};
|
|
158
|
+
};
|
|
@@ -88,22 +88,151 @@ var createElementMutationsWatcher = function createElementMutationsWatcher(remov
|
|
|
88
88
|
return 'mutation:element';
|
|
89
89
|
};
|
|
90
90
|
};
|
|
91
|
+
var createElementMutationsWatcherNew = function createElementMutationsWatcherNew(removedNodeRects, isWithinThirdPartySegment, isWithinSmartAnswersSegment, hasSameDeletedNode, timestamp, isTargetReactRoot, getSSRState, getSSRPlaceholderHandler) {
|
|
92
|
+
return function (_ref2) {
|
|
93
|
+
var target = _ref2.target,
|
|
94
|
+
rect = _ref2.rect;
|
|
95
|
+
if (getSSRState) {
|
|
96
|
+
var ssrState = getSSRState();
|
|
97
|
+
var SSRStateEnum = {
|
|
98
|
+
normal: 1,
|
|
99
|
+
waitingForFirstRender: 2,
|
|
100
|
+
ignoring: 3
|
|
101
|
+
};
|
|
102
|
+
if (ssrState.state === SSRStateEnum.waitingForFirstRender && timestamp > ssrState.renderStart && isTargetReactRoot) {
|
|
103
|
+
ssrState.state = SSRStateEnum.ignoring;
|
|
104
|
+
if (ssrState.renderStop === -1) {
|
|
105
|
+
// arbitrary 500ms DOM update window
|
|
106
|
+
ssrState.renderStop = timestamp + 500;
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
type: 'ssr-hydration',
|
|
110
|
+
mutationData: {
|
|
111
|
+
timestamp: timestamp
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
if (ssrState.state === SSRStateEnum.ignoring && timestamp > ssrState.renderStart && isTargetReactRoot) {
|
|
116
|
+
if (timestamp <= ssrState.renderStop) {
|
|
117
|
+
return {
|
|
118
|
+
type: 'ssr-hydration',
|
|
119
|
+
mutationData: {
|
|
120
|
+
timestamp: timestamp
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
} else {
|
|
124
|
+
ssrState.state = SSRStateEnum.normal;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (getSSRPlaceholderHandler) {
|
|
129
|
+
var ssrPlaceholderHandler = getSSRPlaceholderHandler();
|
|
130
|
+
if (ssrPlaceholderHandler) {
|
|
131
|
+
if ((ssrPlaceholderHandler.isPlaceholderV4(target) || ssrPlaceholderHandler.isPlaceholderIgnored(target)) && ssrPlaceholderHandler.checkIfExistedAndSizeMatchingV3(target)) {
|
|
132
|
+
return {
|
|
133
|
+
type: 'mutation:ssr-placeholder',
|
|
134
|
+
mutationData: {
|
|
135
|
+
timestamp: timestamp
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
if ((ssrPlaceholderHandler.isPlaceholderReplacementV4(target) || ssrPlaceholderHandler.isPlaceholderIgnored(target)) && ssrPlaceholderHandler.validateReactComponentMatchToPlaceholderV4(target)) {
|
|
140
|
+
return {
|
|
141
|
+
type: 'mutation:ssr-placeholder',
|
|
142
|
+
mutationData: {
|
|
143
|
+
timestamp: timestamp
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (hasSameDeletedNode && isInVCIgnoreIfNoLayoutShiftMarker(target)) {
|
|
150
|
+
return {
|
|
151
|
+
type: 'mutation:remount',
|
|
152
|
+
mutationData: {
|
|
153
|
+
timestamp: timestamp
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
if (isContainedWithinMediaWrapper(target)) {
|
|
158
|
+
return {
|
|
159
|
+
type: 'mutation:media',
|
|
160
|
+
mutationData: {
|
|
161
|
+
timestamp: timestamp
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
if (isWithinThirdPartySegment) {
|
|
166
|
+
return {
|
|
167
|
+
type: 'mutation:third-party-element',
|
|
168
|
+
mutationData: {
|
|
169
|
+
timestamp: timestamp
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
if (isWithinSmartAnswersSegment) {
|
|
174
|
+
return {
|
|
175
|
+
type: 'mutation:smart-answers-element',
|
|
176
|
+
mutationData: {
|
|
177
|
+
timestamp: timestamp
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
var isInIgnoreLsMarker = isInVCIgnoreIfNoLayoutShiftMarker(target);
|
|
182
|
+
if (!isInIgnoreLsMarker) {
|
|
183
|
+
return {
|
|
184
|
+
type: 'mutation:element',
|
|
185
|
+
mutationData: {
|
|
186
|
+
timestamp: timestamp
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
var isRLLPlaceholder = RLLPlaceholderHandlers.getInstance().isRLLPlaceholderHydration(rect);
|
|
191
|
+
if (isRLLPlaceholder && isInIgnoreLsMarker) {
|
|
192
|
+
return {
|
|
193
|
+
type: 'mutation:rll-placeholder',
|
|
194
|
+
mutationData: {
|
|
195
|
+
timestamp: timestamp
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
var wasDeleted = removedNodeRects.some(function (nr) {
|
|
200
|
+
return isSameRectDimensions(nr, rect);
|
|
201
|
+
});
|
|
202
|
+
if (wasDeleted && isInIgnoreLsMarker) {
|
|
203
|
+
return {
|
|
204
|
+
type: 'mutation:element-replacement',
|
|
205
|
+
mutationData: {
|
|
206
|
+
timestamp: timestamp
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
return {
|
|
211
|
+
type: 'mutation:element',
|
|
212
|
+
mutationData: {
|
|
213
|
+
timestamp: timestamp
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
};
|
|
217
|
+
};
|
|
91
218
|
var ViewportObserver = /*#__PURE__*/function () {
|
|
92
219
|
// SSR context functions
|
|
93
220
|
|
|
94
|
-
function ViewportObserver(
|
|
221
|
+
function ViewportObserver(_ref3) {
|
|
95
222
|
var _this = this;
|
|
96
|
-
var onChange =
|
|
97
|
-
getSSRState =
|
|
98
|
-
getSSRPlaceholderHandler =
|
|
99
|
-
|
|
223
|
+
var onChange = _ref3.onChange,
|
|
224
|
+
getSSRState = _ref3.getSSRState,
|
|
225
|
+
getSSRPlaceholderHandler = _ref3.getSSRPlaceholderHandler,
|
|
226
|
+
_ref3$trackLayoutShif = _ref3.trackLayoutShiftOffenders,
|
|
227
|
+
trackLayoutShiftOffenders = _ref3$trackLayoutShif === void 0 ? false : _ref3$trackLayoutShif,
|
|
228
|
+
searchPageConfig = _ref3.searchPageConfig;
|
|
100
229
|
_classCallCheck(this, ViewportObserver);
|
|
101
|
-
_defineProperty(this, "handleIntersectionEntry", function (
|
|
102
|
-
var target =
|
|
103
|
-
rect =
|
|
104
|
-
time =
|
|
105
|
-
type =
|
|
106
|
-
mutationData =
|
|
230
|
+
_defineProperty(this, "handleIntersectionEntry", function (_ref4) {
|
|
231
|
+
var target = _ref4.target,
|
|
232
|
+
rect = _ref4.rect,
|
|
233
|
+
time = _ref4.time,
|
|
234
|
+
type = _ref4.type,
|
|
235
|
+
mutationData = _ref4.mutationData;
|
|
107
236
|
if (!target) {
|
|
108
237
|
return;
|
|
109
238
|
}
|
|
@@ -121,12 +250,12 @@ var ViewportObserver = /*#__PURE__*/function () {
|
|
|
121
250
|
});
|
|
122
251
|
});
|
|
123
252
|
_defineProperty(this, "handleChildListMutation", /*#__PURE__*/function () {
|
|
124
|
-
var
|
|
253
|
+
var _ref6 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(_ref5) {
|
|
125
254
|
var target, addedNodes, removedNodes, timestamp, removedNodeRects, targetNode, _iterator, _step, _loop;
|
|
126
255
|
return _regeneratorRuntime.wrap(function _callee$(_context2) {
|
|
127
256
|
while (1) switch (_context2.prev = _context2.next) {
|
|
128
257
|
case 0:
|
|
129
|
-
target =
|
|
258
|
+
target = _ref5.target, addedNodes = _ref5.addedNodes, removedNodes = _ref5.removedNodes, timestamp = _ref5.timestamp;
|
|
130
259
|
removedNodeRects = removedNodes.map(function (ref) {
|
|
131
260
|
var n = ref.deref();
|
|
132
261
|
if (!n) {
|
|
@@ -161,7 +290,7 @@ var ViewportObserver = /*#__PURE__*/function () {
|
|
|
161
290
|
_checkWithinComponent = checkWithinComponent(addedNode, 'UFOThirdPartySegment', _this.mapIs3pResult), isWithinThirdPartySegment = _checkWithinComponent.isWithin;
|
|
162
291
|
isWithinSmartAnswersSegment = Boolean(_this.shouldCheckSmartAnswersMutations() && isContainedWithinSmartAnswers(addedNode));
|
|
163
292
|
isTargetReactRoot = targetNode === ((_this$getSSRState = _this.getSSRState) === null || _this$getSSRState === void 0 || (_this$getSSRState = _this$getSSRState.call(_this)) === null || _this$getSSRState === void 0 ? void 0 : _this$getSSRState.reactRootElement);
|
|
164
|
-
(_this$intersectionObs = _this.intersectionObserver) === null || _this$intersectionObs === void 0 || _this$intersectionObs.watchAndTag(addedNode, createElementMutationsWatcher(removedNodeRects, isWithinThirdPartySegment, isWithinSmartAnswersSegment, !!hasSameDeletedNode, timestamp, isTargetReactRoot, _this.getSSRState, _this.getSSRPlaceholderHandler));
|
|
293
|
+
(_this$intersectionObs = _this.intersectionObserver) === null || _this$intersectionObs === void 0 || _this$intersectionObs.watchAndTag(addedNode, (_this.trackLayoutShiftOffenders ? createElementMutationsWatcherNew : createElementMutationsWatcher)(removedNodeRects, isWithinThirdPartySegment, isWithinSmartAnswersSegment, !!hasSameDeletedNode, timestamp, isTargetReactRoot, _this.getSSRState, _this.getSSRPlaceholderHandler));
|
|
165
294
|
case 9:
|
|
166
295
|
case "end":
|
|
167
296
|
return _context.stop();
|
|
@@ -202,25 +331,27 @@ var ViewportObserver = /*#__PURE__*/function () {
|
|
|
202
331
|
}, _callee, null, [[4, 15, 18, 21]]);
|
|
203
332
|
}));
|
|
204
333
|
return function (_x) {
|
|
205
|
-
return
|
|
334
|
+
return _ref6.apply(this, arguments);
|
|
206
335
|
};
|
|
207
336
|
}());
|
|
208
|
-
_defineProperty(this, "handleAttributeMutation", function (
|
|
337
|
+
_defineProperty(this, "handleAttributeMutation", function (_ref7) {
|
|
209
338
|
var _this$intersectionObs2;
|
|
210
|
-
var target =
|
|
211
|
-
attributeName =
|
|
212
|
-
oldValue =
|
|
213
|
-
newValue =
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
339
|
+
var target = _ref7.target,
|
|
340
|
+
attributeName = _ref7.attributeName,
|
|
341
|
+
oldValue = _ref7.oldValue,
|
|
342
|
+
newValue = _ref7.newValue,
|
|
343
|
+
timestamp = _ref7.timestamp;
|
|
344
|
+
(_this$intersectionObs2 = _this.intersectionObserver) === null || _this$intersectionObs2 === void 0 || _this$intersectionObs2.watchAndTag(target, function (_ref8) {
|
|
345
|
+
var target = _ref8.target,
|
|
346
|
+
rect = _ref8.rect;
|
|
217
347
|
if (isContainedWithinMediaWrapper(target)) {
|
|
218
348
|
return {
|
|
219
349
|
type: 'mutation:media',
|
|
220
350
|
mutationData: {
|
|
221
351
|
attributeName: attributeName,
|
|
222
352
|
oldValue: oldValue,
|
|
223
|
-
newValue: newValue
|
|
353
|
+
newValue: newValue,
|
|
354
|
+
timestamp: timestamp
|
|
224
355
|
}
|
|
225
356
|
};
|
|
226
357
|
}
|
|
@@ -233,7 +364,8 @@ var ViewportObserver = /*#__PURE__*/function () {
|
|
|
233
364
|
mutationData: {
|
|
234
365
|
attributeName: attributeName,
|
|
235
366
|
oldValue: oldValue,
|
|
236
|
-
newValue: newValue
|
|
367
|
+
newValue: newValue,
|
|
368
|
+
timestamp: timestamp
|
|
237
369
|
}
|
|
238
370
|
};
|
|
239
371
|
}
|
|
@@ -259,7 +391,8 @@ var ViewportObserver = /*#__PURE__*/function () {
|
|
|
259
391
|
mutationData: {
|
|
260
392
|
attributeName: attributeName,
|
|
261
393
|
oldValue: oldValue,
|
|
262
|
-
newValue: newValue
|
|
394
|
+
newValue: newValue,
|
|
395
|
+
timestamp: timestamp
|
|
263
396
|
}
|
|
264
397
|
};
|
|
265
398
|
}
|
|
@@ -273,7 +406,8 @@ var ViewportObserver = /*#__PURE__*/function () {
|
|
|
273
406
|
mutationData: {
|
|
274
407
|
attributeName: attributeName,
|
|
275
408
|
oldValue: oldValue,
|
|
276
|
-
newValue: newValue
|
|
409
|
+
newValue: newValue,
|
|
410
|
+
timestamp: timestamp
|
|
277
411
|
}
|
|
278
412
|
};
|
|
279
413
|
}
|
|
@@ -288,7 +422,8 @@ var ViewportObserver = /*#__PURE__*/function () {
|
|
|
288
422
|
mutationData: {
|
|
289
423
|
attributeName: attributeName,
|
|
290
424
|
oldValue: oldValue,
|
|
291
|
-
newValue: newValue
|
|
425
|
+
newValue: newValue,
|
|
426
|
+
timestamp: timestamp
|
|
292
427
|
}
|
|
293
428
|
};
|
|
294
429
|
}
|
|
@@ -299,7 +434,8 @@ var ViewportObserver = /*#__PURE__*/function () {
|
|
|
299
434
|
mutationData: {
|
|
300
435
|
attributeName: attributeName,
|
|
301
436
|
oldValue: oldValue,
|
|
302
|
-
newValue: newValue
|
|
437
|
+
newValue: newValue,
|
|
438
|
+
timestamp: timestamp
|
|
303
439
|
}
|
|
304
440
|
};
|
|
305
441
|
}
|
|
@@ -310,7 +446,8 @@ var ViewportObserver = /*#__PURE__*/function () {
|
|
|
310
446
|
mutationData: {
|
|
311
447
|
attributeName: attributeName,
|
|
312
448
|
oldValue: oldValue,
|
|
313
|
-
newValue: newValue
|
|
449
|
+
newValue: newValue,
|
|
450
|
+
timestamp: timestamp
|
|
314
451
|
}
|
|
315
452
|
};
|
|
316
453
|
}
|
|
@@ -319,14 +456,15 @@ var ViewportObserver = /*#__PURE__*/function () {
|
|
|
319
456
|
mutationData: {
|
|
320
457
|
attributeName: attributeName,
|
|
321
458
|
oldValue: oldValue,
|
|
322
|
-
newValue: newValue
|
|
459
|
+
newValue: newValue,
|
|
460
|
+
timestamp: timestamp
|
|
323
461
|
}
|
|
324
462
|
};
|
|
325
463
|
});
|
|
326
464
|
});
|
|
327
|
-
_defineProperty(this, "handleLayoutShift", function (
|
|
328
|
-
var time =
|
|
329
|
-
changedRects =
|
|
465
|
+
_defineProperty(this, "handleLayoutShift", function (_ref9) {
|
|
466
|
+
var time = _ref9.time,
|
|
467
|
+
changedRects = _ref9.changedRects;
|
|
330
468
|
var _iterator2 = _createForOfIteratorHelper(changedRects),
|
|
331
469
|
_step2;
|
|
332
470
|
try {
|
|
@@ -362,6 +500,7 @@ var ViewportObserver = /*#__PURE__*/function () {
|
|
|
362
500
|
this.intersectionObserver = null;
|
|
363
501
|
this.mutationObserver = null;
|
|
364
502
|
this.performanceObserver = null;
|
|
503
|
+
this.trackLayoutShiftOffenders = trackLayoutShiftOffenders;
|
|
365
504
|
|
|
366
505
|
// Initialize SSR context functions
|
|
367
506
|
this.getSSRState = getSSRState;
|
|
@@ -30,7 +30,7 @@ export function createIntersectionObserver(_ref) {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
// override as display-contents mutation
|
|
33
|
-
if (tagOrCallbackResult && typeof tagOrCallbackResult !== 'string' && tagOrCallbackResult.type === 'mutation:attribute') {
|
|
33
|
+
if (tagOrCallbackResult && typeof tagOrCallbackResult !== 'string' && tagOrCallbackResult.type === 'mutation:attribute' && 'oldValue' in tagOrCallbackResult.mutationData) {
|
|
34
34
|
var _tagOrCallbackResult$ = tagOrCallbackResult.mutationData,
|
|
35
35
|
attributeName = _tagOrCallbackResult$.attributeName,
|
|
36
36
|
oldValue = _tagOrCallbackResult$.oldValue,
|
|
@@ -53,7 +53,8 @@ function createMutationObserver(_ref) {
|
|
|
53
53
|
target: mut.target,
|
|
54
54
|
attributeName: (_mut$attributeName = mut.attributeName) !== null && _mut$attributeName !== void 0 ? _mut$attributeName : 'unknown',
|
|
55
55
|
oldValue: oldValue,
|
|
56
|
-
newValue: newValue
|
|
56
|
+
newValue: newValue,
|
|
57
|
+
timestamp: mut.timestamp || performance.now()
|
|
57
58
|
});
|
|
58
59
|
}
|
|
59
60
|
return 0; // continue
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type createPayloads } from '../create-payload';
|
|
2
|
+
import type { HiddenTimingItem } from '../hidden-timing';
|
|
2
3
|
import { type LabelStack } from '../interaction-context';
|
|
3
4
|
import { type VCObserver } from '../vc/vc-observer';
|
|
4
5
|
import type { AbortReasonType, ApdexType, HoldActive, InteractionError, InteractionType, MinorInteraction, SegmentInfo } from './common/types';
|
|
@@ -120,6 +121,7 @@ export type ReactUFOPayload = {
|
|
|
120
121
|
'ufo:wasPageHiddenBeforeInit'?: boolean;
|
|
121
122
|
'ufo:isOpenedInBackground'?: boolean;
|
|
122
123
|
'ufo:isTabThrottled'?: boolean;
|
|
124
|
+
'ufo:pageVisibilityTimeline'?: HiddenTimingItem[];
|
|
123
125
|
interactionMetrics: {
|
|
124
126
|
namePrefix: string;
|
|
125
127
|
segmentPrefix: string;
|
|
@@ -118,6 +118,7 @@ export type CalculateTTVCResult = {
|
|
|
118
118
|
vcDetails: RevisionPayloadVCDetails;
|
|
119
119
|
ssrRatio: number;
|
|
120
120
|
speedIndex: number;
|
|
121
|
+
VC90layoutShiftInsights: LayoutShiftInsights;
|
|
121
122
|
};
|
|
122
123
|
export type RawObservation = {
|
|
123
124
|
t: number;
|
|
@@ -130,8 +131,31 @@ export type RawEventObservation = {
|
|
|
130
131
|
t: number;
|
|
131
132
|
evt: number;
|
|
132
133
|
};
|
|
134
|
+
export type LayoutShiftInsightsPayload = {
|
|
135
|
+
impact: number;
|
|
136
|
+
sources: number;
|
|
137
|
+
same: {
|
|
138
|
+
dir: boolean;
|
|
139
|
+
dist: boolean;
|
|
140
|
+
};
|
|
141
|
+
total_mut: number;
|
|
142
|
+
mut: Array<{
|
|
143
|
+
e: string;
|
|
144
|
+
size: number;
|
|
145
|
+
attr: {
|
|
146
|
+
t_before: boolean;
|
|
147
|
+
p_above: 'all' | 'some' | 'none';
|
|
148
|
+
p_left: 'all' | 'some' | 'none';
|
|
149
|
+
p_right: 'all' | 'some' | 'none';
|
|
150
|
+
p_h_overlap: 'all' | 'some' | 'none';
|
|
151
|
+
p_v_overlap: 'all' | 'some' | 'none';
|
|
152
|
+
p_same_offset: 'all' | 'some' | 'none';
|
|
153
|
+
};
|
|
154
|
+
}>;
|
|
155
|
+
};
|
|
133
156
|
export type RevisionPayloadEntry = {
|
|
134
157
|
'metric:vc90': number | null;
|
|
158
|
+
'vc90:ls'?: LayoutShiftInsightsPayload;
|
|
135
159
|
revision: string;
|
|
136
160
|
clean: boolean;
|
|
137
161
|
vcDetails?: RevisionPayloadVCDetails;
|
|
@@ -157,4 +181,35 @@ export type RevisionPayloadEntry = {
|
|
|
157
181
|
rawVCTime?: number;
|
|
158
182
|
};
|
|
159
183
|
export type RevisionPayload = RevisionPayloadEntry[];
|
|
184
|
+
export type LayoutShiftVariables = {
|
|
185
|
+
allHaveRects: false;
|
|
186
|
+
allMovedSameWay: false;
|
|
187
|
+
allMovedSameAmount: false;
|
|
188
|
+
} | {
|
|
189
|
+
allHaveRects: true;
|
|
190
|
+
allMovedSameWay: boolean;
|
|
191
|
+
allMovedSameAmount: boolean;
|
|
192
|
+
deltaX: number;
|
|
193
|
+
deltaY: number;
|
|
194
|
+
};
|
|
195
|
+
export type LayoutShiftOffenderMatchState = 'all' | 'some' | 'none';
|
|
196
|
+
export type LayoutShiftOffender = {
|
|
197
|
+
offender: string;
|
|
198
|
+
happenedBefore: boolean;
|
|
199
|
+
distanceToLS: number;
|
|
200
|
+
isAbove: LayoutShiftOffenderMatchState;
|
|
201
|
+
isLeft: LayoutShiftOffenderMatchState;
|
|
202
|
+
isRight: LayoutShiftOffenderMatchState;
|
|
203
|
+
hasHorizontalOverlap: LayoutShiftOffenderMatchState;
|
|
204
|
+
hasVerticalOverlap: LayoutShiftOffenderMatchState;
|
|
205
|
+
matchesLayoutShiftDelta: boolean;
|
|
206
|
+
};
|
|
207
|
+
export type LayoutShiftInsights = {
|
|
208
|
+
layoutShiftOffendersResult: {
|
|
209
|
+
layoutShiftVariables: LayoutShiftVariables;
|
|
210
|
+
layoutShiftOffenders: LayoutShiftOffender[];
|
|
211
|
+
};
|
|
212
|
+
layoutShiftEntriesCount: number;
|
|
213
|
+
layoutShiftImpact: number;
|
|
214
|
+
} | null;
|
|
160
215
|
export {};
|
|
@@ -51,3 +51,12 @@ export declare function getThrottleMeasurements(startTime: number, endTime: numb
|
|
|
51
51
|
* @param measurement - The throttle measurement to inject
|
|
52
52
|
*/
|
|
53
53
|
export declare function __injectThrottleMeasurementForTesting(measurement: ThrottleMeasurement): void;
|
|
54
|
+
/**
|
|
55
|
+
* Returns the page visibility timeline entries within the specified time window.
|
|
56
|
+
* Each entry contains the time (relative to startTime) and whether the page was hidden.
|
|
57
|
+
*
|
|
58
|
+
* @param startTime - The start timestamp of the window (DOMHighResTimeStamp)
|
|
59
|
+
* @param endTime - The end timestamp of the window (DOMHighResTimeStamp)
|
|
60
|
+
* @returns Array of HiddenTimingItem entries within the time window, with times relative to startTime
|
|
61
|
+
*/
|
|
62
|
+
export declare function getPageVisibilityTimeline(startTime: number, endTime: number): HiddenTimingItem[];
|
package/dist/types/vc/types.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export type GetVCResultType = {
|
|
|
19
19
|
interactionAbortReason?: AbortReasonType;
|
|
20
20
|
includeRawData?: boolean;
|
|
21
21
|
rawDataStopTime?: number;
|
|
22
|
+
reportLayoutShiftOffenders?: boolean;
|
|
22
23
|
};
|
|
23
24
|
export type SelectorConfig = {
|
|
24
25
|
id: boolean;
|
|
@@ -48,6 +49,7 @@ export type VCObserverOptions = {
|
|
|
48
49
|
isPostInteraction?: boolean;
|
|
49
50
|
ssrEnablePageLayoutPlaceholder?: boolean;
|
|
50
51
|
ssrPlaceholderHandler?: any;
|
|
52
|
+
trackLayoutShiftOffenders?: boolean;
|
|
51
53
|
searchPageConfig?: SearchPageConfig;
|
|
52
54
|
};
|
|
53
55
|
export interface VCObserverInterface {
|
|
@@ -10,6 +10,7 @@ export type VCObserverNewConfig = {
|
|
|
10
10
|
enablePageLayoutPlaceholder?: boolean;
|
|
11
11
|
};
|
|
12
12
|
ssrPlaceholderHandler?: SSRPlaceholderHandlers | null;
|
|
13
|
+
trackLayoutShiftOffenders?: boolean;
|
|
13
14
|
searchPageConfig?: SearchPageConfig;
|
|
14
15
|
};
|
|
15
16
|
declare const SSRState: {
|
|
@@ -31,6 +32,7 @@ export default class VCObserverNew {
|
|
|
31
32
|
private windowEventObserver;
|
|
32
33
|
private entriesTimeline;
|
|
33
34
|
private isPostInteraction;
|
|
35
|
+
private trackLayoutShiftOffenders;
|
|
34
36
|
private ssrPlaceholderHandler;
|
|
35
37
|
private ssr;
|
|
36
38
|
constructor(config: VCObserverNewConfig);
|
|
@@ -25,5 +25,5 @@ export default abstract class AbstractVCCalculatorBase implements VCCalculator {
|
|
|
25
25
|
private calculateRatios;
|
|
26
26
|
private getLabelStacks;
|
|
27
27
|
private calculateWithDebugInfo;
|
|
28
|
-
calculate({ startTime, stopTime, orderedEntries, interactionId, isPostInteraction, include3p, excludeSmartAnswersInSearch, includeSSRRatio, interactionType, isPageVisible, interactionAbortReason, }: VCCalculatorParam): Promise<RevisionPayloadEntry | undefined>;
|
|
28
|
+
calculate({ startTime, stopTime, orderedEntries, interactionId, isPostInteraction, include3p, excludeSmartAnswersInSearch, includeSSRRatio, interactionType, isPageVisible, interactionAbortReason, reportLayoutShiftOffenders, }: VCCalculatorParam): Promise<RevisionPayloadEntry | undefined>;
|
|
29
29
|
}
|
|
@@ -13,6 +13,7 @@ export type VCCalculatorParam = {
|
|
|
13
13
|
interactionType: InteractionType;
|
|
14
14
|
isPageVisible: boolean;
|
|
15
15
|
interactionAbortReason?: AbortReasonType;
|
|
16
|
+
reportLayoutShiftOffenders?: boolean;
|
|
16
17
|
};
|
|
17
18
|
export interface VCCalculator {
|
|
18
19
|
calculate(param: VCCalculatorParam): Promise<RevisionPayloadEntry | undefined>;
|