UNPKG

21.3 kBJavaScriptView Raw
1(function (global, factory) {
2 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3 typeof define === 'function' && define.amd ? define(['exports'], factory) :
4 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ResizeObserver = {}));
5})(this, (function (exports) { 'use strict';
6
7 var resizeObservers = [];
8
9 var hasActiveObservations = function () {
10 return resizeObservers.some(function (ro) { return ro.activeTargets.length > 0; });
11 };
12
13 var hasSkippedObservations = function () {
14 return resizeObservers.some(function (ro) { return ro.skippedTargets.length > 0; });
15 };
16
17 var msg = 'ResizeObserver loop completed with undelivered notifications.';
18 var deliverResizeLoopError = function () {
19 var event;
20 if (typeof ErrorEvent === 'function') {
21 event = new ErrorEvent('error', {
22 message: msg
23 });
24 }
25 else {
26 event = document.createEvent('Event');
27 event.initEvent('error', false, false);
28 event.message = msg;
29 }
30 window.dispatchEvent(event);
31 };
32
33 var ResizeObserverBoxOptions;
34 (function (ResizeObserverBoxOptions) {
35 ResizeObserverBoxOptions["BORDER_BOX"] = "border-box";
36 ResizeObserverBoxOptions["CONTENT_BOX"] = "content-box";
37 ResizeObserverBoxOptions["DEVICE_PIXEL_CONTENT_BOX"] = "device-pixel-content-box";
38 })(ResizeObserverBoxOptions || (ResizeObserverBoxOptions = {}));
39
40 var freeze = function (obj) { return Object.freeze(obj); };
41
42 var ResizeObserverSize = (function () {
43 function ResizeObserverSize(inlineSize, blockSize) {
44 this.inlineSize = inlineSize;
45 this.blockSize = blockSize;
46 freeze(this);
47 }
48 return ResizeObserverSize;
49 }());
50
51 var DOMRectReadOnly = (function () {
52 function DOMRectReadOnly(x, y, width, height) {
53 this.x = x;
54 this.y = y;
55 this.width = width;
56 this.height = height;
57 this.top = this.y;
58 this.left = this.x;
59 this.bottom = this.top + this.height;
60 this.right = this.left + this.width;
61 return freeze(this);
62 }
63 DOMRectReadOnly.prototype.toJSON = function () {
64 var _a = this, x = _a.x, y = _a.y, top = _a.top, right = _a.right, bottom = _a.bottom, left = _a.left, width = _a.width, height = _a.height;
65 return { x: x, y: y, top: top, right: right, bottom: bottom, left: left, width: width, height: height };
66 };
67 DOMRectReadOnly.fromRect = function (rectangle) {
68 return new DOMRectReadOnly(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
69 };
70 return DOMRectReadOnly;
71 }());
72
73 var isSVG = function (target) { return target instanceof SVGElement && 'getBBox' in target; };
74 var isHidden = function (target) {
75 if (isSVG(target)) {
76 var _a = target.getBBox(), width = _a.width, height = _a.height;
77 return !width && !height;
78 }
79 var _b = target, offsetWidth = _b.offsetWidth, offsetHeight = _b.offsetHeight;
80 return !(offsetWidth || offsetHeight || target.getClientRects().length);
81 };
82 var isElement = function (obj) {
83 var _a;
84 if (obj instanceof Element) {
85 return true;
86 }
87 var scope = (_a = obj === null || obj === void 0 ? void 0 : obj.ownerDocument) === null || _a === void 0 ? void 0 : _a.defaultView;
88 return !!(scope && obj instanceof scope.Element);
89 };
90 var isReplacedElement = function (target) {
91 switch (target.tagName) {
92 case 'INPUT':
93 if (target.type !== 'image') {
94 break;
95 }
96 case 'VIDEO':
97 case 'AUDIO':
98 case 'EMBED':
99 case 'OBJECT':
100 case 'CANVAS':
101 case 'IFRAME':
102 case 'IMG':
103 return true;
104 }
105 return false;
106 };
107
108 var global = typeof window !== 'undefined' ? window : {};
109
110 var cache = new WeakMap();
111 var scrollRegexp = /auto|scroll/;
112 var verticalRegexp = /^tb|vertical/;
113 var IE = (/msie|trident/i).test(global.navigator && global.navigator.userAgent);
114 var parseDimension = function (pixel) { return parseFloat(pixel || '0'); };
115 var size = function (inlineSize, blockSize, switchSizes) {
116 if (inlineSize === void 0) { inlineSize = 0; }
117 if (blockSize === void 0) { blockSize = 0; }
118 if (switchSizes === void 0) { switchSizes = false; }
119 return new ResizeObserverSize((switchSizes ? blockSize : inlineSize) || 0, (switchSizes ? inlineSize : blockSize) || 0);
120 };
121 var zeroBoxes = freeze({
122 devicePixelContentBoxSize: size(),
123 borderBoxSize: size(),
124 contentBoxSize: size(),
125 contentRect: new DOMRectReadOnly(0, 0, 0, 0)
126 });
127 var calculateBoxSizes = function (target, forceRecalculation) {
128 if (forceRecalculation === void 0) { forceRecalculation = false; }
129 if (cache.has(target) && !forceRecalculation) {
130 return cache.get(target);
131 }
132 if (isHidden(target)) {
133 cache.set(target, zeroBoxes);
134 return zeroBoxes;
135 }
136 var cs = getComputedStyle(target);
137 var svg = isSVG(target) && target.ownerSVGElement && target.getBBox();
138 var removePadding = !IE && cs.boxSizing === 'border-box';
139 var switchSizes = verticalRegexp.test(cs.writingMode || '');
140 var canScrollVertically = !svg && scrollRegexp.test(cs.overflowY || '');
141 var canScrollHorizontally = !svg && scrollRegexp.test(cs.overflowX || '');
142 var paddingTop = svg ? 0 : parseDimension(cs.paddingTop);
143 var paddingRight = svg ? 0 : parseDimension(cs.paddingRight);
144 var paddingBottom = svg ? 0 : parseDimension(cs.paddingBottom);
145 var paddingLeft = svg ? 0 : parseDimension(cs.paddingLeft);
146 var borderTop = svg ? 0 : parseDimension(cs.borderTopWidth);
147 var borderRight = svg ? 0 : parseDimension(cs.borderRightWidth);
148 var borderBottom = svg ? 0 : parseDimension(cs.borderBottomWidth);
149 var borderLeft = svg ? 0 : parseDimension(cs.borderLeftWidth);
150 var horizontalPadding = paddingLeft + paddingRight;
151 var verticalPadding = paddingTop + paddingBottom;
152 var horizontalBorderArea = borderLeft + borderRight;
153 var verticalBorderArea = borderTop + borderBottom;
154 var horizontalScrollbarThickness = !canScrollHorizontally ? 0 : target.offsetHeight - verticalBorderArea - target.clientHeight;
155 var verticalScrollbarThickness = !canScrollVertically ? 0 : target.offsetWidth - horizontalBorderArea - target.clientWidth;
156 var widthReduction = removePadding ? horizontalPadding + horizontalBorderArea : 0;
157 var heightReduction = removePadding ? verticalPadding + verticalBorderArea : 0;
158 var contentWidth = svg ? svg.width : parseDimension(cs.width) - widthReduction - verticalScrollbarThickness;
159 var contentHeight = svg ? svg.height : parseDimension(cs.height) - heightReduction - horizontalScrollbarThickness;
160 var borderBoxWidth = contentWidth + horizontalPadding + verticalScrollbarThickness + horizontalBorderArea;
161 var borderBoxHeight = contentHeight + verticalPadding + horizontalScrollbarThickness + verticalBorderArea;
162 var boxes = freeze({
163 devicePixelContentBoxSize: size(Math.round(contentWidth * devicePixelRatio), Math.round(contentHeight * devicePixelRatio), switchSizes),
164 borderBoxSize: size(borderBoxWidth, borderBoxHeight, switchSizes),
165 contentBoxSize: size(contentWidth, contentHeight, switchSizes),
166 contentRect: new DOMRectReadOnly(paddingLeft, paddingTop, contentWidth, contentHeight)
167 });
168 cache.set(target, boxes);
169 return boxes;
170 };
171 var calculateBoxSize = function (target, observedBox, forceRecalculation) {
172 var _a = calculateBoxSizes(target, forceRecalculation), borderBoxSize = _a.borderBoxSize, contentBoxSize = _a.contentBoxSize, devicePixelContentBoxSize = _a.devicePixelContentBoxSize;
173 switch (observedBox) {
174 case ResizeObserverBoxOptions.DEVICE_PIXEL_CONTENT_BOX:
175 return devicePixelContentBoxSize;
176 case ResizeObserverBoxOptions.BORDER_BOX:
177 return borderBoxSize;
178 default:
179 return contentBoxSize;
180 }
181 };
182
183 var ResizeObserverEntry = (function () {
184 function ResizeObserverEntry(target) {
185 var boxes = calculateBoxSizes(target);
186 this.target = target;
187 this.contentRect = boxes.contentRect;
188 this.borderBoxSize = freeze([boxes.borderBoxSize]);
189 this.contentBoxSize = freeze([boxes.contentBoxSize]);
190 this.devicePixelContentBoxSize = freeze([boxes.devicePixelContentBoxSize]);
191 }
192 return ResizeObserverEntry;
193 }());
194
195 var calculateDepthForNode = function (node) {
196 if (isHidden(node)) {
197 return Infinity;
198 }
199 var depth = 0;
200 var parent = node.parentNode;
201 while (parent) {
202 depth += 1;
203 parent = parent.parentNode;
204 }
205 return depth;
206 };
207
208 var broadcastActiveObservations = function () {
209 var shallowestDepth = Infinity;
210 var callbacks = [];
211 resizeObservers.forEach(function processObserver(ro) {
212 if (ro.activeTargets.length === 0) {
213 return;
214 }
215 var entries = [];
216 ro.activeTargets.forEach(function processTarget(ot) {
217 var entry = new ResizeObserverEntry(ot.target);
218 var targetDepth = calculateDepthForNode(ot.target);
219 entries.push(entry);
220 ot.lastReportedSize = calculateBoxSize(ot.target, ot.observedBox);
221 if (targetDepth < shallowestDepth) {
222 shallowestDepth = targetDepth;
223 }
224 });
225 callbacks.push(function resizeObserverCallback() {
226 ro.callback.call(ro.observer, entries, ro.observer);
227 });
228 ro.activeTargets.splice(0, ro.activeTargets.length);
229 });
230 for (var _i = 0, callbacks_1 = callbacks; _i < callbacks_1.length; _i++) {
231 var callback = callbacks_1[_i];
232 callback();
233 }
234 return shallowestDepth;
235 };
236
237 var gatherActiveObservationsAtDepth = function (depth) {
238 resizeObservers.forEach(function processObserver(ro) {
239 ro.activeTargets.splice(0, ro.activeTargets.length);
240 ro.skippedTargets.splice(0, ro.skippedTargets.length);
241 ro.observationTargets.forEach(function processTarget(ot) {
242 if (ot.isActive()) {
243 if (calculateDepthForNode(ot.target) > depth) {
244 ro.activeTargets.push(ot);
245 }
246 else {
247 ro.skippedTargets.push(ot);
248 }
249 }
250 });
251 });
252 };
253
254 var process = function () {
255 var depth = 0;
256 gatherActiveObservationsAtDepth(depth);
257 while (hasActiveObservations()) {
258 depth = broadcastActiveObservations();
259 gatherActiveObservationsAtDepth(depth);
260 }
261 if (hasSkippedObservations()) {
262 deliverResizeLoopError();
263 }
264 return depth > 0;
265 };
266
267 var trigger;
268 var callbacks = [];
269 var notify = function () { return callbacks.splice(0).forEach(function (cb) { return cb(); }); };
270 var queueMicroTask = function (callback) {
271 if (!trigger) {
272 var toggle_1 = 0;
273 var el_1 = document.createTextNode('');
274 var config = { characterData: true };
275 new MutationObserver(function () { return notify(); }).observe(el_1, config);
276 trigger = function () { el_1.textContent = "".concat(toggle_1 ? toggle_1-- : toggle_1++); };
277 }
278 callbacks.push(callback);
279 trigger();
280 };
281
282 var queueResizeObserver = function (cb) {
283 queueMicroTask(function ResizeObserver() {
284 requestAnimationFrame(cb);
285 });
286 };
287
288 var watching = 0;
289 var isWatching = function () { return !!watching; };
290 var CATCH_PERIOD = 250;
291 var observerConfig = { attributes: true, characterData: true, childList: true, subtree: true };
292 var events = [
293 'resize',
294 'load',
295 'transitionend',
296 'animationend',
297 'animationstart',
298 'animationiteration',
299 'keyup',
300 'keydown',
301 'mouseup',
302 'mousedown',
303 'mouseover',
304 'mouseout',
305 'blur',
306 'focus'
307 ];
308 var time = function (timeout) {
309 if (timeout === void 0) { timeout = 0; }
310 return Date.now() + timeout;
311 };
312 var scheduled = false;
313 var Scheduler = (function () {
314 function Scheduler() {
315 var _this = this;
316 this.stopped = true;
317 this.listener = function () { return _this.schedule(); };
318 }
319 Scheduler.prototype.run = function (timeout) {
320 var _this = this;
321 if (timeout === void 0) { timeout = CATCH_PERIOD; }
322 if (scheduled) {
323 return;
324 }
325 scheduled = true;
326 var until = time(timeout);
327 queueResizeObserver(function () {
328 var elementsHaveResized = false;
329 try {
330 elementsHaveResized = process();
331 }
332 finally {
333 scheduled = false;
334 timeout = until - time();
335 if (!isWatching()) {
336 return;
337 }
338 if (elementsHaveResized) {
339 _this.run(1000);
340 }
341 else if (timeout > 0) {
342 _this.run(timeout);
343 }
344 else {
345 _this.start();
346 }
347 }
348 });
349 };
350 Scheduler.prototype.schedule = function () {
351 this.stop();
352 this.run();
353 };
354 Scheduler.prototype.observe = function () {
355 var _this = this;
356 var cb = function () { return _this.observer && _this.observer.observe(document.body, observerConfig); };
357 document.body ? cb() : global.addEventListener('DOMContentLoaded', cb);
358 };
359 Scheduler.prototype.start = function () {
360 var _this = this;
361 if (this.stopped) {
362 this.stopped = false;
363 this.observer = new MutationObserver(this.listener);
364 this.observe();
365 events.forEach(function (name) { return global.addEventListener(name, _this.listener, true); });
366 }
367 };
368 Scheduler.prototype.stop = function () {
369 var _this = this;
370 if (!this.stopped) {
371 this.observer && this.observer.disconnect();
372 events.forEach(function (name) { return global.removeEventListener(name, _this.listener, true); });
373 this.stopped = true;
374 }
375 };
376 return Scheduler;
377 }());
378 var scheduler = new Scheduler();
379 var updateCount = function (n) {
380 !watching && n > 0 && scheduler.start();
381 watching += n;
382 !watching && scheduler.stop();
383 };
384
385 var skipNotifyOnElement = function (target) {
386 return !isSVG(target)
387 && !isReplacedElement(target)
388 && getComputedStyle(target).display === 'inline';
389 };
390 var ResizeObservation = (function () {
391 function ResizeObservation(target, observedBox) {
392 this.target = target;
393 this.observedBox = observedBox || ResizeObserverBoxOptions.CONTENT_BOX;
394 this.lastReportedSize = {
395 inlineSize: 0,
396 blockSize: 0
397 };
398 }
399 ResizeObservation.prototype.isActive = function () {
400 var size = calculateBoxSize(this.target, this.observedBox, true);
401 if (skipNotifyOnElement(this.target)) {
402 this.lastReportedSize = size;
403 }
404 if (this.lastReportedSize.inlineSize !== size.inlineSize
405 || this.lastReportedSize.blockSize !== size.blockSize) {
406 return true;
407 }
408 return false;
409 };
410 return ResizeObservation;
411 }());
412
413 var ResizeObserverDetail = (function () {
414 function ResizeObserverDetail(resizeObserver, callback) {
415 this.activeTargets = [];
416 this.skippedTargets = [];
417 this.observationTargets = [];
418 this.observer = resizeObserver;
419 this.callback = callback;
420 }
421 return ResizeObserverDetail;
422 }());
423
424 var observerMap = new WeakMap();
425 var getObservationIndex = function (observationTargets, target) {
426 for (var i = 0; i < observationTargets.length; i += 1) {
427 if (observationTargets[i].target === target) {
428 return i;
429 }
430 }
431 return -1;
432 };
433 var ResizeObserverController = (function () {
434 function ResizeObserverController() {
435 }
436 ResizeObserverController.connect = function (resizeObserver, callback) {
437 var detail = new ResizeObserverDetail(resizeObserver, callback);
438 observerMap.set(resizeObserver, detail);
439 };
440 ResizeObserverController.observe = function (resizeObserver, target, options) {
441 var detail = observerMap.get(resizeObserver);
442 var firstObservation = detail.observationTargets.length === 0;
443 if (getObservationIndex(detail.observationTargets, target) < 0) {
444 firstObservation && resizeObservers.push(detail);
445 detail.observationTargets.push(new ResizeObservation(target, options && options.box));
446 updateCount(1);
447 scheduler.schedule();
448 }
449 };
450 ResizeObserverController.unobserve = function (resizeObserver, target) {
451 var detail = observerMap.get(resizeObserver);
452 var index = getObservationIndex(detail.observationTargets, target);
453 var lastObservation = detail.observationTargets.length === 1;
454 if (index >= 0) {
455 lastObservation && resizeObservers.splice(resizeObservers.indexOf(detail), 1);
456 detail.observationTargets.splice(index, 1);
457 updateCount(-1);
458 }
459 };
460 ResizeObserverController.disconnect = function (resizeObserver) {
461 var _this = this;
462 var detail = observerMap.get(resizeObserver);
463 detail.observationTargets.slice().forEach(function (ot) { return _this.unobserve(resizeObserver, ot.target); });
464 detail.activeTargets.splice(0, detail.activeTargets.length);
465 };
466 return ResizeObserverController;
467 }());
468
469 var ResizeObserver = (function () {
470 function ResizeObserver(callback) {
471 if (arguments.length === 0) {
472 throw new TypeError("Failed to construct 'ResizeObserver': 1 argument required, but only 0 present.");
473 }
474 if (typeof callback !== 'function') {
475 throw new TypeError("Failed to construct 'ResizeObserver': The callback provided as parameter 1 is not a function.");
476 }
477 ResizeObserverController.connect(this, callback);
478 }
479 ResizeObserver.prototype.observe = function (target, options) {
480 if (arguments.length === 0) {
481 throw new TypeError("Failed to execute 'observe' on 'ResizeObserver': 1 argument required, but only 0 present.");
482 }
483 if (!isElement(target)) {
484 throw new TypeError("Failed to execute 'observe' on 'ResizeObserver': parameter 1 is not of type 'Element");
485 }
486 ResizeObserverController.observe(this, target, options);
487 };
488 ResizeObserver.prototype.unobserve = function (target) {
489 if (arguments.length === 0) {
490 throw new TypeError("Failed to execute 'unobserve' on 'ResizeObserver': 1 argument required, but only 0 present.");
491 }
492 if (!isElement(target)) {
493 throw new TypeError("Failed to execute 'unobserve' on 'ResizeObserver': parameter 1 is not of type 'Element");
494 }
495 ResizeObserverController.unobserve(this, target);
496 };
497 ResizeObserver.prototype.disconnect = function () {
498 ResizeObserverController.disconnect(this);
499 };
500 ResizeObserver.toString = function () {
501 return 'function ResizeObserver () { [polyfill code] }';
502 };
503 return ResizeObserver;
504 }());
505
506 exports.ResizeObserver = ResizeObserver;
507 exports.ResizeObserverEntry = ResizeObserverEntry;
508 exports.ResizeObserverSize = ResizeObserverSize;
509
510 Object.defineProperty(exports, '__esModule', { value: true });
511
512}));