@dotcms/uve 0.0.1-beta.17 → 0.0.1-beta.19
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/index.cjs.js +10 -90
- package/{constants.cjs.js → index.cjs2.js} +383 -0
- package/index.esm.js +2 -88
- package/{constants.esm.js → index.esm2.js} +380 -2
- package/internal.cjs.js +31 -128
- package/internal.esm.js +2 -104
- package/package.json +1 -1
- package/src/lib/editor/public.d.ts +24 -0
- package/src/script/utils.d.ts +9 -3
package/index.cjs.js
CHANGED
|
@@ -1,94 +1,14 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
|
|
3
|
+
var internal = require('./index.cjs2.js');
|
|
4
|
+
require('./types.cjs.js');
|
|
5
5
|
|
|
6
|
-
/**
|
|
7
|
-
* Gets the current state of the Universal Visual Editor (UVE).
|
|
8
|
-
*
|
|
9
|
-
* This function checks if the code is running inside the DotCMS Universal Visual Editor
|
|
10
|
-
* and returns information about its current state, including the editor mode.
|
|
11
|
-
*
|
|
12
|
-
* @export
|
|
13
|
-
* @return {UVEState | undefined} Returns the UVE state object if running inside the editor,
|
|
14
|
-
* undefined otherwise.
|
|
15
|
-
*
|
|
16
|
-
* The state includes:
|
|
17
|
-
* - mode: The current editor mode (preview, edit, live)
|
|
18
|
-
* - languageId: The language ID of the current page setted on the UVE
|
|
19
|
-
* - persona: The persona of the current page setted on the UVE
|
|
20
|
-
* - variantName: The name of the current variant
|
|
21
|
-
* - experimentId: The ID of the current experiment
|
|
22
|
-
* - publishDate: The publish date of the current page setted on the UVE
|
|
23
|
-
*
|
|
24
|
-
* @note The absence of any of these properties means that the value is the default one.
|
|
25
|
-
*
|
|
26
|
-
* @example
|
|
27
|
-
* ```ts
|
|
28
|
-
* const editorState = getUVEState();
|
|
29
|
-
* if (editorState?.mode === 'edit') {
|
|
30
|
-
* // Enable editing features
|
|
31
|
-
* }
|
|
32
|
-
* ```
|
|
33
|
-
*/
|
|
34
|
-
function getUVEState() {
|
|
35
|
-
if (typeof window === 'undefined' || window.parent === window || !window.location) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
const url = new URL(window.location.href);
|
|
39
|
-
const possibleModes = Object.values(types.UVE_MODE);
|
|
40
|
-
let mode = url.searchParams.get('mode') ?? types.UVE_MODE.EDIT;
|
|
41
|
-
const languageId = url.searchParams.get('language_id');
|
|
42
|
-
const persona = url.searchParams.get('personaId');
|
|
43
|
-
const variantName = url.searchParams.get('variantName');
|
|
44
|
-
const experimentId = url.searchParams.get('experimentId');
|
|
45
|
-
const publishDate = url.searchParams.get('publishDate');
|
|
46
|
-
if (!possibleModes.includes(mode)) {
|
|
47
|
-
mode = types.UVE_MODE.EDIT;
|
|
48
|
-
}
|
|
49
|
-
return {
|
|
50
|
-
mode,
|
|
51
|
-
languageId,
|
|
52
|
-
persona,
|
|
53
|
-
variantName,
|
|
54
|
-
experimentId,
|
|
55
|
-
publishDate
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Creates a subscription to a UVE event.
|
|
60
|
-
*
|
|
61
|
-
* @param eventType - The type of event to subscribe to
|
|
62
|
-
* @param callback - The callback function that will be called when the event occurs
|
|
63
|
-
* @returns An event subscription that can be used to unsubscribe
|
|
64
|
-
*
|
|
65
|
-
* @example
|
|
66
|
-
* ```ts
|
|
67
|
-
* // Subscribe to page changes
|
|
68
|
-
* const subscription = createUVESubscription(UVEEventType.CONTENT_CHANGES, (changes) => {
|
|
69
|
-
* console.log('Content changes:', changes);
|
|
70
|
-
* });
|
|
71
|
-
*
|
|
72
|
-
* // Later, unsubscribe when no longer needed
|
|
73
|
-
* subscription.unsubscribe();
|
|
74
|
-
* ```
|
|
75
|
-
*/
|
|
76
|
-
function createUVESubscription(eventType, callback) {
|
|
77
|
-
if (!getUVEState()) {
|
|
78
|
-
console.warn('UVE Subscription: Not running inside UVE');
|
|
79
|
-
return constants.__UVE_EVENT_ERROR_FALLBACK__(eventType);
|
|
80
|
-
}
|
|
81
|
-
const eventCallback = constants.__UVE_EVENTS__[eventType];
|
|
82
|
-
if (!eventCallback) {
|
|
83
|
-
console.error(`UVE Subscription: Event ${eventType} not found`);
|
|
84
|
-
return constants.__UVE_EVENT_ERROR_FALLBACK__(eventType);
|
|
85
|
-
}
|
|
86
|
-
return eventCallback(callback);
|
|
87
|
-
}
|
|
88
6
|
|
|
89
|
-
|
|
90
|
-
exports.
|
|
91
|
-
exports.
|
|
92
|
-
exports.
|
|
93
|
-
exports.
|
|
94
|
-
exports.
|
|
7
|
+
|
|
8
|
+
exports.createUVESubscription = internal.createUVESubscription;
|
|
9
|
+
exports.editContentlet = internal.editContentlet;
|
|
10
|
+
exports.getUVEState = internal.getUVEState;
|
|
11
|
+
exports.initInlineEditing = internal.initInlineEditing;
|
|
12
|
+
exports.initUVE = internal.initUVE;
|
|
13
|
+
exports.reorderMenu = internal.reorderMenu;
|
|
14
|
+
exports.sendMessageToUVE = internal.sendMessageToUVE;
|
|
@@ -372,6 +372,161 @@ function getDotContainerAttributes({
|
|
|
372
372
|
};
|
|
373
373
|
}
|
|
374
374
|
|
|
375
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
376
|
+
/**
|
|
377
|
+
* Sets up scroll event handlers for the window to notify the editor about scroll events.
|
|
378
|
+
* Adds listeners for both 'scroll' and 'scrollend' events, sending appropriate messages
|
|
379
|
+
* to the editor when these events occur.
|
|
380
|
+
*/
|
|
381
|
+
function scrollHandler() {
|
|
382
|
+
const scrollCallback = () => {
|
|
383
|
+
sendMessageToUVE({
|
|
384
|
+
action: types.DotCMSUVEAction.IFRAME_SCROLL
|
|
385
|
+
});
|
|
386
|
+
};
|
|
387
|
+
const scrollEndCallback = () => {
|
|
388
|
+
sendMessageToUVE({
|
|
389
|
+
action: types.DotCMSUVEAction.IFRAME_SCROLL_END
|
|
390
|
+
});
|
|
391
|
+
};
|
|
392
|
+
window.addEventListener('scroll', scrollCallback);
|
|
393
|
+
window.addEventListener('scrollend', scrollEndCallback);
|
|
394
|
+
return {
|
|
395
|
+
destroyScrollHandler: () => {
|
|
396
|
+
window.removeEventListener('scroll', scrollCallback);
|
|
397
|
+
window.removeEventListener('scrollend', scrollEndCallback);
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Adds 'empty-contentlet' class to contentlet elements that have no height.
|
|
403
|
+
* This helps identify and style empty contentlets in the editor view.
|
|
404
|
+
*
|
|
405
|
+
* @remarks
|
|
406
|
+
* The function queries all elements with data-dot-object="contentlet" attribute
|
|
407
|
+
* and checks their clientHeight. If an element has no height (clientHeight = 0),
|
|
408
|
+
* it adds the 'empty-contentlet' class to that element.
|
|
409
|
+
*/
|
|
410
|
+
function addClassToEmptyContentlets() {
|
|
411
|
+
const contentlets = document.querySelectorAll('[data-dot-object="contentlet"]');
|
|
412
|
+
contentlets.forEach(contentlet => {
|
|
413
|
+
if (contentlet.clientHeight) {
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
contentlet.classList.add('empty-contentlet');
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Registers event handlers for various UVE (Universal Visual Editor) events.
|
|
421
|
+
*
|
|
422
|
+
* This function sets up subscriptions for:
|
|
423
|
+
* - Page reload events that refresh the window
|
|
424
|
+
* - Bounds request events to update editor boundaries
|
|
425
|
+
* - Iframe scroll events to handle smooth scrolling within bounds
|
|
426
|
+
* - Contentlet hover events to notify the editor
|
|
427
|
+
*
|
|
428
|
+
* @remarks
|
|
429
|
+
* For scroll events, the function includes logic to prevent scrolling beyond
|
|
430
|
+
* the top or bottom boundaries of the iframe, which helps maintain proper
|
|
431
|
+
* scroll event handling.
|
|
432
|
+
*/
|
|
433
|
+
function registerUVEEvents() {
|
|
434
|
+
const pageReloadSubscription = createUVESubscription(types.UVEEventType.PAGE_RELOAD, () => {
|
|
435
|
+
window.location.reload();
|
|
436
|
+
});
|
|
437
|
+
const requestBoundsSubscription = createUVESubscription(types.UVEEventType.REQUEST_BOUNDS, bounds => {
|
|
438
|
+
setBounds(bounds);
|
|
439
|
+
});
|
|
440
|
+
const iframeScrollSubscription = createUVESubscription(types.UVEEventType.IFRAME_SCROLL, direction => {
|
|
441
|
+
if (window.scrollY === 0 && direction === 'up' || computeScrollIsInBottom() && direction === 'down') {
|
|
442
|
+
// If the iframe scroll is at the top or bottom, do not send anything.
|
|
443
|
+
// This avoids losing the scrollend event.
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
const scrollY = direction === 'up' ? -120 : 120;
|
|
447
|
+
window.scrollBy({
|
|
448
|
+
left: 0,
|
|
449
|
+
top: scrollY,
|
|
450
|
+
behavior: 'smooth'
|
|
451
|
+
});
|
|
452
|
+
});
|
|
453
|
+
const contentletHoveredSubscription = createUVESubscription(types.UVEEventType.CONTENTLET_HOVERED, contentletHovered => {
|
|
454
|
+
sendMessageToUVE({
|
|
455
|
+
action: types.DotCMSUVEAction.SET_CONTENTLET,
|
|
456
|
+
payload: contentletHovered
|
|
457
|
+
});
|
|
458
|
+
});
|
|
459
|
+
return {
|
|
460
|
+
subscriptions: [pageReloadSubscription, requestBoundsSubscription, iframeScrollSubscription, contentletHoveredSubscription]
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Notifies the editor that the UVE client is ready to receive messages.
|
|
465
|
+
*
|
|
466
|
+
* This function sends a message to the editor indicating that the client-side
|
|
467
|
+
* initialization is complete and it's ready to handle editor interactions.
|
|
468
|
+
*
|
|
469
|
+
* @remarks
|
|
470
|
+
* This is typically called after all UVE event handlers and DOM listeners
|
|
471
|
+
* have been set up successfully.
|
|
472
|
+
*/
|
|
473
|
+
function setClientIsReady() {
|
|
474
|
+
sendMessageToUVE({
|
|
475
|
+
action: types.DotCMSUVEAction.CLIENT_READY
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* Listen for block editor inline event.
|
|
480
|
+
*/
|
|
481
|
+
function listenBlockEditorInlineEvent() {
|
|
482
|
+
if (document.readyState === 'complete') {
|
|
483
|
+
// The page is fully loaded or interactive
|
|
484
|
+
listenBlockEditorClick();
|
|
485
|
+
return {
|
|
486
|
+
destroyListenBlockEditorInlineEvent: () => {
|
|
487
|
+
window.removeEventListener('load', () => listenBlockEditorClick());
|
|
488
|
+
}
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
window.addEventListener('load', () => listenBlockEditorClick());
|
|
492
|
+
return {
|
|
493
|
+
destroyListenBlockEditorInlineEvent: () => {
|
|
494
|
+
window.removeEventListener('load', () => listenBlockEditorClick());
|
|
495
|
+
}
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
const listenBlockEditorClick = () => {
|
|
499
|
+
const editBlockEditorNodes = document.querySelectorAll('[data-block-editor-content]');
|
|
500
|
+
if (!editBlockEditorNodes.length) {
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
editBlockEditorNodes.forEach(node => {
|
|
504
|
+
const {
|
|
505
|
+
inode,
|
|
506
|
+
language = '1',
|
|
507
|
+
contentType,
|
|
508
|
+
fieldName,
|
|
509
|
+
blockEditorContent
|
|
510
|
+
} = node.dataset;
|
|
511
|
+
const content = JSON.parse(blockEditorContent || '');
|
|
512
|
+
if (!inode || !language || !contentType || !fieldName) {
|
|
513
|
+
console.error('Missing data attributes for block editor inline editing.');
|
|
514
|
+
console.warn('inode, language, contentType and fieldName are required.');
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
node.classList.add('dotcms__inline-edit-field');
|
|
518
|
+
node.addEventListener('click', () => {
|
|
519
|
+
initInlineEditing('BLOCK_EDITOR', {
|
|
520
|
+
inode,
|
|
521
|
+
content,
|
|
522
|
+
language: parseInt(language),
|
|
523
|
+
fieldName,
|
|
524
|
+
contentType
|
|
525
|
+
});
|
|
526
|
+
});
|
|
527
|
+
});
|
|
528
|
+
};
|
|
529
|
+
|
|
375
530
|
/**
|
|
376
531
|
* Post message to dotcms page editor
|
|
377
532
|
*
|
|
@@ -444,6 +599,146 @@ function initInlineEditing(type, data) {
|
|
|
444
599
|
}
|
|
445
600
|
});
|
|
446
601
|
}
|
|
602
|
+
/**
|
|
603
|
+
* Initializes the Universal Visual Editor (UVE) with required handlers and event listeners.
|
|
604
|
+
*
|
|
605
|
+
* This function sets up:
|
|
606
|
+
* - Scroll handling
|
|
607
|
+
* - Empty contentlet styling
|
|
608
|
+
* - Block editor inline event listening
|
|
609
|
+
* - Client ready state
|
|
610
|
+
* - UVE event subscriptions
|
|
611
|
+
*
|
|
612
|
+
* @returns {Object} An object containing the cleanup function
|
|
613
|
+
* @returns {Function} destroyUVESubscriptions - Function to clean up all UVE event subscriptions
|
|
614
|
+
*
|
|
615
|
+
* @example
|
|
616
|
+
* ```typescript
|
|
617
|
+
* const { destroyUVESubscriptions } = initUVE();
|
|
618
|
+
*
|
|
619
|
+
* // When done with UVE
|
|
620
|
+
* destroyUVESubscriptions();
|
|
621
|
+
* ```
|
|
622
|
+
*/
|
|
623
|
+
function initUVE() {
|
|
624
|
+
addClassToEmptyContentlets();
|
|
625
|
+
setClientIsReady();
|
|
626
|
+
const {
|
|
627
|
+
subscriptions
|
|
628
|
+
} = registerUVEEvents();
|
|
629
|
+
const {
|
|
630
|
+
destroyScrollHandler
|
|
631
|
+
} = scrollHandler();
|
|
632
|
+
const {
|
|
633
|
+
destroyListenBlockEditorInlineEvent
|
|
634
|
+
} = listenBlockEditorInlineEvent();
|
|
635
|
+
return {
|
|
636
|
+
destroyUVESubscriptions: () => {
|
|
637
|
+
subscriptions.forEach(subscription => subscription.unsubscribe());
|
|
638
|
+
destroyScrollHandler();
|
|
639
|
+
destroyListenBlockEditorInlineEvent();
|
|
640
|
+
}
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* Sets the bounds of the containers in the editor.
|
|
646
|
+
* Retrieves the containers from the DOM and sends their position data to the editor.
|
|
647
|
+
* @private
|
|
648
|
+
* @memberof DotCMSPageEditor
|
|
649
|
+
*/
|
|
650
|
+
function setBounds(bounds) {
|
|
651
|
+
sendMessageToUVE({
|
|
652
|
+
action: types.DotCMSUVEAction.SET_BOUNDS,
|
|
653
|
+
payload: bounds
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
/**
|
|
657
|
+
* Validates the structure of a Block Editor block.
|
|
658
|
+
*
|
|
659
|
+
* This function checks that:
|
|
660
|
+
* 1. The blocks parameter is a valid object
|
|
661
|
+
* 2. The block has a 'doc' type
|
|
662
|
+
* 3. The block has a valid content array that is not empty
|
|
663
|
+
*
|
|
664
|
+
* @param {Block} blocks - The blocks structure to validate
|
|
665
|
+
* @returns {BlockEditorState} Object containing validation state and any error message
|
|
666
|
+
* @property {boolean} BlockEditorState.isValid - Whether the blocks structure is valid
|
|
667
|
+
* @property {string | null} BlockEditorState.error - Error message if invalid, null if valid
|
|
668
|
+
*/
|
|
669
|
+
const isValidBlocks = blocks => {
|
|
670
|
+
if (!blocks) {
|
|
671
|
+
return {
|
|
672
|
+
error: `Error: Blocks object is not defined`
|
|
673
|
+
};
|
|
674
|
+
}
|
|
675
|
+
if (typeof blocks !== 'object') {
|
|
676
|
+
return {
|
|
677
|
+
error: `Error: Blocks must be an object, but received: ${typeof blocks}`
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
if (blocks.type !== 'doc') {
|
|
681
|
+
return {
|
|
682
|
+
error: `Error: Invalid block type. Expected 'doc' but received: '${blocks.type}'`
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
if (!blocks.content) {
|
|
686
|
+
return {
|
|
687
|
+
error: 'Error: Blocks content is missing'
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
if (!Array.isArray(blocks.content)) {
|
|
691
|
+
return {
|
|
692
|
+
error: `Error: Blocks content must be an array, but received: ${typeof blocks.content}`
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
if (blocks.content.length === 0) {
|
|
696
|
+
return {
|
|
697
|
+
error: 'Error: Blocks content is empty. At least one block is required.'
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
// Validate each block in the content array
|
|
701
|
+
for (let i = 0; i < blocks.content.length; i++) {
|
|
702
|
+
const block = blocks.content[i];
|
|
703
|
+
if (!block.type) {
|
|
704
|
+
return {
|
|
705
|
+
error: `Error: Block at index ${i} is missing required 'type' property`
|
|
706
|
+
};
|
|
707
|
+
}
|
|
708
|
+
if (typeof block.type !== 'string') {
|
|
709
|
+
return {
|
|
710
|
+
error: `Error: Block type at index ${i} must be a string, but received: ${typeof block.type}`
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
// Validate block attributes if present
|
|
714
|
+
if (block.attrs && typeof block.attrs !== 'object') {
|
|
715
|
+
return {
|
|
716
|
+
error: `Error: Block attributes at index ${i} must be an object, but received: ${typeof block.attrs}`
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
// Validate nested content if present
|
|
720
|
+
if (block.content) {
|
|
721
|
+
if (!Array.isArray(block.content)) {
|
|
722
|
+
return {
|
|
723
|
+
error: `Error: Block content at index ${i} must be an array, but received: ${typeof block.content}`
|
|
724
|
+
};
|
|
725
|
+
}
|
|
726
|
+
// Recursively validate nested blocks
|
|
727
|
+
const nestedValidation = isValidBlocks({
|
|
728
|
+
type: 'doc',
|
|
729
|
+
content: block.content
|
|
730
|
+
});
|
|
731
|
+
if (nestedValidation.error) {
|
|
732
|
+
return {
|
|
733
|
+
error: `Error in nested block at index ${i}: ${nestedValidation.error}`
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
return {
|
|
739
|
+
error: null
|
|
740
|
+
};
|
|
741
|
+
};
|
|
447
742
|
|
|
448
743
|
/**
|
|
449
744
|
* Enum representing the different types of blocks available in the Block Editor
|
|
@@ -739,6 +1034,89 @@ const EMPTY_CONTAINER_STYLE_ANGULAR = {
|
|
|
739
1034
|
*/
|
|
740
1035
|
const CUSTOM_NO_COMPONENT = 'CustomNoComponent';
|
|
741
1036
|
|
|
1037
|
+
/**
|
|
1038
|
+
* Gets the current state of the Universal Visual Editor (UVE).
|
|
1039
|
+
*
|
|
1040
|
+
* This function checks if the code is running inside the DotCMS Universal Visual Editor
|
|
1041
|
+
* and returns information about its current state, including the editor mode.
|
|
1042
|
+
*
|
|
1043
|
+
* @export
|
|
1044
|
+
* @return {UVEState | undefined} Returns the UVE state object if running inside the editor,
|
|
1045
|
+
* undefined otherwise.
|
|
1046
|
+
*
|
|
1047
|
+
* The state includes:
|
|
1048
|
+
* - mode: The current editor mode (preview, edit, live)
|
|
1049
|
+
* - languageId: The language ID of the current page setted on the UVE
|
|
1050
|
+
* - persona: The persona of the current page setted on the UVE
|
|
1051
|
+
* - variantName: The name of the current variant
|
|
1052
|
+
* - experimentId: The ID of the current experiment
|
|
1053
|
+
* - publishDate: The publish date of the current page setted on the UVE
|
|
1054
|
+
*
|
|
1055
|
+
* @note The absence of any of these properties means that the value is the default one.
|
|
1056
|
+
*
|
|
1057
|
+
* @example
|
|
1058
|
+
* ```ts
|
|
1059
|
+
* const editorState = getUVEState();
|
|
1060
|
+
* if (editorState?.mode === 'edit') {
|
|
1061
|
+
* // Enable editing features
|
|
1062
|
+
* }
|
|
1063
|
+
* ```
|
|
1064
|
+
*/
|
|
1065
|
+
function getUVEState() {
|
|
1066
|
+
if (typeof window === 'undefined' || window.parent === window || !window.location) {
|
|
1067
|
+
return undefined;
|
|
1068
|
+
}
|
|
1069
|
+
const url = new URL(window.location.href);
|
|
1070
|
+
const possibleModes = Object.values(types.UVE_MODE);
|
|
1071
|
+
let mode = url.searchParams.get('mode') ?? types.UVE_MODE.EDIT;
|
|
1072
|
+
const languageId = url.searchParams.get('language_id');
|
|
1073
|
+
const persona = url.searchParams.get('personaId');
|
|
1074
|
+
const variantName = url.searchParams.get('variantName');
|
|
1075
|
+
const experimentId = url.searchParams.get('experimentId');
|
|
1076
|
+
const publishDate = url.searchParams.get('publishDate');
|
|
1077
|
+
if (!possibleModes.includes(mode)) {
|
|
1078
|
+
mode = types.UVE_MODE.EDIT;
|
|
1079
|
+
}
|
|
1080
|
+
return {
|
|
1081
|
+
mode,
|
|
1082
|
+
languageId,
|
|
1083
|
+
persona,
|
|
1084
|
+
variantName,
|
|
1085
|
+
experimentId,
|
|
1086
|
+
publishDate
|
|
1087
|
+
};
|
|
1088
|
+
}
|
|
1089
|
+
/**
|
|
1090
|
+
* Creates a subscription to a UVE event.
|
|
1091
|
+
*
|
|
1092
|
+
* @param eventType - The type of event to subscribe to
|
|
1093
|
+
* @param callback - The callback function that will be called when the event occurs
|
|
1094
|
+
* @returns An event subscription that can be used to unsubscribe
|
|
1095
|
+
*
|
|
1096
|
+
* @example
|
|
1097
|
+
* ```ts
|
|
1098
|
+
* // Subscribe to page changes
|
|
1099
|
+
* const subscription = createUVESubscription(UVEEventType.CONTENT_CHANGES, (changes) => {
|
|
1100
|
+
* console.log('Content changes:', changes);
|
|
1101
|
+
* });
|
|
1102
|
+
*
|
|
1103
|
+
* // Later, unsubscribe when no longer needed
|
|
1104
|
+
* subscription.unsubscribe();
|
|
1105
|
+
* ```
|
|
1106
|
+
*/
|
|
1107
|
+
function createUVESubscription(eventType, callback) {
|
|
1108
|
+
if (!getUVEState()) {
|
|
1109
|
+
console.warn('UVE Subscription: Not running inside UVE');
|
|
1110
|
+
return __UVE_EVENT_ERROR_FALLBACK__(eventType);
|
|
1111
|
+
}
|
|
1112
|
+
const eventCallback = __UVE_EVENTS__[eventType];
|
|
1113
|
+
if (!eventCallback) {
|
|
1114
|
+
console.error(`UVE Subscription: Event ${eventType} not found`);
|
|
1115
|
+
return __UVE_EVENT_ERROR_FALLBACK__(eventType);
|
|
1116
|
+
}
|
|
1117
|
+
return eventCallback(callback);
|
|
1118
|
+
}
|
|
1119
|
+
|
|
742
1120
|
exports.CUSTOM_NO_COMPONENT = CUSTOM_NO_COMPONENT;
|
|
743
1121
|
exports.DEVELOPMENT_MODE = DEVELOPMENT_MODE;
|
|
744
1122
|
exports.EMPTY_CONTAINER_STYLE_ANGULAR = EMPTY_CONTAINER_STYLE_ANGULAR;
|
|
@@ -750,6 +1128,7 @@ exports.__UVE_EVENTS__ = __UVE_EVENTS__;
|
|
|
750
1128
|
exports.__UVE_EVENT_ERROR_FALLBACK__ = __UVE_EVENT_ERROR_FALLBACK__;
|
|
751
1129
|
exports.combineClasses = combineClasses;
|
|
752
1130
|
exports.computeScrollIsInBottom = computeScrollIsInBottom;
|
|
1131
|
+
exports.createUVESubscription = createUVESubscription;
|
|
753
1132
|
exports.editContentlet = editContentlet;
|
|
754
1133
|
exports.findDotCMSElement = findDotCMSElement;
|
|
755
1134
|
exports.findDotCMSVTLData = findDotCMSVTLData;
|
|
@@ -762,6 +1141,10 @@ exports.getDotCMSContentletsBound = getDotCMSContentletsBound;
|
|
|
762
1141
|
exports.getDotCMSPageBounds = getDotCMSPageBounds;
|
|
763
1142
|
exports.getDotContainerAttributes = getDotContainerAttributes;
|
|
764
1143
|
exports.getDotContentletAttributes = getDotContentletAttributes;
|
|
1144
|
+
exports.getUVEState = getUVEState;
|
|
765
1145
|
exports.initInlineEditing = initInlineEditing;
|
|
1146
|
+
exports.initUVE = initUVE;
|
|
1147
|
+
exports.isValidBlocks = isValidBlocks;
|
|
766
1148
|
exports.reorderMenu = reorderMenu;
|
|
767
1149
|
exports.sendMessageToUVE = sendMessageToUVE;
|
|
1150
|
+
exports.setBounds = setBounds;
|
package/index.esm.js
CHANGED
|
@@ -1,88 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { UVE_MODE } from './types.esm.js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Gets the current state of the Universal Visual Editor (UVE).
|
|
7
|
-
*
|
|
8
|
-
* This function checks if the code is running inside the DotCMS Universal Visual Editor
|
|
9
|
-
* and returns information about its current state, including the editor mode.
|
|
10
|
-
*
|
|
11
|
-
* @export
|
|
12
|
-
* @return {UVEState | undefined} Returns the UVE state object if running inside the editor,
|
|
13
|
-
* undefined otherwise.
|
|
14
|
-
*
|
|
15
|
-
* The state includes:
|
|
16
|
-
* - mode: The current editor mode (preview, edit, live)
|
|
17
|
-
* - languageId: The language ID of the current page setted on the UVE
|
|
18
|
-
* - persona: The persona of the current page setted on the UVE
|
|
19
|
-
* - variantName: The name of the current variant
|
|
20
|
-
* - experimentId: The ID of the current experiment
|
|
21
|
-
* - publishDate: The publish date of the current page setted on the UVE
|
|
22
|
-
*
|
|
23
|
-
* @note The absence of any of these properties means that the value is the default one.
|
|
24
|
-
*
|
|
25
|
-
* @example
|
|
26
|
-
* ```ts
|
|
27
|
-
* const editorState = getUVEState();
|
|
28
|
-
* if (editorState?.mode === 'edit') {
|
|
29
|
-
* // Enable editing features
|
|
30
|
-
* }
|
|
31
|
-
* ```
|
|
32
|
-
*/
|
|
33
|
-
function getUVEState() {
|
|
34
|
-
if (typeof window === 'undefined' || window.parent === window || !window.location) {
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
const url = new URL(window.location.href);
|
|
38
|
-
const possibleModes = Object.values(UVE_MODE);
|
|
39
|
-
let mode = url.searchParams.get('mode') ?? UVE_MODE.EDIT;
|
|
40
|
-
const languageId = url.searchParams.get('language_id');
|
|
41
|
-
const persona = url.searchParams.get('personaId');
|
|
42
|
-
const variantName = url.searchParams.get('variantName');
|
|
43
|
-
const experimentId = url.searchParams.get('experimentId');
|
|
44
|
-
const publishDate = url.searchParams.get('publishDate');
|
|
45
|
-
if (!possibleModes.includes(mode)) {
|
|
46
|
-
mode = UVE_MODE.EDIT;
|
|
47
|
-
}
|
|
48
|
-
return {
|
|
49
|
-
mode,
|
|
50
|
-
languageId,
|
|
51
|
-
persona,
|
|
52
|
-
variantName,
|
|
53
|
-
experimentId,
|
|
54
|
-
publishDate
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Creates a subscription to a UVE event.
|
|
59
|
-
*
|
|
60
|
-
* @param eventType - The type of event to subscribe to
|
|
61
|
-
* @param callback - The callback function that will be called when the event occurs
|
|
62
|
-
* @returns An event subscription that can be used to unsubscribe
|
|
63
|
-
*
|
|
64
|
-
* @example
|
|
65
|
-
* ```ts
|
|
66
|
-
* // Subscribe to page changes
|
|
67
|
-
* const subscription = createUVESubscription(UVEEventType.CONTENT_CHANGES, (changes) => {
|
|
68
|
-
* console.log('Content changes:', changes);
|
|
69
|
-
* });
|
|
70
|
-
*
|
|
71
|
-
* // Later, unsubscribe when no longer needed
|
|
72
|
-
* subscription.unsubscribe();
|
|
73
|
-
* ```
|
|
74
|
-
*/
|
|
75
|
-
function createUVESubscription(eventType, callback) {
|
|
76
|
-
if (!getUVEState()) {
|
|
77
|
-
console.warn('UVE Subscription: Not running inside UVE');
|
|
78
|
-
return __UVE_EVENT_ERROR_FALLBACK__(eventType);
|
|
79
|
-
}
|
|
80
|
-
const eventCallback = __UVE_EVENTS__[eventType];
|
|
81
|
-
if (!eventCallback) {
|
|
82
|
-
console.error(`UVE Subscription: Event ${eventType} not found`);
|
|
83
|
-
return __UVE_EVENT_ERROR_FALLBACK__(eventType);
|
|
84
|
-
}
|
|
85
|
-
return eventCallback(callback);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export { createUVESubscription, getUVEState };
|
|
1
|
+
export { u as createUVESubscription, w as editContentlet, t as getUVEState, y as initInlineEditing, z as initUVE, x as reorderMenu, v as sendMessageToUVE } from './index.esm2.js';
|
|
2
|
+
import './types.esm.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DotCMSUVEAction,
|
|
1
|
+
import { UVEEventType, DotCMSUVEAction, UVE_MODE } from './types.esm.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Actions received from the dotcms editor
|
|
@@ -370,6 +370,161 @@ function getDotContainerAttributes({
|
|
|
370
370
|
};
|
|
371
371
|
}
|
|
372
372
|
|
|
373
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
374
|
+
/**
|
|
375
|
+
* Sets up scroll event handlers for the window to notify the editor about scroll events.
|
|
376
|
+
* Adds listeners for both 'scroll' and 'scrollend' events, sending appropriate messages
|
|
377
|
+
* to the editor when these events occur.
|
|
378
|
+
*/
|
|
379
|
+
function scrollHandler() {
|
|
380
|
+
const scrollCallback = () => {
|
|
381
|
+
sendMessageToUVE({
|
|
382
|
+
action: DotCMSUVEAction.IFRAME_SCROLL
|
|
383
|
+
});
|
|
384
|
+
};
|
|
385
|
+
const scrollEndCallback = () => {
|
|
386
|
+
sendMessageToUVE({
|
|
387
|
+
action: DotCMSUVEAction.IFRAME_SCROLL_END
|
|
388
|
+
});
|
|
389
|
+
};
|
|
390
|
+
window.addEventListener('scroll', scrollCallback);
|
|
391
|
+
window.addEventListener('scrollend', scrollEndCallback);
|
|
392
|
+
return {
|
|
393
|
+
destroyScrollHandler: () => {
|
|
394
|
+
window.removeEventListener('scroll', scrollCallback);
|
|
395
|
+
window.removeEventListener('scrollend', scrollEndCallback);
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Adds 'empty-contentlet' class to contentlet elements that have no height.
|
|
401
|
+
* This helps identify and style empty contentlets in the editor view.
|
|
402
|
+
*
|
|
403
|
+
* @remarks
|
|
404
|
+
* The function queries all elements with data-dot-object="contentlet" attribute
|
|
405
|
+
* and checks their clientHeight. If an element has no height (clientHeight = 0),
|
|
406
|
+
* it adds the 'empty-contentlet' class to that element.
|
|
407
|
+
*/
|
|
408
|
+
function addClassToEmptyContentlets() {
|
|
409
|
+
const contentlets = document.querySelectorAll('[data-dot-object="contentlet"]');
|
|
410
|
+
contentlets.forEach(contentlet => {
|
|
411
|
+
if (contentlet.clientHeight) {
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
contentlet.classList.add('empty-contentlet');
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Registers event handlers for various UVE (Universal Visual Editor) events.
|
|
419
|
+
*
|
|
420
|
+
* This function sets up subscriptions for:
|
|
421
|
+
* - Page reload events that refresh the window
|
|
422
|
+
* - Bounds request events to update editor boundaries
|
|
423
|
+
* - Iframe scroll events to handle smooth scrolling within bounds
|
|
424
|
+
* - Contentlet hover events to notify the editor
|
|
425
|
+
*
|
|
426
|
+
* @remarks
|
|
427
|
+
* For scroll events, the function includes logic to prevent scrolling beyond
|
|
428
|
+
* the top or bottom boundaries of the iframe, which helps maintain proper
|
|
429
|
+
* scroll event handling.
|
|
430
|
+
*/
|
|
431
|
+
function registerUVEEvents() {
|
|
432
|
+
const pageReloadSubscription = createUVESubscription(UVEEventType.PAGE_RELOAD, () => {
|
|
433
|
+
window.location.reload();
|
|
434
|
+
});
|
|
435
|
+
const requestBoundsSubscription = createUVESubscription(UVEEventType.REQUEST_BOUNDS, bounds => {
|
|
436
|
+
setBounds(bounds);
|
|
437
|
+
});
|
|
438
|
+
const iframeScrollSubscription = createUVESubscription(UVEEventType.IFRAME_SCROLL, direction => {
|
|
439
|
+
if (window.scrollY === 0 && direction === 'up' || computeScrollIsInBottom() && direction === 'down') {
|
|
440
|
+
// If the iframe scroll is at the top or bottom, do not send anything.
|
|
441
|
+
// This avoids losing the scrollend event.
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
const scrollY = direction === 'up' ? -120 : 120;
|
|
445
|
+
window.scrollBy({
|
|
446
|
+
left: 0,
|
|
447
|
+
top: scrollY,
|
|
448
|
+
behavior: 'smooth'
|
|
449
|
+
});
|
|
450
|
+
});
|
|
451
|
+
const contentletHoveredSubscription = createUVESubscription(UVEEventType.CONTENTLET_HOVERED, contentletHovered => {
|
|
452
|
+
sendMessageToUVE({
|
|
453
|
+
action: DotCMSUVEAction.SET_CONTENTLET,
|
|
454
|
+
payload: contentletHovered
|
|
455
|
+
});
|
|
456
|
+
});
|
|
457
|
+
return {
|
|
458
|
+
subscriptions: [pageReloadSubscription, requestBoundsSubscription, iframeScrollSubscription, contentletHoveredSubscription]
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Notifies the editor that the UVE client is ready to receive messages.
|
|
463
|
+
*
|
|
464
|
+
* This function sends a message to the editor indicating that the client-side
|
|
465
|
+
* initialization is complete and it's ready to handle editor interactions.
|
|
466
|
+
*
|
|
467
|
+
* @remarks
|
|
468
|
+
* This is typically called after all UVE event handlers and DOM listeners
|
|
469
|
+
* have been set up successfully.
|
|
470
|
+
*/
|
|
471
|
+
function setClientIsReady() {
|
|
472
|
+
sendMessageToUVE({
|
|
473
|
+
action: DotCMSUVEAction.CLIENT_READY
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Listen for block editor inline event.
|
|
478
|
+
*/
|
|
479
|
+
function listenBlockEditorInlineEvent() {
|
|
480
|
+
if (document.readyState === 'complete') {
|
|
481
|
+
// The page is fully loaded or interactive
|
|
482
|
+
listenBlockEditorClick();
|
|
483
|
+
return {
|
|
484
|
+
destroyListenBlockEditorInlineEvent: () => {
|
|
485
|
+
window.removeEventListener('load', () => listenBlockEditorClick());
|
|
486
|
+
}
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
window.addEventListener('load', () => listenBlockEditorClick());
|
|
490
|
+
return {
|
|
491
|
+
destroyListenBlockEditorInlineEvent: () => {
|
|
492
|
+
window.removeEventListener('load', () => listenBlockEditorClick());
|
|
493
|
+
}
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
const listenBlockEditorClick = () => {
|
|
497
|
+
const editBlockEditorNodes = document.querySelectorAll('[data-block-editor-content]');
|
|
498
|
+
if (!editBlockEditorNodes.length) {
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
editBlockEditorNodes.forEach(node => {
|
|
502
|
+
const {
|
|
503
|
+
inode,
|
|
504
|
+
language = '1',
|
|
505
|
+
contentType,
|
|
506
|
+
fieldName,
|
|
507
|
+
blockEditorContent
|
|
508
|
+
} = node.dataset;
|
|
509
|
+
const content = JSON.parse(blockEditorContent || '');
|
|
510
|
+
if (!inode || !language || !contentType || !fieldName) {
|
|
511
|
+
console.error('Missing data attributes for block editor inline editing.');
|
|
512
|
+
console.warn('inode, language, contentType and fieldName are required.');
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
node.classList.add('dotcms__inline-edit-field');
|
|
516
|
+
node.addEventListener('click', () => {
|
|
517
|
+
initInlineEditing('BLOCK_EDITOR', {
|
|
518
|
+
inode,
|
|
519
|
+
content,
|
|
520
|
+
language: parseInt(language),
|
|
521
|
+
fieldName,
|
|
522
|
+
contentType
|
|
523
|
+
});
|
|
524
|
+
});
|
|
525
|
+
});
|
|
526
|
+
};
|
|
527
|
+
|
|
373
528
|
/**
|
|
374
529
|
* Post message to dotcms page editor
|
|
375
530
|
*
|
|
@@ -442,6 +597,146 @@ function initInlineEditing(type, data) {
|
|
|
442
597
|
}
|
|
443
598
|
});
|
|
444
599
|
}
|
|
600
|
+
/**
|
|
601
|
+
* Initializes the Universal Visual Editor (UVE) with required handlers and event listeners.
|
|
602
|
+
*
|
|
603
|
+
* This function sets up:
|
|
604
|
+
* - Scroll handling
|
|
605
|
+
* - Empty contentlet styling
|
|
606
|
+
* - Block editor inline event listening
|
|
607
|
+
* - Client ready state
|
|
608
|
+
* - UVE event subscriptions
|
|
609
|
+
*
|
|
610
|
+
* @returns {Object} An object containing the cleanup function
|
|
611
|
+
* @returns {Function} destroyUVESubscriptions - Function to clean up all UVE event subscriptions
|
|
612
|
+
*
|
|
613
|
+
* @example
|
|
614
|
+
* ```typescript
|
|
615
|
+
* const { destroyUVESubscriptions } = initUVE();
|
|
616
|
+
*
|
|
617
|
+
* // When done with UVE
|
|
618
|
+
* destroyUVESubscriptions();
|
|
619
|
+
* ```
|
|
620
|
+
*/
|
|
621
|
+
function initUVE() {
|
|
622
|
+
addClassToEmptyContentlets();
|
|
623
|
+
setClientIsReady();
|
|
624
|
+
const {
|
|
625
|
+
subscriptions
|
|
626
|
+
} = registerUVEEvents();
|
|
627
|
+
const {
|
|
628
|
+
destroyScrollHandler
|
|
629
|
+
} = scrollHandler();
|
|
630
|
+
const {
|
|
631
|
+
destroyListenBlockEditorInlineEvent
|
|
632
|
+
} = listenBlockEditorInlineEvent();
|
|
633
|
+
return {
|
|
634
|
+
destroyUVESubscriptions: () => {
|
|
635
|
+
subscriptions.forEach(subscription => subscription.unsubscribe());
|
|
636
|
+
destroyScrollHandler();
|
|
637
|
+
destroyListenBlockEditorInlineEvent();
|
|
638
|
+
}
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* Sets the bounds of the containers in the editor.
|
|
644
|
+
* Retrieves the containers from the DOM and sends their position data to the editor.
|
|
645
|
+
* @private
|
|
646
|
+
* @memberof DotCMSPageEditor
|
|
647
|
+
*/
|
|
648
|
+
function setBounds(bounds) {
|
|
649
|
+
sendMessageToUVE({
|
|
650
|
+
action: DotCMSUVEAction.SET_BOUNDS,
|
|
651
|
+
payload: bounds
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* Validates the structure of a Block Editor block.
|
|
656
|
+
*
|
|
657
|
+
* This function checks that:
|
|
658
|
+
* 1. The blocks parameter is a valid object
|
|
659
|
+
* 2. The block has a 'doc' type
|
|
660
|
+
* 3. The block has a valid content array that is not empty
|
|
661
|
+
*
|
|
662
|
+
* @param {Block} blocks - The blocks structure to validate
|
|
663
|
+
* @returns {BlockEditorState} Object containing validation state and any error message
|
|
664
|
+
* @property {boolean} BlockEditorState.isValid - Whether the blocks structure is valid
|
|
665
|
+
* @property {string | null} BlockEditorState.error - Error message if invalid, null if valid
|
|
666
|
+
*/
|
|
667
|
+
const isValidBlocks = blocks => {
|
|
668
|
+
if (!blocks) {
|
|
669
|
+
return {
|
|
670
|
+
error: `Error: Blocks object is not defined`
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
if (typeof blocks !== 'object') {
|
|
674
|
+
return {
|
|
675
|
+
error: `Error: Blocks must be an object, but received: ${typeof blocks}`
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
if (blocks.type !== 'doc') {
|
|
679
|
+
return {
|
|
680
|
+
error: `Error: Invalid block type. Expected 'doc' but received: '${blocks.type}'`
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
if (!blocks.content) {
|
|
684
|
+
return {
|
|
685
|
+
error: 'Error: Blocks content is missing'
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
if (!Array.isArray(blocks.content)) {
|
|
689
|
+
return {
|
|
690
|
+
error: `Error: Blocks content must be an array, but received: ${typeof blocks.content}`
|
|
691
|
+
};
|
|
692
|
+
}
|
|
693
|
+
if (blocks.content.length === 0) {
|
|
694
|
+
return {
|
|
695
|
+
error: 'Error: Blocks content is empty. At least one block is required.'
|
|
696
|
+
};
|
|
697
|
+
}
|
|
698
|
+
// Validate each block in the content array
|
|
699
|
+
for (let i = 0; i < blocks.content.length; i++) {
|
|
700
|
+
const block = blocks.content[i];
|
|
701
|
+
if (!block.type) {
|
|
702
|
+
return {
|
|
703
|
+
error: `Error: Block at index ${i} is missing required 'type' property`
|
|
704
|
+
};
|
|
705
|
+
}
|
|
706
|
+
if (typeof block.type !== 'string') {
|
|
707
|
+
return {
|
|
708
|
+
error: `Error: Block type at index ${i} must be a string, but received: ${typeof block.type}`
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
// Validate block attributes if present
|
|
712
|
+
if (block.attrs && typeof block.attrs !== 'object') {
|
|
713
|
+
return {
|
|
714
|
+
error: `Error: Block attributes at index ${i} must be an object, but received: ${typeof block.attrs}`
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
// Validate nested content if present
|
|
718
|
+
if (block.content) {
|
|
719
|
+
if (!Array.isArray(block.content)) {
|
|
720
|
+
return {
|
|
721
|
+
error: `Error: Block content at index ${i} must be an array, but received: ${typeof block.content}`
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
// Recursively validate nested blocks
|
|
725
|
+
const nestedValidation = isValidBlocks({
|
|
726
|
+
type: 'doc',
|
|
727
|
+
content: block.content
|
|
728
|
+
});
|
|
729
|
+
if (nestedValidation.error) {
|
|
730
|
+
return {
|
|
731
|
+
error: `Error in nested block at index ${i}: ${nestedValidation.error}`
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
return {
|
|
737
|
+
error: null
|
|
738
|
+
};
|
|
739
|
+
};
|
|
445
740
|
|
|
446
741
|
/**
|
|
447
742
|
* Enum representing the different types of blocks available in the Block Editor
|
|
@@ -737,4 +1032,87 @@ const EMPTY_CONTAINER_STYLE_ANGULAR = {
|
|
|
737
1032
|
*/
|
|
738
1033
|
const CUSTOM_NO_COMPONENT = 'CustomNoComponent';
|
|
739
1034
|
|
|
740
|
-
|
|
1035
|
+
/**
|
|
1036
|
+
* Gets the current state of the Universal Visual Editor (UVE).
|
|
1037
|
+
*
|
|
1038
|
+
* This function checks if the code is running inside the DotCMS Universal Visual Editor
|
|
1039
|
+
* and returns information about its current state, including the editor mode.
|
|
1040
|
+
*
|
|
1041
|
+
* @export
|
|
1042
|
+
* @return {UVEState | undefined} Returns the UVE state object if running inside the editor,
|
|
1043
|
+
* undefined otherwise.
|
|
1044
|
+
*
|
|
1045
|
+
* The state includes:
|
|
1046
|
+
* - mode: The current editor mode (preview, edit, live)
|
|
1047
|
+
* - languageId: The language ID of the current page setted on the UVE
|
|
1048
|
+
* - persona: The persona of the current page setted on the UVE
|
|
1049
|
+
* - variantName: The name of the current variant
|
|
1050
|
+
* - experimentId: The ID of the current experiment
|
|
1051
|
+
* - publishDate: The publish date of the current page setted on the UVE
|
|
1052
|
+
*
|
|
1053
|
+
* @note The absence of any of these properties means that the value is the default one.
|
|
1054
|
+
*
|
|
1055
|
+
* @example
|
|
1056
|
+
* ```ts
|
|
1057
|
+
* const editorState = getUVEState();
|
|
1058
|
+
* if (editorState?.mode === 'edit') {
|
|
1059
|
+
* // Enable editing features
|
|
1060
|
+
* }
|
|
1061
|
+
* ```
|
|
1062
|
+
*/
|
|
1063
|
+
function getUVEState() {
|
|
1064
|
+
if (typeof window === 'undefined' || window.parent === window || !window.location) {
|
|
1065
|
+
return undefined;
|
|
1066
|
+
}
|
|
1067
|
+
const url = new URL(window.location.href);
|
|
1068
|
+
const possibleModes = Object.values(UVE_MODE);
|
|
1069
|
+
let mode = url.searchParams.get('mode') ?? UVE_MODE.EDIT;
|
|
1070
|
+
const languageId = url.searchParams.get('language_id');
|
|
1071
|
+
const persona = url.searchParams.get('personaId');
|
|
1072
|
+
const variantName = url.searchParams.get('variantName');
|
|
1073
|
+
const experimentId = url.searchParams.get('experimentId');
|
|
1074
|
+
const publishDate = url.searchParams.get('publishDate');
|
|
1075
|
+
if (!possibleModes.includes(mode)) {
|
|
1076
|
+
mode = UVE_MODE.EDIT;
|
|
1077
|
+
}
|
|
1078
|
+
return {
|
|
1079
|
+
mode,
|
|
1080
|
+
languageId,
|
|
1081
|
+
persona,
|
|
1082
|
+
variantName,
|
|
1083
|
+
experimentId,
|
|
1084
|
+
publishDate
|
|
1085
|
+
};
|
|
1086
|
+
}
|
|
1087
|
+
/**
|
|
1088
|
+
* Creates a subscription to a UVE event.
|
|
1089
|
+
*
|
|
1090
|
+
* @param eventType - The type of event to subscribe to
|
|
1091
|
+
* @param callback - The callback function that will be called when the event occurs
|
|
1092
|
+
* @returns An event subscription that can be used to unsubscribe
|
|
1093
|
+
*
|
|
1094
|
+
* @example
|
|
1095
|
+
* ```ts
|
|
1096
|
+
* // Subscribe to page changes
|
|
1097
|
+
* const subscription = createUVESubscription(UVEEventType.CONTENT_CHANGES, (changes) => {
|
|
1098
|
+
* console.log('Content changes:', changes);
|
|
1099
|
+
* });
|
|
1100
|
+
*
|
|
1101
|
+
* // Later, unsubscribe when no longer needed
|
|
1102
|
+
* subscription.unsubscribe();
|
|
1103
|
+
* ```
|
|
1104
|
+
*/
|
|
1105
|
+
function createUVESubscription(eventType, callback) {
|
|
1106
|
+
if (!getUVEState()) {
|
|
1107
|
+
console.warn('UVE Subscription: Not running inside UVE');
|
|
1108
|
+
return __UVE_EVENT_ERROR_FALLBACK__(eventType);
|
|
1109
|
+
}
|
|
1110
|
+
const eventCallback = __UVE_EVENTS__[eventType];
|
|
1111
|
+
if (!eventCallback) {
|
|
1112
|
+
console.error(`UVE Subscription: Event ${eventType} not found`);
|
|
1113
|
+
return __UVE_EVENT_ERROR_FALLBACK__(eventType);
|
|
1114
|
+
}
|
|
1115
|
+
return eventCallback(callback);
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
export { Blocks as B, CUSTOM_NO_COMPONENT as C, DEVELOPMENT_MODE as D, END_CLASS as E, PRODUCTION_MODE as P, START_CLASS as S, __UVE_EVENTS__ as _, __UVE_EVENT_ERROR_FALLBACK__ as a, EMPTY_CONTAINER_STYLE_REACT as b, EMPTY_CONTAINER_STYLE_ANGULAR as c, __DOTCMS_UVE_EVENT__ as d, getDotCMSContentletsBound as e, getDotCMSContainerData as f, getDotCMSPageBounds as g, getClosestDotCMSContainerData as h, findDotCMSElement as i, findDotCMSVTLData as j, computeScrollIsInBottom as k, combineClasses as l, getColumnPositionClasses as m, getDotContentletAttributes as n, getContainersData as o, getContentletsInContainer as p, getDotContainerAttributes as q, isValidBlocks as r, setBounds as s, getUVEState as t, createUVESubscription as u, sendMessageToUVE as v, editContentlet as w, reorderMenu as x, initInlineEditing as y, initUVE as z };
|
package/internal.cjs.js
CHANGED
|
@@ -1,136 +1,39 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
|
|
3
|
+
var internal = require('./index.cjs2.js');
|
|
4
|
+
require('./types.cjs.js');
|
|
5
|
+
|
|
5
6
|
|
|
6
|
-
/**
|
|
7
|
-
* Sets the bounds of the containers in the editor.
|
|
8
|
-
* Retrieves the containers from the DOM and sends their position data to the editor.
|
|
9
|
-
* @private
|
|
10
|
-
* @memberof DotCMSPageEditor
|
|
11
|
-
*/
|
|
12
|
-
function setBounds(bounds) {
|
|
13
|
-
constants.sendMessageToUVE({
|
|
14
|
-
action: types.DotCMSUVEAction.SET_BOUNDS,
|
|
15
|
-
payload: bounds
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Validates the structure of a Block Editor block.
|
|
20
|
-
*
|
|
21
|
-
* This function checks that:
|
|
22
|
-
* 1. The blocks parameter is a valid object
|
|
23
|
-
* 2. The block has a 'doc' type
|
|
24
|
-
* 3. The block has a valid content array that is not empty
|
|
25
|
-
*
|
|
26
|
-
* @param {Block} blocks - The blocks structure to validate
|
|
27
|
-
* @returns {BlockEditorState} Object containing validation state and any error message
|
|
28
|
-
* @property {boolean} BlockEditorState.isValid - Whether the blocks structure is valid
|
|
29
|
-
* @property {string | null} BlockEditorState.error - Error message if invalid, null if valid
|
|
30
|
-
*/
|
|
31
|
-
const isValidBlocks = blocks => {
|
|
32
|
-
if (!blocks) {
|
|
33
|
-
return {
|
|
34
|
-
error: `Error: Blocks object is not defined`
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
if (typeof blocks !== 'object') {
|
|
38
|
-
return {
|
|
39
|
-
error: `Error: Blocks must be an object, but received: ${typeof blocks}`
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
if (blocks.type !== 'doc') {
|
|
43
|
-
return {
|
|
44
|
-
error: `Error: Invalid block type. Expected 'doc' but received: '${blocks.type}'`
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
if (!blocks.content) {
|
|
48
|
-
return {
|
|
49
|
-
error: 'Error: Blocks content is missing'
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
if (!Array.isArray(blocks.content)) {
|
|
53
|
-
return {
|
|
54
|
-
error: `Error: Blocks content must be an array, but received: ${typeof blocks.content}`
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
if (blocks.content.length === 0) {
|
|
58
|
-
return {
|
|
59
|
-
error: 'Error: Blocks content is empty. At least one block is required.'
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
// Validate each block in the content array
|
|
63
|
-
for (let i = 0; i < blocks.content.length; i++) {
|
|
64
|
-
const block = blocks.content[i];
|
|
65
|
-
if (!block.type) {
|
|
66
|
-
return {
|
|
67
|
-
error: `Error: Block at index ${i} is missing required 'type' property`
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
if (typeof block.type !== 'string') {
|
|
71
|
-
return {
|
|
72
|
-
error: `Error: Block type at index ${i} must be a string, but received: ${typeof block.type}`
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
// Validate block attributes if present
|
|
76
|
-
if (block.attrs && typeof block.attrs !== 'object') {
|
|
77
|
-
return {
|
|
78
|
-
error: `Error: Block attributes at index ${i} must be an object, but received: ${typeof block.attrs}`
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
// Validate nested content if present
|
|
82
|
-
if (block.content) {
|
|
83
|
-
if (!Array.isArray(block.content)) {
|
|
84
|
-
return {
|
|
85
|
-
error: `Error: Block content at index ${i} must be an array, but received: ${typeof block.content}`
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
// Recursively validate nested blocks
|
|
89
|
-
const nestedValidation = isValidBlocks({
|
|
90
|
-
type: 'doc',
|
|
91
|
-
content: block.content
|
|
92
|
-
});
|
|
93
|
-
if (nestedValidation.error) {
|
|
94
|
-
return {
|
|
95
|
-
error: `Error in nested block at index ${i}: ${nestedValidation.error}`
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
return {
|
|
101
|
-
error: null
|
|
102
|
-
};
|
|
103
|
-
};
|
|
104
7
|
|
|
105
8
|
Object.defineProperty(exports, "Blocks", {
|
|
106
|
-
|
|
107
|
-
|
|
9
|
+
enumerable: true,
|
|
10
|
+
get: function () { return internal.Blocks; }
|
|
108
11
|
});
|
|
109
|
-
exports.CUSTOM_NO_COMPONENT =
|
|
110
|
-
exports.DEVELOPMENT_MODE =
|
|
111
|
-
exports.EMPTY_CONTAINER_STYLE_ANGULAR =
|
|
112
|
-
exports.EMPTY_CONTAINER_STYLE_REACT =
|
|
113
|
-
exports.END_CLASS =
|
|
114
|
-
exports.PRODUCTION_MODE =
|
|
115
|
-
exports.START_CLASS =
|
|
12
|
+
exports.CUSTOM_NO_COMPONENT = internal.CUSTOM_NO_COMPONENT;
|
|
13
|
+
exports.DEVELOPMENT_MODE = internal.DEVELOPMENT_MODE;
|
|
14
|
+
exports.EMPTY_CONTAINER_STYLE_ANGULAR = internal.EMPTY_CONTAINER_STYLE_ANGULAR;
|
|
15
|
+
exports.EMPTY_CONTAINER_STYLE_REACT = internal.EMPTY_CONTAINER_STYLE_REACT;
|
|
16
|
+
exports.END_CLASS = internal.END_CLASS;
|
|
17
|
+
exports.PRODUCTION_MODE = internal.PRODUCTION_MODE;
|
|
18
|
+
exports.START_CLASS = internal.START_CLASS;
|
|
116
19
|
Object.defineProperty(exports, "__DOTCMS_UVE_EVENT__", {
|
|
117
|
-
|
|
118
|
-
|
|
20
|
+
enumerable: true,
|
|
21
|
+
get: function () { return internal.__DOTCMS_UVE_EVENT__; }
|
|
119
22
|
});
|
|
120
|
-
exports.__UVE_EVENTS__ =
|
|
121
|
-
exports.__UVE_EVENT_ERROR_FALLBACK__ =
|
|
122
|
-
exports.combineClasses =
|
|
123
|
-
exports.computeScrollIsInBottom =
|
|
124
|
-
exports.findDotCMSElement =
|
|
125
|
-
exports.findDotCMSVTLData =
|
|
126
|
-
exports.getClosestDotCMSContainerData =
|
|
127
|
-
exports.getColumnPositionClasses =
|
|
128
|
-
exports.getContainersData =
|
|
129
|
-
exports.getContentletsInContainer =
|
|
130
|
-
exports.getDotCMSContainerData =
|
|
131
|
-
exports.getDotCMSContentletsBound =
|
|
132
|
-
exports.getDotCMSPageBounds =
|
|
133
|
-
exports.getDotContainerAttributes =
|
|
134
|
-
exports.getDotContentletAttributes =
|
|
135
|
-
exports.isValidBlocks = isValidBlocks;
|
|
136
|
-
exports.setBounds = setBounds;
|
|
23
|
+
exports.__UVE_EVENTS__ = internal.__UVE_EVENTS__;
|
|
24
|
+
exports.__UVE_EVENT_ERROR_FALLBACK__ = internal.__UVE_EVENT_ERROR_FALLBACK__;
|
|
25
|
+
exports.combineClasses = internal.combineClasses;
|
|
26
|
+
exports.computeScrollIsInBottom = internal.computeScrollIsInBottom;
|
|
27
|
+
exports.findDotCMSElement = internal.findDotCMSElement;
|
|
28
|
+
exports.findDotCMSVTLData = internal.findDotCMSVTLData;
|
|
29
|
+
exports.getClosestDotCMSContainerData = internal.getClosestDotCMSContainerData;
|
|
30
|
+
exports.getColumnPositionClasses = internal.getColumnPositionClasses;
|
|
31
|
+
exports.getContainersData = internal.getContainersData;
|
|
32
|
+
exports.getContentletsInContainer = internal.getContentletsInContainer;
|
|
33
|
+
exports.getDotCMSContainerData = internal.getDotCMSContainerData;
|
|
34
|
+
exports.getDotCMSContentletsBound = internal.getDotCMSContentletsBound;
|
|
35
|
+
exports.getDotCMSPageBounds = internal.getDotCMSPageBounds;
|
|
36
|
+
exports.getDotContainerAttributes = internal.getDotContainerAttributes;
|
|
37
|
+
exports.getDotContentletAttributes = internal.getDotContentletAttributes;
|
|
38
|
+
exports.isValidBlocks = internal.isValidBlocks;
|
|
39
|
+
exports.setBounds = internal.setBounds;
|
package/internal.esm.js
CHANGED
|
@@ -1,104 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { DotCMSUVEAction } from './types.esm.js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Sets the bounds of the containers in the editor.
|
|
7
|
-
* Retrieves the containers from the DOM and sends their position data to the editor.
|
|
8
|
-
* @private
|
|
9
|
-
* @memberof DotCMSPageEditor
|
|
10
|
-
*/
|
|
11
|
-
function setBounds(bounds) {
|
|
12
|
-
sendMessageToUVE({
|
|
13
|
-
action: DotCMSUVEAction.SET_BOUNDS,
|
|
14
|
-
payload: bounds
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Validates the structure of a Block Editor block.
|
|
19
|
-
*
|
|
20
|
-
* This function checks that:
|
|
21
|
-
* 1. The blocks parameter is a valid object
|
|
22
|
-
* 2. The block has a 'doc' type
|
|
23
|
-
* 3. The block has a valid content array that is not empty
|
|
24
|
-
*
|
|
25
|
-
* @param {Block} blocks - The blocks structure to validate
|
|
26
|
-
* @returns {BlockEditorState} Object containing validation state and any error message
|
|
27
|
-
* @property {boolean} BlockEditorState.isValid - Whether the blocks structure is valid
|
|
28
|
-
* @property {string | null} BlockEditorState.error - Error message if invalid, null if valid
|
|
29
|
-
*/
|
|
30
|
-
const isValidBlocks = blocks => {
|
|
31
|
-
if (!blocks) {
|
|
32
|
-
return {
|
|
33
|
-
error: `Error: Blocks object is not defined`
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
if (typeof blocks !== 'object') {
|
|
37
|
-
return {
|
|
38
|
-
error: `Error: Blocks must be an object, but received: ${typeof blocks}`
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
if (blocks.type !== 'doc') {
|
|
42
|
-
return {
|
|
43
|
-
error: `Error: Invalid block type. Expected 'doc' but received: '${blocks.type}'`
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
if (!blocks.content) {
|
|
47
|
-
return {
|
|
48
|
-
error: 'Error: Blocks content is missing'
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
if (!Array.isArray(blocks.content)) {
|
|
52
|
-
return {
|
|
53
|
-
error: `Error: Blocks content must be an array, but received: ${typeof blocks.content}`
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
if (blocks.content.length === 0) {
|
|
57
|
-
return {
|
|
58
|
-
error: 'Error: Blocks content is empty. At least one block is required.'
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
// Validate each block in the content array
|
|
62
|
-
for (let i = 0; i < blocks.content.length; i++) {
|
|
63
|
-
const block = blocks.content[i];
|
|
64
|
-
if (!block.type) {
|
|
65
|
-
return {
|
|
66
|
-
error: `Error: Block at index ${i} is missing required 'type' property`
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
if (typeof block.type !== 'string') {
|
|
70
|
-
return {
|
|
71
|
-
error: `Error: Block type at index ${i} must be a string, but received: ${typeof block.type}`
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
// Validate block attributes if present
|
|
75
|
-
if (block.attrs && typeof block.attrs !== 'object') {
|
|
76
|
-
return {
|
|
77
|
-
error: `Error: Block attributes at index ${i} must be an object, but received: ${typeof block.attrs}`
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
// Validate nested content if present
|
|
81
|
-
if (block.content) {
|
|
82
|
-
if (!Array.isArray(block.content)) {
|
|
83
|
-
return {
|
|
84
|
-
error: `Error: Block content at index ${i} must be an array, but received: ${typeof block.content}`
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
// Recursively validate nested blocks
|
|
88
|
-
const nestedValidation = isValidBlocks({
|
|
89
|
-
type: 'doc',
|
|
90
|
-
content: block.content
|
|
91
|
-
});
|
|
92
|
-
if (nestedValidation.error) {
|
|
93
|
-
return {
|
|
94
|
-
error: `Error in nested block at index ${i}: ${nestedValidation.error}`
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
return {
|
|
100
|
-
error: null
|
|
101
|
-
};
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
export { isValidBlocks, setBounds };
|
|
1
|
+
export { B as Blocks, C as CUSTOM_NO_COMPONENT, D as DEVELOPMENT_MODE, c as EMPTY_CONTAINER_STYLE_ANGULAR, b as EMPTY_CONTAINER_STYLE_REACT, E as END_CLASS, P as PRODUCTION_MODE, S as START_CLASS, d as __DOTCMS_UVE_EVENT__, _ as __UVE_EVENTS__, a as __UVE_EVENT_ERROR_FALLBACK__, l as combineClasses, k as computeScrollIsInBottom, i as findDotCMSElement, j as findDotCMSVTLData, h as getClosestDotCMSContainerData, m as getColumnPositionClasses, o as getContainersData, p as getContentletsInContainer, f as getDotCMSContainerData, e as getDotCMSContentletsBound, g as getDotCMSPageBounds, q as getDotContainerAttributes, n as getDotContentletAttributes, r as isValidBlocks, s as setBounds } from './index.esm2.js';
|
|
2
|
+
import './types.esm.js';
|
package/package.json
CHANGED
|
@@ -36,3 +36,27 @@ export declare function reorderMenu(config?: DotCMSReorderMenuConfig): void;
|
|
|
36
36
|
* ```
|
|
37
37
|
*/
|
|
38
38
|
export declare function initInlineEditing(type: DotCMSInlineEditingType, data?: DotCMSInlineEditingPayload): void;
|
|
39
|
+
/**
|
|
40
|
+
* Initializes the Universal Visual Editor (UVE) with required handlers and event listeners.
|
|
41
|
+
*
|
|
42
|
+
* This function sets up:
|
|
43
|
+
* - Scroll handling
|
|
44
|
+
* - Empty contentlet styling
|
|
45
|
+
* - Block editor inline event listening
|
|
46
|
+
* - Client ready state
|
|
47
|
+
* - UVE event subscriptions
|
|
48
|
+
*
|
|
49
|
+
* @returns {Object} An object containing the cleanup function
|
|
50
|
+
* @returns {Function} destroyUVESubscriptions - Function to clean up all UVE event subscriptions
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* const { destroyUVESubscriptions } = initUVE();
|
|
55
|
+
*
|
|
56
|
+
* // When done with UVE
|
|
57
|
+
* destroyUVESubscriptions();
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare function initUVE(): {
|
|
61
|
+
destroyUVESubscriptions: () => void;
|
|
62
|
+
};
|
package/src/script/utils.d.ts
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
* Adds listeners for both 'scroll' and 'scrollend' events, sending appropriate messages
|
|
4
4
|
* to the editor when these events occur.
|
|
5
5
|
*/
|
|
6
|
-
export declare function scrollHandler():
|
|
6
|
+
export declare function scrollHandler(): {
|
|
7
|
+
destroyScrollHandler: () => void;
|
|
8
|
+
};
|
|
7
9
|
/**
|
|
8
10
|
* Adds 'empty-contentlet' class to contentlet elements that have no height.
|
|
9
11
|
* This helps identify and style empty contentlets in the editor view.
|
|
@@ -28,7 +30,9 @@ export declare function addClassToEmptyContentlets(): void;
|
|
|
28
30
|
* the top or bottom boundaries of the iframe, which helps maintain proper
|
|
29
31
|
* scroll event handling.
|
|
30
32
|
*/
|
|
31
|
-
export declare function registerUVEEvents():
|
|
33
|
+
export declare function registerUVEEvents(): {
|
|
34
|
+
subscriptions: import("../lib/types/editor/public").UVEEventSubscription[];
|
|
35
|
+
};
|
|
32
36
|
/**
|
|
33
37
|
* Notifies the editor that the UVE client is ready to receive messages.
|
|
34
38
|
*
|
|
@@ -43,4 +47,6 @@ export declare function setClientIsReady(): void;
|
|
|
43
47
|
/**
|
|
44
48
|
* Listen for block editor inline event.
|
|
45
49
|
*/
|
|
46
|
-
export declare
|
|
50
|
+
export declare function listenBlockEditorInlineEvent(): {
|
|
51
|
+
destroyListenBlockEditorInlineEvent: () => void;
|
|
52
|
+
};
|