@atlaskit/react-ufo 3.13.28 → 3.14.1

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 (55) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cjs/create-payload/index.js +3 -1
  3. package/dist/cjs/ignore-holds/index.js +62 -0
  4. package/dist/cjs/interaction-ignore/ufo-interaction-ignore.js +7 -49
  5. package/dist/cjs/interaction-metrics-init/index.js +3 -0
  6. package/dist/cjs/machine-utilisation/index.js +82 -9
  7. package/dist/cjs/segment/index.js +7 -0
  8. package/dist/cjs/segment/segment.js +3 -1
  9. package/dist/cjs/segment/third-party-segment.js +25 -0
  10. package/dist/cjs/vc/vc-observer-new/metric-calculator/fy25_03/index.js +11 -2
  11. package/dist/cjs/vc/vc-observer-new/viewport-observer/index.js +30 -6
  12. package/dist/cjs/vc/vc-observer-new/viewport-observer/utils/get-component-name-and-child-props.js +85 -0
  13. package/dist/es2019/create-payload/index.js +4 -1
  14. package/dist/es2019/ignore-holds/index.js +51 -0
  15. package/dist/es2019/interaction-ignore/ufo-interaction-ignore.js +7 -45
  16. package/dist/es2019/interaction-metrics-init/index.js +4 -1
  17. package/dist/es2019/machine-utilisation/index.js +72 -5
  18. package/dist/es2019/segment/index.js +2 -1
  19. package/dist/es2019/segment/segment.js +2 -1
  20. package/dist/es2019/segment/third-party-segment.js +18 -0
  21. package/dist/es2019/vc/vc-observer-new/metric-calculator/fy25_03/index.js +11 -2
  22. package/dist/es2019/vc/vc-observer-new/viewport-observer/index.js +32 -6
  23. package/dist/es2019/vc/vc-observer-new/viewport-observer/utils/get-component-name-and-child-props.js +71 -0
  24. package/dist/esm/create-payload/index.js +4 -2
  25. package/dist/esm/ignore-holds/index.js +53 -0
  26. package/dist/esm/interaction-ignore/ufo-interaction-ignore.js +7 -47
  27. package/dist/esm/interaction-metrics-init/index.js +4 -1
  28. package/dist/esm/machine-utilisation/index.js +76 -8
  29. package/dist/esm/segment/index.js +2 -1
  30. package/dist/esm/segment/segment.js +3 -1
  31. package/dist/esm/segment/third-party-segment.js +18 -0
  32. package/dist/esm/vc/vc-observer-new/metric-calculator/fy25_03/index.js +11 -2
  33. package/dist/esm/vc/vc-observer-new/viewport-observer/index.js +30 -6
  34. package/dist/esm/vc/vc-observer-new/viewport-observer/utils/get-component-name-and-child-props.js +76 -0
  35. package/dist/types/create-payload/index.d.ts +160 -0
  36. package/dist/types/ignore-holds/index.d.ts +31 -0
  37. package/dist/types/interaction-ignore/ufo-interaction-ignore.d.ts +6 -21
  38. package/dist/types/machine-utilisation/index.d.ts +10 -1
  39. package/dist/types/machine-utilisation/types.d.ts +6 -0
  40. package/dist/types/segment/index.d.ts +1 -0
  41. package/dist/types/segment/segment.d.ts +4 -2
  42. package/dist/types/segment/third-party-segment.d.ts +6 -0
  43. package/dist/types/vc/vc-observer-new/types.d.ts +1 -1
  44. package/dist/types/vc/vc-observer-new/viewport-observer/utils/get-component-name-and-child-props.d.ts +15 -0
  45. package/dist/types-ts4.5/create-payload/index.d.ts +160 -0
  46. package/dist/types-ts4.5/ignore-holds/index.d.ts +31 -0
  47. package/dist/types-ts4.5/interaction-ignore/ufo-interaction-ignore.d.ts +6 -21
  48. package/dist/types-ts4.5/machine-utilisation/index.d.ts +10 -1
  49. package/dist/types-ts4.5/machine-utilisation/types.d.ts +6 -0
  50. package/dist/types-ts4.5/segment/index.d.ts +1 -0
  51. package/dist/types-ts4.5/segment/segment.d.ts +4 -2
  52. package/dist/types-ts4.5/segment/third-party-segment.d.ts +6 -0
  53. package/dist/types-ts4.5/vc/vc-observer-new/types.d.ts +1 -1
  54. package/dist/types-ts4.5/vc/vc-observer-new/viewport-observer/utils/get-component-name-and-child-props.d.ts +15 -0
  55. package/package.json +10 -1
@@ -2,24 +2,35 @@ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
2
  var BUFFER_MAX_LENGTH = 1000; // ensure we don't blow up this buffer
3
3
  var pressureRecordBuffer = [];
4
4
  var pressureObserver = null;
5
+ var memoryRecordBuffer = [];
6
+ var memoryInterval;
5
7
  export function resetPressureRecordBuffer() {
6
8
  pressureRecordBuffer.length = 0;
7
9
  }
8
- export function removeOldBufferRecords(filter) {
10
+ export function resetMemoryRecordBuffer() {
11
+ memoryRecordBuffer.length = 0;
12
+ }
13
+ export function removeOldPressureBufferRecords(filter) {
9
14
  pressureRecordBuffer = pressureRecordBuffer.filter(function (_ref) {
10
15
  var time = _ref.time;
11
16
  return time > filter;
12
17
  });
13
18
  }
19
+ export function removeOldMemoryBufferRecords(filter) {
20
+ memoryRecordBuffer = memoryRecordBuffer.filter(function (_ref2) {
21
+ var time = _ref2.time;
22
+ return time > filter;
23
+ });
24
+ }
14
25
  export function createPressureStateReport(start, end) {
15
26
  try {
16
27
  // To differentiate between the API not available, vs no PressureRecords added
17
28
  if (!('PressureObserver' in globalThis)) {
18
29
  return null;
19
30
  }
20
- var pressureStateCount = pressureRecordBuffer.reduce(function (pressureReport, _ref2) {
21
- var time = _ref2.time,
22
- state = _ref2.state;
31
+ var pressureStateCount = pressureRecordBuffer.reduce(function (pressureReport, _ref3) {
32
+ var time = _ref3.time,
33
+ state = _ref3.state;
23
34
  if (time >= start && time <= end) {
24
35
  pressureReport[state] += 1;
25
36
  }
@@ -33,7 +44,7 @@ export function createPressureStateReport(start, end) {
33
44
  var pressureStateTotal = Object.values(pressureStateCount).reduce(function (total, count) {
34
45
  return total + count;
35
46
  }) || 1;
36
- removeOldBufferRecords(end);
47
+ removeOldPressureBufferRecords(end);
37
48
  return {
38
49
  count: pressureStateCount,
39
50
  percentage: {
@@ -47,24 +58,81 @@ export function createPressureStateReport(start, end) {
47
58
  return null;
48
59
  }
49
60
  }
61
+ function convertBytesToMegabytes(bytes) {
62
+ return Math.round(Math.round(bytes / (1024 * 1024) * 100) / 100);
63
+ }
64
+ export function createMemoryStateReport(start, end) {
65
+ try {
66
+ if (!('memory' in performance)) {
67
+ return null;
68
+ }
69
+ var accumulatedMemoryUsage = memoryRecordBuffer.reduce(function (acc, snapshot) {
70
+ if (snapshot.time >= start && snapshot.time <= end) {
71
+ acc.totalJSHeapSize += snapshot.totalJSHeapSize;
72
+ acc.usedJSHeapSize += snapshot.usedJSHeapSize;
73
+ acc.snapshotCount += 1;
74
+ }
75
+ return acc;
76
+ }, {
77
+ totalJSHeapSize: 0,
78
+ usedJSHeapSize: 0,
79
+ snapshotCount: 0
80
+ });
81
+ var memoryStateReport = {
82
+ jsHeapSizeLimitInMB: convertBytesToMegabytes(memoryRecordBuffer[0].jsHeapSizeLimit),
83
+ // just use the first record, since this value always remains the same over time
84
+ avgTotalJSHeapSizeInMB: convertBytesToMegabytes(accumulatedMemoryUsage.totalJSHeapSize / accumulatedMemoryUsage.snapshotCount),
85
+ avgUsedJSHeapSizeInMB: convertBytesToMegabytes(accumulatedMemoryUsage.usedJSHeapSize / accumulatedMemoryUsage.snapshotCount)
86
+ };
87
+ removeOldMemoryBufferRecords(end);
88
+ return memoryStateReport;
89
+ } catch (_unused2) {
90
+ return null;
91
+ }
92
+ }
50
93
  export function initialisePressureObserver() {
51
94
  try {
52
95
  if ('PressureObserver' in globalThis) {
53
- var _pressureObserver$obs;
54
96
  pressureObserver = new PressureObserver(function (records) {
55
97
  if (pressureRecordBuffer.length + records.length <= BUFFER_MAX_LENGTH) {
56
98
  var _pressureRecordBuffer;
57
99
  (_pressureRecordBuffer = pressureRecordBuffer).push.apply(_pressureRecordBuffer, _toConsumableArray(records));
58
100
  }
59
101
  });
60
- (_pressureObserver$obs = pressureObserver.observe('cpu', {
102
+ pressureObserver.observe('cpu', {
61
103
  sampleInterval: 100
62
- })) === null || _pressureObserver$obs === void 0 || _pressureObserver$obs.catch();
104
+ }).catch();
63
105
  }
64
106
  } catch (err) {
65
107
  /* do nothing, this is a best efforts metric */
66
108
  }
67
109
  }
110
+ export function initialiseMemoryObserver() {
111
+ try {
112
+ // only set up the interval if `performance.memory` is available in the browser
113
+ if ('memory' in performance) {
114
+ memoryInterval = setInterval(function () {
115
+ // another check of `performance.memory` availability to satisfy typescript
116
+ if ('memory' in performance) {
117
+ var memory = performance.memory;
118
+ if (memoryRecordBuffer.length <= BUFFER_MAX_LENGTH) {
119
+ memoryRecordBuffer.push({
120
+ time: performance.now(),
121
+ jsHeapSizeLimit: memory.jsHeapSizeLimit,
122
+ totalJSHeapSize: memory.totalJSHeapSize,
123
+ usedJSHeapSize: memory.usedJSHeapSize
124
+ });
125
+ }
126
+ }
127
+ }, 100);
128
+ }
129
+ } catch (_unused3) {
130
+ /* do nothing, this is a best efforts metric */
131
+ }
132
+ }
133
+ export function disconnectMemoryObserver() {
134
+ clearInterval(memoryInterval);
135
+ }
68
136
  export function disconnectPressureObserver() {
69
137
  var _pressureObserver;
70
138
  (_pressureObserver = pressureObserver) === null || _pressureObserver === void 0 || _pressureObserver.disconnect();
@@ -1,2 +1,3 @@
1
1
  import UFOSegment from './segment';
2
- export default UFOSegment;
2
+ export default UFOSegment;
3
+ export { UFOThirdPartySegment } from './third-party-segment';
@@ -30,7 +30,9 @@ export default function UFOSegment(_ref) {
30
30
  var segmentName = _ref.name,
31
31
  children = _ref.children,
32
32
  _ref$mode = _ref.mode,
33
- mode = _ref$mode === void 0 ? 'single' : _ref$mode;
33
+ mode = _ref$mode === void 0 ? 'single' : _ref$mode,
34
+ _ref$type = _ref.type,
35
+ type = _ref$type === void 0 ? 'first-party' : _ref$type;
34
36
  var parentContext = useContext(UFOInteractionContext);
35
37
  var segmentIdMap = useMemo(function () {
36
38
  if (!(parentContext !== null && parentContext !== void 0 && parentContext.segmentIdMap)) {
@@ -0,0 +1,18 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
3
+ var _excluded = ["children"];
4
+ import React from 'react';
5
+ import { fg } from '@atlaskit/platform-feature-flags';
6
+ import UFOIgnoreHolds from '../ignore-holds';
7
+ import UFOSegment from './segment';
8
+ export function UFOThirdPartySegment(props) {
9
+ var children = props.children,
10
+ otherProps = _objectWithoutProperties(props, _excluded);
11
+ return /*#__PURE__*/React.createElement(UFOSegment, _extends({
12
+ type: "third-party"
13
+ }, otherProps), /*#__PURE__*/React.createElement(UFOIgnoreHolds, {
14
+ ignore: fg('platform_ufo_exclude_3p_elements_from_ttai'),
15
+ reason: "third-party-element"
16
+ }, children));
17
+ }
18
+ UFOThirdPartySegment.displayName = 'UFOThirdPartySegment';
@@ -10,7 +10,16 @@ import AbstractVCCalculatorBase from '../abstract-base-vc-calculator';
10
10
  import isViewportEntryData from '../utils/is-viewport-entry-data';
11
11
  var ABORTING_WINDOW_EVENT = ['wheel', 'scroll', 'keydown', 'resize'];
12
12
  var REVISION_NO = 'fy25.03';
13
- var CONSIDERED_ENTRY_TYPE = ['mutation:child-element', 'mutation:element', 'mutation:attribute', 'layout-shift', 'window:event'];
13
+ var getConsideredEntryTypes = function getConsideredEntryTypes() {
14
+ var entryTypes = ['mutation:child-element', 'mutation:element', 'mutation:attribute', 'layout-shift', 'window:event'];
15
+
16
+ // If not exclude 3p elements from ttvc,
17
+ // including the tags into the ConsideredEntryTypes so that it won't be ignored for TTVC calculation
18
+ if (!fg('platform_ufo_exclude_3p_elements_from_ttvc')) {
19
+ entryTypes.push('mutation:third-party-element');
20
+ }
21
+ return entryTypes;
22
+ };
14
23
 
15
24
  // TODO: AFO-3523
16
25
  // Those are the attributes we have found when testing the 'fy25.03' manually.
@@ -28,7 +37,7 @@ var VCCalculator_FY25_03 = /*#__PURE__*/function (_AbstractVCCalculator) {
28
37
  return _createClass(VCCalculator_FY25_03, [{
29
38
  key: "isEntryIncluded",
30
39
  value: function isEntryIncluded(entry) {
31
- if (!CONSIDERED_ENTRY_TYPE.includes(entry.data.type)) {
40
+ if (!getConsideredEntryTypes().includes(entry.data.type)) {
32
41
  return false;
33
42
  }
34
43
  if (entry.data.type === 'mutation:attribute') {
@@ -10,6 +10,7 @@ import { RLLPlaceholderHandlers } from '../../vc-observer/observers/rll-placehol
10
10
  import { createIntersectionObserver } from './intersection-observer';
11
11
  import createMutationObserver from './mutation-observer';
12
12
  import createPerformanceObserver from './performance-observer';
13
+ import { checkThirdPartySegmentWithIgnoreReason, createMutationTypeWithIgnoredReason } from './utils/get-component-name-and-child-props';
13
14
  function isElementVisible(element) {
14
15
  if (!(element instanceof HTMLElement)) {
15
16
  return true;
@@ -93,7 +94,7 @@ var ViewportObserver = /*#__PURE__*/function () {
93
94
  return _this.mapVisibleNodeRects.get(n);
94
95
  });
95
96
  addedNodes.forEach(function (addedNodeRef) {
96
- var _this$intersectionObs3;
97
+ var _this$intersectionObs4;
97
98
  var addedNode = addedNodeRef.deref();
98
99
  if (!addedNode) {
99
100
  return;
@@ -115,16 +116,25 @@ var ViewportObserver = /*#__PURE__*/function () {
115
116
  (_this$intersectionObs2 = _this.intersectionObserver) === null || _this$intersectionObs2 === void 0 || _this$intersectionObs2.watchAndTag(addedNode, 'mutation:media');
116
117
  return;
117
118
  }
118
- (_this$intersectionObs3 = _this.intersectionObserver) === null || _this$intersectionObs3 === void 0 || _this$intersectionObs3.watchAndTag(addedNode, createElementMutationsWatcher(removedNodeRects));
119
+ var _checkThirdPartySegme = checkThirdPartySegmentWithIgnoreReason(addedNode),
120
+ isWithinThirdPartySegment = _checkThirdPartySegme.isWithinThirdPartySegment,
121
+ ignoredReason = _checkThirdPartySegme.ignoredReason;
122
+ if (isWithinThirdPartySegment) {
123
+ var _this$intersectionObs3;
124
+ var assignedReason = createMutationTypeWithIgnoredReason(ignoredReason || 'third-party-element');
125
+ (_this$intersectionObs3 = _this.intersectionObserver) === null || _this$intersectionObs3 === void 0 || _this$intersectionObs3.watchAndTag(addedNode, assignedReason);
126
+ return;
127
+ }
128
+ (_this$intersectionObs4 = _this.intersectionObserver) === null || _this$intersectionObs4 === void 0 || _this$intersectionObs4.watchAndTag(addedNode, createElementMutationsWatcher(removedNodeRects));
119
129
  });
120
130
  });
121
131
  _defineProperty(this, "handleAttributeMutation", function (_ref5) {
122
- var _this$intersectionObs4;
132
+ var _this$intersectionObs5;
123
133
  var target = _ref5.target,
124
134
  attributeName = _ref5.attributeName,
125
135
  oldValue = _ref5.oldValue,
126
136
  newValue = _ref5.newValue;
127
- (_this$intersectionObs4 = _this.intersectionObserver) === null || _this$intersectionObs4 === void 0 || _this$intersectionObs4.watchAndTag(target, function (_ref6) {
137
+ (_this$intersectionObs5 = _this.intersectionObserver) === null || _this$intersectionObs5 === void 0 || _this$intersectionObs5.watchAndTag(target, function (_ref6) {
128
138
  var target = _ref6.target,
129
139
  rect = _ref6.rect;
130
140
  if (isContainedWithinMediaWrapper(target)) {
@@ -162,6 +172,20 @@ var ViewportObserver = /*#__PURE__*/function () {
162
172
  }
163
173
  };
164
174
  }
175
+ var _checkThirdPartySegme2 = checkThirdPartySegmentWithIgnoreReason(target),
176
+ isWithinThirdPartySegment = _checkThirdPartySegme2.isWithinThirdPartySegment,
177
+ ignoredReason = _checkThirdPartySegme2.ignoredReason;
178
+ if (isWithinThirdPartySegment) {
179
+ var assignedReason = createMutationTypeWithIgnoredReason(ignoredReason || 'third-party-element');
180
+ return {
181
+ type: assignedReason,
182
+ mutationData: {
183
+ attributeName: attributeName,
184
+ oldValue: oldValue,
185
+ newValue: newValue
186
+ }
187
+ };
188
+ }
165
189
  var lastElementRect = _this.mapVisibleNodeRects.get(target);
166
190
  if (lastElementRect && sameRectSize(rect, lastElementRect)) {
167
191
  return {
@@ -258,12 +282,12 @@ var ViewportObserver = /*#__PURE__*/function () {
258
282
  }, {
259
283
  key: "stop",
260
284
  value: function stop() {
261
- var _this$mutationObserve2, _this$intersectionObs5, _this$performanceObse2;
285
+ var _this$mutationObserve2, _this$intersectionObs6, _this$performanceObse2;
262
286
  if (!this.isStarted) {
263
287
  return;
264
288
  }
265
289
  (_this$mutationObserve2 = this.mutationObserver) === null || _this$mutationObserve2 === void 0 || _this$mutationObserve2.disconnect();
266
- (_this$intersectionObs5 = this.intersectionObserver) === null || _this$intersectionObs5 === void 0 || _this$intersectionObs5.disconnect();
290
+ (_this$intersectionObs6 = this.intersectionObserver) === null || _this$intersectionObs6 === void 0 || _this$intersectionObs6.disconnect();
267
291
  (_this$performanceObse2 = this.performanceObserver) === null || _this$performanceObse2 === void 0 || _this$performanceObse2.disconnect();
268
292
  this.isStarted = false;
269
293
  }
@@ -0,0 +1,76 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import _typeof from "@babel/runtime/helpers/typeof";
3
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
5
+ // Using the React Fiber tree to traverse up the DOM and check if a node is within a specific component
6
+ // and extract child component props if needed.
7
+ export function checkWithinComponentAndExtractChildProps(node, targetComponentName, childComponentConfig) {
8
+ // Get the React fiber from the DOM node
9
+ var key = Object.keys(node).find(function (key) {
10
+ return key.startsWith('__reactFiber$') || key.startsWith('__reactInternalInstance$');
11
+ });
12
+ if (!key) {
13
+ return {
14
+ isWithin: false
15
+ };
16
+ }
17
+ var fiber = node[key];
18
+ if (!fiber) {
19
+ return {
20
+ isWithin: false
21
+ };
22
+ }
23
+
24
+ // Traverse up the fiber tree
25
+ var currentFiber = fiber;
26
+ var childProp;
27
+ while (currentFiber) {
28
+ var componentName = void 0;
29
+ if (currentFiber.type) {
30
+ if (typeof currentFiber.type === 'function') {
31
+ componentName = currentFiber.type.displayName || currentFiber.type.name;
32
+ } else if (_typeof(currentFiber.type) === 'object' && (currentFiber.type.displayName || currentFiber.type.name)) {
33
+ componentName = currentFiber.type.displayName || currentFiber.type.name;
34
+ }
35
+ }
36
+
37
+ // Check if this is a child component we're looking for
38
+ if (childComponentConfig && componentName === childComponentConfig.componentName) {
39
+ var props = currentFiber.memoizedProps || currentFiber.pendingProps;
40
+ if (props && props[childComponentConfig.propName] !== undefined) {
41
+ // Overwrite with the nearest child prop (closest to the target component)
42
+ childProp = childComponentConfig.extractValue ? childComponentConfig.extractValue(props) : props[childComponentConfig.propName];
43
+ }
44
+ }
45
+
46
+ // Check if we found the target component
47
+ if (componentName === targetComponentName) {
48
+ return _objectSpread({
49
+ isWithin: true
50
+ }, childComponentConfig && {
51
+ childProp: childProp
52
+ });
53
+ }
54
+ currentFiber = currentFiber.return;
55
+ }
56
+ return {
57
+ isWithin: false
58
+ };
59
+ }
60
+
61
+ // Check if the node is within a UFOThirdPartySegment and extract any UFOIgnoreHolds reason
62
+ export function checkThirdPartySegmentWithIgnoreReason(node) {
63
+ var result = checkWithinComponentAndExtractChildProps(node, 'UFOThirdPartySegment', {
64
+ componentName: 'UFOIgnoreHolds',
65
+ propName: 'reason'
66
+ });
67
+ return {
68
+ isWithinThirdPartySegment: result.isWithin,
69
+ ignoredReason: result.childProp
70
+ };
71
+ }
72
+
73
+ // Helper function to create mutation type from UFOIgnoreHoldsReason
74
+ export function createMutationTypeWithIgnoredReason(reason) {
75
+ return "mutation:".concat(reason);
76
+ }