@aehrc/smart-forms-renderer 0.41.0 → 0.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/.storybook/iframeResizerChild.js +1063 -0
  2. package/.storybook/preview.tsx +1 -0
  3. package/README.md +3 -1
  4. package/lib/components/FormComponents/RepeatGroup/RepeatGroup.js +2 -3
  5. package/lib/components/FormComponents/RepeatGroup/RepeatGroup.js.map +1 -1
  6. package/lib/components/Renderer/BaseRenderer.js +3 -4
  7. package/lib/components/Renderer/BaseRenderer.js.map +1 -1
  8. package/lib/components/Renderer/SmartFormsRenderer.js +0 -1
  9. package/lib/components/Renderer/SmartFormsRenderer.js.map +1 -1
  10. package/lib/stores/questionnaireResponseStore.js +5 -6
  11. package/lib/stores/questionnaireResponseStore.js.map +1 -1
  12. package/lib/stores/questionnaireStore.js +3 -4
  13. package/lib/stores/questionnaireStore.js.map +1 -1
  14. package/lib/utils/calculatedExpression.js +1 -2
  15. package/lib/utils/calculatedExpression.js.map +1 -1
  16. package/lib/utils/enableWhen.js +1 -2
  17. package/lib/utils/enableWhen.js.map +1 -1
  18. package/lib/utils/groupTable.js +1 -2
  19. package/lib/utils/groupTable.js.map +1 -1
  20. package/lib/utils/manageForm.js +2 -3
  21. package/lib/utils/manageForm.js.map +1 -1
  22. package/lib/utils/questionnaireStoreUtils/extractOtherExtensions.js +1 -2
  23. package/lib/utils/questionnaireStoreUtils/extractOtherExtensions.js.map +1 -1
  24. package/lib/utils/removeEmptyAnswers.js +1 -2
  25. package/lib/utils/removeEmptyAnswers.js.map +1 -1
  26. package/lib/utils/repopulateItems.js +1 -2
  27. package/lib/utils/repopulateItems.js.map +1 -1
  28. package/package.json +11 -11
  29. package/src/components/FormComponents/RepeatGroup/RepeatGroup.tsx +2 -3
  30. package/src/components/Renderer/BaseRenderer.tsx +3 -4
  31. package/src/components/Renderer/SmartFormsRenderer.tsx +0 -2
  32. package/src/stores/questionnaireResponseStore.ts +5 -6
  33. package/src/stores/questionnaireStore.ts +3 -4
  34. package/src/stories/assets/questionnaires/QChoice.ts +1 -1
  35. package/src/stories/storybookWrappers/PrePopWrapperForStorybook.tsx +7 -1
  36. package/src/utils/calculatedExpression.ts +1 -2
  37. package/src/utils/enableWhen.ts +1 -2
  38. package/src/utils/groupTable.ts +1 -2
  39. package/src/utils/manageForm.ts +2 -3
  40. package/src/utils/questionnaireStoreUtils/extractOtherExtensions.ts +1 -2
  41. package/src/utils/removeEmptyAnswers.ts +1 -2
  42. package/src/utils/repopulateItems.ts +1 -2
@@ -0,0 +1,1063 @@
1
+ /*
2
+ * Copyright 2024 Commonwealth Scientific and Industrial Research
3
+ * Organisation (CSIRO) ABN 41 687 119 230.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ *
17
+ * Modified from:
18
+ * GitHub: https://github.com/davidjbradshaw/iframe-resizer/tree/v4
19
+ * Author: David J. Bradshaw - info@iframe-resizer.com
20
+ * License: MIT
21
+ */
22
+
23
+ const SIZE_ATTR = 'data-iframe-size';
24
+ const OVERFLOW_ATTR = 'data-overflowed';
25
+
26
+ const HEIGHT_EDGE = 'bottom';
27
+ const WIDTH_EDGE = 'right';
28
+
29
+ function addEventListener(el, evt, func, options) {
30
+ el.addEventListener(evt, func, options || false);
31
+ }
32
+
33
+ function removeEventListener(el, evt, func) {
34
+ el.removeEventListener(evt, func, false);
35
+ }
36
+
37
+ export const id = (x) => x;
38
+
39
+ function overflowObserver(options) {
40
+ const side = options.side || HEIGHT_EDGE;
41
+ const onChange = options.onChange || id;
42
+
43
+ const observerOptions = {
44
+ root: options.root,
45
+ rootMargin: '0px',
46
+ threshold: 1
47
+ };
48
+
49
+ function emit() {
50
+ const overflowedNodeList = document.querySelectorAll(`[${OVERFLOW_ATTR}]`);
51
+ onChange(overflowedNodeList);
52
+ }
53
+
54
+ const emitAfterReflow = () => requestAnimationFrame(emit);
55
+
56
+ function callback(entries) {
57
+ for (const entry of entries) {
58
+ const { boundingClientRect, rootBounds, target } = entry;
59
+ const edge = boundingClientRect[side];
60
+ const hasOverflow = edge === 0 || edge > rootBounds[side];
61
+ target.toggleAttribute(OVERFLOW_ATTR, hasOverflow);
62
+ }
63
+
64
+ emitAfterReflow();
65
+ }
66
+
67
+ const observer = new IntersectionObserver(callback, observerOptions);
68
+ const observed = new WeakSet();
69
+
70
+ return function (nodeList) {
71
+ for (const node of nodeList) {
72
+ if (node.nodeType !== Node.ELEMENT_NODE || observed.has(node)) continue;
73
+
74
+ observer.observe(node);
75
+ observed.add(node);
76
+ }
77
+ };
78
+ }
79
+
80
+ function iframeResizerChild() {
81
+ const checkVisibilityOptions = {
82
+ contentVisibilityAuto: true,
83
+ opacityProperty: true,
84
+ visibilityProperty: true
85
+ };
86
+ const customCalcMethods = {
87
+ height: () => {
88
+ return getHeight.auto();
89
+ },
90
+ width: () => {
91
+ return getWidth.auto();
92
+ }
93
+ };
94
+ const eventCancelTimer = 128;
95
+ const eventHandlersByName = {};
96
+ const hasCheckVisibility = 'checkVisibility' in window;
97
+ const msgID = '[iFrameSizer]'; // Must match host page msg ID
98
+ const msgIdLen = msgID.length;
99
+ const resetRequiredMethods = {
100
+ max: 1,
101
+ min: 1,
102
+ bodyScroll: 1,
103
+ documentElementScroll: 1
104
+ };
105
+ const widthCalcModeDefault = 'scroll';
106
+
107
+ let autoResize = true;
108
+ let bodyBackground = '';
109
+ let bodyMargin = 0;
110
+ let bodyMarginStr = '';
111
+ let bodyPadding = '';
112
+ let calculateHeight = true;
113
+ let calculateWidth = false;
114
+ let firstRun = true;
115
+ let hasOverflow = false;
116
+ let hasTags = false;
117
+ let height = 1;
118
+ let heightCalcModeDefault = 'auto';
119
+ let heightCalcMode = heightCalcModeDefault;
120
+ let initLock = true;
121
+ let initMsg = '';
122
+ let inPageLinks = {};
123
+ let mouseEvents = false;
124
+ let myID = '';
125
+ let offsetHeight;
126
+ let offsetWidth;
127
+ let observeOverflow = id;
128
+ let overflowedNodeList = [];
129
+ let resizeFrom = 'child';
130
+ let resizeObserver = null;
131
+ let taggedElements = [];
132
+ let target = window.parent;
133
+ let targetOriginDefault = '*';
134
+ let timerActive;
135
+ let tolerance = 0;
136
+ let triggerLocked = false;
137
+ let width = 1;
138
+ let widthCalcMode = widthCalcModeDefault;
139
+ let win = window;
140
+
141
+ let onReady = () => {};
142
+ let onPageInfo = null;
143
+ let onParentInfo = null;
144
+
145
+ function init() {
146
+ readDataFromParent();
147
+ readDataFromPage();
148
+
149
+ checkHeightMode();
150
+ checkWidthMode();
151
+ checkDeprecatedAttrs();
152
+
153
+ checkAndSetupTags();
154
+
155
+ setupObserveOverflow();
156
+ setupPublicMethods();
157
+ setupMouseEvents();
158
+ inPageLinks = setupInPageLinks();
159
+
160
+ addOverflowObservers(getAllElements(document)());
161
+
162
+ setMargin();
163
+ setBodyStyle('background', bodyBackground);
164
+ setBodyStyle('padding', bodyPadding);
165
+
166
+ injectClearFixIntoBodyElement();
167
+ stopInfiniteResizingOfIframe();
168
+
169
+ sendSize('init', 'Init message from host page', undefined, undefined, undefined);
170
+
171
+ initEventListeners();
172
+ setTimeout(onReady);
173
+ }
174
+
175
+ function onOverflowChange(nodeList) {
176
+ overflowedNodeList = nodeList;
177
+ hasOverflow = overflowedNodeList.length > 0;
178
+
179
+ sendSize('overflowChanged', 'Overflow updated');
180
+ }
181
+
182
+ function setupObserveOverflow() {
183
+ if (calculateHeight === calculateWidth) {
184
+ return;
185
+ }
186
+
187
+ observeOverflow = overflowObserver({
188
+ onChange: onOverflowChange,
189
+ root: document.documentElement,
190
+ side: calculateHeight ? HEIGHT_EDGE : WIDTH_EDGE
191
+ });
192
+ }
193
+
194
+ function checkAndSetupTags() {
195
+ taggedElements = document.querySelectorAll(`[${SIZE_ATTR}]`);
196
+ hasTags = taggedElements.length > 0;
197
+ }
198
+
199
+ function addOverflowObservers(nodeList) {
200
+ if (!hasTags) {
201
+ observeOverflow(nodeList);
202
+ }
203
+ }
204
+
205
+ function readDataFromParent() {
206
+ const strBool = (str) => str === 'true';
207
+ const data = initMsg.slice(msgIdLen).split(':');
208
+
209
+ myID = data[0];
210
+ bodyMargin = undefined === data[1] ? bodyMargin : Number(data[1]); // For V1 compatibility
211
+ calculateWidth = undefined === data[2] ? calculateWidth : strBool(data[2]);
212
+ autoResize = undefined === data[3] ? autoResize : strBool(data[3]);
213
+ bodyMarginStr = data[4];
214
+ heightCalcMode = undefined === data[5] ? heightCalcMode : data[5];
215
+ bodyBackground = data[6];
216
+ bodyPadding = data[7];
217
+ tolerance = undefined === data[8] ? tolerance : Number(data[8]);
218
+ inPageLinks.enable = undefined === data[9] ? false : strBool(data[9]);
219
+ resizeFrom = undefined === data[10] ? resizeFrom : data[10];
220
+ widthCalcMode = undefined === data[11] ? widthCalcMode : data[11];
221
+ mouseEvents = undefined === data[12] ? mouseEvents : strBool(data[12]);
222
+ }
223
+
224
+ function readDataFromPage() {
225
+ function readData(data) {
226
+ if (typeof data?.offset === 'number') {
227
+ if (calculateHeight) offsetHeight = data?.offset;
228
+ if (calculateWidth) offsetWidth = data?.offset;
229
+ }
230
+
231
+ if (typeof data?.offsetSize === 'number') {
232
+ if (calculateHeight) offsetHeight = data?.offsetSize;
233
+ if (calculateWidth) offsetWidth = data?.offsetSize;
234
+ }
235
+
236
+ targetOriginDefault = data?.targetOrigin || targetOriginDefault;
237
+ heightCalcMode = data?.heightCalculationMethod || heightCalcMode;
238
+ widthCalcMode = data?.widthCalculationMethod || widthCalcMode;
239
+ }
240
+
241
+ function setupCustomCalcMethods(calcMode, calcFunc) {
242
+ if (typeof calcMode === 'function') {
243
+ customCalcMethods[calcFunc] = calcMode;
244
+ calcMode = 'custom';
245
+ }
246
+
247
+ return calcMode;
248
+ }
249
+
250
+ const data = window.iframeResizer || window.iFrameResizer;
251
+
252
+ if (typeof data !== 'object') {
253
+ return;
254
+ }
255
+
256
+ readData(data);
257
+ heightCalcMode = setupCustomCalcMethods(heightCalcMode, 'height');
258
+ widthCalcMode = setupCustomCalcMethods(widthCalcMode, 'width');
259
+ }
260
+
261
+ function chkCSS(attr, value) {
262
+ if (value.includes('-')) {
263
+ value = '';
264
+ }
265
+
266
+ return value;
267
+ }
268
+
269
+ function setBodyStyle(attr, value) {
270
+ if (undefined !== value && value !== '' && value !== 'null') {
271
+ document.body.style.setProperty(attr, value);
272
+ }
273
+ }
274
+
275
+ function setMargin() {
276
+ // If called via V1 script, convert bodyMargin from int to str
277
+ if (undefined === bodyMarginStr) {
278
+ bodyMarginStr = `${bodyMargin}px`;
279
+ }
280
+
281
+ setBodyStyle('margin', chkCSS('margin', bodyMarginStr));
282
+ }
283
+
284
+ function stopInfiniteResizingOfIframe() {
285
+ const setAutoHeight = (el) =>
286
+ el.style.setProperty('height', heightCalcModeDefault, 'important');
287
+
288
+ setAutoHeight(document.documentElement);
289
+ setAutoHeight(document.body);
290
+ }
291
+
292
+ function manageTriggerEvent(options) {
293
+ const listener = {
294
+ add(eventName) {
295
+ function handleEvent() {
296
+ sendSize(options.eventName, options.eventType);
297
+ }
298
+
299
+ eventHandlersByName[eventName] = handleEvent;
300
+
301
+ addEventListener(window, eventName, handleEvent, { passive: true });
302
+ },
303
+ remove(eventName) {
304
+ const handleEvent = eventHandlersByName[eventName];
305
+ delete eventHandlersByName[eventName];
306
+
307
+ removeEventListener(window, eventName, handleEvent);
308
+ }
309
+ };
310
+
311
+ listener[options.method](options.eventName);
312
+ }
313
+
314
+ function manageEventListeners(method) {
315
+ manageTriggerEvent({
316
+ method,
317
+ eventType: 'After Print',
318
+ eventName: 'afterprint'
319
+ });
320
+
321
+ manageTriggerEvent({
322
+ method,
323
+ eventType: 'Before Print',
324
+ eventName: 'beforeprint'
325
+ });
326
+
327
+ manageTriggerEvent({
328
+ method,
329
+ eventType: 'Ready State Change',
330
+ eventName: 'readystatechange'
331
+ });
332
+ }
333
+
334
+ function checkDeprecatedAttrs() {
335
+ let found = false;
336
+
337
+ const checkAttrs = (attr) =>
338
+ document.querySelectorAll(`[${attr}]`).forEach((el) => {
339
+ found = true;
340
+ el.removeAttribute(attr);
341
+ el.toggleAttribute(SIZE_ATTR, true);
342
+ });
343
+
344
+ checkAttrs('data-iframe-height');
345
+ checkAttrs('data-iframe-width');
346
+ }
347
+
348
+ function checkCalcMode(calcMode, calcModeDefault, modes) {
349
+ if (calcModeDefault !== calcMode) {
350
+ if (!(calcMode in modes)) {
351
+ calcMode = calcModeDefault;
352
+ }
353
+ }
354
+
355
+ return calcMode;
356
+ }
357
+
358
+ function checkHeightMode() {
359
+ heightCalcMode = checkCalcMode(heightCalcMode, heightCalcModeDefault, getHeight);
360
+ }
361
+
362
+ function checkWidthMode() {
363
+ widthCalcMode = checkCalcMode(widthCalcMode, widthCalcModeDefault, getWidth);
364
+ }
365
+
366
+ function initEventListeners() {
367
+ manageEventListeners('add');
368
+ setupMutationObserver();
369
+ setupResizeObservers();
370
+ }
371
+
372
+ function injectClearFixIntoBodyElement() {
373
+ const clearFix = document.createElement('div');
374
+
375
+ clearFix.style.clear = 'both';
376
+ // Guard against the following having been globally redefined in CSS.
377
+ clearFix.style.display = 'block';
378
+ clearFix.style.height = '0';
379
+ document.body.append(clearFix);
380
+ }
381
+
382
+ function setupInPageLinks() {
383
+ function getPagePosition() {
384
+ return {
385
+ x: document.documentElement.scrollLeft,
386
+ y: document.documentElement.scrollTop
387
+ };
388
+ }
389
+
390
+ function getElementPosition(el) {
391
+ const elPosition = el.getBoundingClientRect();
392
+ const { x, y } = getPagePosition();
393
+
394
+ return {
395
+ x: parseInt(elPosition.left, 10) + parseInt(x.toString(), 10),
396
+ y: parseInt(elPosition.top, 10) + parseInt(y.toString(), 10)
397
+ };
398
+ }
399
+
400
+ function findTarget(location) {
401
+ function jumpToTarget(target) {
402
+ const jumpPosition = getElementPosition(target);
403
+
404
+ sendMsg(jumpPosition.y, jumpPosition.x, 'scrollToOffset'); // X&Y reversed at sendMsg uses height/width
405
+ }
406
+
407
+ const hash = location.split('#')[1] || location; // Remove # if present
408
+ const hashData = decodeURIComponent(hash);
409
+ const target = document.getElementById(hashData) || document.getElementsByName(hashData)[0];
410
+
411
+ if (target !== undefined) {
412
+ jumpToTarget(target);
413
+ return;
414
+ }
415
+
416
+ sendMsg(0, 0, 'inPageLink', `#${hash}`);
417
+
418
+ // Don't run for server side render
419
+ if (typeof window !== 'undefined') {
420
+ iframeResizerChild();
421
+ }
422
+ }
423
+
424
+ function checkLocationHash() {
425
+ const { hash, href } = window.location;
426
+
427
+ if (hash !== '' && hash !== '#') {
428
+ findTarget(href);
429
+ }
430
+ }
431
+
432
+ function bindAnchors() {
433
+ for (const link of document.querySelectorAll('a[href^="#"]')) {
434
+ if (link.getAttribute('href') !== '#') {
435
+ addEventListener(link, 'click', (e) => {
436
+ e.preventDefault();
437
+ findTarget(link.getAttribute('href'));
438
+ });
439
+ }
440
+ }
441
+ }
442
+
443
+ function bindLocationHash() {
444
+ addEventListener(window, 'hashchange', checkLocationHash);
445
+ }
446
+
447
+ function initCheck() {
448
+ // Check if page loaded with location hash after init resize
449
+ setTimeout(checkLocationHash, eventCancelTimer);
450
+ }
451
+
452
+ function enableInPageLinks() {
453
+ bindAnchors();
454
+ bindLocationHash();
455
+ initCheck();
456
+ }
457
+
458
+ if (inPageLinks.enable) {
459
+ enableInPageLinks();
460
+ }
461
+
462
+ return {
463
+ findTarget
464
+ };
465
+ }
466
+
467
+ function setupMouseEvents() {
468
+ if (mouseEvents !== true) return;
469
+
470
+ function sendMouse(e) {
471
+ sendMsg(0, 0, e.type, `${e.screenY}:${e.screenX}`);
472
+ }
473
+
474
+ function addMouseListener(evt) {
475
+ addEventListener(window.document, evt, sendMouse);
476
+ }
477
+
478
+ addMouseListener('mouseenter');
479
+ addMouseListener('mouseleave');
480
+ }
481
+
482
+ function setupPublicMethods() {
483
+ win.parentIframe = Object.freeze({
484
+ autoResize: (resize) => {
485
+ if (resize === true && autoResize === false) {
486
+ autoResize = true;
487
+ sendSize('autoResizeEnabled', 'Auto Resize enabled');
488
+ } else if (resize === false && autoResize === true) {
489
+ autoResize = false;
490
+ }
491
+
492
+ sendMsg(0, 0, 'autoResize', JSON.stringify(autoResize));
493
+
494
+ return autoResize;
495
+ },
496
+
497
+ close() {
498
+ sendMsg(0, 0, 'close');
499
+ },
500
+
501
+ getId: () => myID,
502
+
503
+ getPageInfo(callback) {
504
+ if (typeof callback === 'function') {
505
+ onPageInfo = callback;
506
+ sendMsg(0, 0, 'pageInfo');
507
+ return;
508
+ }
509
+
510
+ onPageInfo = null;
511
+ sendMsg(0, 0, 'pageInfoStop');
512
+ },
513
+
514
+ getParentProps(callback) {
515
+ if (typeof callback !== 'function') {
516
+ throw new TypeError('parentIframe.getParentProps(callback) callback not a function');
517
+ }
518
+
519
+ onParentInfo = callback;
520
+ sendMsg(0, 0, 'parentInfo');
521
+
522
+ return () => {
523
+ onParentInfo = null;
524
+ sendMsg(0, 0, 'parentInfoStop');
525
+ };
526
+ },
527
+
528
+ getParentProperties(callback) {
529
+ this.getParentProps(callback);
530
+ },
531
+
532
+ moveToAnchor(hash) {
533
+ inPageLinks.findTarget(hash);
534
+ },
535
+
536
+ reset() {
537
+ resetIframe();
538
+ },
539
+
540
+ scrollBy(x, y) {
541
+ sendMsg(y, x, 'scrollBy'); // X&Y reversed at sendMsg uses height/width
542
+ },
543
+
544
+ scrollTo(x, y) {
545
+ sendMsg(y, x, 'scrollTo'); // X&Y reversed at sendMsg uses height/width
546
+ },
547
+
548
+ scrollToOffset(x, y) {
549
+ sendMsg(y, x, 'scrollToOffset'); // X&Y reversed at sendMsg uses height/width
550
+ },
551
+
552
+ sendMessage(msg, targetOrigin) {
553
+ sendMsg(0, 0, 'message', JSON.stringify(msg), targetOrigin);
554
+ },
555
+
556
+ setHeightCalculationMethod(heightCalculationMethod) {
557
+ heightCalcMode = heightCalculationMethod;
558
+ checkHeightMode();
559
+ },
560
+
561
+ setWidthCalculationMethod(widthCalculationMethod) {
562
+ widthCalcMode = widthCalculationMethod;
563
+ checkWidthMode();
564
+ },
565
+
566
+ setTargetOrigin(targetOrigin) {
567
+ targetOriginDefault = targetOrigin;
568
+ },
569
+
570
+ resize(customHeight, customWidth) {
571
+ const valString = `${customHeight || ''}${customWidth ? `,${customWidth}` : ''}`;
572
+
573
+ sendSize('resizeParent', `parentIframe.resize(${valString})`, customHeight, customWidth);
574
+ },
575
+
576
+ size(customHeight, customWidth) {
577
+ this.resize(customHeight, customWidth);
578
+ }
579
+ });
580
+
581
+ win.parentIFrame = win.parentIframe;
582
+ }
583
+
584
+ function resizeObserved(entries) {
585
+ if (!Array.isArray(entries) || entries.length === 0) return;
586
+
587
+ sendSize('resizeObserver', `Resize Observed:`);
588
+ }
589
+
590
+ const resizeSet = new WeakSet();
591
+
592
+ // This function has to iterate over all page elements during load
593
+ // so is optimized for performance, rather than best practices.
594
+ function attachResizeObserverToNonStaticElements(rootElement) {
595
+ if (rootElement.nodeType !== Node.ELEMENT_NODE) return;
596
+
597
+ if (!resizeSet.has(rootElement)) {
598
+ const position = getComputedStyle(rootElement)?.position;
599
+ if (!(position === '' || position === 'static')) {
600
+ resizeObserver.observe(rootElement);
601
+ resizeSet.add(rootElement);
602
+ }
603
+ }
604
+
605
+ const nodeList = getAllElements(rootElement)();
606
+
607
+ for (const node of nodeList) {
608
+ if (resizeSet.has(node) || node?.nodeType !== Node.ELEMENT_NODE) continue;
609
+
610
+ const position = getComputedStyle(node)?.position;
611
+ if (position === '' || position === 'static') continue;
612
+
613
+ resizeObserver.observe(node);
614
+ resizeSet.add(node);
615
+ }
616
+ }
617
+
618
+ function setupResizeObservers() {
619
+ resizeObserver = new ResizeObserver(resizeObserved);
620
+ resizeObserver.observe(document.body);
621
+ resizeSet.add(document.body);
622
+ attachResizeObserverToNonStaticElements(document.body);
623
+ }
624
+
625
+ function setupMutationObserver() {
626
+ const observedMutations = new Set();
627
+ let pending = false;
628
+ let newMutations = [];
629
+
630
+ const updateMutation = (mutations) => {
631
+ for (const mutation of mutations) {
632
+ const { addedNodes, removedNodes } = mutation;
633
+
634
+ for (const node of addedNodes) {
635
+ observedMutations.add(node);
636
+ }
637
+
638
+ for (const node of removedNodes) {
639
+ observedMutations.delete(node);
640
+ }
641
+ }
642
+ };
643
+
644
+ let delayCount = 1;
645
+
646
+ function processMutations() {
647
+ delayCount = 1;
648
+
649
+ newMutations.forEach(updateMutation);
650
+ newMutations = [];
651
+
652
+ if (observedMutations.size === 0) {
653
+ pending = false;
654
+ return;
655
+ }
656
+
657
+ // Rebuild tagged elements list for size calculation
658
+ checkAndSetupTags();
659
+
660
+ // Add observers to new elements
661
+ addOverflowObservers(observedMutations);
662
+ observedMutations.forEach(attachResizeObserverToNonStaticElements);
663
+
664
+ observedMutations.clear();
665
+
666
+ pending = false;
667
+ }
668
+
669
+ function mutationObserved(mutations) {
670
+ newMutations.push(mutations);
671
+ if (pending) return;
672
+
673
+ pending = true;
674
+ requestAnimationFrame(processMutations);
675
+ }
676
+
677
+ function createMutationObserver() {
678
+ const observer = new window.MutationObserver(mutationObserved);
679
+ const target = document.querySelector('body');
680
+ const config = {
681
+ attributes: false,
682
+ attributeOldValue: false,
683
+ characterData: false,
684
+ characterDataOldValue: false,
685
+ childList: true,
686
+ subtree: true
687
+ };
688
+
689
+ observer.observe(target, config);
690
+
691
+ return observer;
692
+ }
693
+
694
+ const observer = createMutationObserver();
695
+
696
+ return {
697
+ disconnect() {
698
+ observer.disconnect();
699
+ }
700
+ };
701
+ }
702
+
703
+ function getMaxElement(side) {
704
+ let elVal = 0;
705
+ let maxEl = document.documentElement;
706
+ let maxVal = hasTags ? 0 : document.documentElement.getBoundingClientRect().bottom;
707
+
708
+ const targetElements = hasTags
709
+ ? taggedElements
710
+ : hasOverflow
711
+ ? overflowedNodeList
712
+ : getAllElements(document)(); // We should never get here, but just in case
713
+
714
+ let len = targetElements.length;
715
+
716
+ for (const element of targetElements) {
717
+ if (
718
+ !hasTags &&
719
+ hasCheckVisibility && // Safari was missing checkVisibility until March 2024
720
+ !element.checkVisibility(checkVisibilityOptions ?? undefined)
721
+ ) {
722
+ len -= 1;
723
+ continue;
724
+ }
725
+
726
+ elVal =
727
+ element.getBoundingClientRect()[side] +
728
+ parseFloat(getComputedStyle(element).getPropertyValue(`margin-${side}`));
729
+
730
+ if (elVal > maxVal) {
731
+ maxVal = elVal;
732
+ maxEl = element;
733
+ }
734
+ }
735
+
736
+ return maxVal;
737
+ }
738
+
739
+ const getAllMeasurements = (dimension) => [
740
+ dimension.bodyOffset(),
741
+ dimension.bodyScroll(),
742
+ dimension.documentElementOffset(),
743
+ dimension.documentElementScroll(),
744
+ dimension.boundingClientRect()
745
+ ];
746
+
747
+ const getAllElements = (element) => () =>
748
+ element.querySelectorAll(
749
+ '* :not(head):not(meta):not(base):not(title):not(script):not(link):not(style):not(map):not(area):not(option):not(optgroup):not(template):not(track):not(wbr):not(nobr)'
750
+ );
751
+
752
+ const prevScrollSize = {
753
+ height: 0,
754
+ width: 0
755
+ };
756
+
757
+ const prevBoundingSize = {
758
+ height: 0,
759
+ width: 0
760
+ };
761
+
762
+ const getAdjustedScroll = (getDimension) =>
763
+ getDimension.documentElementScroll() + Math.max(0, getDimension.getOffset());
764
+
765
+ function getAutoSize(getDimension) {
766
+ function returnBoundingClientRect() {
767
+ prevBoundingSize[dimension] = boundingSize;
768
+ prevScrollSize[dimension] = scrollSize;
769
+ return boundingSize;
770
+ }
771
+
772
+ const isHeight = getDimension === getHeight;
773
+ const dimension = isHeight ? 'height' : 'width';
774
+ const boundingSize = getDimension.boundingClientRect();
775
+ const ceilBoundingSize = Math.ceil(boundingSize);
776
+ const floorBoundingSize = Math.floor(boundingSize);
777
+ const scrollSize = getAdjustedScroll(getDimension);
778
+
779
+ switch (true) {
780
+ case !getDimension.enabled():
781
+ return scrollSize;
782
+
783
+ case hasTags:
784
+ return getDimension.taggedElement();
785
+
786
+ case !hasOverflow && prevBoundingSize[dimension] === 0 && prevScrollSize[dimension] === 0:
787
+ return returnBoundingClientRect();
788
+
789
+ case triggerLocked &&
790
+ boundingSize === prevBoundingSize[dimension] &&
791
+ scrollSize === prevScrollSize[dimension]:
792
+ return Math.max(boundingSize, scrollSize);
793
+
794
+ case boundingSize === 0:
795
+ return scrollSize;
796
+
797
+ case !hasOverflow &&
798
+ boundingSize !== prevBoundingSize[dimension] &&
799
+ scrollSize <= prevScrollSize[dimension]:
800
+ return returnBoundingClientRect();
801
+
802
+ case !isHeight:
803
+ return getDimension.taggedElement();
804
+
805
+ case !hasOverflow && boundingSize < prevBoundingSize[dimension]:
806
+ return returnBoundingClientRect();
807
+
808
+ case scrollSize === floorBoundingSize || scrollSize === ceilBoundingSize:
809
+ return returnBoundingClientRect();
810
+
811
+ case boundingSize > scrollSize:
812
+ return returnBoundingClientRect();
813
+
814
+ default:
815
+ }
816
+
817
+ return Math.max(getDimension.taggedElement(), returnBoundingClientRect());
818
+ }
819
+
820
+ const getBodyOffset = () => {
821
+ const { body } = document;
822
+ const style = getComputedStyle(body);
823
+
824
+ return body.offsetHeight + parseInt(style.marginTop, 10) + parseInt(style.marginBottom, 10);
825
+ };
826
+
827
+ const getHeight = {
828
+ enabled: () => calculateHeight,
829
+ getOffset: () => offsetHeight,
830
+ auto: () => getAutoSize(getHeight),
831
+ bodyOffset: getBodyOffset,
832
+ bodyScroll: () => document.body.scrollHeight,
833
+ offset: () => getHeight.bodyOffset(), // Backwards compatibility
834
+ custom: () => customCalcMethods.height(),
835
+ documentElementOffset: () => document.documentElement.offsetHeight,
836
+ documentElementScroll: () => document.documentElement.scrollHeight,
837
+ boundingClientRect: () =>
838
+ Math.max(
839
+ document.documentElement.getBoundingClientRect().bottom,
840
+ document.body.getBoundingClientRect().bottom
841
+ ),
842
+ max: () => Math.max(...getAllMeasurements(getHeight)),
843
+ min: () => Math.min(...getAllMeasurements(getHeight)),
844
+ grow: () => getHeight.max(),
845
+ taggedElement: () => getMaxElement(HEIGHT_EDGE)
846
+ };
847
+
848
+ const getWidth = {
849
+ enabled: () => calculateWidth,
850
+ getOffset: () => offsetWidth,
851
+ auto: () => getAutoSize(getWidth),
852
+ bodyScroll: () => document.body.scrollWidth,
853
+ bodyOffset: () => document.body.offsetWidth,
854
+ custom: () => customCalcMethods.width(),
855
+ documentElementScroll: () => document.documentElement.scrollWidth,
856
+ documentElementOffset: () => document.documentElement.offsetWidth,
857
+ boundingClientRect: () =>
858
+ Math.max(
859
+ document.documentElement.getBoundingClientRect().right,
860
+ document.body.getBoundingClientRect().right
861
+ ),
862
+ max: () => Math.max(...getAllMeasurements(getWidth)),
863
+ min: () => Math.min(...getAllMeasurements(getWidth)),
864
+ scroll: () => Math.max(getWidth.bodyScroll(), getWidth.documentElementScroll()),
865
+ taggedElement: () => getMaxElement(WIDTH_EDGE)
866
+ };
867
+
868
+ const checkTolerance = (a, b) => !(Math.abs(a - b) <= tolerance);
869
+
870
+ function sizeIframe(triggerEvent, triggerEventDesc, customHeight, customWidth, msg) {
871
+ const isForceResizableEvent = () => !(triggerEvent in { init: 1, interval: 1, size: 1 });
872
+
873
+ const isForceResizableCalcMode = () =>
874
+ (calculateHeight && heightCalcMode in resetRequiredMethods) ||
875
+ (calculateWidth && widthCalcMode in resetRequiredMethods);
876
+
877
+ const isSizeChangeDetected = () =>
878
+ (calculateHeight && checkTolerance(height, newHeight)) ||
879
+ (calculateWidth && checkTolerance(width, newWidth));
880
+
881
+ const newHeight = undefined === customHeight ? getHeight[heightCalcMode]() : customHeight;
882
+ const newWidth = undefined === customWidth ? getWidth[widthCalcMode]() : customWidth;
883
+
884
+ if (isSizeChangeDetected() || triggerEvent === 'init') {
885
+ lockTrigger();
886
+ height = newHeight;
887
+ width = newWidth;
888
+ sendMsg(height, width, triggerEvent, msg);
889
+ } else if (isForceResizableEvent() && isForceResizableCalcMode()) {
890
+ resetIframe();
891
+ } else {
892
+ timerActive = false; // We're not resizing, so turn off the timer
893
+ }
894
+ }
895
+
896
+ let sendPending = false;
897
+
898
+ function sendSize(triggerEvent, triggerEventDesc, customHeight, customWidth, msg) {
899
+ if (!autoResize && triggerEvent in { reset: 1, resetPage: 1, init: 1 }) {
900
+ return;
901
+ }
902
+
903
+ if (document.hidden) {
904
+ // Currently only correctly supported in firefox
905
+ // This is checked again on the parent page
906
+ return;
907
+ }
908
+
909
+ if (!sendPending) {
910
+ timerActive = true;
911
+ sizeIframe(triggerEvent, triggerEventDesc, customHeight, customWidth, msg);
912
+ requestAnimationFrame(() => {
913
+ sendPending = false;
914
+ });
915
+ }
916
+
917
+ sendPending = true;
918
+ }
919
+
920
+ function lockTrigger() {
921
+ if (triggerLocked) return;
922
+
923
+ triggerLocked = true;
924
+
925
+ requestAnimationFrame(() => {
926
+ triggerLocked = false;
927
+ });
928
+ }
929
+
930
+ function triggerReset(triggerEvent) {
931
+ height = getHeight[heightCalcMode]();
932
+ width = getWidth[widthCalcMode]();
933
+
934
+ sendMsg(height, width, triggerEvent);
935
+ }
936
+
937
+ function resetIframe() {
938
+ const hcm = heightCalcMode;
939
+ heightCalcMode = heightCalcModeDefault;
940
+
941
+ lockTrigger();
942
+ triggerReset('reset');
943
+
944
+ heightCalcMode = hcm;
945
+ }
946
+
947
+ function sendMsg(height, width, triggerEvent, msg, targetOrigin) {
948
+ function setTargetOrigin() {
949
+ if (undefined === targetOrigin) {
950
+ targetOrigin = targetOriginDefault;
951
+ }
952
+ }
953
+
954
+ function sendToParent() {
955
+ const size = `${height + (offsetHeight || 0)}:${width + (offsetWidth || 0)}`;
956
+ const message = `${myID}:${size}:${triggerEvent}${undefined === msg ? '' : `:${msg}`}`;
957
+
958
+ timerActive = false;
959
+
960
+ target.postMessage(msgID + message, targetOrigin);
961
+ }
962
+
963
+ setTargetOrigin();
964
+ sendToParent();
965
+ }
966
+
967
+ function receiver(event) {
968
+ const processRequestFromParent = {
969
+ init: function initFromParent() {
970
+ initMsg = event.data;
971
+ target = event.source;
972
+
973
+ init();
974
+ firstRun = false;
975
+ setTimeout(() => {
976
+ initLock = false;
977
+ }, eventCancelTimer);
978
+ },
979
+
980
+ reset() {
981
+ if (initLock) {
982
+ return;
983
+ }
984
+ triggerReset('resetPage');
985
+ },
986
+
987
+ resize() {
988
+ sendSize('resizeParent', 'Parent window requested size check');
989
+ },
990
+
991
+ moveToAnchor() {
992
+ inPageLinks.findTarget(getData());
993
+ },
994
+
995
+ inPageLink() {
996
+ this.moveToAnchor();
997
+ }, // Backward compatibility
998
+
999
+ pageInfo() {
1000
+ const msgBody = getData();
1001
+ if (onPageInfo) {
1002
+ setTimeout(() => onPageInfo(JSON.parse(msgBody)));
1003
+ } else {
1004
+ // not expected, so cancel more messages
1005
+ sendMsg(0, 0, 'pageInfoStop');
1006
+ }
1007
+ }
1008
+ };
1009
+
1010
+ const isMessageForUs = () => msgID === `${event.data}`.slice(0, msgIdLen);
1011
+
1012
+ const getMessageType = () => event.data.split(']')[1].split(':')[0];
1013
+
1014
+ const getData = () => event.data.slice(event.data.indexOf(':') + 1);
1015
+
1016
+ // Test if this message is from a child below us. This is an ugly test, however, updating
1017
+ // the message format would break backwards compatibility.
1018
+ const isInitMsg = () => event.data.split(':')[2] in { true: 1, false: 1 };
1019
+
1020
+ function callFromParent() {
1021
+ const messageType = getMessageType();
1022
+
1023
+ if (messageType in processRequestFromParent) {
1024
+ processRequestFromParent[messageType]();
1025
+ }
1026
+ }
1027
+
1028
+ function processMessage() {
1029
+ if (firstRun === false) {
1030
+ callFromParent();
1031
+ return;
1032
+ }
1033
+
1034
+ if (isInitMsg()) {
1035
+ processRequestFromParent.init();
1036
+ }
1037
+ }
1038
+
1039
+ if (isMessageForUs()) {
1040
+ processMessage();
1041
+ }
1042
+ }
1043
+
1044
+ // Normally the parent kicks things off when it detects the iFrame has loaded.
1045
+ // If this script is async-loaded, then tell parent page to retry init.
1046
+ function chkLateLoaded() {
1047
+ if (document.readyState !== 'loading') {
1048
+ window.parent.postMessage('[iFrameResizerChild]Ready', '*');
1049
+ }
1050
+ }
1051
+
1052
+ if (!('iframeChildListener' in window)) {
1053
+ window.iframeChildListener = (data) => setTimeout(() => receiver({ data }));
1054
+ addEventListener(window, 'message', receiver);
1055
+ addEventListener(window, 'readystatechange', chkLateLoaded);
1056
+ chkLateLoaded();
1057
+ }
1058
+ }
1059
+
1060
+ // Don't run for server side render
1061
+ if (typeof window !== 'undefined') {
1062
+ iframeResizerChild();
1063
+ }