@atlaskit/react-ufo 3.10.3 → 3.10.4
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 +8 -0
- package/dist/cjs/vc/vc-observer-new/entries-timeline/index.js +1 -3
- package/dist/cjs/vc/vc-observer-new/metric-calculator/percentile-calc/canvas-heatmap/canvas-pixel.js +25 -7
- package/dist/cjs/vc/vc-observer-new/viewport-observer/index.js +136 -115
- package/dist/es2019/vc/vc-observer-new/entries-timeline/index.js +1 -3
- package/dist/es2019/vc/vc-observer-new/metric-calculator/percentile-calc/canvas-heatmap/canvas-pixel.js +23 -7
- package/dist/es2019/vc/vc-observer-new/viewport-observer/index.js +122 -103
- package/dist/esm/vc/vc-observer-new/entries-timeline/index.js +1 -3
- package/dist/esm/vc/vc-observer-new/metric-calculator/percentile-calc/canvas-heatmap/canvas-pixel.js +25 -7
- package/dist/esm/vc/vc-observer-new/viewport-observer/index.js +136 -115
- package/dist/types/vc/vc-observer-new/metric-calculator/percentile-calc/canvas-heatmap/canvas-pixel.d.ts +8 -3
- package/dist/types/vc/vc-observer-new/viewport-observer/index.d.ts +8 -1
- package/dist/types-ts4.5/vc/vc-observer-new/metric-calculator/percentile-calc/canvas-heatmap/canvas-pixel.d.ts +8 -3
- package/dist/types-ts4.5/vc/vc-observer-new/viewport-observer/index.d.ts +8 -1
- package/package.json +4 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @atlaskit/ufo-interaction-ignore
|
|
2
2
|
|
|
3
|
+
## 3.10.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#152686](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/152686)
|
|
8
|
+
[`d4b943e998cff`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/d4b943e998cff) -
|
|
9
|
+
AFO-3823 improve VCObserverNew perf overhead
|
|
10
|
+
|
|
3
11
|
## 3.10.3
|
|
4
12
|
|
|
5
13
|
### Patch Changes
|
|
@@ -7,13 +7,11 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
7
7
|
exports.default = void 0;
|
|
8
8
|
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
|
9
9
|
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
10
|
-
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
11
10
|
var EntriesTimeline = exports.default = /*#__PURE__*/function () {
|
|
12
11
|
function EntriesTimeline() {
|
|
13
12
|
(0, _classCallCheck2.default)(this, EntriesTimeline);
|
|
14
|
-
(0, _defineProperty2.default)(this, "unorderedEntries", []);
|
|
15
|
-
(0, _defineProperty2.default)(this, "sortedEntriesCache", new Map());
|
|
16
13
|
this.unorderedEntries = [];
|
|
14
|
+
this.sortedEntriesCache = new Map();
|
|
17
15
|
}
|
|
18
16
|
return (0, _createClass2.default)(EntriesTimeline, [{
|
|
19
17
|
key: "push",
|
package/dist/cjs/vc/vc-observer-new/metric-calculator/percentile-calc/canvas-heatmap/canvas-pixel.js
CHANGED
|
@@ -11,15 +11,16 @@ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"))
|
|
|
11
11
|
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
12
12
|
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
|
13
13
|
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
14
|
+
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
14
15
|
var _taskYield = _interopRequireDefault(require("../../utils/task-yield"));
|
|
15
16
|
// 24-bit color value
|
|
16
17
|
/**
|
|
17
18
|
* Class responsible for managing a scaled canvas and tracking pixel drawing operations.
|
|
18
|
-
* It uses an OffscreenCanvas
|
|
19
|
-
* colors and timestamps for pixel counting purposes.
|
|
19
|
+
* It uses either an OffscreenCanvas (if available) or a regular HTML Canvas for better performance
|
|
20
|
+
* and maintains a mapping between colors and timestamps for pixel counting purposes.
|
|
20
21
|
*/
|
|
21
22
|
var ViewportCanvas = exports.ViewportCanvas = /*#__PURE__*/function () {
|
|
22
|
-
/** The underlying
|
|
23
|
+
/** The underlying Canvas instance (either OffscreenCanvas or HTMLCanvasElement) */
|
|
23
24
|
|
|
24
25
|
/** The 2D rendering context of the canvas */
|
|
25
26
|
|
|
@@ -50,10 +51,8 @@ var ViewportCanvas = exports.ViewportCanvas = /*#__PURE__*/function () {
|
|
|
50
51
|
this.scaleX = this.scaledWidth / safeViewportWidth;
|
|
51
52
|
this.scaleY = this.scaledHeight / safeViewportHeight;
|
|
52
53
|
|
|
53
|
-
// Initialize
|
|
54
|
-
this.canvas =
|
|
55
|
-
this.canvas.width = this.scaledWidth;
|
|
56
|
-
this.canvas.height = this.scaledHeight;
|
|
54
|
+
// Initialize canvas with scaled dimensions
|
|
55
|
+
this.canvas = this.createCanvas(this.scaledWidth, this.scaledHeight);
|
|
57
56
|
var ctx = this.canvas.getContext('2d', {
|
|
58
57
|
alpha: false,
|
|
59
58
|
// Disable alpha channel for better performance
|
|
@@ -66,9 +65,28 @@ var ViewportCanvas = exports.ViewportCanvas = /*#__PURE__*/function () {
|
|
|
66
65
|
}
|
|
67
66
|
this.ctx = ctx;
|
|
68
67
|
this.ctx.globalCompositeOperation = 'source-over';
|
|
68
|
+
if ((0, _platformFeatureFlags.fg)('platform_ufo_use_offscreen_canvas')) {
|
|
69
|
+
this.ctx.imageSmoothingEnabled = false; // Disable image smoothing for better performance
|
|
70
|
+
}
|
|
69
71
|
this.clear();
|
|
70
72
|
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Creates a canvas instance, falling back to HTMLCanvasElement if OffscreenCanvas is not available
|
|
76
|
+
* or if the feature flag is disabled
|
|
77
|
+
*/
|
|
71
78
|
return (0, _createClass2.default)(ViewportCanvas, [{
|
|
79
|
+
key: "createCanvas",
|
|
80
|
+
value: function createCanvas(width, height) {
|
|
81
|
+
if (typeof OffscreenCanvas !== 'undefined' && (0, _platformFeatureFlags.fg)('platform_ufo_use_offscreen_canvas')) {
|
|
82
|
+
return new OffscreenCanvas(width, height);
|
|
83
|
+
}
|
|
84
|
+
var canvas = document.createElement('canvas');
|
|
85
|
+
canvas.width = width;
|
|
86
|
+
canvas.height = height;
|
|
87
|
+
return canvas;
|
|
88
|
+
}
|
|
89
|
+
}, {
|
|
72
90
|
key: "getScaledDimensions",
|
|
73
91
|
value: function getScaledDimensions() {
|
|
74
92
|
return {
|
|
@@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
7
7
|
exports.default = void 0;
|
|
8
8
|
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
|
9
9
|
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
10
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
10
11
|
var _vcUtils = require("../../vc-observer/media-wrapper/vc-utils");
|
|
11
12
|
var _isNonVisualStyleMutation = _interopRequireDefault(require("../../vc-observer/observers/non-visual-styles/is-non-visual-style-mutation"));
|
|
12
13
|
var _intersectionObserver = require("./intersection-observer");
|
|
@@ -61,139 +62,154 @@ var ViewportObserver = exports.default = /*#__PURE__*/function () {
|
|
|
61
62
|
var _this = this;
|
|
62
63
|
var onChange = _ref2.onChange;
|
|
63
64
|
(0, _classCallCheck2.default)(this, ViewportObserver);
|
|
64
|
-
this
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (!target) {
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
var visible = isElementVisible(target);
|
|
76
|
-
var lastElementRect = _this.mapVisibleNodeRects.get(target);
|
|
77
|
-
_this.mapVisibleNodeRects.set(target, rect);
|
|
78
|
-
onChange({
|
|
79
|
-
time: time,
|
|
80
|
-
type: type,
|
|
81
|
-
elementRef: new WeakRef(target),
|
|
82
|
-
visible: visible,
|
|
83
|
-
rect: rect,
|
|
84
|
-
previousRect: lastElementRect,
|
|
85
|
-
mutationData: mutationData
|
|
86
|
-
});
|
|
65
|
+
(0, _defineProperty2.default)(this, "handleIntersectionEntry", function (_ref3) {
|
|
66
|
+
var target = _ref3.target,
|
|
67
|
+
rect = _ref3.rect,
|
|
68
|
+
time = _ref3.time,
|
|
69
|
+
type = _ref3.type,
|
|
70
|
+
mutationData = _ref3.mutationData;
|
|
71
|
+
if (!target) {
|
|
72
|
+
return;
|
|
87
73
|
}
|
|
74
|
+
var visible = isElementVisible(target);
|
|
75
|
+
var lastElementRect = _this.mapVisibleNodeRects.get(target);
|
|
76
|
+
_this.mapVisibleNodeRects.set(target, rect);
|
|
77
|
+
_this.onChange({
|
|
78
|
+
time: time,
|
|
79
|
+
type: type,
|
|
80
|
+
elementRef: new WeakRef(target),
|
|
81
|
+
visible: visible,
|
|
82
|
+
rect: rect,
|
|
83
|
+
previousRect: lastElementRect,
|
|
84
|
+
mutationData: mutationData
|
|
85
|
+
});
|
|
88
86
|
});
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
// for (const elem of addedNode.querySelectorAll('*')) {
|
|
100
|
-
// this.intersectionObserver?.watchAndTag(elem, 'mutation:child-element');
|
|
101
|
-
// }
|
|
102
|
-
|
|
103
|
-
var sameDeletedNode = removedNodes.find(function (n) {
|
|
104
|
-
return n.isEqualNode(addedNode);
|
|
105
|
-
});
|
|
106
|
-
if (sameDeletedNode) {
|
|
107
|
-
var _this$intersectionObs;
|
|
108
|
-
(_this$intersectionObs = _this.intersectionObserver) === null || _this$intersectionObs === void 0 || _this$intersectionObs.watchAndTag(addedNode, 'mutation:remount');
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
if ((0, _vcUtils.isContainedWithinMediaWrapper)(addedNode)) {
|
|
112
|
-
var _this$intersectionObs2;
|
|
113
|
-
(_this$intersectionObs2 = _this.intersectionObserver) === null || _this$intersectionObs2 === void 0 || _this$intersectionObs2.watchAndTag(addedNode, 'mutation:media');
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
(_this$intersectionObs3 = _this.intersectionObserver) === null || _this$intersectionObs3 === void 0 || _this$intersectionObs3.watchAndTag(addedNode, createElementMutationsWatcher(removedNodeRects));
|
|
87
|
+
(0, _defineProperty2.default)(this, "handleChildListMutation", function (_ref4) {
|
|
88
|
+
var addedNodes = _ref4.addedNodes,
|
|
89
|
+
removedNodes = _ref4.removedNodes;
|
|
90
|
+
var removedNodeRects = removedNodes.map(function (n) {
|
|
91
|
+
return _this.mapVisibleNodeRects.get(n);
|
|
92
|
+
});
|
|
93
|
+
addedNodes.forEach(function (addedNode) {
|
|
94
|
+
var _this$intersectionObs3;
|
|
95
|
+
var sameDeletedNode = removedNodes.find(function (n) {
|
|
96
|
+
return n.isEqualNode(addedNode);
|
|
117
97
|
});
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
(
|
|
124
|
-
var
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
return {
|
|
140
|
-
type: 'mutation:attribute:non-visual-style',
|
|
141
|
-
mutationData: {
|
|
142
|
-
attributeName: attributeName
|
|
143
|
-
}
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
var lastElementRect = _this.mapVisibleNodeRects.get(target);
|
|
147
|
-
if (lastElementRect && sameRectSize(rect, lastElementRect)) {
|
|
148
|
-
return {
|
|
149
|
-
type: 'mutation:attribute:no-layout-shift',
|
|
150
|
-
mutationData: {
|
|
151
|
-
attributeName: attributeName
|
|
152
|
-
}
|
|
153
|
-
};
|
|
154
|
-
}
|
|
98
|
+
if (sameDeletedNode) {
|
|
99
|
+
var _this$intersectionObs;
|
|
100
|
+
(_this$intersectionObs = _this.intersectionObserver) === null || _this$intersectionObs === void 0 || _this$intersectionObs.watchAndTag(addedNode, 'mutation:remount');
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if ((0, _vcUtils.isContainedWithinMediaWrapper)(addedNode)) {
|
|
104
|
+
var _this$intersectionObs2;
|
|
105
|
+
(_this$intersectionObs2 = _this.intersectionObserver) === null || _this$intersectionObs2 === void 0 || _this$intersectionObs2.watchAndTag(addedNode, 'mutation:media');
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
(_this$intersectionObs3 = _this.intersectionObserver) === null || _this$intersectionObs3 === void 0 || _this$intersectionObs3.watchAndTag(addedNode, createElementMutationsWatcher(removedNodeRects));
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
(0, _defineProperty2.default)(this, "handleAttributeMutation", function (_ref5) {
|
|
112
|
+
var _this$intersectionObs4;
|
|
113
|
+
var target = _ref5.target,
|
|
114
|
+
attributeName = _ref5.attributeName;
|
|
115
|
+
(_this$intersectionObs4 = _this.intersectionObserver) === null || _this$intersectionObs4 === void 0 || _this$intersectionObs4.watchAndTag(target, function (_ref6) {
|
|
116
|
+
var target = _ref6.target,
|
|
117
|
+
rect = _ref6.rect;
|
|
118
|
+
if ((0, _vcUtils.isContainedWithinMediaWrapper)(target)) {
|
|
155
119
|
return {
|
|
156
|
-
type: 'mutation:
|
|
120
|
+
type: 'mutation:media',
|
|
157
121
|
mutationData: {
|
|
158
122
|
attributeName: attributeName
|
|
159
123
|
}
|
|
160
124
|
};
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
previousRect: changedRect.previousRect,
|
|
181
|
-
type: 'layout-shift'
|
|
182
|
-
});
|
|
125
|
+
}
|
|
126
|
+
if ((0, _isNonVisualStyleMutation.default)({
|
|
127
|
+
target: target,
|
|
128
|
+
attributeName: attributeName,
|
|
129
|
+
type: 'attributes'
|
|
130
|
+
})) {
|
|
131
|
+
return {
|
|
132
|
+
type: 'mutation:attribute:non-visual-style',
|
|
133
|
+
mutationData: {
|
|
134
|
+
attributeName: attributeName
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
var lastElementRect = _this.mapVisibleNodeRects.get(target);
|
|
139
|
+
if (lastElementRect && sameRectSize(rect, lastElementRect)) {
|
|
140
|
+
return {
|
|
141
|
+
type: 'mutation:attribute:no-layout-shift',
|
|
142
|
+
mutationData: {
|
|
143
|
+
attributeName: attributeName
|
|
183
144
|
}
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
type: 'mutation:attribute',
|
|
149
|
+
mutationData: {
|
|
150
|
+
attributeName: attributeName
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
(0, _defineProperty2.default)(this, "handleLayoutShift", function (_ref7) {
|
|
156
|
+
var time = _ref7.time,
|
|
157
|
+
changedRects = _ref7.changedRects;
|
|
158
|
+
var _iterator = _createForOfIteratorHelper(changedRects),
|
|
159
|
+
_step;
|
|
160
|
+
try {
|
|
161
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
162
|
+
var changedRect = _step.value;
|
|
163
|
+
var target = changedRect.node;
|
|
164
|
+
if (target) {
|
|
165
|
+
_this.onChange({
|
|
166
|
+
time: time,
|
|
167
|
+
elementRef: new WeakRef(target),
|
|
168
|
+
visible: true,
|
|
169
|
+
rect: changedRect.rect,
|
|
170
|
+
previousRect: changedRect.previousRect,
|
|
171
|
+
type: 'layout-shift'
|
|
172
|
+
});
|
|
184
173
|
}
|
|
185
|
-
} catch (err) {
|
|
186
|
-
_iterator.e(err);
|
|
187
|
-
} finally {
|
|
188
|
-
_iterator.f();
|
|
189
174
|
}
|
|
175
|
+
} catch (err) {
|
|
176
|
+
_iterator.e(err);
|
|
177
|
+
} finally {
|
|
178
|
+
_iterator.f();
|
|
190
179
|
}
|
|
191
180
|
});
|
|
181
|
+
this.mapVisibleNodeRects = new WeakMap();
|
|
182
|
+
this.onChange = onChange;
|
|
183
|
+
this.isStarted = false;
|
|
184
|
+
this.intersectionObserver = null;
|
|
185
|
+
this.mutationObserver = null;
|
|
186
|
+
this.performanceObserver = null;
|
|
192
187
|
}
|
|
193
188
|
return (0, _createClass2.default)(ViewportObserver, [{
|
|
189
|
+
key: "initializeObservers",
|
|
190
|
+
value: function initializeObservers() {
|
|
191
|
+
if (this.isStarted) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
this.intersectionObserver = (0, _intersectionObserver.createIntersectionObserver)({
|
|
195
|
+
onEntry: this.handleIntersectionEntry
|
|
196
|
+
});
|
|
197
|
+
this.mutationObserver = (0, _mutationObserver.default)({
|
|
198
|
+
onChildListMutation: this.handleChildListMutation,
|
|
199
|
+
onAttributeMutation: this.handleAttributeMutation
|
|
200
|
+
});
|
|
201
|
+
this.performanceObserver = (0, _performanceObserver.default)({
|
|
202
|
+
onLayoutShift: this.handleLayoutShift
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}, {
|
|
194
206
|
key: "start",
|
|
195
207
|
value: function start() {
|
|
196
208
|
var _this$mutationObserve, _this$performanceObse;
|
|
209
|
+
if (this.isStarted) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
this.initializeObservers();
|
|
197
213
|
(_this$mutationObserve = this.mutationObserver) === null || _this$mutationObserve === void 0 || _this$mutationObserve.observe(document.body, {
|
|
198
214
|
attributeOldValue: true,
|
|
199
215
|
attributes: true,
|
|
@@ -206,14 +222,19 @@ var ViewportObserver = exports.default = /*#__PURE__*/function () {
|
|
|
206
222
|
// @ts-ignore-error
|
|
207
223
|
durationThreshold: 30
|
|
208
224
|
});
|
|
225
|
+
this.isStarted = true;
|
|
209
226
|
}
|
|
210
227
|
}, {
|
|
211
228
|
key: "stop",
|
|
212
229
|
value: function stop() {
|
|
213
230
|
var _this$mutationObserve2, _this$intersectionObs5, _this$performanceObse2;
|
|
231
|
+
if (!this.isStarted) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
214
234
|
(_this$mutationObserve2 = this.mutationObserver) === null || _this$mutationObserve2 === void 0 || _this$mutationObserve2.disconnect();
|
|
215
235
|
(_this$intersectionObs5 = this.intersectionObserver) === null || _this$intersectionObs5 === void 0 || _this$intersectionObs5.disconnect();
|
|
216
236
|
(_this$performanceObse2 = this.performanceObserver) === null || _this$performanceObse2 === void 0 || _this$performanceObse2.disconnect();
|
|
237
|
+
this.isStarted = false;
|
|
217
238
|
}
|
|
218
239
|
}]);
|
|
219
240
|
}();
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
1
|
export default class EntriesTimeline {
|
|
3
2
|
constructor() {
|
|
4
|
-
_defineProperty(this, "unorderedEntries", []);
|
|
5
|
-
_defineProperty(this, "sortedEntriesCache", new Map());
|
|
6
3
|
this.unorderedEntries = [];
|
|
4
|
+
this.sortedEntriesCache = new Map();
|
|
7
5
|
}
|
|
8
6
|
push(entry) {
|
|
9
7
|
this.unorderedEntries.push(entry);
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
1
2
|
import taskYield from '../../utils/task-yield';
|
|
2
3
|
|
|
3
4
|
// 24-bit color value
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Class responsible for managing a scaled canvas and tracking pixel drawing operations.
|
|
7
|
-
* It uses an OffscreenCanvas
|
|
8
|
-
* colors and timestamps for pixel counting purposes.
|
|
8
|
+
* It uses either an OffscreenCanvas (if available) or a regular HTML Canvas for better performance
|
|
9
|
+
* and maintains a mapping between colors and timestamps for pixel counting purposes.
|
|
9
10
|
*/
|
|
10
11
|
export class ViewportCanvas {
|
|
11
|
-
/** The underlying
|
|
12
|
+
/** The underlying Canvas instance (either OffscreenCanvas or HTMLCanvasElement) */
|
|
12
13
|
|
|
13
14
|
/** The 2D rendering context of the canvas */
|
|
14
15
|
|
|
@@ -37,10 +38,8 @@ export class ViewportCanvas {
|
|
|
37
38
|
this.scaleX = this.scaledWidth / safeViewportWidth;
|
|
38
39
|
this.scaleY = this.scaledHeight / safeViewportHeight;
|
|
39
40
|
|
|
40
|
-
// Initialize
|
|
41
|
-
this.canvas =
|
|
42
|
-
this.canvas.width = this.scaledWidth;
|
|
43
|
-
this.canvas.height = this.scaledHeight;
|
|
41
|
+
// Initialize canvas with scaled dimensions
|
|
42
|
+
this.canvas = this.createCanvas(this.scaledWidth, this.scaledHeight);
|
|
44
43
|
const ctx = this.canvas.getContext('2d', {
|
|
45
44
|
alpha: false,
|
|
46
45
|
// Disable alpha channel for better performance
|
|
@@ -53,8 +52,25 @@ export class ViewportCanvas {
|
|
|
53
52
|
}
|
|
54
53
|
this.ctx = ctx;
|
|
55
54
|
this.ctx.globalCompositeOperation = 'source-over';
|
|
55
|
+
if (fg('platform_ufo_use_offscreen_canvas')) {
|
|
56
|
+
this.ctx.imageSmoothingEnabled = false; // Disable image smoothing for better performance
|
|
57
|
+
}
|
|
56
58
|
this.clear();
|
|
57
59
|
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Creates a canvas instance, falling back to HTMLCanvasElement if OffscreenCanvas is not available
|
|
63
|
+
* or if the feature flag is disabled
|
|
64
|
+
*/
|
|
65
|
+
createCanvas(width, height) {
|
|
66
|
+
if (typeof OffscreenCanvas !== 'undefined' && fg('platform_ufo_use_offscreen_canvas')) {
|
|
67
|
+
return new OffscreenCanvas(width, height);
|
|
68
|
+
}
|
|
69
|
+
const canvas = document.createElement('canvas');
|
|
70
|
+
canvas.width = width;
|
|
71
|
+
canvas.height = height;
|
|
72
|
+
return canvas;
|
|
73
|
+
}
|
|
58
74
|
getScaledDimensions() {
|
|
59
75
|
return {
|
|
60
76
|
width: this.scaledWidth,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
1
2
|
import { isContainedWithinMediaWrapper } from '../../vc-observer/media-wrapper/vc-utils';
|
|
2
3
|
import isNonVisualStyleMutation from '../../vc-observer/observers/non-visual-styles/is-non-visual-style-mutation';
|
|
3
4
|
import { createIntersectionObserver } from './intersection-observer';
|
|
@@ -43,131 +44,144 @@ const createElementMutationsWatcher = removedNodeRects => ({
|
|
|
43
44
|
};
|
|
44
45
|
export default class ViewportObserver {
|
|
45
46
|
constructor({
|
|
46
|
-
onChange
|
|
47
|
+
onChange
|
|
47
48
|
}) {
|
|
48
|
-
this
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
_defineProperty(this, "handleIntersectionEntry", ({
|
|
50
|
+
target,
|
|
51
|
+
rect,
|
|
52
|
+
time,
|
|
53
|
+
type,
|
|
54
|
+
mutationData
|
|
55
|
+
}) => {
|
|
56
|
+
if (!target) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const visible = isElementVisible(target);
|
|
60
|
+
const lastElementRect = this.mapVisibleNodeRects.get(target);
|
|
61
|
+
this.mapVisibleNodeRects.set(target, rect);
|
|
62
|
+
this.onChange({
|
|
53
63
|
time,
|
|
54
64
|
type,
|
|
65
|
+
elementRef: new WeakRef(target),
|
|
66
|
+
visible,
|
|
67
|
+
rect,
|
|
68
|
+
previousRect: lastElementRect,
|
|
55
69
|
mutationData
|
|
56
|
-
})
|
|
57
|
-
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
_defineProperty(this, "handleChildListMutation", ({
|
|
73
|
+
addedNodes,
|
|
74
|
+
removedNodes
|
|
75
|
+
}) => {
|
|
76
|
+
const removedNodeRects = removedNodes.map(n => this.mapVisibleNodeRects.get(n));
|
|
77
|
+
addedNodes.forEach(addedNode => {
|
|
78
|
+
var _this$intersectionObs3;
|
|
79
|
+
const sameDeletedNode = removedNodes.find(n => n.isEqualNode(addedNode));
|
|
80
|
+
if (sameDeletedNode) {
|
|
81
|
+
var _this$intersectionObs;
|
|
82
|
+
(_this$intersectionObs = this.intersectionObserver) === null || _this$intersectionObs === void 0 ? void 0 : _this$intersectionObs.watchAndTag(addedNode, 'mutation:remount');
|
|
58
83
|
return;
|
|
59
84
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
visible,
|
|
68
|
-
rect,
|
|
69
|
-
previousRect: lastElementRect,
|
|
70
|
-
mutationData
|
|
71
|
-
});
|
|
72
|
-
}
|
|
85
|
+
if (isContainedWithinMediaWrapper(addedNode)) {
|
|
86
|
+
var _this$intersectionObs2;
|
|
87
|
+
(_this$intersectionObs2 = this.intersectionObserver) === null || _this$intersectionObs2 === void 0 ? void 0 : _this$intersectionObs2.watchAndTag(addedNode, 'mutation:media');
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
(_this$intersectionObs3 = this.intersectionObserver) === null || _this$intersectionObs3 === void 0 ? void 0 : _this$intersectionObs3.watchAndTag(addedNode, createElementMutationsWatcher(removedNodeRects));
|
|
91
|
+
});
|
|
73
92
|
});
|
|
74
|
-
this
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const removedNodeRects = (_removedNodes$map = removedNodes === null || removedNodes === void 0 ? void 0 : removedNodes.map(n => this.mapVisibleNodeRects.get(n))) !== null && _removedNodes$map !== void 0 ? _removedNodes$map : [];
|
|
81
|
-
addedNodes.forEach(addedNode => {
|
|
82
|
-
var _this$intersectionObs3;
|
|
83
|
-
// for (const elem of addedNode.querySelectorAll('*')) {
|
|
84
|
-
// this.intersectionObserver?.watchAndTag(elem, 'mutation:child-element');
|
|
85
|
-
// }
|
|
86
|
-
|
|
87
|
-
const sameDeletedNode = removedNodes.find(n => n.isEqualNode(addedNode));
|
|
88
|
-
if (sameDeletedNode) {
|
|
89
|
-
var _this$intersectionObs;
|
|
90
|
-
(_this$intersectionObs = this.intersectionObserver) === null || _this$intersectionObs === void 0 ? void 0 : _this$intersectionObs.watchAndTag(addedNode, 'mutation:remount');
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
if (isContainedWithinMediaWrapper(addedNode)) {
|
|
94
|
-
var _this$intersectionObs2;
|
|
95
|
-
(_this$intersectionObs2 = this.intersectionObserver) === null || _this$intersectionObs2 === void 0 ? void 0 : _this$intersectionObs2.watchAndTag(addedNode, 'mutation:media');
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
(_this$intersectionObs3 = this.intersectionObserver) === null || _this$intersectionObs3 === void 0 ? void 0 : _this$intersectionObs3.watchAndTag(addedNode, createElementMutationsWatcher(removedNodeRects));
|
|
99
|
-
});
|
|
100
|
-
},
|
|
101
|
-
onAttributeMutation: ({
|
|
93
|
+
_defineProperty(this, "handleAttributeMutation", ({
|
|
94
|
+
target,
|
|
95
|
+
attributeName
|
|
96
|
+
}) => {
|
|
97
|
+
var _this$intersectionObs4;
|
|
98
|
+
(_this$intersectionObs4 = this.intersectionObserver) === null || _this$intersectionObs4 === void 0 ? void 0 : _this$intersectionObs4.watchAndTag(target, ({
|
|
102
99
|
target,
|
|
103
|
-
|
|
100
|
+
rect
|
|
104
101
|
}) => {
|
|
105
|
-
|
|
106
|
-
|
|
102
|
+
if (isContainedWithinMediaWrapper(target)) {
|
|
103
|
+
return {
|
|
104
|
+
type: 'mutation:media',
|
|
105
|
+
mutationData: {
|
|
106
|
+
attributeName
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
if (isNonVisualStyleMutation({
|
|
107
111
|
target,
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
return {
|
|
112
|
-
type: 'mutation:media',
|
|
113
|
-
mutationData: {
|
|
114
|
-
attributeName
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
if (isNonVisualStyleMutation({
|
|
119
|
-
target,
|
|
120
|
-
attributeName,
|
|
121
|
-
type: 'attributes'
|
|
122
|
-
})) {
|
|
123
|
-
return {
|
|
124
|
-
type: 'mutation:attribute:non-visual-style',
|
|
125
|
-
mutationData: {
|
|
126
|
-
attributeName
|
|
127
|
-
}
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
const lastElementRect = this.mapVisibleNodeRects.get(target);
|
|
131
|
-
if (lastElementRect && sameRectSize(rect, lastElementRect)) {
|
|
132
|
-
return {
|
|
133
|
-
type: 'mutation:attribute:no-layout-shift',
|
|
134
|
-
mutationData: {
|
|
135
|
-
attributeName
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
|
-
}
|
|
112
|
+
attributeName,
|
|
113
|
+
type: 'attributes'
|
|
114
|
+
})) {
|
|
139
115
|
return {
|
|
140
|
-
type: 'mutation:attribute',
|
|
116
|
+
type: 'mutation:attribute:non-visual-style',
|
|
141
117
|
mutationData: {
|
|
142
118
|
attributeName
|
|
143
119
|
}
|
|
144
120
|
};
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
visible: true,
|
|
160
|
-
rect: changedRect.rect,
|
|
161
|
-
previousRect: changedRect.previousRect,
|
|
162
|
-
type: 'layout-shift'
|
|
163
|
-
});
|
|
121
|
+
}
|
|
122
|
+
const lastElementRect = this.mapVisibleNodeRects.get(target);
|
|
123
|
+
if (lastElementRect && sameRectSize(rect, lastElementRect)) {
|
|
124
|
+
return {
|
|
125
|
+
type: 'mutation:attribute:no-layout-shift',
|
|
126
|
+
mutationData: {
|
|
127
|
+
attributeName
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
type: 'mutation:attribute',
|
|
133
|
+
mutationData: {
|
|
134
|
+
attributeName
|
|
164
135
|
}
|
|
136
|
+
};
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
_defineProperty(this, "handleLayoutShift", ({
|
|
140
|
+
time,
|
|
141
|
+
changedRects
|
|
142
|
+
}) => {
|
|
143
|
+
for (const changedRect of changedRects) {
|
|
144
|
+
const target = changedRect.node;
|
|
145
|
+
if (target) {
|
|
146
|
+
this.onChange({
|
|
147
|
+
time,
|
|
148
|
+
elementRef: new WeakRef(target),
|
|
149
|
+
visible: true,
|
|
150
|
+
rect: changedRect.rect,
|
|
151
|
+
previousRect: changedRect.previousRect,
|
|
152
|
+
type: 'layout-shift'
|
|
153
|
+
});
|
|
165
154
|
}
|
|
166
155
|
}
|
|
167
156
|
});
|
|
157
|
+
this.mapVisibleNodeRects = new WeakMap();
|
|
158
|
+
this.onChange = onChange;
|
|
159
|
+
this.isStarted = false;
|
|
160
|
+
this.intersectionObserver = null;
|
|
161
|
+
this.mutationObserver = null;
|
|
162
|
+
this.performanceObserver = null;
|
|
163
|
+
}
|
|
164
|
+
initializeObservers() {
|
|
165
|
+
if (this.isStarted) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
this.intersectionObserver = createIntersectionObserver({
|
|
169
|
+
onEntry: this.handleIntersectionEntry
|
|
170
|
+
});
|
|
171
|
+
this.mutationObserver = createMutationObserver({
|
|
172
|
+
onChildListMutation: this.handleChildListMutation,
|
|
173
|
+
onAttributeMutation: this.handleAttributeMutation
|
|
174
|
+
});
|
|
175
|
+
this.performanceObserver = createPerformanceObserver({
|
|
176
|
+
onLayoutShift: this.handleLayoutShift
|
|
177
|
+
});
|
|
168
178
|
}
|
|
169
179
|
start() {
|
|
170
180
|
var _this$mutationObserve, _this$performanceObse;
|
|
181
|
+
if (this.isStarted) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
this.initializeObservers();
|
|
171
185
|
(_this$mutationObserve = this.mutationObserver) === null || _this$mutationObserve === void 0 ? void 0 : _this$mutationObserve.observe(document.body, {
|
|
172
186
|
attributeOldValue: true,
|
|
173
187
|
attributes: true,
|
|
@@ -180,11 +194,16 @@ export default class ViewportObserver {
|
|
|
180
194
|
// @ts-ignore-error
|
|
181
195
|
durationThreshold: 30
|
|
182
196
|
});
|
|
197
|
+
this.isStarted = true;
|
|
183
198
|
}
|
|
184
199
|
stop() {
|
|
185
200
|
var _this$mutationObserve2, _this$intersectionObs5, _this$performanceObse2;
|
|
201
|
+
if (!this.isStarted) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
186
204
|
(_this$mutationObserve2 = this.mutationObserver) === null || _this$mutationObserve2 === void 0 ? void 0 : _this$mutationObserve2.disconnect();
|
|
187
205
|
(_this$intersectionObs5 = this.intersectionObserver) === null || _this$intersectionObs5 === void 0 ? void 0 : _this$intersectionObs5.disconnect();
|
|
188
206
|
(_this$performanceObse2 = this.performanceObserver) === null || _this$performanceObse2 === void 0 ? void 0 : _this$performanceObse2.disconnect();
|
|
207
|
+
this.isStarted = false;
|
|
189
208
|
}
|
|
190
209
|
}
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
|
|
2
2
|
import _createClass from "@babel/runtime/helpers/createClass";
|
|
3
|
-
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
4
3
|
var EntriesTimeline = /*#__PURE__*/function () {
|
|
5
4
|
function EntriesTimeline() {
|
|
6
5
|
_classCallCheck(this, EntriesTimeline);
|
|
7
|
-
_defineProperty(this, "unorderedEntries", []);
|
|
8
|
-
_defineProperty(this, "sortedEntriesCache", new Map());
|
|
9
6
|
this.unorderedEntries = [];
|
|
7
|
+
this.sortedEntriesCache = new Map();
|
|
10
8
|
}
|
|
11
9
|
return _createClass(EntriesTimeline, [{
|
|
12
10
|
key: "push",
|
package/dist/esm/vc/vc-observer-new/metric-calculator/percentile-calc/canvas-heatmap/canvas-pixel.js
CHANGED
|
@@ -2,17 +2,18 @@ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
|
2
2
|
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
|
|
3
3
|
import _createClass from "@babel/runtime/helpers/createClass";
|
|
4
4
|
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
5
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
5
6
|
import taskYield from '../../utils/task-yield';
|
|
6
7
|
|
|
7
8
|
// 24-bit color value
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Class responsible for managing a scaled canvas and tracking pixel drawing operations.
|
|
11
|
-
* It uses an OffscreenCanvas
|
|
12
|
-
* colors and timestamps for pixel counting purposes.
|
|
12
|
+
* It uses either an OffscreenCanvas (if available) or a regular HTML Canvas for better performance
|
|
13
|
+
* and maintains a mapping between colors and timestamps for pixel counting purposes.
|
|
13
14
|
*/
|
|
14
15
|
export var ViewportCanvas = /*#__PURE__*/function () {
|
|
15
|
-
/** The underlying
|
|
16
|
+
/** The underlying Canvas instance (either OffscreenCanvas or HTMLCanvasElement) */
|
|
16
17
|
|
|
17
18
|
/** The 2D rendering context of the canvas */
|
|
18
19
|
|
|
@@ -43,10 +44,8 @@ export var ViewportCanvas = /*#__PURE__*/function () {
|
|
|
43
44
|
this.scaleX = this.scaledWidth / safeViewportWidth;
|
|
44
45
|
this.scaleY = this.scaledHeight / safeViewportHeight;
|
|
45
46
|
|
|
46
|
-
// Initialize
|
|
47
|
-
this.canvas =
|
|
48
|
-
this.canvas.width = this.scaledWidth;
|
|
49
|
-
this.canvas.height = this.scaledHeight;
|
|
47
|
+
// Initialize canvas with scaled dimensions
|
|
48
|
+
this.canvas = this.createCanvas(this.scaledWidth, this.scaledHeight);
|
|
50
49
|
var ctx = this.canvas.getContext('2d', {
|
|
51
50
|
alpha: false,
|
|
52
51
|
// Disable alpha channel for better performance
|
|
@@ -59,9 +58,28 @@ export var ViewportCanvas = /*#__PURE__*/function () {
|
|
|
59
58
|
}
|
|
60
59
|
this.ctx = ctx;
|
|
61
60
|
this.ctx.globalCompositeOperation = 'source-over';
|
|
61
|
+
if (fg('platform_ufo_use_offscreen_canvas')) {
|
|
62
|
+
this.ctx.imageSmoothingEnabled = false; // Disable image smoothing for better performance
|
|
63
|
+
}
|
|
62
64
|
this.clear();
|
|
63
65
|
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Creates a canvas instance, falling back to HTMLCanvasElement if OffscreenCanvas is not available
|
|
69
|
+
* or if the feature flag is disabled
|
|
70
|
+
*/
|
|
64
71
|
return _createClass(ViewportCanvas, [{
|
|
72
|
+
key: "createCanvas",
|
|
73
|
+
value: function createCanvas(width, height) {
|
|
74
|
+
if (typeof OffscreenCanvas !== 'undefined' && fg('platform_ufo_use_offscreen_canvas')) {
|
|
75
|
+
return new OffscreenCanvas(width, height);
|
|
76
|
+
}
|
|
77
|
+
var canvas = document.createElement('canvas');
|
|
78
|
+
canvas.width = width;
|
|
79
|
+
canvas.height = height;
|
|
80
|
+
return canvas;
|
|
81
|
+
}
|
|
82
|
+
}, {
|
|
65
83
|
key: "getScaledDimensions",
|
|
66
84
|
value: function getScaledDimensions() {
|
|
67
85
|
return {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
|
|
2
2
|
import _createClass from "@babel/runtime/helpers/createClass";
|
|
3
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
3
4
|
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; } } }; }
|
|
4
5
|
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; } }
|
|
5
6
|
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; }
|
|
@@ -54,139 +55,154 @@ var ViewportObserver = /*#__PURE__*/function () {
|
|
|
54
55
|
var _this = this;
|
|
55
56
|
var onChange = _ref2.onChange;
|
|
56
57
|
_classCallCheck(this, ViewportObserver);
|
|
57
|
-
this
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (!target) {
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
var visible = isElementVisible(target);
|
|
69
|
-
var lastElementRect = _this.mapVisibleNodeRects.get(target);
|
|
70
|
-
_this.mapVisibleNodeRects.set(target, rect);
|
|
71
|
-
onChange({
|
|
72
|
-
time: time,
|
|
73
|
-
type: type,
|
|
74
|
-
elementRef: new WeakRef(target),
|
|
75
|
-
visible: visible,
|
|
76
|
-
rect: rect,
|
|
77
|
-
previousRect: lastElementRect,
|
|
78
|
-
mutationData: mutationData
|
|
79
|
-
});
|
|
58
|
+
_defineProperty(this, "handleIntersectionEntry", function (_ref3) {
|
|
59
|
+
var target = _ref3.target,
|
|
60
|
+
rect = _ref3.rect,
|
|
61
|
+
time = _ref3.time,
|
|
62
|
+
type = _ref3.type,
|
|
63
|
+
mutationData = _ref3.mutationData;
|
|
64
|
+
if (!target) {
|
|
65
|
+
return;
|
|
80
66
|
}
|
|
67
|
+
var visible = isElementVisible(target);
|
|
68
|
+
var lastElementRect = _this.mapVisibleNodeRects.get(target);
|
|
69
|
+
_this.mapVisibleNodeRects.set(target, rect);
|
|
70
|
+
_this.onChange({
|
|
71
|
+
time: time,
|
|
72
|
+
type: type,
|
|
73
|
+
elementRef: new WeakRef(target),
|
|
74
|
+
visible: visible,
|
|
75
|
+
rect: rect,
|
|
76
|
+
previousRect: lastElementRect,
|
|
77
|
+
mutationData: mutationData
|
|
78
|
+
});
|
|
81
79
|
});
|
|
82
|
-
this
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
// for (const elem of addedNode.querySelectorAll('*')) {
|
|
93
|
-
// this.intersectionObserver?.watchAndTag(elem, 'mutation:child-element');
|
|
94
|
-
// }
|
|
95
|
-
|
|
96
|
-
var sameDeletedNode = removedNodes.find(function (n) {
|
|
97
|
-
return n.isEqualNode(addedNode);
|
|
98
|
-
});
|
|
99
|
-
if (sameDeletedNode) {
|
|
100
|
-
var _this$intersectionObs;
|
|
101
|
-
(_this$intersectionObs = _this.intersectionObserver) === null || _this$intersectionObs === void 0 || _this$intersectionObs.watchAndTag(addedNode, 'mutation:remount');
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
if (isContainedWithinMediaWrapper(addedNode)) {
|
|
105
|
-
var _this$intersectionObs2;
|
|
106
|
-
(_this$intersectionObs2 = _this.intersectionObserver) === null || _this$intersectionObs2 === void 0 || _this$intersectionObs2.watchAndTag(addedNode, 'mutation:media');
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
(_this$intersectionObs3 = _this.intersectionObserver) === null || _this$intersectionObs3 === void 0 || _this$intersectionObs3.watchAndTag(addedNode, createElementMutationsWatcher(removedNodeRects));
|
|
80
|
+
_defineProperty(this, "handleChildListMutation", function (_ref4) {
|
|
81
|
+
var addedNodes = _ref4.addedNodes,
|
|
82
|
+
removedNodes = _ref4.removedNodes;
|
|
83
|
+
var removedNodeRects = removedNodes.map(function (n) {
|
|
84
|
+
return _this.mapVisibleNodeRects.get(n);
|
|
85
|
+
});
|
|
86
|
+
addedNodes.forEach(function (addedNode) {
|
|
87
|
+
var _this$intersectionObs3;
|
|
88
|
+
var sameDeletedNode = removedNodes.find(function (n) {
|
|
89
|
+
return n.isEqualNode(addedNode);
|
|
110
90
|
});
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
var
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
return {
|
|
133
|
-
type: 'mutation:attribute:non-visual-style',
|
|
134
|
-
mutationData: {
|
|
135
|
-
attributeName: attributeName
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
var lastElementRect = _this.mapVisibleNodeRects.get(target);
|
|
140
|
-
if (lastElementRect && sameRectSize(rect, lastElementRect)) {
|
|
141
|
-
return {
|
|
142
|
-
type: 'mutation:attribute:no-layout-shift',
|
|
143
|
-
mutationData: {
|
|
144
|
-
attributeName: attributeName
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
}
|
|
91
|
+
if (sameDeletedNode) {
|
|
92
|
+
var _this$intersectionObs;
|
|
93
|
+
(_this$intersectionObs = _this.intersectionObserver) === null || _this$intersectionObs === void 0 || _this$intersectionObs.watchAndTag(addedNode, 'mutation:remount');
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (isContainedWithinMediaWrapper(addedNode)) {
|
|
97
|
+
var _this$intersectionObs2;
|
|
98
|
+
(_this$intersectionObs2 = _this.intersectionObserver) === null || _this$intersectionObs2 === void 0 || _this$intersectionObs2.watchAndTag(addedNode, 'mutation:media');
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
(_this$intersectionObs3 = _this.intersectionObserver) === null || _this$intersectionObs3 === void 0 || _this$intersectionObs3.watchAndTag(addedNode, createElementMutationsWatcher(removedNodeRects));
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
_defineProperty(this, "handleAttributeMutation", function (_ref5) {
|
|
105
|
+
var _this$intersectionObs4;
|
|
106
|
+
var target = _ref5.target,
|
|
107
|
+
attributeName = _ref5.attributeName;
|
|
108
|
+
(_this$intersectionObs4 = _this.intersectionObserver) === null || _this$intersectionObs4 === void 0 || _this$intersectionObs4.watchAndTag(target, function (_ref6) {
|
|
109
|
+
var target = _ref6.target,
|
|
110
|
+
rect = _ref6.rect;
|
|
111
|
+
if (isContainedWithinMediaWrapper(target)) {
|
|
148
112
|
return {
|
|
149
|
-
type: 'mutation:
|
|
113
|
+
type: 'mutation:media',
|
|
150
114
|
mutationData: {
|
|
151
115
|
attributeName: attributeName
|
|
152
116
|
}
|
|
153
117
|
};
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
previousRect: changedRect.previousRect,
|
|
174
|
-
type: 'layout-shift'
|
|
175
|
-
});
|
|
118
|
+
}
|
|
119
|
+
if (isNonVisualStyleMutation({
|
|
120
|
+
target: target,
|
|
121
|
+
attributeName: attributeName,
|
|
122
|
+
type: 'attributes'
|
|
123
|
+
})) {
|
|
124
|
+
return {
|
|
125
|
+
type: 'mutation:attribute:non-visual-style',
|
|
126
|
+
mutationData: {
|
|
127
|
+
attributeName: attributeName
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
var lastElementRect = _this.mapVisibleNodeRects.get(target);
|
|
132
|
+
if (lastElementRect && sameRectSize(rect, lastElementRect)) {
|
|
133
|
+
return {
|
|
134
|
+
type: 'mutation:attribute:no-layout-shift',
|
|
135
|
+
mutationData: {
|
|
136
|
+
attributeName: attributeName
|
|
176
137
|
}
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
type: 'mutation:attribute',
|
|
142
|
+
mutationData: {
|
|
143
|
+
attributeName: attributeName
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
_defineProperty(this, "handleLayoutShift", function (_ref7) {
|
|
149
|
+
var time = _ref7.time,
|
|
150
|
+
changedRects = _ref7.changedRects;
|
|
151
|
+
var _iterator = _createForOfIteratorHelper(changedRects),
|
|
152
|
+
_step;
|
|
153
|
+
try {
|
|
154
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
155
|
+
var changedRect = _step.value;
|
|
156
|
+
var target = changedRect.node;
|
|
157
|
+
if (target) {
|
|
158
|
+
_this.onChange({
|
|
159
|
+
time: time,
|
|
160
|
+
elementRef: new WeakRef(target),
|
|
161
|
+
visible: true,
|
|
162
|
+
rect: changedRect.rect,
|
|
163
|
+
previousRect: changedRect.previousRect,
|
|
164
|
+
type: 'layout-shift'
|
|
165
|
+
});
|
|
177
166
|
}
|
|
178
|
-
} catch (err) {
|
|
179
|
-
_iterator.e(err);
|
|
180
|
-
} finally {
|
|
181
|
-
_iterator.f();
|
|
182
167
|
}
|
|
168
|
+
} catch (err) {
|
|
169
|
+
_iterator.e(err);
|
|
170
|
+
} finally {
|
|
171
|
+
_iterator.f();
|
|
183
172
|
}
|
|
184
173
|
});
|
|
174
|
+
this.mapVisibleNodeRects = new WeakMap();
|
|
175
|
+
this.onChange = onChange;
|
|
176
|
+
this.isStarted = false;
|
|
177
|
+
this.intersectionObserver = null;
|
|
178
|
+
this.mutationObserver = null;
|
|
179
|
+
this.performanceObserver = null;
|
|
185
180
|
}
|
|
186
181
|
return _createClass(ViewportObserver, [{
|
|
182
|
+
key: "initializeObservers",
|
|
183
|
+
value: function initializeObservers() {
|
|
184
|
+
if (this.isStarted) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
this.intersectionObserver = createIntersectionObserver({
|
|
188
|
+
onEntry: this.handleIntersectionEntry
|
|
189
|
+
});
|
|
190
|
+
this.mutationObserver = createMutationObserver({
|
|
191
|
+
onChildListMutation: this.handleChildListMutation,
|
|
192
|
+
onAttributeMutation: this.handleAttributeMutation
|
|
193
|
+
});
|
|
194
|
+
this.performanceObserver = createPerformanceObserver({
|
|
195
|
+
onLayoutShift: this.handleLayoutShift
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}, {
|
|
187
199
|
key: "start",
|
|
188
200
|
value: function start() {
|
|
189
201
|
var _this$mutationObserve, _this$performanceObse;
|
|
202
|
+
if (this.isStarted) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
this.initializeObservers();
|
|
190
206
|
(_this$mutationObserve = this.mutationObserver) === null || _this$mutationObserve === void 0 || _this$mutationObserve.observe(document.body, {
|
|
191
207
|
attributeOldValue: true,
|
|
192
208
|
attributes: true,
|
|
@@ -199,14 +215,19 @@ var ViewportObserver = /*#__PURE__*/function () {
|
|
|
199
215
|
// @ts-ignore-error
|
|
200
216
|
durationThreshold: 30
|
|
201
217
|
});
|
|
218
|
+
this.isStarted = true;
|
|
202
219
|
}
|
|
203
220
|
}, {
|
|
204
221
|
key: "stop",
|
|
205
222
|
value: function stop() {
|
|
206
223
|
var _this$mutationObserve2, _this$intersectionObs5, _this$performanceObse2;
|
|
224
|
+
if (!this.isStarted) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
207
227
|
(_this$mutationObserve2 = this.mutationObserver) === null || _this$mutationObserve2 === void 0 || _this$mutationObserve2.disconnect();
|
|
208
228
|
(_this$intersectionObs5 = this.intersectionObserver) === null || _this$intersectionObs5 === void 0 || _this$intersectionObs5.disconnect();
|
|
209
229
|
(_this$performanceObse2 = this.performanceObserver) === null || _this$performanceObse2 === void 0 || _this$performanceObse2.disconnect();
|
|
230
|
+
this.isStarted = false;
|
|
210
231
|
}
|
|
211
232
|
}]);
|
|
212
233
|
}();
|
|
@@ -5,11 +5,11 @@ type Viewport = {
|
|
|
5
5
|
};
|
|
6
6
|
/**
|
|
7
7
|
* Class responsible for managing a scaled canvas and tracking pixel drawing operations.
|
|
8
|
-
* It uses an OffscreenCanvas
|
|
9
|
-
* colors and timestamps for pixel counting purposes.
|
|
8
|
+
* It uses either an OffscreenCanvas (if available) or a regular HTML Canvas for better performance
|
|
9
|
+
* and maintains a mapping between colors and timestamps for pixel counting purposes.
|
|
10
10
|
*/
|
|
11
11
|
export declare class ViewportCanvas {
|
|
12
|
-
/** The underlying
|
|
12
|
+
/** The underlying Canvas instance (either OffscreenCanvas or HTMLCanvasElement) */
|
|
13
13
|
private readonly canvas;
|
|
14
14
|
/** The 2D rendering context of the canvas */
|
|
15
15
|
private readonly ctx;
|
|
@@ -30,6 +30,11 @@ export declare class ViewportCanvas {
|
|
|
30
30
|
* @throws {Error} If canvas context cannot be obtained
|
|
31
31
|
*/
|
|
32
32
|
constructor(viewport: Viewport, scaleFactor?: number);
|
|
33
|
+
/**
|
|
34
|
+
* Creates a canvas instance, falling back to HTMLCanvasElement if OffscreenCanvas is not available
|
|
35
|
+
* or if the feature flag is disabled
|
|
36
|
+
*/
|
|
37
|
+
private createCanvas;
|
|
33
38
|
getScaledDimensions(): {
|
|
34
39
|
width: number;
|
|
35
40
|
height: number;
|
|
@@ -16,7 +16,14 @@ export default class ViewportObserver {
|
|
|
16
16
|
private mutationObserver;
|
|
17
17
|
private performanceObserver;
|
|
18
18
|
private mapVisibleNodeRects;
|
|
19
|
-
|
|
19
|
+
private onChange;
|
|
20
|
+
private isStarted;
|
|
21
|
+
constructor({ onChange }: ViewPortObserverConstructorArgs);
|
|
22
|
+
private handleIntersectionEntry;
|
|
23
|
+
private handleChildListMutation;
|
|
24
|
+
private handleAttributeMutation;
|
|
25
|
+
private handleLayoutShift;
|
|
26
|
+
private initializeObservers;
|
|
20
27
|
start(): void;
|
|
21
28
|
stop(): void;
|
|
22
29
|
}
|
|
@@ -5,11 +5,11 @@ type Viewport = {
|
|
|
5
5
|
};
|
|
6
6
|
/**
|
|
7
7
|
* Class responsible for managing a scaled canvas and tracking pixel drawing operations.
|
|
8
|
-
* It uses an OffscreenCanvas
|
|
9
|
-
* colors and timestamps for pixel counting purposes.
|
|
8
|
+
* It uses either an OffscreenCanvas (if available) or a regular HTML Canvas for better performance
|
|
9
|
+
* and maintains a mapping between colors and timestamps for pixel counting purposes.
|
|
10
10
|
*/
|
|
11
11
|
export declare class ViewportCanvas {
|
|
12
|
-
/** The underlying
|
|
12
|
+
/** The underlying Canvas instance (either OffscreenCanvas or HTMLCanvasElement) */
|
|
13
13
|
private readonly canvas;
|
|
14
14
|
/** The 2D rendering context of the canvas */
|
|
15
15
|
private readonly ctx;
|
|
@@ -30,6 +30,11 @@ export declare class ViewportCanvas {
|
|
|
30
30
|
* @throws {Error} If canvas context cannot be obtained
|
|
31
31
|
*/
|
|
32
32
|
constructor(viewport: Viewport, scaleFactor?: number);
|
|
33
|
+
/**
|
|
34
|
+
* Creates a canvas instance, falling back to HTMLCanvasElement if OffscreenCanvas is not available
|
|
35
|
+
* or if the feature flag is disabled
|
|
36
|
+
*/
|
|
37
|
+
private createCanvas;
|
|
33
38
|
getScaledDimensions(): {
|
|
34
39
|
width: number;
|
|
35
40
|
height: number;
|
|
@@ -16,7 +16,14 @@ export default class ViewportObserver {
|
|
|
16
16
|
private mutationObserver;
|
|
17
17
|
private performanceObserver;
|
|
18
18
|
private mapVisibleNodeRects;
|
|
19
|
-
|
|
19
|
+
private onChange;
|
|
20
|
+
private isStarted;
|
|
21
|
+
constructor({ onChange }: ViewPortObserverConstructorArgs);
|
|
22
|
+
private handleIntersectionEntry;
|
|
23
|
+
private handleChildListMutation;
|
|
24
|
+
private handleAttributeMutation;
|
|
25
|
+
private handleLayoutShift;
|
|
26
|
+
private initializeObservers;
|
|
20
27
|
start(): void;
|
|
21
28
|
stop(): void;
|
|
22
29
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/react-ufo",
|
|
3
|
-
"version": "3.10.
|
|
3
|
+
"version": "3.10.4",
|
|
4
4
|
"description": "Parts of React UFO that are publicly available",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -127,6 +127,9 @@
|
|
|
127
127
|
}
|
|
128
128
|
},
|
|
129
129
|
"platform-feature-flags": {
|
|
130
|
+
"platform_ufo_use_offscreen_canvas": {
|
|
131
|
+
"type": "boolean"
|
|
132
|
+
},
|
|
130
133
|
"platform_ufo_canvas_heatmap_full_precision": {
|
|
131
134
|
"type": "boolean"
|
|
132
135
|
},
|