@dotcms/uve 0.0.1-beta.24 → 0.0.1-beta.26
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 -9
- package/index.esm.js +3 -2
- package/internal.cjs.js +99 -35
- package/internal.esm.js +75 -2
- package/package.json +4 -10
- package/{index.cjs2.js → public.cjs.js} +504 -577
- package/{index.esm2.js → public.esm.js} +506 -579
- package/src/internal/constants.d.ts +1 -1
- package/src/internal/events.d.ts +1 -1
- package/src/internal/index.d.ts +1 -0
- package/src/internal/tinymce.config.d.ts +45 -0
- package/src/internal.d.ts +0 -3
- package/src/lib/core/core.utils.d.ts +1 -1
- package/src/lib/dom/dom.utils.d.ts +6 -7
- package/src/lib/editor/internal.d.ts +3 -3
- package/src/lib/editor/public.d.ts +2 -3
- package/src/script/utils.d.ts +2 -2
- package/src/lib/types/block-editor-renderer/internal.d.ts +0 -46
- package/src/lib/types/block-editor-renderer/public.d.ts +0 -38
- package/src/lib/types/editor/internal.d.ts +0 -119
- package/src/lib/types/editor/public.d.ts +0 -273
- package/src/lib/types/events/internal.d.ts +0 -34
- package/src/lib/types/events/public.d.ts +0 -18
- package/src/lib/types/page/public.d.ts +0 -485
- package/src/types.d.ts +0 -4
- package/types.cjs.d.ts +0 -1
- package/types.cjs.default.js +0 -1
- package/types.cjs.js +0 -111
- package/types.cjs.mjs +0 -2
- package/types.esm.d.ts +0 -1
- package/types.esm.js +0 -111
|
@@ -1,42 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var types = require('
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Actions received from the dotcms editor
|
|
7
|
-
*
|
|
8
|
-
* @export
|
|
9
|
-
* @enum {number}
|
|
10
|
-
*/
|
|
11
|
-
exports.__DOTCMS_UVE_EVENT__ = void 0;
|
|
12
|
-
(function (__DOTCMS_UVE_EVENT__) {
|
|
13
|
-
/**
|
|
14
|
-
* Request to page to reload
|
|
15
|
-
*/
|
|
16
|
-
__DOTCMS_UVE_EVENT__["UVE_RELOAD_PAGE"] = "uve-reload-page";
|
|
17
|
-
/**
|
|
18
|
-
* Request the bounds for the elements
|
|
19
|
-
*/
|
|
20
|
-
__DOTCMS_UVE_EVENT__["UVE_REQUEST_BOUNDS"] = "uve-request-bounds";
|
|
21
|
-
/**
|
|
22
|
-
* Received pong from the editor
|
|
23
|
-
*/
|
|
24
|
-
__DOTCMS_UVE_EVENT__["UVE_EDITOR_PONG"] = "uve-editor-pong";
|
|
25
|
-
/**
|
|
26
|
-
* Received scroll event trigger from the editor
|
|
27
|
-
*/
|
|
28
|
-
__DOTCMS_UVE_EVENT__["UVE_SCROLL_INSIDE_IFRAME"] = "uve-scroll-inside-iframe";
|
|
29
|
-
/**
|
|
30
|
-
* TODO:
|
|
31
|
-
* Set the page data - This is used to catch the "changes" event.
|
|
32
|
-
* We must to re-check the name late.
|
|
33
|
-
*/
|
|
34
|
-
__DOTCMS_UVE_EVENT__["UVE_SET_PAGE_DATA"] = "uve-set-page-data";
|
|
35
|
-
/**
|
|
36
|
-
* Copy contentlet inline editing success
|
|
37
|
-
*/
|
|
38
|
-
__DOTCMS_UVE_EVENT__["UVE_COPY_CONTENTLET_INLINE_EDITING_SUCCESS"] = "uve-copy-contentlet-inline-editing-success";
|
|
39
|
-
})(exports.__DOTCMS_UVE_EVENT__ || (exports.__DOTCMS_UVE_EVENT__ = {}));
|
|
3
|
+
var types = require('@dotcms/types');
|
|
4
|
+
var internal = require('@dotcms/types/internal');
|
|
40
5
|
|
|
41
6
|
/**
|
|
42
7
|
* Calculates the bounding information for each page element within the given containers.
|
|
@@ -255,7 +220,7 @@ const getColumnPositionClasses = column => {
|
|
|
255
220
|
*
|
|
256
221
|
*
|
|
257
222
|
* Helper function that returns an object containing the dotCMS data attributes.
|
|
258
|
-
* @param {
|
|
223
|
+
* @param {DotCMSBasicContentlet} contentlet - The contentlet to get the attributes for
|
|
259
224
|
* @param {string} container - The container to get the attributes for
|
|
260
225
|
* @returns {DotContentletAttributes} The dotCMS data attributes
|
|
261
226
|
*/
|
|
@@ -267,7 +232,7 @@ function getDotContentletAttributes(contentlet, container) {
|
|
|
267
232
|
'data-dot-inode': contentlet?.inode,
|
|
268
233
|
'data-dot-type': contentlet?.contentType,
|
|
269
234
|
'data-dot-container': container,
|
|
270
|
-
'data-dot-on-number-of-pages': contentlet?.['onNumberOfPages']
|
|
235
|
+
'data-dot-on-number-of-pages': contentlet?.['onNumberOfPages'] || '1'
|
|
271
236
|
};
|
|
272
237
|
}
|
|
273
238
|
/**
|
|
@@ -319,7 +284,7 @@ const getContainersData = (dotCMSPageAsset, columContainer) => {
|
|
|
319
284
|
*
|
|
320
285
|
* @param {DotCMSPageAsset} dotCMSPageAsset - The page asset containing all containers data
|
|
321
286
|
* @param {DotCMSColumnContainer} columContainer - The container reference from the layout
|
|
322
|
-
* @returns {
|
|
287
|
+
* @returns {DotCMSBasicContentlet[]} Array of contentlets in the container
|
|
323
288
|
*
|
|
324
289
|
* @example
|
|
325
290
|
* const contentlets = getContentletsInContainer(pageAsset, containerRef);
|
|
@@ -372,274 +337,345 @@ function getDotContainerAttributes({
|
|
|
372
337
|
};
|
|
373
338
|
}
|
|
374
339
|
|
|
375
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
376
340
|
/**
|
|
377
|
-
*
|
|
378
|
-
*
|
|
379
|
-
* to
|
|
341
|
+
* Subscribes to content changes in the UVE editor
|
|
342
|
+
*
|
|
343
|
+
* @param {UVEEventHandler} callback - Function to be called when content changes are detected
|
|
344
|
+
* @returns {Object} Object containing unsubscribe function and event type
|
|
345
|
+
* @returns {Function} .unsubscribe - Function to remove the event listener
|
|
346
|
+
* @returns {UVEEventType} .event - The event type being subscribed to
|
|
347
|
+
* @internal
|
|
380
348
|
*/
|
|
381
|
-
function
|
|
382
|
-
const
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
}
|
|
386
|
-
};
|
|
387
|
-
const scrollEndCallback = () => {
|
|
388
|
-
sendMessageToUVE({
|
|
389
|
-
action: types.DotCMSUVEAction.IFRAME_SCROLL_END
|
|
390
|
-
});
|
|
349
|
+
function onContentChanges(callback) {
|
|
350
|
+
const messageCallback = event => {
|
|
351
|
+
if (event.data.name === internal.__DOTCMS_UVE_EVENT__.UVE_SET_PAGE_DATA) {
|
|
352
|
+
callback(event.data.payload);
|
|
353
|
+
}
|
|
391
354
|
};
|
|
392
|
-
window.addEventListener('
|
|
393
|
-
window.addEventListener('scrollend', scrollEndCallback);
|
|
355
|
+
window.addEventListener('message', messageCallback);
|
|
394
356
|
return {
|
|
395
|
-
|
|
396
|
-
window.removeEventListener('
|
|
397
|
-
|
|
398
|
-
|
|
357
|
+
unsubscribe: () => {
|
|
358
|
+
window.removeEventListener('message', messageCallback);
|
|
359
|
+
},
|
|
360
|
+
event: types.UVEEventType.CONTENT_CHANGES
|
|
399
361
|
};
|
|
400
362
|
}
|
|
401
363
|
/**
|
|
402
|
-
*
|
|
403
|
-
* This helps identify and style empty contentlets in the editor view.
|
|
364
|
+
* Subscribes to page reload events in the UVE editor
|
|
404
365
|
*
|
|
405
|
-
* @
|
|
406
|
-
*
|
|
407
|
-
*
|
|
408
|
-
*
|
|
366
|
+
* @param {UVEEventHandler} callback - Function to be called when page reload is triggered
|
|
367
|
+
* @returns {Object} Object containing unsubscribe function and event type
|
|
368
|
+
* @returns {Function} .unsubscribe - Function to remove the event listener
|
|
369
|
+
* @returns {UVEEventType} .event - The event type being subscribed to
|
|
370
|
+
* @internal
|
|
409
371
|
*/
|
|
410
|
-
function
|
|
411
|
-
const
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
return;
|
|
372
|
+
function onPageReload(callback) {
|
|
373
|
+
const messageCallback = event => {
|
|
374
|
+
if (event.data.name === internal.__DOTCMS_UVE_EVENT__.UVE_RELOAD_PAGE) {
|
|
375
|
+
callback();
|
|
415
376
|
}
|
|
416
|
-
|
|
417
|
-
|
|
377
|
+
};
|
|
378
|
+
window.addEventListener('message', messageCallback);
|
|
379
|
+
return {
|
|
380
|
+
unsubscribe: () => {
|
|
381
|
+
window.removeEventListener('message', messageCallback);
|
|
382
|
+
},
|
|
383
|
+
event: types.UVEEventType.PAGE_RELOAD
|
|
384
|
+
};
|
|
418
385
|
}
|
|
419
386
|
/**
|
|
420
|
-
*
|
|
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
|
|
387
|
+
* Subscribes to request bounds events in the UVE editor
|
|
427
388
|
*
|
|
428
|
-
* @
|
|
429
|
-
*
|
|
430
|
-
*
|
|
431
|
-
*
|
|
389
|
+
* @param {UVEEventHandler} callback - Function to be called when bounds are requested
|
|
390
|
+
* @returns {Object} Object containing unsubscribe function and event type
|
|
391
|
+
* @returns {Function} .unsubscribe - Function to remove the event listener
|
|
392
|
+
* @returns {UVEEventType} .event - The event type being subscribed to
|
|
393
|
+
* @internal
|
|
432
394
|
*/
|
|
433
|
-
function
|
|
434
|
-
const
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
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;
|
|
395
|
+
function onRequestBounds(callback) {
|
|
396
|
+
const messageCallback = event => {
|
|
397
|
+
if (event.data.name === internal.__DOTCMS_UVE_EVENT__.UVE_REQUEST_BOUNDS) {
|
|
398
|
+
const containers = Array.from(document.querySelectorAll('[data-dot-object="container"]'));
|
|
399
|
+
const positionData = getDotCMSPageBounds(containers);
|
|
400
|
+
callback(positionData);
|
|
445
401
|
}
|
|
446
|
-
|
|
447
|
-
|
|
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
|
-
});
|
|
402
|
+
};
|
|
403
|
+
window.addEventListener('message', messageCallback);
|
|
459
404
|
return {
|
|
460
|
-
|
|
405
|
+
unsubscribe: () => {
|
|
406
|
+
window.removeEventListener('message', messageCallback);
|
|
407
|
+
},
|
|
408
|
+
event: types.UVEEventType.REQUEST_BOUNDS
|
|
461
409
|
};
|
|
462
410
|
}
|
|
463
411
|
/**
|
|
464
|
-
*
|
|
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.
|
|
412
|
+
* Subscribes to iframe scroll events in the UVE editor
|
|
468
413
|
*
|
|
469
|
-
* @
|
|
470
|
-
*
|
|
471
|
-
*
|
|
414
|
+
* @param {UVEEventHandler} callback - Function to be called when iframe scroll occurs
|
|
415
|
+
* @returns {Object} Object containing unsubscribe function and event type
|
|
416
|
+
* @returns {Function} .unsubscribe - Function to remove the event listener
|
|
417
|
+
* @returns {UVEEventType} .event - The event type being subscribed to
|
|
418
|
+
* @internal
|
|
472
419
|
*/
|
|
473
|
-
function
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
420
|
+
function onIframeScroll(callback) {
|
|
421
|
+
const messageCallback = event => {
|
|
422
|
+
if (event.data.name === internal.__DOTCMS_UVE_EVENT__.UVE_SCROLL_INSIDE_IFRAME) {
|
|
423
|
+
const direction = event.data.direction;
|
|
424
|
+
callback(direction);
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
window.addEventListener('message', messageCallback);
|
|
428
|
+
return {
|
|
429
|
+
unsubscribe: () => {
|
|
430
|
+
window.removeEventListener('message', messageCallback);
|
|
431
|
+
},
|
|
432
|
+
event: types.UVEEventType.IFRAME_SCROLL
|
|
433
|
+
};
|
|
478
434
|
}
|
|
479
435
|
/**
|
|
480
|
-
*
|
|
436
|
+
* Subscribes to contentlet hover events in the UVE editor
|
|
437
|
+
*
|
|
438
|
+
* @param {UVEEventHandler} callback - Function to be called when a contentlet is hovered
|
|
439
|
+
* @returns {Object} Object containing unsubscribe function and event type
|
|
440
|
+
* @returns {Function} .unsubscribe - Function to remove the event listener
|
|
441
|
+
* @returns {UVEEventType} .event - The event type being subscribed to
|
|
442
|
+
* @internal
|
|
481
443
|
*/
|
|
482
|
-
function
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
444
|
+
function onContentletHovered(callback) {
|
|
445
|
+
const pointerMoveCallback = event => {
|
|
446
|
+
const foundElement = findDotCMSElement(event.target);
|
|
447
|
+
if (!foundElement) return;
|
|
448
|
+
const {
|
|
449
|
+
x,
|
|
450
|
+
y,
|
|
451
|
+
width,
|
|
452
|
+
height
|
|
453
|
+
} = foundElement.getBoundingClientRect();
|
|
454
|
+
const isContainer = foundElement.dataset?.['dotObject'] === 'container';
|
|
455
|
+
const contentletForEmptyContainer = {
|
|
456
|
+
identifier: 'TEMP_EMPTY_CONTENTLET',
|
|
457
|
+
title: 'TEMP_EMPTY_CONTENTLET',
|
|
458
|
+
contentType: 'TEMP_EMPTY_CONTENTLET_TYPE',
|
|
459
|
+
inode: 'TEMPY_EMPTY_CONTENTLET_INODE',
|
|
460
|
+
widgetTitle: 'TEMP_EMPTY_CONTENTLET',
|
|
461
|
+
baseType: 'TEMP_EMPTY_CONTENTLET',
|
|
462
|
+
onNumberOfPages: 1
|
|
490
463
|
};
|
|
491
|
-
|
|
492
|
-
|
|
464
|
+
const contentlet = {
|
|
465
|
+
identifier: foundElement.dataset?.['dotIdentifier'],
|
|
466
|
+
title: foundElement.dataset?.['dotTitle'],
|
|
467
|
+
inode: foundElement.dataset?.['dotInode'],
|
|
468
|
+
contentType: foundElement.dataset?.['dotType'],
|
|
469
|
+
baseType: foundElement.dataset?.['dotBasetype'],
|
|
470
|
+
widgetTitle: foundElement.dataset?.['dotWidgetTitle'],
|
|
471
|
+
onNumberOfPages: foundElement.dataset?.['dotOnNumberOfPages']
|
|
472
|
+
};
|
|
473
|
+
const vtlFiles = findDotCMSVTLData(foundElement);
|
|
474
|
+
const contentletPayload = {
|
|
475
|
+
container:
|
|
476
|
+
// Here extract dot-container from contentlet if it is Headless
|
|
477
|
+
// or search in parent container if it is VTL
|
|
478
|
+
foundElement.dataset?.['dotContainer'] ? JSON.parse(foundElement.dataset?.['dotContainer']) : getClosestDotCMSContainerData(foundElement),
|
|
479
|
+
contentlet: isContainer ? contentletForEmptyContainer : contentlet,
|
|
480
|
+
vtlFiles
|
|
481
|
+
};
|
|
482
|
+
const contentletHoveredPayload = {
|
|
483
|
+
x,
|
|
484
|
+
y,
|
|
485
|
+
width,
|
|
486
|
+
height,
|
|
487
|
+
payload: contentletPayload
|
|
488
|
+
};
|
|
489
|
+
callback(contentletHoveredPayload);
|
|
490
|
+
};
|
|
491
|
+
document.addEventListener('pointermove', pointerMoveCallback);
|
|
493
492
|
return {
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
}
|
|
493
|
+
unsubscribe: () => {
|
|
494
|
+
document.removeEventListener('pointermove', pointerMoveCallback);
|
|
495
|
+
},
|
|
496
|
+
event: types.UVEEventType.CONTENTLET_HOVERED
|
|
497
497
|
};
|
|
498
498
|
}
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Events that can be subscribed to in the UVE
|
|
502
|
+
*
|
|
503
|
+
* @internal
|
|
504
|
+
* @type {Record<UVEEventType, UVEEventSubscriber>}
|
|
505
|
+
*/
|
|
506
|
+
const __UVE_EVENTS__ = {
|
|
507
|
+
[types.UVEEventType.CONTENT_CHANGES]: callback => {
|
|
508
|
+
return onContentChanges(callback);
|
|
509
|
+
},
|
|
510
|
+
[types.UVEEventType.PAGE_RELOAD]: callback => {
|
|
511
|
+
return onPageReload(callback);
|
|
512
|
+
},
|
|
513
|
+
[types.UVEEventType.REQUEST_BOUNDS]: callback => {
|
|
514
|
+
return onRequestBounds(callback);
|
|
515
|
+
},
|
|
516
|
+
[types.UVEEventType.IFRAME_SCROLL]: callback => {
|
|
517
|
+
return onIframeScroll(callback);
|
|
518
|
+
},
|
|
519
|
+
[types.UVEEventType.CONTENTLET_HOVERED]: callback => {
|
|
520
|
+
return onContentletHovered(callback);
|
|
503
521
|
}
|
|
504
|
-
editBlockEditorNodes.forEach(node => {
|
|
505
|
-
const {
|
|
506
|
-
inode,
|
|
507
|
-
language = '1',
|
|
508
|
-
contentType,
|
|
509
|
-
fieldName,
|
|
510
|
-
blockEditorContent
|
|
511
|
-
} = node.dataset;
|
|
512
|
-
const content = JSON.parse(blockEditorContent || '');
|
|
513
|
-
if (!inode || !language || !contentType || !fieldName) {
|
|
514
|
-
console.error('Missing data attributes for block editor inline editing.');
|
|
515
|
-
console.warn('inode, language, contentType and fieldName are required.');
|
|
516
|
-
return;
|
|
517
|
-
}
|
|
518
|
-
node.classList.add('dotcms__inline-edit-field');
|
|
519
|
-
node.addEventListener('click', () => {
|
|
520
|
-
initInlineEditing('BLOCK_EDITOR', {
|
|
521
|
-
inode,
|
|
522
|
-
content,
|
|
523
|
-
language: parseInt(language),
|
|
524
|
-
fieldName,
|
|
525
|
-
contentType
|
|
526
|
-
});
|
|
527
|
-
});
|
|
528
|
-
});
|
|
529
522
|
};
|
|
530
|
-
|
|
531
523
|
/**
|
|
532
|
-
*
|
|
524
|
+
* Default UVE event
|
|
533
525
|
*
|
|
534
|
-
* @
|
|
535
|
-
* @
|
|
536
|
-
* @param {DotCMSUVEMessage<T>} message
|
|
526
|
+
* @param {string} event - The event to subscribe to.
|
|
527
|
+
* @internal
|
|
537
528
|
*/
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
529
|
+
const __UVE_EVENT_ERROR_FALLBACK__ = event => {
|
|
530
|
+
return {
|
|
531
|
+
unsubscribe: () => {
|
|
532
|
+
/* do nothing */
|
|
533
|
+
},
|
|
534
|
+
event
|
|
535
|
+
};
|
|
536
|
+
};
|
|
541
537
|
/**
|
|
542
|
-
*
|
|
538
|
+
* Development mode
|
|
543
539
|
*
|
|
544
|
-
*
|
|
540
|
+
* @internal
|
|
541
|
+
*/
|
|
542
|
+
const DEVELOPMENT_MODE = 'development';
|
|
543
|
+
/**
|
|
544
|
+
* Production mode
|
|
545
545
|
*
|
|
546
|
-
* @
|
|
547
|
-
* @template T
|
|
548
|
-
* @param {Contentlet<T>} contentlet - The contentlet to edit.
|
|
546
|
+
* @internal
|
|
549
547
|
*/
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
payload: contentlet
|
|
554
|
-
});
|
|
555
|
-
}
|
|
556
|
-
/*
|
|
557
|
-
* Reorders the menu based on the provided configuration.
|
|
548
|
+
const PRODUCTION_MODE = 'production';
|
|
549
|
+
/**
|
|
550
|
+
* End class
|
|
558
551
|
*
|
|
559
|
-
* @
|
|
560
|
-
|
|
561
|
-
|
|
552
|
+
* @internal
|
|
553
|
+
*/
|
|
554
|
+
const END_CLASS = 'col-end-';
|
|
555
|
+
/**
|
|
556
|
+
* Start class
|
|
562
557
|
*
|
|
563
|
-
*
|
|
564
|
-
* start level and depth, and sends a message to the editor to perform the reorder action.
|
|
558
|
+
* @internal
|
|
565
559
|
*/
|
|
566
|
-
|
|
567
|
-
const {
|
|
568
|
-
startLevel = 1,
|
|
569
|
-
depth = 2
|
|
570
|
-
} = config || {};
|
|
571
|
-
sendMessageToUVE({
|
|
572
|
-
action: types.DotCMSUVEAction.REORDER_MENU,
|
|
573
|
-
payload: {
|
|
574
|
-
startLevel,
|
|
575
|
-
depth
|
|
576
|
-
}
|
|
577
|
-
});
|
|
578
|
-
}
|
|
560
|
+
const START_CLASS = 'col-start-';
|
|
579
561
|
/**
|
|
580
|
-
*
|
|
562
|
+
* Empty container style for React
|
|
563
|
+
*
|
|
564
|
+
* @internal
|
|
565
|
+
*/
|
|
566
|
+
const EMPTY_CONTAINER_STYLE_REACT = {
|
|
567
|
+
width: '100%',
|
|
568
|
+
backgroundColor: '#ECF0FD',
|
|
569
|
+
display: 'flex',
|
|
570
|
+
justifyContent: 'center',
|
|
571
|
+
alignItems: 'center',
|
|
572
|
+
color: '#030E32',
|
|
573
|
+
height: '10rem'
|
|
574
|
+
};
|
|
575
|
+
/**
|
|
576
|
+
* Empty container style for Angular
|
|
577
|
+
*
|
|
578
|
+
* @internal
|
|
579
|
+
*/
|
|
580
|
+
const EMPTY_CONTAINER_STYLE_ANGULAR = {
|
|
581
|
+
width: '100%',
|
|
582
|
+
'background-color': '#ECF0FD',
|
|
583
|
+
display: 'flex',
|
|
584
|
+
'justify-content': 'center',
|
|
585
|
+
'align-items': 'center',
|
|
586
|
+
color: '#030E32',
|
|
587
|
+
height: '10rem'
|
|
588
|
+
};
|
|
589
|
+
/**
|
|
590
|
+
* Custom no component
|
|
591
|
+
*
|
|
592
|
+
* @internal
|
|
593
|
+
*/
|
|
594
|
+
const CUSTOM_NO_COMPONENT = 'CustomNoComponent';
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Gets the current state of the Universal Visual Editor (UVE).
|
|
598
|
+
*
|
|
599
|
+
* This function checks if the code is running inside the DotCMS Universal Visual Editor
|
|
600
|
+
* and returns information about its current state, including the editor mode.
|
|
581
601
|
*
|
|
582
602
|
* @export
|
|
583
|
-
* @
|
|
584
|
-
*
|
|
585
|
-
* @return {*}
|
|
603
|
+
* @return {UVEState | undefined} Returns the UVE state object if running inside the editor,
|
|
604
|
+
* undefined otherwise.
|
|
586
605
|
*
|
|
587
|
-
*
|
|
588
|
-
*
|
|
589
|
-
*
|
|
590
|
-
*
|
|
591
|
-
*
|
|
606
|
+
* The state includes:
|
|
607
|
+
* - mode: The current editor mode (preview, edit, live)
|
|
608
|
+
* - languageId: The language ID of the current page setted on the UVE
|
|
609
|
+
* - persona: The persona of the current page setted on the UVE
|
|
610
|
+
* - variantName: The name of the current variant
|
|
611
|
+
* - experimentId: The ID of the current experiment
|
|
612
|
+
* - publishDate: The publish date of the current page setted on the UVE
|
|
613
|
+
*
|
|
614
|
+
* @note The absence of any of these properties means that the value is the default one.
|
|
615
|
+
*
|
|
616
|
+
* @example
|
|
617
|
+
* ```ts
|
|
618
|
+
* const editorState = getUVEState();
|
|
619
|
+
* if (editorState?.mode === 'edit') {
|
|
620
|
+
* // Enable editing features
|
|
621
|
+
* }
|
|
592
622
|
* ```
|
|
593
623
|
*/
|
|
594
|
-
function
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
624
|
+
function getUVEState() {
|
|
625
|
+
if (typeof window === 'undefined' || window.parent === window || !window.location) {
|
|
626
|
+
return undefined;
|
|
627
|
+
}
|
|
628
|
+
const url = new URL(window.location.href);
|
|
629
|
+
const possibleModes = Object.values(types.UVE_MODE);
|
|
630
|
+
let mode = url.searchParams.get('mode') ?? types.UVE_MODE.EDIT;
|
|
631
|
+
const languageId = url.searchParams.get('language_id');
|
|
632
|
+
const persona = url.searchParams.get('personaId');
|
|
633
|
+
const variantName = url.searchParams.get('variantName');
|
|
634
|
+
const experimentId = url.searchParams.get('experimentId');
|
|
635
|
+
const publishDate = url.searchParams.get('publishDate');
|
|
636
|
+
const dotCMSHost = url.searchParams.get('dotCMSHost');
|
|
637
|
+
if (!possibleModes.includes(mode)) {
|
|
638
|
+
mode = types.UVE_MODE.EDIT;
|
|
639
|
+
}
|
|
640
|
+
return {
|
|
641
|
+
mode,
|
|
642
|
+
languageId,
|
|
643
|
+
persona,
|
|
644
|
+
variantName,
|
|
645
|
+
experimentId,
|
|
646
|
+
publishDate,
|
|
647
|
+
dotCMSHost
|
|
648
|
+
};
|
|
602
649
|
}
|
|
603
650
|
/**
|
|
604
|
-
*
|
|
605
|
-
*
|
|
606
|
-
* This function sets up:
|
|
607
|
-
* - Scroll handling
|
|
608
|
-
* - Empty contentlet styling
|
|
609
|
-
* - Block editor inline event listening
|
|
610
|
-
* - Client ready state
|
|
611
|
-
* - UVE event subscriptions
|
|
651
|
+
* Creates a subscription to a UVE event.
|
|
612
652
|
*
|
|
613
|
-
* @
|
|
614
|
-
* @
|
|
653
|
+
* @param eventType - The type of event to subscribe to
|
|
654
|
+
* @param callback - The callback function that will be called when the event occurs
|
|
655
|
+
* @returns An event subscription that can be used to unsubscribe
|
|
615
656
|
*
|
|
616
657
|
* @example
|
|
617
|
-
* ```
|
|
618
|
-
*
|
|
658
|
+
* ```ts
|
|
659
|
+
* // Subscribe to page changes
|
|
660
|
+
* const subscription = createUVESubscription(UVEEventType.CONTENT_CHANGES, (changes) => {
|
|
661
|
+
* console.log('Content changes:', changes);
|
|
662
|
+
* });
|
|
619
663
|
*
|
|
620
|
-
* //
|
|
621
|
-
*
|
|
664
|
+
* // Later, unsubscribe when no longer needed
|
|
665
|
+
* subscription.unsubscribe();
|
|
622
666
|
* ```
|
|
623
667
|
*/
|
|
624
|
-
function
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
} = listenBlockEditorInlineEvent();
|
|
636
|
-
return {
|
|
637
|
-
destroyUVESubscriptions: () => {
|
|
638
|
-
subscriptions.forEach(subscription => subscription.unsubscribe());
|
|
639
|
-
destroyScrollHandler();
|
|
640
|
-
destroyListenBlockEditorInlineEvent();
|
|
641
|
-
}
|
|
642
|
-
};
|
|
668
|
+
function createUVESubscription(eventType, callback) {
|
|
669
|
+
if (!getUVEState()) {
|
|
670
|
+
console.warn('UVE Subscription: Not running inside UVE');
|
|
671
|
+
return __UVE_EVENT_ERROR_FALLBACK__(eventType);
|
|
672
|
+
}
|
|
673
|
+
const eventCallback = __UVE_EVENTS__[eventType];
|
|
674
|
+
if (!eventCallback) {
|
|
675
|
+
console.error(`UVE Subscription: Event ${eventType} not found`);
|
|
676
|
+
return __UVE_EVENT_ERROR_FALLBACK__(eventType);
|
|
677
|
+
}
|
|
678
|
+
return eventCallback(callback);
|
|
643
679
|
}
|
|
644
680
|
|
|
645
681
|
/**
|
|
@@ -741,383 +777,274 @@ const isValidBlocks = blocks => {
|
|
|
741
777
|
};
|
|
742
778
|
};
|
|
743
779
|
|
|
780
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
744
781
|
/**
|
|
745
|
-
*
|
|
746
|
-
*
|
|
747
|
-
*
|
|
748
|
-
* @enum {string}
|
|
782
|
+
* Sets up scroll event handlers for the window to notify the editor about scroll events.
|
|
783
|
+
* Adds listeners for both 'scroll' and 'scrollend' events, sending appropriate messages
|
|
784
|
+
* to the editor when these events occur.
|
|
749
785
|
*/
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
Blocks["HEADING"] = "heading";
|
|
756
|
-
/** Represents a text block */
|
|
757
|
-
Blocks["TEXT"] = "text";
|
|
758
|
-
/** Represents a bullet/unordered list block */
|
|
759
|
-
Blocks["BULLET_LIST"] = "bulletList";
|
|
760
|
-
/** Represents an ordered/numbered list block */
|
|
761
|
-
Blocks["ORDERED_LIST"] = "orderedList";
|
|
762
|
-
/** Represents a list item within a list block */
|
|
763
|
-
Blocks["LIST_ITEM"] = "listItem";
|
|
764
|
-
/** Represents a blockquote block */
|
|
765
|
-
Blocks["BLOCK_QUOTE"] = "blockquote";
|
|
766
|
-
/** Represents a code block */
|
|
767
|
-
Blocks["CODE_BLOCK"] = "codeBlock";
|
|
768
|
-
/** Represents a hard break (line break) */
|
|
769
|
-
Blocks["HARDBREAK"] = "hardBreak";
|
|
770
|
-
/** Represents a horizontal rule/divider */
|
|
771
|
-
Blocks["HORIZONTAL_RULE"] = "horizontalRule";
|
|
772
|
-
/** Represents a DotCMS image block */
|
|
773
|
-
Blocks["DOT_IMAGE"] = "dotImage";
|
|
774
|
-
/** Represents a DotCMS video block */
|
|
775
|
-
Blocks["DOT_VIDEO"] = "dotVideo";
|
|
776
|
-
/** Represents a table block */
|
|
777
|
-
Blocks["TABLE"] = "table";
|
|
778
|
-
/** Represents a DotCMS content block */
|
|
779
|
-
Blocks["DOT_CONTENT"] = "dotContent";
|
|
780
|
-
})(exports.Blocks || (exports.Blocks = {}));
|
|
781
|
-
|
|
782
|
-
/**
|
|
783
|
-
* Subscribes to content changes in the UVE editor
|
|
784
|
-
*
|
|
785
|
-
* @param {UVEEventHandler} callback - Function to be called when content changes are detected
|
|
786
|
-
* @returns {Object} Object containing unsubscribe function and event type
|
|
787
|
-
* @returns {Function} .unsubscribe - Function to remove the event listener
|
|
788
|
-
* @returns {UVEEventType} .event - The event type being subscribed to
|
|
789
|
-
* @internal
|
|
790
|
-
*/
|
|
791
|
-
function onContentChanges(callback) {
|
|
792
|
-
const messageCallback = event => {
|
|
793
|
-
if (event.data.name === exports.__DOTCMS_UVE_EVENT__.UVE_SET_PAGE_DATA) {
|
|
794
|
-
callback(event.data.payload);
|
|
795
|
-
}
|
|
786
|
+
function scrollHandler() {
|
|
787
|
+
const scrollCallback = () => {
|
|
788
|
+
sendMessageToUVE({
|
|
789
|
+
action: types.DotCMSUVEAction.IFRAME_SCROLL
|
|
790
|
+
});
|
|
796
791
|
};
|
|
797
|
-
|
|
792
|
+
const scrollEndCallback = () => {
|
|
793
|
+
sendMessageToUVE({
|
|
794
|
+
action: types.DotCMSUVEAction.IFRAME_SCROLL_END
|
|
795
|
+
});
|
|
796
|
+
};
|
|
797
|
+
window.addEventListener('scroll', scrollCallback);
|
|
798
|
+
window.addEventListener('scrollend', scrollEndCallback);
|
|
798
799
|
return {
|
|
799
|
-
|
|
800
|
-
window.removeEventListener('
|
|
801
|
-
|
|
802
|
-
|
|
800
|
+
destroyScrollHandler: () => {
|
|
801
|
+
window.removeEventListener('scroll', scrollCallback);
|
|
802
|
+
window.removeEventListener('scrollend', scrollEndCallback);
|
|
803
|
+
}
|
|
803
804
|
};
|
|
804
805
|
}
|
|
805
806
|
/**
|
|
806
|
-
*
|
|
807
|
+
* Adds 'empty-contentlet' class to contentlet elements that have no height.
|
|
808
|
+
* This helps identify and style empty contentlets in the editor view.
|
|
807
809
|
*
|
|
808
|
-
* @
|
|
809
|
-
*
|
|
810
|
-
*
|
|
811
|
-
*
|
|
812
|
-
* @internal
|
|
810
|
+
* @remarks
|
|
811
|
+
* The function queries all elements with data-dot-object="contentlet" attribute
|
|
812
|
+
* and checks their clientHeight. If an element has no height (clientHeight = 0),
|
|
813
|
+
* it adds the 'empty-contentlet' class to that element.
|
|
813
814
|
*/
|
|
814
|
-
function
|
|
815
|
-
const
|
|
816
|
-
|
|
817
|
-
|
|
815
|
+
function addClassToEmptyContentlets() {
|
|
816
|
+
const contentlets = document.querySelectorAll('[data-dot-object="contentlet"]');
|
|
817
|
+
contentlets.forEach(contentlet => {
|
|
818
|
+
if (contentlet.clientHeight) {
|
|
819
|
+
return;
|
|
818
820
|
}
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
return {
|
|
822
|
-
unsubscribe: () => {
|
|
823
|
-
window.removeEventListener('message', messageCallback);
|
|
824
|
-
},
|
|
825
|
-
event: types.UVEEventType.PAGE_RELOAD
|
|
826
|
-
};
|
|
821
|
+
contentlet.classList.add('empty-contentlet');
|
|
822
|
+
});
|
|
827
823
|
}
|
|
828
824
|
/**
|
|
829
|
-
*
|
|
825
|
+
* Registers event handlers for various UVE (Universal Visual Editor) events.
|
|
830
826
|
*
|
|
831
|
-
*
|
|
832
|
-
*
|
|
833
|
-
*
|
|
834
|
-
*
|
|
835
|
-
*
|
|
827
|
+
* This function sets up subscriptions for:
|
|
828
|
+
* - Page reload events that refresh the window
|
|
829
|
+
* - Bounds request events to update editor boundaries
|
|
830
|
+
* - Iframe scroll events to handle smooth scrolling within bounds
|
|
831
|
+
* - Contentlet hover events to notify the editor
|
|
832
|
+
*
|
|
833
|
+
* @remarks
|
|
834
|
+
* For scroll events, the function includes logic to prevent scrolling beyond
|
|
835
|
+
* the top or bottom boundaries of the iframe, which helps maintain proper
|
|
836
|
+
* scroll event handling.
|
|
836
837
|
*/
|
|
837
|
-
function
|
|
838
|
-
const
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
838
|
+
function registerUVEEvents() {
|
|
839
|
+
const pageReloadSubscription = createUVESubscription(types.UVEEventType.PAGE_RELOAD, () => {
|
|
840
|
+
window.location.reload();
|
|
841
|
+
});
|
|
842
|
+
const requestBoundsSubscription = createUVESubscription(types.UVEEventType.REQUEST_BOUNDS, bounds => {
|
|
843
|
+
setBounds(bounds);
|
|
844
|
+
});
|
|
845
|
+
const iframeScrollSubscription = createUVESubscription(types.UVEEventType.IFRAME_SCROLL, direction => {
|
|
846
|
+
if (window.scrollY === 0 && direction === 'up' || computeScrollIsInBottom() && direction === 'down') {
|
|
847
|
+
// If the iframe scroll is at the top or bottom, do not send anything.
|
|
848
|
+
// This avoids losing the scrollend event.
|
|
849
|
+
return;
|
|
843
850
|
}
|
|
844
|
-
|
|
845
|
-
|
|
851
|
+
const scrollY = direction === 'up' ? -120 : 120;
|
|
852
|
+
window.scrollBy({
|
|
853
|
+
left: 0,
|
|
854
|
+
top: scrollY,
|
|
855
|
+
behavior: 'smooth'
|
|
856
|
+
});
|
|
857
|
+
});
|
|
858
|
+
const contentletHoveredSubscription = createUVESubscription(types.UVEEventType.CONTENTLET_HOVERED, contentletHovered => {
|
|
859
|
+
sendMessageToUVE({
|
|
860
|
+
action: types.DotCMSUVEAction.SET_CONTENTLET,
|
|
861
|
+
payload: contentletHovered
|
|
862
|
+
});
|
|
863
|
+
});
|
|
846
864
|
return {
|
|
847
|
-
|
|
848
|
-
window.removeEventListener('message', messageCallback);
|
|
849
|
-
},
|
|
850
|
-
event: types.UVEEventType.REQUEST_BOUNDS
|
|
865
|
+
subscriptions: [pageReloadSubscription, requestBoundsSubscription, iframeScrollSubscription, contentletHoveredSubscription]
|
|
851
866
|
};
|
|
852
867
|
}
|
|
853
868
|
/**
|
|
854
|
-
*
|
|
869
|
+
* Notifies the editor that the UVE client is ready to receive messages.
|
|
855
870
|
*
|
|
856
|
-
*
|
|
857
|
-
*
|
|
858
|
-
*
|
|
859
|
-
* @
|
|
860
|
-
*
|
|
871
|
+
* This function sends a message to the editor indicating that the client-side
|
|
872
|
+
* initialization is complete and it's ready to handle editor interactions.
|
|
873
|
+
*
|
|
874
|
+
* @remarks
|
|
875
|
+
* This is typically called after all UVE event handlers and DOM listeners
|
|
876
|
+
* have been set up successfully.
|
|
861
877
|
*/
|
|
862
|
-
function
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
}
|
|
868
|
-
};
|
|
869
|
-
window.addEventListener('message', messageCallback);
|
|
870
|
-
return {
|
|
871
|
-
unsubscribe: () => {
|
|
872
|
-
window.removeEventListener('message', messageCallback);
|
|
873
|
-
},
|
|
874
|
-
event: types.UVEEventType.IFRAME_SCROLL
|
|
875
|
-
};
|
|
878
|
+
function setClientIsReady(config) {
|
|
879
|
+
sendMessageToUVE({
|
|
880
|
+
action: types.DotCMSUVEAction.CLIENT_READY,
|
|
881
|
+
payload: config
|
|
882
|
+
});
|
|
876
883
|
}
|
|
877
884
|
/**
|
|
878
|
-
*
|
|
879
|
-
*
|
|
880
|
-
* @param {UVEEventHandler} callback - Function to be called when a contentlet is hovered
|
|
881
|
-
* @returns {Object} Object containing unsubscribe function and event type
|
|
882
|
-
* @returns {Function} .unsubscribe - Function to remove the event listener
|
|
883
|
-
* @returns {UVEEventType} .event - The event type being subscribed to
|
|
884
|
-
* @internal
|
|
885
|
+
* Listen for block editor inline event.
|
|
885
886
|
*/
|
|
886
|
-
function
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
height
|
|
895
|
-
} = foundElement.getBoundingClientRect();
|
|
896
|
-
const isContainer = foundElement.dataset?.['dotObject'] === 'container';
|
|
897
|
-
const contentletForEmptyContainer = {
|
|
898
|
-
identifier: 'TEMP_EMPTY_CONTENTLET',
|
|
899
|
-
title: 'TEMP_EMPTY_CONTENTLET',
|
|
900
|
-
contentType: 'TEMP_EMPTY_CONTENTLET_TYPE',
|
|
901
|
-
inode: 'TEMPY_EMPTY_CONTENTLET_INODE',
|
|
902
|
-
widgetTitle: 'TEMP_EMPTY_CONTENTLET',
|
|
903
|
-
baseType: 'TEMP_EMPTY_CONTENTLET',
|
|
904
|
-
onNumberOfPages: 1
|
|
905
|
-
};
|
|
906
|
-
const contentlet = {
|
|
907
|
-
identifier: foundElement.dataset?.['dotIdentifier'],
|
|
908
|
-
title: foundElement.dataset?.['dotTitle'],
|
|
909
|
-
inode: foundElement.dataset?.['dotInode'],
|
|
910
|
-
contentType: foundElement.dataset?.['dotType'],
|
|
911
|
-
baseType: foundElement.dataset?.['dotBasetype'],
|
|
912
|
-
widgetTitle: foundElement.dataset?.['dotWidgetTitle'],
|
|
913
|
-
onNumberOfPages: foundElement.dataset?.['dotOnNumberOfPages']
|
|
914
|
-
};
|
|
915
|
-
const vtlFiles = findDotCMSVTLData(foundElement);
|
|
916
|
-
const contentletPayload = {
|
|
917
|
-
container:
|
|
918
|
-
// Here extract dot-container from contentlet if it is Headless
|
|
919
|
-
// or search in parent container if it is VTL
|
|
920
|
-
foundElement.dataset?.['dotContainer'] ? JSON.parse(foundElement.dataset?.['dotContainer']) : getClosestDotCMSContainerData(foundElement),
|
|
921
|
-
contentlet: isContainer ? contentletForEmptyContainer : contentlet,
|
|
922
|
-
vtlFiles
|
|
923
|
-
};
|
|
924
|
-
const contentletHoveredPayload = {
|
|
925
|
-
x,
|
|
926
|
-
y,
|
|
927
|
-
width,
|
|
928
|
-
height,
|
|
929
|
-
payload: contentletPayload
|
|
887
|
+
function listenBlockEditorInlineEvent() {
|
|
888
|
+
if (document.readyState === 'complete') {
|
|
889
|
+
// The page is fully loaded or interactive
|
|
890
|
+
listenBlockEditorClick();
|
|
891
|
+
return {
|
|
892
|
+
destroyListenBlockEditorInlineEvent: () => {
|
|
893
|
+
window.removeEventListener('load', () => listenBlockEditorClick());
|
|
894
|
+
}
|
|
930
895
|
};
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
document.addEventListener('pointermove', pointerMoveCallback);
|
|
896
|
+
}
|
|
897
|
+
window.addEventListener('load', () => listenBlockEditorClick());
|
|
934
898
|
return {
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
}
|
|
938
|
-
event: types.UVEEventType.CONTENTLET_HOVERED
|
|
899
|
+
destroyListenBlockEditorInlineEvent: () => {
|
|
900
|
+
window.removeEventListener('load', () => listenBlockEditorClick());
|
|
901
|
+
}
|
|
939
902
|
};
|
|
940
903
|
}
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
* @internal
|
|
946
|
-
* @type {Record<UVEEventType, UVEEventSubscriber>}
|
|
947
|
-
*/
|
|
948
|
-
const __UVE_EVENTS__ = {
|
|
949
|
-
[types.UVEEventType.CONTENT_CHANGES]: callback => {
|
|
950
|
-
return onContentChanges(callback);
|
|
951
|
-
},
|
|
952
|
-
[types.UVEEventType.PAGE_RELOAD]: callback => {
|
|
953
|
-
return onPageReload(callback);
|
|
954
|
-
},
|
|
955
|
-
[types.UVEEventType.REQUEST_BOUNDS]: callback => {
|
|
956
|
-
return onRequestBounds(callback);
|
|
957
|
-
},
|
|
958
|
-
[types.UVEEventType.IFRAME_SCROLL]: callback => {
|
|
959
|
-
return onIframeScroll(callback);
|
|
960
|
-
},
|
|
961
|
-
[types.UVEEventType.CONTENTLET_HOVERED]: callback => {
|
|
962
|
-
return onContentletHovered(callback);
|
|
904
|
+
const listenBlockEditorClick = () => {
|
|
905
|
+
const editBlockEditorNodes = document.querySelectorAll('[data-block-editor-content]');
|
|
906
|
+
if (!editBlockEditorNodes.length) {
|
|
907
|
+
return;
|
|
963
908
|
}
|
|
909
|
+
editBlockEditorNodes.forEach(node => {
|
|
910
|
+
const {
|
|
911
|
+
inode,
|
|
912
|
+
language = '1',
|
|
913
|
+
contentType,
|
|
914
|
+
fieldName,
|
|
915
|
+
blockEditorContent
|
|
916
|
+
} = node.dataset;
|
|
917
|
+
const content = JSON.parse(blockEditorContent || '');
|
|
918
|
+
if (!inode || !language || !contentType || !fieldName) {
|
|
919
|
+
console.error('Missing data attributes for block editor inline editing.');
|
|
920
|
+
console.warn('inode, language, contentType and fieldName are required.');
|
|
921
|
+
return;
|
|
922
|
+
}
|
|
923
|
+
node.classList.add('dotcms__inline-edit-field');
|
|
924
|
+
node.addEventListener('click', () => {
|
|
925
|
+
initInlineEditing('BLOCK_EDITOR', {
|
|
926
|
+
inode,
|
|
927
|
+
content,
|
|
928
|
+
language: parseInt(language),
|
|
929
|
+
fieldName,
|
|
930
|
+
contentType
|
|
931
|
+
});
|
|
932
|
+
});
|
|
933
|
+
});
|
|
964
934
|
};
|
|
935
|
+
|
|
965
936
|
/**
|
|
966
|
-
*
|
|
967
|
-
*
|
|
968
|
-
* @param {string} event - The event to subscribe to.
|
|
969
|
-
* @internal
|
|
970
|
-
*/
|
|
971
|
-
const __UVE_EVENT_ERROR_FALLBACK__ = event => {
|
|
972
|
-
return {
|
|
973
|
-
unsubscribe: () => {
|
|
974
|
-
/* do nothing */
|
|
975
|
-
},
|
|
976
|
-
event
|
|
977
|
-
};
|
|
978
|
-
};
|
|
979
|
-
/**
|
|
980
|
-
* Development mode
|
|
981
|
-
*
|
|
982
|
-
* @internal
|
|
983
|
-
*/
|
|
984
|
-
const DEVELOPMENT_MODE = 'development';
|
|
985
|
-
/**
|
|
986
|
-
* Production mode
|
|
987
|
-
*
|
|
988
|
-
* @internal
|
|
989
|
-
*/
|
|
990
|
-
const PRODUCTION_MODE = 'production';
|
|
991
|
-
/**
|
|
992
|
-
* End class
|
|
937
|
+
* Post message to dotcms page editor
|
|
993
938
|
*
|
|
994
|
-
* @
|
|
939
|
+
* @export
|
|
940
|
+
* @template T
|
|
941
|
+
* @param {DotCMSUVEMessage<T>} message
|
|
995
942
|
*/
|
|
996
|
-
|
|
943
|
+
function sendMessageToUVE(message) {
|
|
944
|
+
window.parent.postMessage(message, '*');
|
|
945
|
+
}
|
|
997
946
|
/**
|
|
998
|
-
*
|
|
947
|
+
* You can use this function to edit a contentlet in the editor.
|
|
999
948
|
*
|
|
1000
|
-
*
|
|
1001
|
-
*/
|
|
1002
|
-
const START_CLASS = 'col-start-';
|
|
1003
|
-
/**
|
|
1004
|
-
* Empty container style for React
|
|
949
|
+
* Calling this function inside the editor, will prompt the UVE to open a dialog to edit the contentlet.
|
|
1005
950
|
*
|
|
1006
|
-
* @
|
|
951
|
+
* @export
|
|
952
|
+
* @template T
|
|
953
|
+
* @param {Contentlet<T>} contentlet - The contentlet to edit.
|
|
1007
954
|
*/
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
};
|
|
1017
|
-
/**
|
|
1018
|
-
* Empty container style for Angular
|
|
955
|
+
function editContentlet(contentlet) {
|
|
956
|
+
sendMessageToUVE({
|
|
957
|
+
action: types.DotCMSUVEAction.EDIT_CONTENTLET,
|
|
958
|
+
payload: contentlet
|
|
959
|
+
});
|
|
960
|
+
}
|
|
961
|
+
/*
|
|
962
|
+
* Reorders the menu based on the provided configuration.
|
|
1019
963
|
*
|
|
1020
|
-
* @
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
width: '100%',
|
|
1024
|
-
'background-color': '#ECF0FD',
|
|
1025
|
-
display: 'flex',
|
|
1026
|
-
'justify-content': 'center',
|
|
1027
|
-
'align-items': 'center',
|
|
1028
|
-
color: '#030E32',
|
|
1029
|
-
height: '10rem'
|
|
1030
|
-
};
|
|
1031
|
-
/**
|
|
1032
|
-
* Custom no component
|
|
964
|
+
* @param {ReorderMenuConfig} [config] - Optional configuration for reordering the menu.
|
|
965
|
+
* @param {number} [config.startLevel=1] - The starting level of the menu to reorder.
|
|
966
|
+
* @param {number} [config.depth=2] - The depth of the menu to reorder.
|
|
1033
967
|
*
|
|
1034
|
-
*
|
|
968
|
+
* This function constructs a URL for the reorder menu page with the specified
|
|
969
|
+
* start level and depth, and sends a message to the editor to perform the reorder action.
|
|
1035
970
|
*/
|
|
1036
|
-
|
|
1037
|
-
|
|
971
|
+
function reorderMenu(config) {
|
|
972
|
+
const {
|
|
973
|
+
startLevel = 1,
|
|
974
|
+
depth = 2
|
|
975
|
+
} = config || {};
|
|
976
|
+
sendMessageToUVE({
|
|
977
|
+
action: types.DotCMSUVEAction.REORDER_MENU,
|
|
978
|
+
payload: {
|
|
979
|
+
startLevel,
|
|
980
|
+
depth
|
|
981
|
+
}
|
|
982
|
+
});
|
|
983
|
+
}
|
|
1038
984
|
/**
|
|
1039
|
-
*
|
|
1040
|
-
*
|
|
1041
|
-
* This function checks if the code is running inside the DotCMS Universal Visual Editor
|
|
1042
|
-
* and returns information about its current state, including the editor mode.
|
|
985
|
+
* Initializes the inline editing in the editor.
|
|
1043
986
|
*
|
|
1044
987
|
* @export
|
|
1045
|
-
* @
|
|
1046
|
-
*
|
|
1047
|
-
*
|
|
1048
|
-
* The state includes:
|
|
1049
|
-
* - mode: The current editor mode (preview, edit, live)
|
|
1050
|
-
* - languageId: The language ID of the current page setted on the UVE
|
|
1051
|
-
* - persona: The persona of the current page setted on the UVE
|
|
1052
|
-
* - variantName: The name of the current variant
|
|
1053
|
-
* - experimentId: The ID of the current experiment
|
|
1054
|
-
* - publishDate: The publish date of the current page setted on the UVE
|
|
1055
|
-
*
|
|
1056
|
-
* @note The absence of any of these properties means that the value is the default one.
|
|
988
|
+
* @param {INLINE_EDITING_EVENT_KEY} type
|
|
989
|
+
* @param {InlineEditEventData} eventData
|
|
990
|
+
* @return {*}
|
|
1057
991
|
*
|
|
1058
|
-
* @example
|
|
1059
|
-
* ```
|
|
1060
|
-
*
|
|
1061
|
-
*
|
|
1062
|
-
*
|
|
1063
|
-
* }
|
|
992
|
+
* * @example
|
|
993
|
+
* ```html
|
|
994
|
+
* <div onclick="initInlineEditing('BLOCK_EDITOR', { inode, languageId, contentType, fieldName, content })">
|
|
995
|
+
* ${My Content}
|
|
996
|
+
* </div>
|
|
1064
997
|
* ```
|
|
1065
998
|
*/
|
|
1066
|
-
function
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
const persona = url.searchParams.get('personaId');
|
|
1075
|
-
const variantName = url.searchParams.get('variantName');
|
|
1076
|
-
const experimentId = url.searchParams.get('experimentId');
|
|
1077
|
-
const publishDate = url.searchParams.get('publishDate');
|
|
1078
|
-
const dotCMSHost = url.searchParams.get('dotCMSHost');
|
|
1079
|
-
if (!possibleModes.includes(mode)) {
|
|
1080
|
-
mode = types.UVE_MODE.EDIT;
|
|
1081
|
-
}
|
|
1082
|
-
return {
|
|
1083
|
-
mode,
|
|
1084
|
-
languageId,
|
|
1085
|
-
persona,
|
|
1086
|
-
variantName,
|
|
1087
|
-
experimentId,
|
|
1088
|
-
publishDate,
|
|
1089
|
-
dotCMSHost
|
|
1090
|
-
};
|
|
999
|
+
function initInlineEditing(type, data) {
|
|
1000
|
+
sendMessageToUVE({
|
|
1001
|
+
action: types.DotCMSUVEAction.INIT_INLINE_EDITING,
|
|
1002
|
+
payload: {
|
|
1003
|
+
type,
|
|
1004
|
+
data
|
|
1005
|
+
}
|
|
1006
|
+
});
|
|
1091
1007
|
}
|
|
1092
1008
|
/**
|
|
1093
|
-
*
|
|
1009
|
+
* Initializes the Universal Visual Editor (UVE) with required handlers and event listeners.
|
|
1094
1010
|
*
|
|
1095
|
-
*
|
|
1096
|
-
*
|
|
1097
|
-
*
|
|
1011
|
+
* This function sets up:
|
|
1012
|
+
* - Scroll handling
|
|
1013
|
+
* - Empty contentlet styling
|
|
1014
|
+
* - Block editor inline event listening
|
|
1015
|
+
* - Client ready state
|
|
1016
|
+
* - UVE event subscriptions
|
|
1017
|
+
*
|
|
1018
|
+
* @returns {Object} An object containing the cleanup function
|
|
1019
|
+
* @returns {Function} destroyUVESubscriptions - Function to clean up all UVE event subscriptions
|
|
1098
1020
|
*
|
|
1099
1021
|
* @example
|
|
1100
|
-
* ```
|
|
1101
|
-
*
|
|
1102
|
-
* const subscription = createUVESubscription(UVEEventType.CONTENT_CHANGES, (changes) => {
|
|
1103
|
-
* console.log('Content changes:', changes);
|
|
1104
|
-
* });
|
|
1022
|
+
* ```typescript
|
|
1023
|
+
* const { destroyUVESubscriptions } = initUVE();
|
|
1105
1024
|
*
|
|
1106
|
-
* //
|
|
1107
|
-
*
|
|
1025
|
+
* // When done with UVE
|
|
1026
|
+
* destroyUVESubscriptions();
|
|
1108
1027
|
* ```
|
|
1109
1028
|
*/
|
|
1110
|
-
function
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1029
|
+
function initUVE(config = {}) {
|
|
1030
|
+
addClassToEmptyContentlets();
|
|
1031
|
+
setClientIsReady(config);
|
|
1032
|
+
const {
|
|
1033
|
+
subscriptions
|
|
1034
|
+
} = registerUVEEvents();
|
|
1035
|
+
const {
|
|
1036
|
+
destroyScrollHandler
|
|
1037
|
+
} = scrollHandler();
|
|
1038
|
+
const {
|
|
1039
|
+
destroyListenBlockEditorInlineEvent
|
|
1040
|
+
} = listenBlockEditorInlineEvent();
|
|
1041
|
+
return {
|
|
1042
|
+
destroyUVESubscriptions: () => {
|
|
1043
|
+
subscriptions.forEach(subscription => subscription.unsubscribe());
|
|
1044
|
+
destroyScrollHandler();
|
|
1045
|
+
destroyListenBlockEditorInlineEvent();
|
|
1046
|
+
}
|
|
1047
|
+
};
|
|
1121
1048
|
}
|
|
1122
1049
|
|
|
1123
1050
|
exports.CUSTOM_NO_COMPONENT = CUSTOM_NO_COMPONENT;
|