@atlaskit/react-ufo 5.2.8 → 5.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/AGENTS.md +118 -73
  2. package/CHANGELOG.md +14 -0
  3. package/dist/cjs/experience-trace-id-context/index.js +3 -3
  4. package/dist/cjs/interaction-metrics/index.js +1 -0
  5. package/dist/cjs/interaction-metrics-init/index.js +2 -1
  6. package/dist/cjs/vc/index.js +4 -2
  7. package/dist/cjs/vc/vc-observer-new/index.js +10 -4
  8. package/dist/cjs/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.js +84 -29
  9. package/dist/cjs/vc/vc-observer-new/metric-calculator/utils/detect-layout-shift-cause.js +164 -0
  10. package/dist/cjs/vc/vc-observer-new/viewport-observer/index.js +173 -34
  11. package/dist/cjs/vc/vc-observer-new/viewport-observer/intersection-observer/index.js +1 -1
  12. package/dist/cjs/vc/vc-observer-new/viewport-observer/mutation-observer/index.js +2 -1
  13. package/dist/es2019/experience-trace-id-context/index.js +3 -3
  14. package/dist/es2019/interaction-metrics/index.js +1 -0
  15. package/dist/es2019/interaction-metrics-init/index.js +2 -1
  16. package/dist/es2019/vc/index.js +4 -2
  17. package/dist/es2019/vc/vc-observer-new/index.js +10 -5
  18. package/dist/es2019/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.js +61 -7
  19. package/dist/es2019/vc/vc-observer-new/metric-calculator/utils/detect-layout-shift-cause.js +138 -0
  20. package/dist/es2019/vc/vc-observer-new/metric-calculator/vc-next/index.js +1 -1
  21. package/dist/es2019/vc/vc-observer-new/viewport-observer/index.js +145 -10
  22. package/dist/es2019/vc/vc-observer-new/viewport-observer/intersection-observer/index.js +1 -1
  23. package/dist/es2019/vc/vc-observer-new/viewport-observer/mutation-observer/index.js +2 -1
  24. package/dist/esm/experience-trace-id-context/index.js +3 -3
  25. package/dist/esm/interaction-metrics/index.js +1 -0
  26. package/dist/esm/interaction-metrics-init/index.js +2 -1
  27. package/dist/esm/vc/index.js +4 -2
  28. package/dist/esm/vc/vc-observer-new/index.js +10 -4
  29. package/dist/esm/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.js +84 -29
  30. package/dist/esm/vc/vc-observer-new/metric-calculator/utils/detect-layout-shift-cause.js +158 -0
  31. package/dist/esm/vc/vc-observer-new/metric-calculator/vc-next/index.js +1 -1
  32. package/dist/esm/vc/vc-observer-new/viewport-observer/index.js +173 -34
  33. package/dist/esm/vc/vc-observer-new/viewport-observer/intersection-observer/index.js +1 -1
  34. package/dist/esm/vc/vc-observer-new/viewport-observer/mutation-observer/index.js +2 -1
  35. package/dist/types/common/vc/types.d.ts +55 -0
  36. package/dist/types/config/index.d.ts +1 -0
  37. package/dist/types/create-payload/utils/get-visibility-state-from-performance.d.ts +1 -1
  38. package/dist/types/vc/types.d.ts +2 -0
  39. package/dist/types/vc/vc-observer-new/index.d.ts +2 -0
  40. package/dist/types/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.d.ts +1 -1
  41. package/dist/types/vc/vc-observer-new/metric-calculator/types.d.ts +1 -0
  42. package/dist/types/vc/vc-observer-new/metric-calculator/utils/detect-layout-shift-cause.d.ts +31 -0
  43. package/dist/types/vc/vc-observer-new/metric-calculator/vc-next/index.d.ts +2 -2
  44. package/dist/types/vc/vc-observer-new/types.d.ts +2 -0
  45. package/dist/types/vc/vc-observer-new/viewport-observer/index.d.ts +3 -1
  46. package/dist/types/vc/vc-observer-new/viewport-observer/mutation-observer/index.d.ts +1 -0
  47. package/dist/types/vc/vc-observer-new/viewport-observer/types.d.ts +5 -2
  48. package/dist/types-ts4.5/common/vc/types.d.ts +55 -0
  49. package/dist/types-ts4.5/config/index.d.ts +1 -0
  50. package/dist/types-ts4.5/create-payload/utils/get-visibility-state-from-performance.d.ts +1 -1
  51. package/dist/types-ts4.5/vc/types.d.ts +2 -0
  52. package/dist/types-ts4.5/vc/vc-observer-new/index.d.ts +2 -0
  53. package/dist/types-ts4.5/vc/vc-observer-new/metric-calculator/abstract-base-vc-calculator.d.ts +1 -1
  54. package/dist/types-ts4.5/vc/vc-observer-new/metric-calculator/types.d.ts +1 -0
  55. package/dist/types-ts4.5/vc/vc-observer-new/metric-calculator/utils/detect-layout-shift-cause.d.ts +31 -0
  56. package/dist/types-ts4.5/vc/vc-observer-new/metric-calculator/vc-next/index.d.ts +2 -2
  57. package/dist/types-ts4.5/vc/vc-observer-new/types.d.ts +2 -0
  58. package/dist/types-ts4.5/vc/vc-observer-new/viewport-observer/index.d.ts +3 -1
  59. package/dist/types-ts4.5/vc/vc-observer-new/viewport-observer/mutation-observer/index.d.ts +1 -0
  60. package/dist/types-ts4.5/vc/vc-observer-new/viewport-observer/types.d.ts +5 -2
  61. package/package.json +1 -1
@@ -0,0 +1,138 @@
1
+ const calculateOffenderState = (current, matchesCurrentEntry) => {
2
+ // Once we know it's mixed across entries, we can short-circuit.
3
+ if (current === 'some') {
4
+ return 'some';
5
+ }
6
+ const entryState = matchesCurrentEntry ? 'all' : 'none';
7
+ if (current == null) {
8
+ return entryState;
9
+ }
10
+
11
+ // If the state flips between entries (all <-> none), it's "some".
12
+ if (current !== entryState) {
13
+ return 'some';
14
+ }
15
+ return current;
16
+ };
17
+ const calculateLayoutShiftMovement = layoutShiftEntries => {
18
+ const movements = layoutShiftEntries.map(lsEntry => {
19
+ const rect = lsEntry.rect;
20
+ const previousRect = lsEntry.previousRect;
21
+ if (!rect || !previousRect) {
22
+ return null;
23
+ }
24
+ const dx = rect.x - previousRect.x;
25
+ const dy = rect.y - previousRect.y;
26
+ return {
27
+ dx,
28
+ dy,
29
+ movedX: dx !== 0,
30
+ movedY: dy !== 0,
31
+ dirX: Math.sign(dx),
32
+ dirY: Math.sign(dy),
33
+ absDx: Math.abs(dx),
34
+ absDy: Math.abs(dy)
35
+ };
36
+ });
37
+ const hasMovement = m => m !== null;
38
+ const validMovements = movements.filter(hasMovement);
39
+ const allHaveRects = layoutShiftEntries.length > 0 && validMovements.length === layoutShiftEntries.length;
40
+ if (!allHaveRects) {
41
+ return {
42
+ allHaveRects,
43
+ allMovedSameWay: false,
44
+ allMovedSameAmount: false
45
+ };
46
+ }
47
+ const first = validMovements[0];
48
+ const allMovedSameWay = validMovements.every(m => m.movedX === first.movedX && m.movedY === first.movedY && m.dirX === first.dirX && m.dirY === first.dirY);
49
+ const allMovedSameAmount = allMovedSameWay && validMovements.every(m => m.absDx === first.absDx && m.absDy === first.absDy);
50
+ return {
51
+ allHaveRects,
52
+ allMovedSameWay,
53
+ allMovedSameAmount,
54
+ deltaX: first.dx,
55
+ deltaY: first.dy
56
+ };
57
+ };
58
+ export const detectLayoutShiftCause = ({
59
+ viewportEntries,
60
+ layoutShiftEntries,
61
+ time,
62
+ startTime,
63
+ offenderWindowMs = 250
64
+ }) => {
65
+ const checkpointTimestamp = startTime + time;
66
+ const filteredLSPotentialOffenders = viewportEntries.filter(viewportEntry => (viewportEntry.time < checkpointTimestamp && viewportEntry.time > checkpointTimestamp - offenderWindowMs || viewportEntry.time > checkpointTimestamp && viewportEntry.time < checkpointTimestamp + offenderWindowMs) && viewportEntry.data.type !== 'layout-shift');
67
+
68
+ // Summarize whether all layout-shift entries moved in a consistent direction and by the same amount.
69
+ const layoutShiftVariables = calculateLayoutShiftMovement(layoutShiftEntries);
70
+
71
+ // Classify each offender against *all* layout-shift entries when the layout shift is consistently moving in a
72
+ // single axis (pure X or pure Y) so we can reason about whether an offender could have caused the movement.
73
+ const layoutShiftOffenders = filteredLSPotentialOffenders.reduce((acc, offender) => {
74
+ var _offenderData$origina, _isAbove, _isLeft, _isRight, _hasHorizontalOverlap, _hasVerticalOverlap;
75
+ const offenderData = offender.data;
76
+ const offenderRect = offenderData.rect;
77
+ if (!offenderRect) {
78
+ return acc;
79
+ }
80
+ const offenderTimestamp = (_offenderData$origina = offenderData.originalMutationTimestamp) !== null && _offenderData$origina !== void 0 ? _offenderData$origina : offender.time;
81
+ const happenedBefore = offenderTimestamp <= checkpointTimestamp;
82
+ const offenderLeft = offenderRect.x;
83
+ const offenderRight = offenderRect.x + offenderRect.width;
84
+ const offenderTop = offenderRect.y;
85
+ const offenderBottom = offenderRect.y + offenderRect.height;
86
+ const shouldClassifyAgainstAllEntries = layoutShiftVariables.allMovedSameWay && 'deltaX' in layoutShiftVariables && 'deltaY' in layoutShiftVariables && layoutShiftVariables.deltaX === 0 !== (layoutShiftVariables.deltaY === 0);
87
+ let isAbove = null;
88
+ let isLeft = null;
89
+ let isRight = null;
90
+ let hasHorizontalOverlap = null;
91
+ let hasVerticalOverlap = null;
92
+ if (shouldClassifyAgainstAllEntries) {
93
+ for (const lsEntry of layoutShiftEntries) {
94
+ const lsRect = lsEntry.rect;
95
+ if (!lsRect) {
96
+ continue;
97
+ }
98
+ const lsLeft = lsRect.x;
99
+ const lsRight = lsRect.x + lsRect.width;
100
+ const lsTop = lsRect.y;
101
+ const lsBottom = lsRect.y + lsRect.height;
102
+ isAbove = calculateOffenderState(isAbove, offenderBottom <= lsTop);
103
+ isLeft = calculateOffenderState(isLeft, offenderRight <= lsLeft);
104
+ isRight = calculateOffenderState(isRight, offenderLeft >= lsRight);
105
+ hasHorizontalOverlap = calculateOffenderState(hasHorizontalOverlap, offenderLeft < lsRight && offenderRight > lsLeft);
106
+ hasVerticalOverlap = calculateOffenderState(hasVerticalOverlap, offenderTop < lsBottom && offenderBottom > lsTop);
107
+ }
108
+ }
109
+ let matchesLayoutShiftDelta = false;
110
+ if (shouldClassifyAgainstAllEntries && layoutShiftVariables.allMovedSameAmount && offenderData.previousRect) {
111
+ const dx = offenderRect.x - offenderData.previousRect.x;
112
+ const dy = offenderRect.y - offenderData.previousRect.y;
113
+ const isPureX = layoutShiftVariables.deltaX !== 0 && layoutShiftVariables.deltaY === 0;
114
+ const isPureY = layoutShiftVariables.deltaY !== 0 && layoutShiftVariables.deltaX === 0;
115
+ if (isPureX) {
116
+ matchesLayoutShiftDelta = dx === layoutShiftVariables.deltaX && dy === 0;
117
+ } else if (isPureY) {
118
+ matchesLayoutShiftDelta = dy === layoutShiftVariables.deltaY && dx === 0;
119
+ }
120
+ }
121
+ acc.push({
122
+ offender: offenderData.elementName,
123
+ happenedBefore,
124
+ distanceToLS: Math.round(offenderTimestamp - checkpointTimestamp),
125
+ isAbove: (_isAbove = isAbove) !== null && _isAbove !== void 0 ? _isAbove : 'none',
126
+ isLeft: (_isLeft = isLeft) !== null && _isLeft !== void 0 ? _isLeft : 'none',
127
+ isRight: (_isRight = isRight) !== null && _isRight !== void 0 ? _isRight : 'none',
128
+ hasHorizontalOverlap: (_hasHorizontalOverlap = hasHorizontalOverlap) !== null && _hasHorizontalOverlap !== void 0 ? _hasHorizontalOverlap : 'none',
129
+ hasVerticalOverlap: (_hasVerticalOverlap = hasVerticalOverlap) !== null && _hasVerticalOverlap !== void 0 ? _hasVerticalOverlap : 'none',
130
+ matchesLayoutShiftDelta
131
+ });
132
+ return acc;
133
+ }, []);
134
+ return {
135
+ layoutShiftVariables,
136
+ layoutShiftOffenders
137
+ };
138
+ };
@@ -1,4 +1,4 @@
1
- import VCCalculator_FY26_04 from "../fy26_04";
1
+ import VCCalculator_FY26_04 from '../fy26_04';
2
2
  const getConsideredEntryTypes = () => {
3
3
  const consideredEntryTypes = [];
4
4
  return consideredEntryTypes;
@@ -78,6 +78,130 @@ const createElementMutationsWatcher = (removedNodeRects, isWithinThirdPartySegme
78
78
  }
79
79
  return 'mutation:element';
80
80
  };
81
+ const createElementMutationsWatcherNew = (removedNodeRects, isWithinThirdPartySegment, isWithinSmartAnswersSegment, hasSameDeletedNode, timestamp, isTargetReactRoot, getSSRState, getSSRPlaceholderHandler) => ({
82
+ target,
83
+ rect
84
+ }) => {
85
+ if (getSSRState) {
86
+ const ssrState = getSSRState();
87
+ const SSRStateEnum = {
88
+ normal: 1,
89
+ waitingForFirstRender: 2,
90
+ ignoring: 3
91
+ };
92
+ if (ssrState.state === SSRStateEnum.waitingForFirstRender && timestamp > ssrState.renderStart && isTargetReactRoot) {
93
+ ssrState.state = SSRStateEnum.ignoring;
94
+ if (ssrState.renderStop === -1) {
95
+ // arbitrary 500ms DOM update window
96
+ ssrState.renderStop = timestamp + 500;
97
+ }
98
+ return {
99
+ type: 'ssr-hydration',
100
+ mutationData: {
101
+ timestamp
102
+ }
103
+ };
104
+ }
105
+ if (ssrState.state === SSRStateEnum.ignoring && timestamp > ssrState.renderStart && isTargetReactRoot) {
106
+ if (timestamp <= ssrState.renderStop) {
107
+ return {
108
+ type: 'ssr-hydration',
109
+ mutationData: {
110
+ timestamp
111
+ }
112
+ };
113
+ } else {
114
+ ssrState.state = SSRStateEnum.normal;
115
+ }
116
+ }
117
+ }
118
+ if (getSSRPlaceholderHandler) {
119
+ const ssrPlaceholderHandler = getSSRPlaceholderHandler();
120
+ if (ssrPlaceholderHandler) {
121
+ if ((ssrPlaceholderHandler.isPlaceholderV4(target) || ssrPlaceholderHandler.isPlaceholderIgnored(target)) && ssrPlaceholderHandler.checkIfExistedAndSizeMatchingV3(target)) {
122
+ return {
123
+ type: 'mutation:ssr-placeholder',
124
+ mutationData: {
125
+ timestamp
126
+ }
127
+ };
128
+ }
129
+ if ((ssrPlaceholderHandler.isPlaceholderReplacementV4(target) || ssrPlaceholderHandler.isPlaceholderIgnored(target)) && ssrPlaceholderHandler.validateReactComponentMatchToPlaceholderV4(target)) {
130
+ return {
131
+ type: 'mutation:ssr-placeholder',
132
+ mutationData: {
133
+ timestamp
134
+ }
135
+ };
136
+ }
137
+ }
138
+ }
139
+ if (hasSameDeletedNode && isInVCIgnoreIfNoLayoutShiftMarker(target)) {
140
+ return {
141
+ type: 'mutation:remount',
142
+ mutationData: {
143
+ timestamp
144
+ }
145
+ };
146
+ }
147
+ if (isContainedWithinMediaWrapper(target)) {
148
+ return {
149
+ type: 'mutation:media',
150
+ mutationData: {
151
+ timestamp
152
+ }
153
+ };
154
+ }
155
+ if (isWithinThirdPartySegment) {
156
+ return {
157
+ type: 'mutation:third-party-element',
158
+ mutationData: {
159
+ timestamp
160
+ }
161
+ };
162
+ }
163
+ if (isWithinSmartAnswersSegment) {
164
+ return {
165
+ type: 'mutation:smart-answers-element',
166
+ mutationData: {
167
+ timestamp
168
+ }
169
+ };
170
+ }
171
+ const isInIgnoreLsMarker = isInVCIgnoreIfNoLayoutShiftMarker(target);
172
+ if (!isInIgnoreLsMarker) {
173
+ return {
174
+ type: 'mutation:element',
175
+ mutationData: {
176
+ timestamp
177
+ }
178
+ };
179
+ }
180
+ const isRLLPlaceholder = RLLPlaceholderHandlers.getInstance().isRLLPlaceholderHydration(rect);
181
+ if (isRLLPlaceholder && isInIgnoreLsMarker) {
182
+ return {
183
+ type: 'mutation:rll-placeholder',
184
+ mutationData: {
185
+ timestamp
186
+ }
187
+ };
188
+ }
189
+ const wasDeleted = removedNodeRects.some(nr => isSameRectDimensions(nr, rect));
190
+ if (wasDeleted && isInIgnoreLsMarker) {
191
+ return {
192
+ type: 'mutation:element-replacement',
193
+ mutationData: {
194
+ timestamp
195
+ }
196
+ };
197
+ }
198
+ return {
199
+ type: 'mutation:element',
200
+ mutationData: {
201
+ timestamp
202
+ }
203
+ };
204
+ };
81
205
  export default class ViewportObserver {
82
206
  // SSR context functions
83
207
 
@@ -85,6 +209,7 @@ export default class ViewportObserver {
85
209
  onChange,
86
210
  getSSRState,
87
211
  getSSRPlaceholderHandler,
212
+ trackLayoutShiftOffenders = false,
88
213
  searchPageConfig
89
214
  }) {
90
215
  _defineProperty(this, "handleIntersectionEntry", ({
@@ -142,14 +267,15 @@ export default class ViewportObserver {
142
267
  } = checkWithinComponent(addedNode, 'UFOThirdPartySegment', this.mapIs3pResult);
143
268
  const isWithinSmartAnswersSegment = Boolean(this.shouldCheckSmartAnswersMutations() && isContainedWithinSmartAnswers(addedNode));
144
269
  const isTargetReactRoot = targetNode === ((_this$getSSRState = this.getSSRState) === null || _this$getSSRState === void 0 ? void 0 : (_this$getSSRState$cal = _this$getSSRState.call(this)) === null || _this$getSSRState$cal === void 0 ? void 0 : _this$getSSRState$cal.reactRootElement);
145
- (_this$intersectionObs = this.intersectionObserver) === null || _this$intersectionObs === void 0 ? void 0 : _this$intersectionObs.watchAndTag(addedNode, createElementMutationsWatcher(removedNodeRects, isWithinThirdPartySegment, isWithinSmartAnswersSegment, !!hasSameDeletedNode, timestamp, isTargetReactRoot, this.getSSRState, this.getSSRPlaceholderHandler));
270
+ (_this$intersectionObs = this.intersectionObserver) === null || _this$intersectionObs === void 0 ? void 0 : _this$intersectionObs.watchAndTag(addedNode, (this.trackLayoutShiftOffenders ? createElementMutationsWatcherNew : createElementMutationsWatcher)(removedNodeRects, isWithinThirdPartySegment, isWithinSmartAnswersSegment, !!hasSameDeletedNode, timestamp, isTargetReactRoot, this.getSSRState, this.getSSRPlaceholderHandler));
146
271
  }
147
272
  });
148
273
  _defineProperty(this, "handleAttributeMutation", ({
149
274
  target,
150
275
  attributeName,
151
276
  oldValue,
152
- newValue
277
+ newValue,
278
+ timestamp
153
279
  }) => {
154
280
  var _this$intersectionObs2;
155
281
  (_this$intersectionObs2 = this.intersectionObserver) === null || _this$intersectionObs2 === void 0 ? void 0 : _this$intersectionObs2.watchAndTag(target, ({
@@ -162,7 +288,8 @@ export default class ViewportObserver {
162
288
  mutationData: {
163
289
  attributeName,
164
290
  oldValue,
165
- newValue
291
+ newValue,
292
+ timestamp
166
293
  }
167
294
  };
168
295
  }
@@ -176,7 +303,8 @@ export default class ViewportObserver {
176
303
  mutationData: {
177
304
  attributeName,
178
305
  oldValue,
179
- newValue
306
+ newValue,
307
+ timestamp
180
308
  }
181
309
  };
182
310
  }
@@ -202,7 +330,8 @@ export default class ViewportObserver {
202
330
  mutationData: {
203
331
  attributeName,
204
332
  oldValue,
205
- newValue
333
+ newValue,
334
+ timestamp
206
335
  }
207
336
  };
208
337
  }
@@ -216,7 +345,8 @@ export default class ViewportObserver {
216
345
  mutationData: {
217
346
  attributeName,
218
347
  oldValue,
219
- newValue
348
+ newValue,
349
+ timestamp
220
350
  }
221
351
  };
222
352
  }
@@ -231,7 +361,8 @@ export default class ViewportObserver {
231
361
  mutationData: {
232
362
  attributeName,
233
363
  oldValue,
234
- newValue
364
+ newValue,
365
+ timestamp
235
366
  }
236
367
  };
237
368
  }
@@ -242,7 +373,8 @@ export default class ViewportObserver {
242
373
  mutationData: {
243
374
  attributeName,
244
375
  oldValue,
245
- newValue
376
+ newValue,
377
+ timestamp
246
378
  }
247
379
  };
248
380
  }
@@ -253,7 +385,8 @@ export default class ViewportObserver {
253
385
  mutationData: {
254
386
  attributeName,
255
387
  oldValue,
256
- newValue
388
+ newValue,
389
+ timestamp
257
390
  }
258
391
  };
259
392
  }
@@ -262,7 +395,8 @@ export default class ViewportObserver {
262
395
  mutationData: {
263
396
  attributeName,
264
397
  oldValue,
265
- newValue
398
+ newValue,
399
+ timestamp
266
400
  }
267
401
  };
268
402
  });
@@ -297,6 +431,7 @@ export default class ViewportObserver {
297
431
  this.intersectionObserver = null;
298
432
  this.mutationObserver = null;
299
433
  this.performanceObserver = null;
434
+ this.trackLayoutShiftOffenders = trackLayoutShiftOffenders;
300
435
 
301
436
  // Initialize SSR context functions
302
437
  this.getSSRState = getSSRState;
@@ -29,7 +29,7 @@ export function createIntersectionObserver({
29
29
  }
30
30
 
31
31
  // override as display-contents mutation
32
- if (tagOrCallbackResult && typeof tagOrCallbackResult !== 'string' && tagOrCallbackResult.type === 'mutation:attribute') {
32
+ if (tagOrCallbackResult && typeof tagOrCallbackResult !== 'string' && tagOrCallbackResult.type === 'mutation:attribute' && 'oldValue' in tagOrCallbackResult.mutationData) {
33
33
  const {
34
34
  attributeName,
35
35
  oldValue,
@@ -45,7 +45,8 @@ function createMutationObserver({
45
45
  target: mut.target,
46
46
  attributeName: (_mut$attributeName = mut.attributeName) !== null && _mut$attributeName !== void 0 ? _mut$attributeName : 'unknown',
47
47
  oldValue,
48
- newValue
48
+ newValue,
49
+ timestamp: mut.timestamp || performance.now()
49
50
  });
50
51
  }
51
52
  continue;
@@ -5,9 +5,9 @@ import { makeTraceHttpRequestHeaders } from './utils/make-trace-http-request-hea
5
5
  var state = {
6
6
  context: null
7
7
  };
8
- var traceIdKey = createContextKey("traceId");
9
- var spanIdKey = createContextKey("spanId");
10
- var experienceTypeKey = createContextKey("type");
8
+ var traceIdKey = createContextKey('traceId');
9
+ var spanIdKey = createContextKey('spanId');
10
+ var experienceTypeKey = createContextKey('type');
11
11
 
12
12
  // DO NOT CALL THIS FUNCTION DIRECTLY!!!!
13
13
  // It is only to be called by React UFO libraries for the automatic handling of trace context for experiences.
@@ -1147,6 +1147,7 @@ export function addNewInteraction(interactionId, ufoName, type, startTime, rate,
1147
1147
  devToolsEnabled: config.vc.devToolsEnabled,
1148
1148
  selectorConfig: config.vc.selectorConfig,
1149
1149
  ssrEnablePageLayoutPlaceholder: config.vc.ssrEnablePageLayoutPlaceholder,
1150
+ trackLayoutShiftOffenders: config.vc.trackLayoutShiftOffenders,
1150
1151
  searchPageConfig: searchPageConfig
1151
1152
  };
1152
1153
  vcObserver = newVCObserver(vcOptions);
@@ -173,7 +173,8 @@ export function init(analyticsWebClientAsync, config) {
173
173
  oldDomUpdates: config.vc.oldDomUpdates,
174
174
  devToolsEnabled: config.vc.devToolsEnabled,
175
175
  selectorConfig: config.vc.selectorConfig,
176
- ssrEnablePageLayoutPlaceholder: config.vc.ssrEnablePageLayoutPlaceholder
176
+ ssrEnablePageLayoutPlaceholder: config.vc.ssrEnablePageLayoutPlaceholder,
177
+ trackLayoutShiftOffenders: config.vc.trackLayoutShiftOffenders
177
178
  };
178
179
  postInteractionLog.initializeVCObserver(vcOptions);
179
180
  if (config !== null && config !== void 0 && (_config$experimentalI = config.experimentalInteractionMetrics) !== null && _config$experimentalI !== void 0 && _config$experimentalI.enabled) {
@@ -26,7 +26,7 @@ export var VCObserverWrapper = /*#__PURE__*/function () {
26
26
  enablePageLayoutPlaceholder: (_opts$ssrEnablePageLa = opts.ssrEnablePageLayoutPlaceholder) !== null && _opts$ssrEnablePageLa !== void 0 ? _opts$ssrEnablePageLa : false
27
27
  });
28
28
  if (isVCRevisionEnabled('fy25.03') || isVCRevisionEnabled('fy26.04')) {
29
- var _opts$ssrEnablePageLa2;
29
+ var _opts$ssrEnablePageLa2, _opts$trackLayoutShif;
30
30
  this.newVCObserver = new VCObserverNew({
31
31
  selectorConfig: opts.selectorConfig,
32
32
  isPostInteraction: opts.isPostInteraction,
@@ -34,6 +34,7 @@ export var VCObserverWrapper = /*#__PURE__*/function () {
34
34
  enablePageLayoutPlaceholder: (_opts$ssrEnablePageLa2 = opts.ssrEnablePageLayoutPlaceholder) !== null && _opts$ssrEnablePageLa2 !== void 0 ? _opts$ssrEnablePageLa2 : false
35
35
  },
36
36
  ssrPlaceholderHandler: this.ssrPlaceholderHandler,
37
+ trackLayoutShiftOffenders: (_opts$trackLayoutShif = opts.trackLayoutShiftOffenders) !== null && _opts$trackLayoutShif !== void 0 ? _opts$trackLayoutShif : false,
37
38
  searchPageConfig: opts.searchPageConfig
38
39
  });
39
40
  }
@@ -150,7 +151,8 @@ export var VCObserverWrapper = /*#__PURE__*/function () {
150
151
  interactionAbortReason: param.interactionAbortReason,
151
152
  includeRawData: includeRawData,
152
153
  includeSSRInV3: param.includeSSRInV3,
153
- rawDataStopTime: param.rawDataStopTime
154
+ rawDataStopTime: param.rawDataStopTime,
155
+ reportLayoutShiftOffenders: param.reportLayoutShiftOffenders
154
156
  });
155
157
  case 12:
156
158
  _context.t1 = _context.sent;
@@ -39,6 +39,7 @@ var VCObserverNew = /*#__PURE__*/function () {
39
39
  function VCObserverNew(config) {
40
40
  var _config$isPostInterac,
41
41
  _config$selectorConfi,
42
+ _config$trackLayoutSh,
42
43
  _this = this;
43
44
  _classCallCheck(this, VCObserverNew);
44
45
  _defineProperty(this, "viewportObserver", null);
@@ -64,6 +65,7 @@ var VCObserverNew = /*#__PURE__*/function () {
64
65
  enablePageLayoutPlaceholder: (_config$SSRConfig$ena = (_config$SSRConfig = config.SSRConfig) === null || _config$SSRConfig === void 0 ? void 0 : _config$SSRConfig.enablePageLayoutPlaceholder) !== null && _config$SSRConfig$ena !== void 0 ? _config$SSRConfig$ena : false
65
66
  });
66
67
  }
68
+ this.trackLayoutShiftOffenders = (_config$trackLayoutSh = config.trackLayoutShiftOffenders) !== null && _config$trackLayoutSh !== void 0 ? _config$trackLayoutSh : false;
67
69
  this.viewportObserver = new ViewportObserver({
68
70
  onChange: function onChange(onChangeArg) {
69
71
  var time = onChangeArg.time,
@@ -86,7 +88,8 @@ var VCObserverNew = /*#__PURE__*/function () {
86
88
  visible: visible,
87
89
  attributeName: mutationData === null || mutationData === void 0 ? void 0 : mutationData.attributeName,
88
90
  oldValue: mutationData === null || mutationData === void 0 ? void 0 : mutationData.oldValue,
89
- newValue: mutationData === null || mutationData === void 0 ? void 0 : mutationData.newValue
91
+ newValue: mutationData === null || mutationData === void 0 ? void 0 : mutationData.newValue,
92
+ originalMutationTimestamp: mutationData === null || mutationData === void 0 ? void 0 : mutationData.timestamp
90
93
  };
91
94
  if (element) {
92
95
  var labelStacks = getLabelStacks(element);
@@ -108,7 +111,8 @@ var VCObserverNew = /*#__PURE__*/function () {
108
111
  getSSRPlaceholderHandler: function getSSRPlaceholderHandler() {
109
112
  return _this.getSSRPlaceholderHandler();
110
113
  },
111
- searchPageConfig: config.searchPageConfig
114
+ searchPageConfig: config.searchPageConfig,
115
+ trackLayoutShiftOffenders: this.trackLayoutShiftOffenders
112
116
  });
113
117
  this.windowEventObserver = new WindowEventObserver({
114
118
  onEvent: function onEvent(_ref) {
@@ -308,7 +312,8 @@ var VCObserverNew = /*#__PURE__*/function () {
308
312
  excludeSmartAnswersInSearch: excludeSmartAnswersInSearch,
309
313
  includeSSRRatio: includeSSRRatio,
310
314
  isPageVisible: isPageVisible,
311
- interactionAbortReason: interactionAbortReason
315
+ interactionAbortReason: interactionAbortReason,
316
+ reportLayoutShiftOffenders: this.trackLayoutShiftOffenders
312
317
  });
313
318
  case 10:
314
319
  _context.t0 = _context.sent;
@@ -339,7 +344,8 @@ var VCObserverNew = /*#__PURE__*/function () {
339
344
  excludeSmartAnswersInSearch: excludeSmartAnswersInSearch,
340
345
  includeSSRRatio: includeSSRRatio,
341
346
  isPageVisible: isPageVisible,
342
- interactionAbortReason: interactionAbortReason
347
+ interactionAbortReason: interactionAbortReason,
348
+ reportLayoutShiftOffenders: this.trackLayoutShiftOffenders
343
349
  };
344
350
  _context.next = 22;
345
351
  return Promise.all([isVCRevisionEnabled('fy26.04') ? calculator_fy26_04.calculate(calculatorParams) : null, isVCRevisionEnabled('next') ? calculator_next.calculate(calculatorParams) : null]);