@dotcms/uve 1.6.0 → 1.7.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.
- package/README.md +24 -22
- package/index.esm.js +1 -1
- package/internal.cjs.js +8 -1
- package/internal.esm.js +1 -1
- package/package.json +1 -1
- package/public.cjs.js +434 -211
- package/public.esm.js +427 -211
- package/src/internal/constants.d.ts +23 -0
- package/src/internal/contentlet-sentinel.constants.d.ts +13 -0
- package/src/internal/events.d.ts +36 -8
- package/src/internal/index.d.ts +1 -0
- package/src/internal.d.ts +0 -1
- package/src/lib/dom/dom.utils.d.ts +60 -1
- package/src/script/utils.d.ts +0 -28
- package/src/lib/dom/document-height-observer.d.ts +0 -18
package/public.cjs.js
CHANGED
|
@@ -3,6 +3,20 @@
|
|
|
3
3
|
var types = require('@dotcms/types');
|
|
4
4
|
var internal = require('@dotcms/types/internal');
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Sentinel values for the placeholder contentlet used when the UVE represents
|
|
8
|
+
* an empty container (e.g. hover / selection without a real contentlet).
|
|
9
|
+
*
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
const TEMP_EMPTY_CONTENTLET = 'TEMP_EMPTY_CONTENTLET';
|
|
13
|
+
/**
|
|
14
|
+
* Placeholder `contentType` for {@link TEMP_EMPTY_CONTENTLET}.
|
|
15
|
+
*
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
const TEMP_EMPTY_CONTENTLET_TYPE = 'TEMP_EMPTY_CONTENTLET_TYPE';
|
|
19
|
+
|
|
6
20
|
/**
|
|
7
21
|
* Calculates the bounding information for each page element within the given containers.
|
|
8
22
|
*
|
|
@@ -243,6 +257,38 @@ function getDotContentletAttributes(contentlet, container) {
|
|
|
243
257
|
})
|
|
244
258
|
};
|
|
245
259
|
}
|
|
260
|
+
/**
|
|
261
|
+
*
|
|
262
|
+
* Returns the minimal set of contentlet data attributes required by DotCMS
|
|
263
|
+
* Analytics (impression & click tracking) to identify a contentlet.
|
|
264
|
+
*
|
|
265
|
+
* Used in live mode where the full editor metadata is stripped but Analytics
|
|
266
|
+
* still needs to resolve the contentlet behind an impression/click.
|
|
267
|
+
*
|
|
268
|
+
* @param {DotCMSBasicContentlet} contentlet - The contentlet to get the attributes for
|
|
269
|
+
* @returns {DotAnalyticsContentletAttributes} The Analytics-required data attributes
|
|
270
|
+
*/
|
|
271
|
+
function getAnalyticsContentletAttributes(contentlet) {
|
|
272
|
+
return {
|
|
273
|
+
'data-dot-identifier': contentlet?.identifier,
|
|
274
|
+
'data-dot-inode': contentlet?.inode,
|
|
275
|
+
'data-dot-title': contentlet?.['widgetTitle'] || contentlet?.title,
|
|
276
|
+
'data-dot-type': contentlet?.contentType,
|
|
277
|
+
'data-dot-basetype': contentlet?.baseType
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
*
|
|
282
|
+
* Checks whether DotCMS Analytics is initialized and active on the page.
|
|
283
|
+
*
|
|
284
|
+
* The SDKs use this in live mode to decide whether to keep the minimal
|
|
285
|
+
* contentlet attributes Analytics depends on.
|
|
286
|
+
*
|
|
287
|
+
* @returns {boolean} `true` when analytics is active, otherwise `false`
|
|
288
|
+
*/
|
|
289
|
+
function isDotAnalyticsActive() {
|
|
290
|
+
return typeof window !== 'undefined' && window[ANALYTICS_ACTIVE_WINDOW_KEY] === true;
|
|
291
|
+
}
|
|
246
292
|
/**
|
|
247
293
|
*
|
|
248
294
|
*
|
|
@@ -342,6 +388,59 @@ function getDotContainerAttributes({
|
|
|
342
388
|
'data-dot-uuid': uuid
|
|
343
389
|
};
|
|
344
390
|
}
|
|
391
|
+
/**
|
|
392
|
+
* Read a contentlet's dataset attributes off a DOM element and return a
|
|
393
|
+
* normalized contentlet object. Mirrors the shape consumed by the editor's
|
|
394
|
+
* SET_BOUNDS and CONTENTLET_CLICKED events. Optionally parses the
|
|
395
|
+
* `dotStyleProperties` JSON when present.
|
|
396
|
+
*/
|
|
397
|
+
function readContentletDataset(element) {
|
|
398
|
+
const dataset = element.dataset ?? {};
|
|
399
|
+
return {
|
|
400
|
+
identifier: dataset['dotIdentifier'],
|
|
401
|
+
title: dataset['dotTitle'],
|
|
402
|
+
inode: dataset['dotInode'],
|
|
403
|
+
contentType: dataset['dotType'],
|
|
404
|
+
baseType: dataset['dotBasetype'],
|
|
405
|
+
widgetTitle: dataset['dotWidgetTitle'],
|
|
406
|
+
onNumberOfPages: dataset['dotOnNumberOfPages'],
|
|
407
|
+
...(dataset['dotStyleProperties'] && {
|
|
408
|
+
dotStyleProperties: JSON.parse(dataset['dotStyleProperties'])
|
|
409
|
+
})
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Returns Zone.js's *unpatched* native `addEventListener` / `removeEventListener`
|
|
414
|
+
* bound to `target`, falling back to the standard methods when Zone.js is absent.
|
|
415
|
+
*
|
|
416
|
+
* UVE reuses a single iframe and rewrites it with `document.open()/write()/close()`
|
|
417
|
+
* on every in-editor navigation. When Zone.js is loaded inside that iframe it runs
|
|
418
|
+
* in global-events mode: one native "gateway" listener per (target, eventType)
|
|
419
|
+
* plus a JS-level task list stored on the target node. `document.open()` tears down
|
|
420
|
+
* the native gateway on the persistent `window`/`document` nodes, but the task list
|
|
421
|
+
* survives on them, so Zone sees "already registered" on re-init and skips
|
|
422
|
+
* re-installing the native gateway — the listener silently goes dead after the
|
|
423
|
+
* first navigation.
|
|
424
|
+
*
|
|
425
|
+
* Hover/click dodge this by binding to `document.documentElement`, a node that
|
|
426
|
+
* `write()` recreates fresh. `scroll`/`message` (on `window`) and
|
|
427
|
+
* `DOMContentLoaded` (on `document`) can't: none of them fire on `<html>`, so
|
|
428
|
+
* there is no fresh node to rebind to. Going through Zone's native (untracked)
|
|
429
|
+
* methods sidesteps the dedup entirely, so the listener rebinds cleanly after
|
|
430
|
+
* every rewrite.
|
|
431
|
+
*/
|
|
432
|
+
function getNativeEventBinder(target) {
|
|
433
|
+
const zone = globalThis.Zone;
|
|
434
|
+
const symbolFor = name => typeof zone?.__symbol__ === 'function' ? zone.__symbol__(name) : `__zone_symbol__${name}`;
|
|
435
|
+
const source = target;
|
|
436
|
+
const base = target;
|
|
437
|
+
const nativeAdd = source[symbolFor('addEventListener')];
|
|
438
|
+
const nativeRemove = source[symbolFor('removeEventListener')];
|
|
439
|
+
return {
|
|
440
|
+
addEventListener: (nativeAdd ?? base.addEventListener).bind(base),
|
|
441
|
+
removeEventListener: (nativeRemove ?? base.removeEventListener).bind(base)
|
|
442
|
+
};
|
|
443
|
+
}
|
|
345
444
|
|
|
346
445
|
/**
|
|
347
446
|
* Subscribes to content changes in the UVE editor
|
|
@@ -358,10 +457,12 @@ function onContentChanges(callback) {
|
|
|
358
457
|
callback(event.data.payload);
|
|
359
458
|
}
|
|
360
459
|
};
|
|
361
|
-
|
|
460
|
+
// Native binder: survives the iframe rewrite under Zone.js. See getNativeEventBinder.
|
|
461
|
+
const nativeWindow = getNativeEventBinder(window);
|
|
462
|
+
nativeWindow.addEventListener('message', messageCallback);
|
|
362
463
|
return {
|
|
363
464
|
unsubscribe: () => {
|
|
364
|
-
|
|
465
|
+
nativeWindow.removeEventListener('message', messageCallback);
|
|
365
466
|
},
|
|
366
467
|
event: types.UVEEventType.CONTENT_CHANGES
|
|
367
468
|
};
|
|
@@ -381,37 +482,135 @@ function onPageReload(callback) {
|
|
|
381
482
|
callback();
|
|
382
483
|
}
|
|
383
484
|
};
|
|
384
|
-
|
|
485
|
+
// Native binder: survives the iframe rewrite under Zone.js. See getNativeEventBinder.
|
|
486
|
+
const nativeWindow = getNativeEventBinder(window);
|
|
487
|
+
nativeWindow.addEventListener('message', messageCallback);
|
|
385
488
|
return {
|
|
386
489
|
unsubscribe: () => {
|
|
387
|
-
|
|
490
|
+
nativeWindow.removeEventListener('message', messageCallback);
|
|
388
491
|
},
|
|
389
492
|
event: types.UVEEventType.PAGE_RELOAD
|
|
390
493
|
};
|
|
391
494
|
}
|
|
495
|
+
const AUTO_BOUNDS_DEBOUNCE_MS = 100;
|
|
392
496
|
/**
|
|
393
|
-
*
|
|
497
|
+
* The single bounds-sync channel. Observes the iframe document and
|
|
498
|
+
* every `[data-dot-object="container"]` with a single ResizeObserver,
|
|
499
|
+
* debounces the trailing edge by {@link AUTO_BOUNDS_DEBOUNCE_MS}ms, and
|
|
500
|
+
* emits the full `getDotCMSPageBounds(...)` payload whenever the layout
|
|
501
|
+
* settles. Also listens on `scroll` (since scrolling moves contentlets
|
|
502
|
+
* without changing layout) and on `UVE_FLUSH_BOUNDS` (the editor's
|
|
503
|
+
* "give me bounds NOW, skip the debounce" message used during drag).
|
|
504
|
+
*
|
|
505
|
+
* Re-runs `querySelectorAll` and the observer wiring whenever a
|
|
506
|
+
* MutationObserver detects child changes that touch container nodes,
|
|
507
|
+
* so containers that mount/unmount after page-load are picked up
|
|
508
|
+
* automatically.
|
|
394
509
|
*
|
|
395
|
-
* @param {UVEEventHandler} callback - Function to be called when bounds are requested
|
|
396
|
-
* @returns {Object} Object containing unsubscribe function and event type
|
|
397
|
-
* @returns {Function} .unsubscribe - Function to remove the event listener
|
|
398
|
-
* @returns {UVEEventType} .event - The event type being subscribed to
|
|
399
510
|
* @internal
|
|
400
511
|
*/
|
|
401
|
-
function
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
512
|
+
function onAutoBounds(callback) {
|
|
513
|
+
let debounceTimer = null;
|
|
514
|
+
let observed = [];
|
|
515
|
+
const emit = () => {
|
|
516
|
+
const containers = Array.from(document.querySelectorAll('[data-dot-object="container"]'));
|
|
517
|
+
callback(getDotCMSPageBounds(containers));
|
|
518
|
+
};
|
|
519
|
+
const scheduleEmit = () => {
|
|
520
|
+
if (debounceTimer !== null) {
|
|
521
|
+
clearTimeout(debounceTimer);
|
|
407
522
|
}
|
|
523
|
+
debounceTimer = setTimeout(() => {
|
|
524
|
+
debounceTimer = null;
|
|
525
|
+
emit();
|
|
526
|
+
}, AUTO_BOUNDS_DEBOUNCE_MS);
|
|
408
527
|
};
|
|
409
|
-
|
|
528
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
529
|
+
scheduleEmit();
|
|
530
|
+
});
|
|
531
|
+
const observeAll = () => {
|
|
532
|
+
// Tear down previous observations before re-wiring.
|
|
533
|
+
for (const el of observed) {
|
|
534
|
+
resizeObserver.unobserve(el);
|
|
535
|
+
}
|
|
536
|
+
observed = Array.from(document.querySelectorAll('[data-dot-object="container"]'));
|
|
537
|
+
resizeObserver.observe(document.documentElement);
|
|
538
|
+
for (const container of observed) {
|
|
539
|
+
resizeObserver.observe(container);
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
observeAll();
|
|
543
|
+
// Containers can mount/unmount after the page first paints (route
|
|
544
|
+
// changes in headless apps, lazy-loaded sections, etc.). Re-wire only
|
|
545
|
+
// when a node carrying [data-dot-object="container"] is added or
|
|
546
|
+
// removed — ignoring text/attribute churn keeps this observer cheap on
|
|
547
|
+
// busy pages.
|
|
548
|
+
const containsContainerNode = nodes => {
|
|
549
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
550
|
+
const node = nodes[i];
|
|
551
|
+
if (node.nodeType !== Node.ELEMENT_NODE) {
|
|
552
|
+
continue;
|
|
553
|
+
}
|
|
554
|
+
const el = node;
|
|
555
|
+
if (el.matches?.('[data-dot-object="container"]') || el.querySelector?.('[data-dot-object="container"]')) {
|
|
556
|
+
return true;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
return false;
|
|
560
|
+
};
|
|
561
|
+
const mutationObserver = new MutationObserver(mutations => {
|
|
562
|
+
for (const m of mutations) {
|
|
563
|
+
if (m.type !== 'childList') continue;
|
|
564
|
+
if (containsContainerNode(m.addedNodes) || containsContainerNode(m.removedNodes)) {
|
|
565
|
+
observeAll();
|
|
566
|
+
scheduleEmit();
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
// The SDK script can run from <head> before <body> exists. Fall back to
|
|
572
|
+
// <html> in that case — childList+subtree on the documentElement still
|
|
573
|
+
// catches container nodes that mount once <body> arrives.
|
|
574
|
+
mutationObserver.observe(document.body ?? document.documentElement, {
|
|
575
|
+
childList: true,
|
|
576
|
+
subtree: true
|
|
577
|
+
});
|
|
578
|
+
// Scrolling doesn't change layout (ResizeObserver won't fire) but moves
|
|
579
|
+
// every contentlet, so re-emit bounds after the scroll settles to re-anchor
|
|
580
|
+
// the selected overlay. Native binder so it survives the iframe rewrite
|
|
581
|
+
// under Zone.js. See getNativeEventBinder.
|
|
582
|
+
const nativeWindow = getNativeEventBinder(window);
|
|
583
|
+
const onScroll = () => scheduleEmit();
|
|
584
|
+
nativeWindow.addEventListener('scroll', onScroll, {
|
|
585
|
+
passive: true
|
|
586
|
+
});
|
|
587
|
+
// Flush channel: the editor occasionally needs an immediate snapshot
|
|
588
|
+
// of bounds (drag enter, where the dropzone has to know container
|
|
589
|
+
// rectangles before the user moves another pixel). Bypass the
|
|
590
|
+
// debounce timer and emit synchronously.
|
|
591
|
+
const onFlush = event => {
|
|
592
|
+
if (event?.data?.name !== internal.__DOTCMS_UVE_EVENT__.UVE_FLUSH_BOUNDS) return;
|
|
593
|
+
if (debounceTimer !== null) {
|
|
594
|
+
clearTimeout(debounceTimer);
|
|
595
|
+
debounceTimer = null;
|
|
596
|
+
}
|
|
597
|
+
emit();
|
|
598
|
+
};
|
|
599
|
+
// Native binder (reused from `scroll` above): survives the iframe rewrite too.
|
|
600
|
+
nativeWindow.addEventListener('message', onFlush);
|
|
410
601
|
return {
|
|
411
602
|
unsubscribe: () => {
|
|
412
|
-
|
|
603
|
+
if (debounceTimer !== null) {
|
|
604
|
+
clearTimeout(debounceTimer);
|
|
605
|
+
debounceTimer = null;
|
|
606
|
+
}
|
|
607
|
+
resizeObserver.disconnect();
|
|
608
|
+
mutationObserver.disconnect();
|
|
609
|
+
nativeWindow.removeEventListener('scroll', onScroll);
|
|
610
|
+
nativeWindow.removeEventListener('message', onFlush);
|
|
611
|
+
observed = [];
|
|
413
612
|
},
|
|
414
|
-
event: types.UVEEventType.
|
|
613
|
+
event: types.UVEEventType.AUTO_BOUNDS
|
|
415
614
|
};
|
|
416
615
|
}
|
|
417
616
|
/**
|
|
@@ -430,10 +629,12 @@ function onIframeScroll(callback) {
|
|
|
430
629
|
callback(direction);
|
|
431
630
|
}
|
|
432
631
|
};
|
|
433
|
-
|
|
632
|
+
// Native binder: survives the iframe rewrite under Zone.js. See getNativeEventBinder.
|
|
633
|
+
const nativeWindow = getNativeEventBinder(window);
|
|
634
|
+
nativeWindow.addEventListener('message', messageCallback);
|
|
434
635
|
return {
|
|
435
636
|
unsubscribe: () => {
|
|
436
|
-
|
|
637
|
+
nativeWindow.removeEventListener('message', messageCallback);
|
|
437
638
|
},
|
|
438
639
|
event: types.UVEEventType.IFRAME_SCROLL
|
|
439
640
|
};
|
|
@@ -463,27 +664,45 @@ function onScrollToSection(callback) {
|
|
|
463
664
|
offsetTop: el.offsetTop
|
|
464
665
|
});
|
|
465
666
|
};
|
|
466
|
-
|
|
667
|
+
// Native binder: survives the iframe rewrite under Zone.js. See getNativeEventBinder.
|
|
668
|
+
const nativeWindow = getNativeEventBinder(window);
|
|
669
|
+
nativeWindow.addEventListener('message', messageCallback);
|
|
467
670
|
return {
|
|
468
671
|
unsubscribe: () => {
|
|
469
|
-
|
|
672
|
+
nativeWindow.removeEventListener('message', messageCallback);
|
|
470
673
|
},
|
|
471
674
|
event: types.UVEEventType.SCROLL_TO_SECTION
|
|
472
675
|
};
|
|
473
676
|
}
|
|
474
677
|
/**
|
|
475
|
-
* Subscribes to contentlet hover events in the UVE editor
|
|
678
|
+
* Subscribes to contentlet hover events in the UVE editor.
|
|
679
|
+
*
|
|
680
|
+
* The callback is invoked with a payload while the pointer is over a
|
|
681
|
+
* DotCMS element, and once with `null` when the pointer leaves the last
|
|
682
|
+
* reported element (transitions onto dead space). The editor uses the
|
|
683
|
+
* `null` signal to clear the hover overlay so it doesn't linger over
|
|
684
|
+
* areas that no longer have a contentlet under the pointer.
|
|
476
685
|
*
|
|
477
|
-
* @param {UVEEventHandler} callback - Function to be called when
|
|
686
|
+
* @param {UVEEventHandler} callback - Function to be called when hover state changes
|
|
478
687
|
* @returns {Object} Object containing unsubscribe function and event type
|
|
479
688
|
* @returns {Function} .unsubscribe - Function to remove the event listener
|
|
480
689
|
* @returns {UVEEventType} .event - The event type being subscribed to
|
|
481
690
|
* @internal
|
|
482
691
|
*/
|
|
483
692
|
function onContentletHovered(callback) {
|
|
693
|
+
let hasHover = false;
|
|
484
694
|
const pointerMoveCallback = event => {
|
|
485
695
|
const foundElement = findDotCMSElement(event.target);
|
|
486
|
-
if (!foundElement)
|
|
696
|
+
if (!foundElement) {
|
|
697
|
+
// Transitioning from a hovered contentlet to dead space — emit
|
|
698
|
+
// a single null so the editor can clear its hover overlay.
|
|
699
|
+
// Subsequent moves over dead space are no-ops.
|
|
700
|
+
if (hasHover) {
|
|
701
|
+
hasHover = false;
|
|
702
|
+
callback(null);
|
|
703
|
+
}
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
487
706
|
const {
|
|
488
707
|
x,
|
|
489
708
|
y,
|
|
@@ -492,26 +711,15 @@ function onContentletHovered(callback) {
|
|
|
492
711
|
} = foundElement.getBoundingClientRect();
|
|
493
712
|
const isContainer = foundElement.dataset?.['dotObject'] === 'container';
|
|
494
713
|
const contentletForEmptyContainer = {
|
|
495
|
-
identifier:
|
|
496
|
-
title:
|
|
497
|
-
contentType:
|
|
714
|
+
identifier: TEMP_EMPTY_CONTENTLET,
|
|
715
|
+
title: TEMP_EMPTY_CONTENTLET,
|
|
716
|
+
contentType: TEMP_EMPTY_CONTENTLET_TYPE,
|
|
498
717
|
inode: 'TEMPY_EMPTY_CONTENTLET_INODE',
|
|
499
|
-
widgetTitle:
|
|
500
|
-
baseType:
|
|
718
|
+
widgetTitle: TEMP_EMPTY_CONTENTLET,
|
|
719
|
+
baseType: TEMP_EMPTY_CONTENTLET,
|
|
501
720
|
onNumberOfPages: 1
|
|
502
721
|
};
|
|
503
|
-
const contentlet =
|
|
504
|
-
identifier: foundElement.dataset?.['dotIdentifier'],
|
|
505
|
-
title: foundElement.dataset?.['dotTitle'],
|
|
506
|
-
inode: foundElement.dataset?.['dotInode'],
|
|
507
|
-
contentType: foundElement.dataset?.['dotType'],
|
|
508
|
-
baseType: foundElement.dataset?.['dotBasetype'],
|
|
509
|
-
widgetTitle: foundElement.dataset?.['dotWidgetTitle'],
|
|
510
|
-
onNumberOfPages: foundElement.dataset?.['dotOnNumberOfPages'],
|
|
511
|
-
...(foundElement.dataset?.['dotStyleProperties'] && {
|
|
512
|
-
dotStyleProperties: JSON.parse(foundElement.dataset['dotStyleProperties'])
|
|
513
|
-
})
|
|
514
|
-
};
|
|
722
|
+
const contentlet = readContentletDataset(foundElement);
|
|
515
723
|
const vtlFiles = findDotCMSVTLData(foundElement);
|
|
516
724
|
const contentletPayload = {
|
|
517
725
|
container:
|
|
@@ -528,16 +736,114 @@ function onContentletHovered(callback) {
|
|
|
528
736
|
height,
|
|
529
737
|
payload: contentletPayload
|
|
530
738
|
};
|
|
739
|
+
hasHover = true;
|
|
531
740
|
callback(contentletHoveredPayload);
|
|
532
741
|
};
|
|
533
|
-
|
|
742
|
+
// We intentionally do not fire null on `pointerleave`: the editor's hover
|
|
743
|
+
// toolbar lives in the parent window, so leaving the iframe usually means
|
|
744
|
+
// the user is reaching for it — killing the overlay would yank it away.
|
|
745
|
+
//
|
|
746
|
+
// Bind to `document.documentElement` (a fresh node on each iframe rewrite)
|
|
747
|
+
// rather than `document`, which goes dead under Zone.js after a rewrite.
|
|
748
|
+
// `pointermove` bubbles to <html>, so no-Zone behavior is identical. See
|
|
749
|
+
// getNativeEventBinder for the full rationale.
|
|
750
|
+
document.documentElement.addEventListener('pointermove', pointerMoveCallback);
|
|
534
751
|
return {
|
|
535
752
|
unsubscribe: () => {
|
|
536
|
-
document.removeEventListener('pointermove', pointerMoveCallback);
|
|
753
|
+
document.documentElement.removeEventListener('pointermove', pointerMoveCallback);
|
|
537
754
|
},
|
|
538
755
|
event: types.UVEEventType.CONTENTLET_HOVERED
|
|
539
756
|
};
|
|
540
757
|
}
|
|
758
|
+
/**
|
|
759
|
+
* Subscribes to contentlet click events in the UVE editor.
|
|
760
|
+
*
|
|
761
|
+
* The editor's hover overlay is `pointer-events: none` so wheel events pass
|
|
762
|
+
* through to the iframe. We detect the user's selection click here instead and
|
|
763
|
+
* post it back to the editor.
|
|
764
|
+
*
|
|
765
|
+
* @param {UVEEventHandler} callback - Function to be called when a contentlet is clicked
|
|
766
|
+
* @returns {Object} Object containing unsubscribe function and event type
|
|
767
|
+
* @internal
|
|
768
|
+
*/
|
|
769
|
+
function onContentletClicked(callback) {
|
|
770
|
+
// Track the last selected contentlet so a second click on the same one
|
|
771
|
+
// lets the page's native click through (links, accordions, etc.). The
|
|
772
|
+
// first click is "select"; subsequent clicks on the selected contentlet
|
|
773
|
+
// are "interact with the page".
|
|
774
|
+
let lastSelectedInode;
|
|
775
|
+
const clickCallback = event => {
|
|
776
|
+
const foundElement = findDotCMSElement(event.target);
|
|
777
|
+
if (!foundElement) return;
|
|
778
|
+
const isContainer = foundElement.dataset?.['dotObject'] === 'container';
|
|
779
|
+
// Only emit for contentlet clicks; an empty container click is a no-op
|
|
780
|
+
// for selection purposes (there's nothing to select).
|
|
781
|
+
if (isContainer) return;
|
|
782
|
+
const inode = foundElement.dataset?.['dotInode'];
|
|
783
|
+
// If the user is clicking the already-selected contentlet, let the
|
|
784
|
+
// page handle the click natively (link navigation, button handlers,
|
|
785
|
+
// form submission). The editor selection toolbar already exposes the
|
|
786
|
+
// edit/delete/etc actions; the contentlet's own UI should still work.
|
|
787
|
+
if (inode && inode === lastSelectedInode) {
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
// First click on this contentlet (or a different one) — select it in
|
|
791
|
+
// the editor and block the page's natural click. Capture phase +
|
|
792
|
+
// preventDefault + stopPropagation suppresses both the default action
|
|
793
|
+
// and any subscribers further down the tree.
|
|
794
|
+
event.preventDefault();
|
|
795
|
+
event.stopPropagation();
|
|
796
|
+
lastSelectedInode = inode;
|
|
797
|
+
const {
|
|
798
|
+
x,
|
|
799
|
+
y,
|
|
800
|
+
width,
|
|
801
|
+
height
|
|
802
|
+
} = foundElement.getBoundingClientRect();
|
|
803
|
+
const contentlet = readContentletDataset(foundElement);
|
|
804
|
+
const vtlFiles = findDotCMSVTLData(foundElement);
|
|
805
|
+
callback({
|
|
806
|
+
x,
|
|
807
|
+
y,
|
|
808
|
+
width,
|
|
809
|
+
height,
|
|
810
|
+
payload: {
|
|
811
|
+
container: foundElement.dataset?.['dotContainer'] ? JSON.parse(foundElement.dataset?.['dotContainer']) : getClosestDotCMSContainerData(foundElement),
|
|
812
|
+
contentlet,
|
|
813
|
+
vtlFiles
|
|
814
|
+
}
|
|
815
|
+
});
|
|
816
|
+
};
|
|
817
|
+
// The editor clears its selection on canvas resize / scroll. When that
|
|
818
|
+
// happens, our lastSelectedInode is stale: a click on what used to be the
|
|
819
|
+
// selected contentlet would be treated as a passthrough (page click) even
|
|
820
|
+
// though the editor no longer has it selected. Listen for the
|
|
821
|
+
// UVE_SELECTION_CLEARED message and reset the tracker.
|
|
822
|
+
const selectionClearedCallback = event => {
|
|
823
|
+
if (event?.data?.name === internal.__DOTCMS_UVE_EVENT__.UVE_SELECTION_CLEARED) {
|
|
824
|
+
lastSelectedInode = undefined;
|
|
825
|
+
}
|
|
826
|
+
};
|
|
827
|
+
// Capture phase so we run BEFORE the page's own click handlers. Bound to
|
|
828
|
+
// `document.documentElement` (a fresh node on each iframe rewrite) rather
|
|
829
|
+
// than `document`, which goes dead under Zone.js after a rewrite; capture on
|
|
830
|
+
// <html> still runs first. See getNativeEventBinder for the full rationale.
|
|
831
|
+
document.documentElement.addEventListener('click', clickCallback, {
|
|
832
|
+
capture: true
|
|
833
|
+
});
|
|
834
|
+
// Native binder: survives the iframe rewrite under Zone.js. See getNativeEventBinder.
|
|
835
|
+
const nativeWindow = getNativeEventBinder(window);
|
|
836
|
+
nativeWindow.addEventListener('message', selectionClearedCallback);
|
|
837
|
+
return {
|
|
838
|
+
unsubscribe: () => {
|
|
839
|
+
document.documentElement.removeEventListener('click', clickCallback, {
|
|
840
|
+
capture: true
|
|
841
|
+
});
|
|
842
|
+
nativeWindow.removeEventListener('message', selectionClearedCallback);
|
|
843
|
+
},
|
|
844
|
+
event: types.UVEEventType.CONTENTLET_CLICKED
|
|
845
|
+
};
|
|
846
|
+
}
|
|
541
847
|
|
|
542
848
|
/**
|
|
543
849
|
* Events that can be subscribed to in the UVE
|
|
@@ -552,17 +858,31 @@ const __UVE_EVENTS__ = {
|
|
|
552
858
|
[types.UVEEventType.PAGE_RELOAD]: callback => {
|
|
553
859
|
return onPageReload(callback);
|
|
554
860
|
},
|
|
555
|
-
[types.UVEEventType.REQUEST_BOUNDS]: callback => {
|
|
556
|
-
return onRequestBounds(callback);
|
|
557
|
-
},
|
|
558
861
|
[types.UVEEventType.IFRAME_SCROLL]: callback => {
|
|
559
862
|
return onIframeScroll(callback);
|
|
560
863
|
},
|
|
561
864
|
[types.UVEEventType.CONTENTLET_HOVERED]: callback => {
|
|
562
865
|
return onContentletHovered(callback);
|
|
563
866
|
},
|
|
867
|
+
[types.UVEEventType.CONTENTLET_CLICKED]: callback => {
|
|
868
|
+
return onContentletClicked(callback);
|
|
869
|
+
},
|
|
564
870
|
[types.UVEEventType.SCROLL_TO_SECTION]: callback => {
|
|
565
871
|
return onScrollToSection(callback);
|
|
872
|
+
},
|
|
873
|
+
// SELECTION_CLEARED is editor→SDK only. No public subscriber surface;
|
|
874
|
+
// onContentletClicked listens for the underlying postMessage internally
|
|
875
|
+
// to reset its lastSelectedInode tracker.
|
|
876
|
+
[types.UVEEventType.SELECTION_CLEARED]: _callback => {
|
|
877
|
+
return {
|
|
878
|
+
unsubscribe: () => {
|
|
879
|
+
/* no-op: SELECTION_CLEARED has no consumer-facing subscription */
|
|
880
|
+
},
|
|
881
|
+
event: types.UVEEventType.SELECTION_CLEARED
|
|
882
|
+
};
|
|
883
|
+
},
|
|
884
|
+
[types.UVEEventType.AUTO_BOUNDS]: callback => {
|
|
885
|
+
return onAutoBounds(callback);
|
|
566
886
|
}
|
|
567
887
|
};
|
|
568
888
|
/**
|
|
@@ -644,6 +964,29 @@ const CUSTOM_NO_COMPONENT = 'CustomNoComponent';
|
|
|
644
964
|
* @internal
|
|
645
965
|
*/
|
|
646
966
|
const DOT_SECTION_ID_PREFIX = 'dot-section-';
|
|
967
|
+
/**
|
|
968
|
+
* Window flag set by `@dotcms/analytics` when content analytics is initialized
|
|
969
|
+
* and active on the page.
|
|
970
|
+
*
|
|
971
|
+
* @important This value is intentionally duplicated from `@dotcms/analytics`
|
|
972
|
+
* (`ANALYTICS_WINDOWS_ACTIVE_KEY` in dot-analytics.constants.ts). The SDKs read
|
|
973
|
+
* it in live mode to decide whether to keep the minimal contentlet attributes
|
|
974
|
+
* Analytics depends on. Both constants MUST stay in sync.
|
|
975
|
+
*
|
|
976
|
+
* @internal
|
|
977
|
+
*/
|
|
978
|
+
const ANALYTICS_ACTIVE_WINDOW_KEY = '__dotAnalyticsActive__';
|
|
979
|
+
/**
|
|
980
|
+
* Event dispatched by `@dotcms/analytics` once analytics is ready. The SDKs
|
|
981
|
+
* listen for it so live-mode contentlets can re-render with the attributes
|
|
982
|
+
* Analytics needs, regardless of initialization order.
|
|
983
|
+
*
|
|
984
|
+
* @important Kept in sync with the `dotcms:analytics:ready` event dispatched by
|
|
985
|
+
* `@dotcms/analytics` (initializeContentAnalytics).
|
|
986
|
+
*
|
|
987
|
+
* @internal
|
|
988
|
+
*/
|
|
989
|
+
const ANALYTICS_READY_EVENT = 'dotcms:analytics:ready';
|
|
647
990
|
|
|
648
991
|
/**
|
|
649
992
|
* Gets the current state of the Universal Visual Editor (UVE).
|
|
@@ -730,97 +1073,6 @@ function createUVESubscription(eventType, callback) {
|
|
|
730
1073
|
return eventCallback(callback);
|
|
731
1074
|
}
|
|
732
1075
|
|
|
733
|
-
/**
|
|
734
|
-
* Observes rendered document height changes and notifies the caller after layout settles.
|
|
735
|
-
*
|
|
736
|
-
* Uses ResizeObserver on <html> for layout/viewport-driven changes and MutationObserver
|
|
737
|
-
* on <body> to catch DOM additions/removals that may shrink the page without a resize.
|
|
738
|
-
* Measurement reads `body.offsetHeight`, which tracks actual content height and
|
|
739
|
-
* decreases correctly after DOM removals, unaffected by CSS min-height on the html element.
|
|
740
|
-
*/
|
|
741
|
-
function observeDocumentHeight({
|
|
742
|
-
onHeightChange,
|
|
743
|
-
documentRef = document,
|
|
744
|
-
windowRef = window,
|
|
745
|
-
debounceMs = 50
|
|
746
|
-
}) {
|
|
747
|
-
const html = documentRef.documentElement;
|
|
748
|
-
const body = documentRef.body;
|
|
749
|
-
let debounceTimer = null;
|
|
750
|
-
let rafOuter = null;
|
|
751
|
-
let rafInner = null;
|
|
752
|
-
let lastHeight = null;
|
|
753
|
-
let destroyed = false;
|
|
754
|
-
const measureAndNotify = () => {
|
|
755
|
-
const height = body.offsetHeight;
|
|
756
|
-
if (!height || height === lastHeight) {
|
|
757
|
-
return;
|
|
758
|
-
}
|
|
759
|
-
lastHeight = height;
|
|
760
|
-
onHeightChange(height);
|
|
761
|
-
};
|
|
762
|
-
const scheduleNotify = () => {
|
|
763
|
-
if (destroyed) {
|
|
764
|
-
return;
|
|
765
|
-
}
|
|
766
|
-
if (debounceTimer !== null) {
|
|
767
|
-
clearTimeout(debounceTimer);
|
|
768
|
-
}
|
|
769
|
-
debounceTimer = setTimeout(() => {
|
|
770
|
-
debounceTimer = null;
|
|
771
|
-
if (destroyed) {
|
|
772
|
-
return;
|
|
773
|
-
}
|
|
774
|
-
rafOuter = windowRef.requestAnimationFrame(() => {
|
|
775
|
-
rafOuter = null;
|
|
776
|
-
if (destroyed) {
|
|
777
|
-
return;
|
|
778
|
-
}
|
|
779
|
-
rafInner = windowRef.requestAnimationFrame(() => {
|
|
780
|
-
rafInner = null;
|
|
781
|
-
if (!destroyed) {
|
|
782
|
-
measureAndNotify();
|
|
783
|
-
}
|
|
784
|
-
});
|
|
785
|
-
});
|
|
786
|
-
}, debounceMs);
|
|
787
|
-
};
|
|
788
|
-
const onLoad = () => scheduleNotify();
|
|
789
|
-
if (documentRef.readyState === 'complete' || documentRef.readyState === 'interactive') {
|
|
790
|
-
scheduleNotify();
|
|
791
|
-
} else {
|
|
792
|
-
windowRef.addEventListener('load', onLoad);
|
|
793
|
-
}
|
|
794
|
-
const resizeObserver = new ResizeObserver(() => scheduleNotify());
|
|
795
|
-
resizeObserver.observe(html);
|
|
796
|
-
const mutationObserver = new MutationObserver(() => scheduleNotify());
|
|
797
|
-
mutationObserver.observe(documentRef.body ?? html, {
|
|
798
|
-
childList: true,
|
|
799
|
-
subtree: true
|
|
800
|
-
});
|
|
801
|
-
return {
|
|
802
|
-
destroy: () => {
|
|
803
|
-
destroyed = true;
|
|
804
|
-
if (debounceTimer !== null) {
|
|
805
|
-
clearTimeout(debounceTimer);
|
|
806
|
-
debounceTimer = null;
|
|
807
|
-
}
|
|
808
|
-
if (rafOuter !== null) {
|
|
809
|
-
windowRef.cancelAnimationFrame(rafOuter);
|
|
810
|
-
rafOuter = null;
|
|
811
|
-
}
|
|
812
|
-
if (rafInner !== null) {
|
|
813
|
-
windowRef.cancelAnimationFrame(rafInner);
|
|
814
|
-
rafInner = null;
|
|
815
|
-
}
|
|
816
|
-
lastHeight = null;
|
|
817
|
-
resizeObserver.disconnect();
|
|
818
|
-
mutationObserver.disconnect();
|
|
819
|
-
windowRef.removeEventListener('load', onLoad);
|
|
820
|
-
}
|
|
821
|
-
};
|
|
822
|
-
}
|
|
823
|
-
|
|
824
1076
|
/**
|
|
825
1077
|
* Sets the bounds of the containers in the editor.
|
|
826
1078
|
* Retrieves the containers from the DOM and sends their position data to the editor.
|
|
@@ -923,7 +1175,6 @@ const isValidBlocks = blocks => {
|
|
|
923
1175
|
};
|
|
924
1176
|
};
|
|
925
1177
|
|
|
926
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
927
1178
|
/**
|
|
928
1179
|
* Sets up scroll event handlers for the window to notify the editor about scroll events.
|
|
929
1180
|
* Adds listeners for both 'scroll' and 'scrollend' events, sending appropriate messages
|
|
@@ -940,12 +1191,19 @@ function scrollHandler() {
|
|
|
940
1191
|
action: types.DotCMSUVEAction.IFRAME_SCROLL_END
|
|
941
1192
|
});
|
|
942
1193
|
};
|
|
943
|
-
|
|
944
|
-
|
|
1194
|
+
// Native binder: scroll survives the iframe rewrite under Zone.js. It can't
|
|
1195
|
+
// move to a fresh `documentElement` like hover/click (viewport scroll only
|
|
1196
|
+
// fires on `window`). See getNativeEventBinder.
|
|
1197
|
+
const {
|
|
1198
|
+
addEventListener,
|
|
1199
|
+
removeEventListener
|
|
1200
|
+
} = getNativeEventBinder(window);
|
|
1201
|
+
addEventListener('scroll', scrollCallback);
|
|
1202
|
+
addEventListener('scrollend', scrollEndCallback);
|
|
945
1203
|
return {
|
|
946
1204
|
destroyScrollHandler: () => {
|
|
947
|
-
|
|
948
|
-
|
|
1205
|
+
removeEventListener('scroll', scrollCallback);
|
|
1206
|
+
removeEventListener('scrollend', scrollEndCallback);
|
|
949
1207
|
}
|
|
950
1208
|
};
|
|
951
1209
|
}
|
|
@@ -985,9 +1243,6 @@ function registerUVEEvents() {
|
|
|
985
1243
|
const pageReloadSubscription = createUVESubscription(types.UVEEventType.PAGE_RELOAD, () => {
|
|
986
1244
|
window.location.reload();
|
|
987
1245
|
});
|
|
988
|
-
const requestBoundsSubscription = createUVESubscription(types.UVEEventType.REQUEST_BOUNDS, bounds => {
|
|
989
|
-
setBounds(bounds);
|
|
990
|
-
});
|
|
991
1246
|
const iframeScrollSubscription = createUVESubscription(types.UVEEventType.IFRAME_SCROLL, direction => {
|
|
992
1247
|
if (window.scrollY === 0 && direction === 'up' || computeScrollIsInBottom() && direction === 'down') {
|
|
993
1248
|
// If the iframe scroll is at the top or bottom, do not send anything.
|
|
@@ -1007,14 +1262,30 @@ function registerUVEEvents() {
|
|
|
1007
1262
|
payload: contentletHovered
|
|
1008
1263
|
});
|
|
1009
1264
|
});
|
|
1265
|
+
const contentletClickedSubscription = createUVESubscription(types.UVEEventType.CONTENTLET_CLICKED, contentletClicked => {
|
|
1266
|
+
sendMessageToUVE({
|
|
1267
|
+
action: types.DotCMSUVEAction.SET_SELECTED_CONTENTLET,
|
|
1268
|
+
payload: contentletClicked
|
|
1269
|
+
});
|
|
1270
|
+
});
|
|
1010
1271
|
const scrollToSectionSubscription = createUVESubscription(types.UVEEventType.SCROLL_TO_SECTION, payload => {
|
|
1011
1272
|
sendMessageToUVE({
|
|
1012
1273
|
action: types.DotCMSUVEAction.SECTION_OFFSET,
|
|
1013
1274
|
payload
|
|
1014
1275
|
});
|
|
1015
1276
|
});
|
|
1277
|
+
// The single bounds-sync channel. The SDK observes layout changes
|
|
1278
|
+
// inside the iframe (media-query reflows, image/font load shifts,
|
|
1279
|
+
// container mount/unmount, scroll, etc.) and emits SET_BOUNDS on the
|
|
1280
|
+
// trailing edge of a debounce window. The editor can also send a
|
|
1281
|
+
// UVE_FLUSH_BOUNDS message to request an immediate synchronous emit
|
|
1282
|
+
// (used during drag/drop, where the dropzone needs current bounds
|
|
1283
|
+
// before the user moves another pixel).
|
|
1284
|
+
const autoBoundsSubscription = createUVESubscription(types.UVEEventType.AUTO_BOUNDS, bounds => {
|
|
1285
|
+
setBounds(bounds);
|
|
1286
|
+
});
|
|
1016
1287
|
return {
|
|
1017
|
-
subscriptions: [pageReloadSubscription,
|
|
1288
|
+
subscriptions: [pageReloadSubscription, iframeScrollSubscription, contentletHoveredSubscription, contentletClickedSubscription, scrollToSectionSubscription, autoBoundsSubscription]
|
|
1018
1289
|
};
|
|
1019
1290
|
}
|
|
1020
1291
|
/**
|
|
@@ -1046,68 +1317,19 @@ function listenBlockEditorInlineEvent() {
|
|
|
1046
1317
|
}
|
|
1047
1318
|
};
|
|
1048
1319
|
}
|
|
1049
|
-
//
|
|
1320
|
+
// Native binder: `DOMContentLoaded` fires on `document` (not `<html>`), so
|
|
1321
|
+
// it survives the iframe rewrite under Zone.js. See getNativeEventBinder.
|
|
1050
1322
|
const handleDOMContentLoaded = () => {
|
|
1051
1323
|
listenBlockEditorClick();
|
|
1052
1324
|
};
|
|
1053
|
-
document.addEventListener('DOMContentLoaded', handleDOMContentLoaded);
|
|
1054
|
-
return {
|
|
1055
|
-
destroyListenBlockEditorInlineEvent: () => {
|
|
1056
|
-
document.removeEventListener('DOMContentLoaded', handleDOMContentLoaded);
|
|
1057
|
-
}
|
|
1058
|
-
};
|
|
1059
|
-
}
|
|
1060
|
-
/**
|
|
1061
|
-
* Returns whether iframe height must be synchronized via postMessage.
|
|
1062
|
-
*
|
|
1063
|
-
* Same-origin parents can measure iframe content directly, so they do not need
|
|
1064
|
-
* child-driven height reporting. Cross-origin parents cannot access the iframe
|
|
1065
|
-
* DOM, so they still need the reporter fallback.
|
|
1066
|
-
*/
|
|
1067
|
-
function shouldReportIframeHeightToParent() {
|
|
1068
|
-
if (window.parent === window) {
|
|
1069
|
-
return false;
|
|
1070
|
-
}
|
|
1071
|
-
try {
|
|
1072
|
-
const parentDocument = window.parent.document;
|
|
1073
|
-
return !parentDocument;
|
|
1074
|
-
} catch {
|
|
1075
|
-
return true;
|
|
1076
|
-
}
|
|
1077
|
-
}
|
|
1078
|
-
/**
|
|
1079
|
-
* Reports the iframe document height to the parent UVE shell via postMessage.
|
|
1080
|
-
*
|
|
1081
|
-
* Uses ResizeObserver on <html> for viewport/font/image-driven size changes, and
|
|
1082
|
-
* MutationObserver on <body> to catch DOM removals (e.g. contentlets deleted by
|
|
1083
|
-
* the editor) that shrink the page without triggering a resize event.
|
|
1084
|
-
*
|
|
1085
|
-
* Measurement reads `document.documentElement.offsetHeight` — the actual rendered
|
|
1086
|
-
* height of the <html> element after layout. `scrollHeight` is intentionally avoided
|
|
1087
|
-
* because it does not reliably decrease when content is removed from the DOM.
|
|
1088
|
-
*
|
|
1089
|
-
* Height sends are coalesced to at most one per double-requestAnimationFrame pair
|
|
1090
|
-
* so they always run after layout and paint have settled.
|
|
1091
|
-
*
|
|
1092
|
-
* @returns {{ destroyHeightReporter: () => void }} Cleanup function that removes
|
|
1093
|
-
* all listeners and disconnects the observers.
|
|
1094
|
-
*/
|
|
1095
|
-
function reportIframeHeight() {
|
|
1096
1325
|
const {
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
action: types.DotCMSUVEAction.IFRAME_HEIGHT,
|
|
1102
|
-
payload: {
|
|
1103
|
-
height
|
|
1104
|
-
}
|
|
1105
|
-
});
|
|
1106
|
-
}
|
|
1107
|
-
});
|
|
1326
|
+
addEventListener,
|
|
1327
|
+
removeEventListener
|
|
1328
|
+
} = getNativeEventBinder(document);
|
|
1329
|
+
addEventListener('DOMContentLoaded', handleDOMContentLoaded);
|
|
1108
1330
|
return {
|
|
1109
|
-
|
|
1110
|
-
|
|
1331
|
+
destroyListenBlockEditorInlineEvent: () => {
|
|
1332
|
+
removeEventListener('DOMContentLoaded', handleDOMContentLoaded);
|
|
1111
1333
|
}
|
|
1112
1334
|
};
|
|
1113
1335
|
}
|
|
@@ -1316,21 +1538,17 @@ function initUVE(config = {}) {
|
|
|
1316
1538
|
const {
|
|
1317
1539
|
destroyListenBlockEditorInlineEvent
|
|
1318
1540
|
} = listenBlockEditorInlineEvent();
|
|
1319
|
-
const {
|
|
1320
|
-
destroyHeightReporter
|
|
1321
|
-
} = shouldReportIframeHeightToParent() ? reportIframeHeight() : {
|
|
1322
|
-
destroyHeightReporter: () => undefined
|
|
1323
|
-
};
|
|
1324
1541
|
return {
|
|
1325
1542
|
destroyUVESubscriptions: () => {
|
|
1326
1543
|
subscriptions.forEach(subscription => subscription.unsubscribe());
|
|
1327
1544
|
destroyScrollHandler();
|
|
1328
1545
|
destroyListenBlockEditorInlineEvent();
|
|
1329
|
-
destroyHeightReporter();
|
|
1330
1546
|
}
|
|
1331
1547
|
};
|
|
1332
1548
|
}
|
|
1333
1549
|
|
|
1550
|
+
exports.ANALYTICS_ACTIVE_WINDOW_KEY = ANALYTICS_ACTIVE_WINDOW_KEY;
|
|
1551
|
+
exports.ANALYTICS_READY_EVENT = ANALYTICS_READY_EVENT;
|
|
1334
1552
|
exports.CUSTOM_NO_COMPONENT = CUSTOM_NO_COMPONENT;
|
|
1335
1553
|
exports.DEVELOPMENT_MODE = DEVELOPMENT_MODE;
|
|
1336
1554
|
exports.DOT_SECTION_ID_PREFIX = DOT_SECTION_ID_PREFIX;
|
|
@@ -1339,6 +1557,8 @@ exports.EMPTY_CONTAINER_STYLE_REACT = EMPTY_CONTAINER_STYLE_REACT;
|
|
|
1339
1557
|
exports.END_CLASS = END_CLASS;
|
|
1340
1558
|
exports.PRODUCTION_MODE = PRODUCTION_MODE;
|
|
1341
1559
|
exports.START_CLASS = START_CLASS;
|
|
1560
|
+
exports.TEMP_EMPTY_CONTENTLET = TEMP_EMPTY_CONTENTLET;
|
|
1561
|
+
exports.TEMP_EMPTY_CONTENTLET_TYPE = TEMP_EMPTY_CONTENTLET_TYPE;
|
|
1342
1562
|
exports.__UVE_EVENTS__ = __UVE_EVENTS__;
|
|
1343
1563
|
exports.__UVE_EVENT_ERROR_FALLBACK__ = __UVE_EVENT_ERROR_FALLBACK__;
|
|
1344
1564
|
exports.combineClasses = combineClasses;
|
|
@@ -1349,6 +1569,7 @@ exports.editContentlet = editContentlet;
|
|
|
1349
1569
|
exports.enableBlockEditorInline = enableBlockEditorInline;
|
|
1350
1570
|
exports.findDotCMSElement = findDotCMSElement;
|
|
1351
1571
|
exports.findDotCMSVTLData = findDotCMSVTLData;
|
|
1572
|
+
exports.getAnalyticsContentletAttributes = getAnalyticsContentletAttributes;
|
|
1352
1573
|
exports.getClosestDotCMSContainerData = getClosestDotCMSContainerData;
|
|
1353
1574
|
exports.getColumnPositionClasses = getColumnPositionClasses;
|
|
1354
1575
|
exports.getContainersData = getContainersData;
|
|
@@ -1358,11 +1579,13 @@ exports.getDotCMSContentletsBound = getDotCMSContentletsBound;
|
|
|
1358
1579
|
exports.getDotCMSPageBounds = getDotCMSPageBounds;
|
|
1359
1580
|
exports.getDotContainerAttributes = getDotContainerAttributes;
|
|
1360
1581
|
exports.getDotContentletAttributes = getDotContentletAttributes;
|
|
1582
|
+
exports.getNativeEventBinder = getNativeEventBinder;
|
|
1361
1583
|
exports.getUVEState = getUVEState;
|
|
1362
1584
|
exports.initInlineEditing = initInlineEditing;
|
|
1363
1585
|
exports.initUVE = initUVE;
|
|
1586
|
+
exports.isDotAnalyticsActive = isDotAnalyticsActive;
|
|
1364
1587
|
exports.isValidBlocks = isValidBlocks;
|
|
1365
|
-
exports.
|
|
1588
|
+
exports.readContentletDataset = readContentletDataset;
|
|
1366
1589
|
exports.reorderMenu = reorderMenu;
|
|
1367
1590
|
exports.sendMessageToUVE = sendMessageToUVE;
|
|
1368
1591
|
exports.setBounds = setBounds;
|