@dotcms/uve 0.0.1-beta.11 → 0.0.1-beta.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +146 -4
- package/index.cjs.js +67 -166
- package/index.esm.js +65 -161
- package/internal.cjs.js +360 -16
- package/internal.esm.js +354 -17
- package/package.json +1 -1
- package/src/index.d.ts +1 -1
- package/src/internal/constants.d.ts +3 -3
- package/src/internal/events.d.ts +66 -0
- package/src/internal.d.ts +1 -0
- package/src/lib/core/core.utils.d.ts +11 -7
- package/src/lib/editor/internal.d.ts +8 -0
- package/src/lib/editor/public.d.ts +38 -0
- package/src/lib/types/editor/internal.d.ts +39 -0
- package/src/lib/types/editor/public.d.ts +55 -12
- package/src/lib/types/events/internal.d.ts +3 -1
- package/src/script/sdk-editor.d.ts +6 -0
- package/src/script/utils.d.ts +46 -0
- package/types.cjs.js +27 -0
- package/types.esm.js +28 -1
package/README.md
CHANGED
|
@@ -1,7 +1,149 @@
|
|
|
1
|
-
#
|
|
1
|
+
# DotCMS UVE SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A JavaScript library to connect your dotCMS pages with the Universal Visual Editor (UVE) and enable content authors to edit pages in real time.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Installation
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
The UVE SDK is automatically included in DotCMS installations. For external usage:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
yarn add @dotcms/uve-sdk
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## Entry Points
|
|
15
|
+
|
|
16
|
+
The library exposes three main entry points:
|
|
17
|
+
|
|
18
|
+
- **`@dotcms/uve`**: Provides everything developers need to communicate with UVE.
|
|
19
|
+
|
|
20
|
+
- **`@dotcms/uve/types`**: Offers TypeScript types, interfaces, and other structures to help users organize their code properly.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Functions
|
|
25
|
+
|
|
26
|
+
### `createUVESubscription`
|
|
27
|
+
|
|
28
|
+
Subscribe to the pages changes. Receive a callback that will be called with the updated content of the page.
|
|
29
|
+
|
|
30
|
+
**Parameters:**
|
|
31
|
+
- `eventType` - The type of event to subscribe to.
|
|
32
|
+
- `callback` - The callback function that will be called when the event occurs.
|
|
33
|
+
|
|
34
|
+
**Returns:**
|
|
35
|
+
- An event subscription that can be used to unsubscribe.
|
|
36
|
+
|
|
37
|
+
**Example:**
|
|
38
|
+
***typescript
|
|
39
|
+
// Subscribe to page changes
|
|
40
|
+
const subscription = createUVESubscription(UVEEventType.CONTENT_CHANGES, (changes) => {
|
|
41
|
+
console.log('Content changes:', changes);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Unsubscribe
|
|
45
|
+
|
|
46
|
+
subscription.unsubscribe()
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
### `getUVEState`
|
|
52
|
+
|
|
53
|
+
Retrieves the current UVE state.
|
|
54
|
+
|
|
55
|
+
**Returns:**
|
|
56
|
+
- A `UVEState` object if running inside the editor, or `undefined` otherwise.
|
|
57
|
+
|
|
58
|
+
The state includes:
|
|
59
|
+
- `mode`: The current editor mode (preview, edit, live).
|
|
60
|
+
- `languageId`: The language ID of the current page set in the UVE.
|
|
61
|
+
- `persona`: The persona of the current page set in the UVE.
|
|
62
|
+
- `variantName`: The name of the current variant.
|
|
63
|
+
- `experimentId`: The ID of the current experiment.
|
|
64
|
+
- `publishDate`: The publish date of the current page set in the UVE.
|
|
65
|
+
|
|
66
|
+
> **Note:** If any of these properties are absent, it means the value is the default one.
|
|
67
|
+
|
|
68
|
+
**Example:**
|
|
69
|
+
```typescript
|
|
70
|
+
const editorState = getUVEState();
|
|
71
|
+
if (editorState?.mode === 'edit') {
|
|
72
|
+
// Enable editing features
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
### `editContentlet`
|
|
79
|
+
|
|
80
|
+
Allows you to edit a contentlet in the editor.
|
|
81
|
+
|
|
82
|
+
Calling this function within the editor prompts the UVE to open a dialog to edit the specified contentlet.
|
|
83
|
+
|
|
84
|
+
**Parameters:**
|
|
85
|
+
- `contentlet<T>` - The contentlet to edit.
|
|
86
|
+
|
|
87
|
+
**Example:**
|
|
88
|
+
```typescript
|
|
89
|
+
editContentlet(myContentlet);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
### `reorderMenu`
|
|
95
|
+
|
|
96
|
+
Reorders the menu based on the provided configuration.
|
|
97
|
+
|
|
98
|
+
**Parameters:**
|
|
99
|
+
- `config` (optional): Configuration for reordering the menu.
|
|
100
|
+
- `startLevel` (default: `1`): The starting level of the menu to reorder.
|
|
101
|
+
- `depth` (default: `2`): The depth of the menu to reorder.
|
|
102
|
+
|
|
103
|
+
This function constructs a URL for the reorder menu page with the specified `startLevel` and `depth`, then sends a message to the editor to perform the reorder action.
|
|
104
|
+
|
|
105
|
+
**Example:**
|
|
106
|
+
```typescript
|
|
107
|
+
reorderMenu({ startLevel: 2, depth: 3 });
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
### `initInlineEditing`
|
|
113
|
+
|
|
114
|
+
Initializes inline editing in the editor.
|
|
115
|
+
|
|
116
|
+
**Example:**
|
|
117
|
+
```typescript
|
|
118
|
+
initInlineEditing();
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
### `sendMessageToUVE`
|
|
124
|
+
|
|
125
|
+
The `sendMessageToUVE` function allows you to send messages to the dotCMS page editor. This is useful for triggering specific actions or updating the editor's state.
|
|
126
|
+
|
|
127
|
+
This function is primarily used within other libraries but can be helpful if you need to trigger specific behavior by sending a message to the UVE.
|
|
128
|
+
|
|
129
|
+
**Example:**
|
|
130
|
+
```typescript
|
|
131
|
+
sendMessageToEditor({ type: 'CUSTOM_MESSAGE': DotCMSUVEAction, payload: { key: 'value' } });
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Available Message Types (DotCMSUVEAction)
|
|
135
|
+
|
|
136
|
+
| **Type** | **Description** |
|
|
137
|
+
|--------------------------------------|---------------------------------------------------------------------------------------------------|
|
|
138
|
+
| `set-url` | Notifies the dotCMS editor that the page has changed. |
|
|
139
|
+
| `set-bounds` | Sends the position of rows, columns, containers, and contentlets to the editor. |
|
|
140
|
+
| `set-contentlet` | Sends information about the currently hovered contentlet. |
|
|
141
|
+
| `scroll` | Informs the editor that the page is being scrolled. |
|
|
142
|
+
| `scroll-end` | Notifies the editor that scrolling has stopped.
|
|
143
|
+
| `init-inline-editing` | Initializes the inline editing mode in the editor. |
|
|
144
|
+
| `copy-contentlet-inline-editing` | Opens the "Copy Contentlet" dialog to duplicate and edit a contentlet inline. |
|
|
145
|
+
| `update-contentlet-inline-editing` | Triggers the save action for inline-edited contentlets. |
|
|
146
|
+
| `reorder-menu` | Triggers the menu reorder action with a specified configuration. |
|
|
147
|
+
| `get-page-data` | Requests the current page information from the editor. |
|
|
148
|
+
| `client-ready` | Indicates that the client has sent a GraphQL query to the editor. |
|
|
149
|
+
| `edit-contentlet` | Opens the contentlet editing dialog in the editor. |
|
package/index.cjs.js
CHANGED
|
@@ -58,209 +58,110 @@ function getUVEState() {
|
|
|
58
58
|
/**
|
|
59
59
|
* Creates a subscription to a UVE event.
|
|
60
60
|
*
|
|
61
|
-
* @param
|
|
62
|
-
* @param
|
|
63
|
-
* @
|
|
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
64
|
*
|
|
65
65
|
* @example
|
|
66
66
|
* ```ts
|
|
67
|
-
*
|
|
68
|
-
*
|
|
67
|
+
* // Subscribe to page changes
|
|
68
|
+
* const subscription = createUVESubscription(UVEEventType.CONTENT_CHANGES, (changes) => {
|
|
69
|
+
* console.log('Content changes:', changes);
|
|
69
70
|
* });
|
|
71
|
+
*
|
|
72
|
+
* // Later, unsubscribe when no longer needed
|
|
73
|
+
* subscription.unsubscribe();
|
|
70
74
|
* ```
|
|
71
75
|
*/
|
|
72
|
-
function createUVESubscription(
|
|
76
|
+
function createUVESubscription(eventType, callback) {
|
|
73
77
|
if (!getUVEState()) {
|
|
74
78
|
console.warn('UVE Subscription: Not running inside UVE');
|
|
75
|
-
return internal.__UVE_EVENT_ERROR_FALLBACK__(
|
|
79
|
+
return internal.__UVE_EVENT_ERROR_FALLBACK__(eventType);
|
|
76
80
|
}
|
|
77
|
-
const eventCallback = internal.__UVE_EVENTS__[
|
|
81
|
+
const eventCallback = internal.__UVE_EVENTS__[eventType];
|
|
78
82
|
if (!eventCallback) {
|
|
79
|
-
console.error(`UVE Subscription: Event ${
|
|
80
|
-
return internal.__UVE_EVENT_ERROR_FALLBACK__(
|
|
83
|
+
console.error(`UVE Subscription: Event ${eventType} not found`);
|
|
84
|
+
return internal.__UVE_EVENT_ERROR_FALLBACK__(eventType);
|
|
81
85
|
}
|
|
82
86
|
return eventCallback(callback);
|
|
83
87
|
}
|
|
84
88
|
|
|
85
89
|
/**
|
|
86
|
-
*
|
|
90
|
+
* Post message to dotcms page editor
|
|
87
91
|
*
|
|
88
92
|
* @export
|
|
89
|
-
* @
|
|
90
|
-
* @
|
|
91
|
-
* @example
|
|
92
|
-
* ```ts
|
|
93
|
-
* const containers = document.querySelectorAll('.container');
|
|
94
|
-
* const bounds = getDotCMSPageBounds(containers);
|
|
95
|
-
* console.log(bounds);
|
|
96
|
-
* ```
|
|
93
|
+
* @template T
|
|
94
|
+
* @param {DotCMSUVEMessage<T>} message
|
|
97
95
|
*/
|
|
98
|
-
function
|
|
99
|
-
|
|
100
|
-
const containerRect = container.getBoundingClientRect();
|
|
101
|
-
const contentlets = Array.from(container.querySelectorAll('[data-dot-object="contentlet"]'));
|
|
102
|
-
return {
|
|
103
|
-
x: containerRect.x,
|
|
104
|
-
y: containerRect.y,
|
|
105
|
-
width: containerRect.width,
|
|
106
|
-
height: containerRect.height,
|
|
107
|
-
payload: JSON.stringify({
|
|
108
|
-
container: getDotCMSContainerData(container)
|
|
109
|
-
}),
|
|
110
|
-
contentlets: getDotCMSContentletsBound(containerRect, contentlets)
|
|
111
|
-
};
|
|
112
|
-
});
|
|
96
|
+
function sendMessageToUVE(message) {
|
|
97
|
+
window.parent.postMessage(message, '*');
|
|
113
98
|
}
|
|
114
99
|
/**
|
|
115
|
-
*
|
|
100
|
+
* You can use this function to edit a contentlet in the editor.
|
|
101
|
+
*
|
|
102
|
+
* Calling this function inside the editor, will prompt the UVE to open a dialog to edit the contentlet.
|
|
116
103
|
*
|
|
117
104
|
* @export
|
|
118
|
-
* @
|
|
119
|
-
* @param {
|
|
120
|
-
* @return {DotCMSContentletBound[]} An array of objects containing the bounding information for each contentlet.
|
|
121
|
-
* @example
|
|
122
|
-
* ```ts
|
|
123
|
-
* const containerRect = container.getBoundingClientRect();
|
|
124
|
-
* const contentlets = container.querySelectorAll('.contentlet');
|
|
125
|
-
* const bounds = getDotCMSContentletsBound(containerRect, contentlets);
|
|
126
|
-
* console.log(bounds); // Element bounds within the container
|
|
127
|
-
* ```
|
|
105
|
+
* @template T
|
|
106
|
+
* @param {Contentlet<T>} contentlet - The contentlet to edit.
|
|
128
107
|
*/
|
|
129
|
-
function
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
x: 0,
|
|
134
|
-
y: contentletRect.y - containerRect.y,
|
|
135
|
-
width: contentletRect.width,
|
|
136
|
-
height: contentletRect.height,
|
|
137
|
-
payload: JSON.stringify({
|
|
138
|
-
container: contentlet.dataset?.['dotContainer'] ? JSON.parse(contentlet.dataset?.['dotContainer']) : getClosestDotCMSContainerData(contentlet),
|
|
139
|
-
contentlet: {
|
|
140
|
-
identifier: contentlet.dataset?.['dotIdentifier'],
|
|
141
|
-
title: contentlet.dataset?.['dotTitle'],
|
|
142
|
-
inode: contentlet.dataset?.['dotInode'],
|
|
143
|
-
contentType: contentlet.dataset?.['dotType']
|
|
144
|
-
}
|
|
145
|
-
})
|
|
146
|
-
};
|
|
108
|
+
function editContentlet(contentlet) {
|
|
109
|
+
sendMessageToUVE({
|
|
110
|
+
action: types.DotCMSUVEAction.EDIT_CONTENTLET,
|
|
111
|
+
payload: contentlet
|
|
147
112
|
});
|
|
148
113
|
}
|
|
149
|
-
|
|
150
|
-
*
|
|
114
|
+
/*
|
|
115
|
+
* Reorders the menu based on the provided configuration.
|
|
151
116
|
*
|
|
152
|
-
* @
|
|
153
|
-
* @param {
|
|
154
|
-
* @
|
|
155
|
-
* @example
|
|
156
|
-
* ```ts
|
|
157
|
-
* const container = document.querySelector('.container');
|
|
158
|
-
* const data = getContainerData(container);
|
|
159
|
-
* console.log(data);
|
|
160
|
-
* ```
|
|
161
|
-
*/
|
|
162
|
-
function getDotCMSContainerData(container) {
|
|
163
|
-
return {
|
|
164
|
-
acceptTypes: container.dataset?.['dotAcceptTypes'] || '',
|
|
165
|
-
identifier: container.dataset?.['dotIdentifier'] || '',
|
|
166
|
-
maxContentlets: container.dataset?.['maxContentlets'] || '',
|
|
167
|
-
uuid: container.dataset?.['dotUuid'] || ''
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Get the closest container data from the contentlet.
|
|
117
|
+
* @param {ReorderMenuConfig} [config] - Optional configuration for reordering the menu.
|
|
118
|
+
* @param {number} [config.startLevel=1] - The starting level of the menu to reorder.
|
|
119
|
+
* @param {number} [config.depth=2] - The depth of the menu to reorder.
|
|
172
120
|
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
* @return {object | null} An object containing the closest container data or null if no container is found.
|
|
176
|
-
* @example
|
|
177
|
-
* ```ts
|
|
178
|
-
* const contentlet = document.querySelector('.contentlet');
|
|
179
|
-
* const data = getClosestDotCMSContainerData(contentlet);
|
|
180
|
-
* console.log(data);
|
|
181
|
-
* ```
|
|
121
|
+
* This function constructs a URL for the reorder menu page with the specified
|
|
122
|
+
* start level and depth, and sends a message to the editor to perform the reorder action.
|
|
182
123
|
*/
|
|
183
|
-
function
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
}
|
|
124
|
+
function reorderMenu(config) {
|
|
125
|
+
const {
|
|
126
|
+
startLevel = 1,
|
|
127
|
+
depth = 2
|
|
128
|
+
} = config || {};
|
|
129
|
+
sendMessageToUVE({
|
|
130
|
+
action: types.DotCMSUVEAction.REORDER_MENU,
|
|
131
|
+
payload: {
|
|
132
|
+
startLevel,
|
|
133
|
+
depth
|
|
134
|
+
}
|
|
135
|
+
});
|
|
195
136
|
}
|
|
196
137
|
/**
|
|
197
|
-
*
|
|
138
|
+
* Initializes the inline editing in the editor.
|
|
198
139
|
*
|
|
199
140
|
* @export
|
|
200
|
-
* @param {
|
|
201
|
-
* @
|
|
202
|
-
* @
|
|
203
|
-
* const element = document.querySelector('.some-element');
|
|
204
|
-
* const contentlet = findDotCMSElement(element);
|
|
205
|
-
* console.log(contentlet);
|
|
206
|
-
*/
|
|
207
|
-
function findDotCMSElement(element) {
|
|
208
|
-
if (!element) return null;
|
|
209
|
-
if (element?.dataset?.['dotObject'] === 'contentlet' || element?.dataset?.['dotObject'] === 'container' && element.children.length === 0) {
|
|
210
|
-
return element;
|
|
211
|
-
}
|
|
212
|
-
return findDotCMSElement(element?.['parentElement']);
|
|
213
|
-
}
|
|
214
|
-
/**
|
|
215
|
-
* Find VTL data within a target element.
|
|
141
|
+
* @param {INLINE_EDITING_EVENT_KEY} type
|
|
142
|
+
* @param {InlineEditEventData} eventData
|
|
143
|
+
* @return {*}
|
|
216
144
|
*
|
|
217
|
-
* @
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
* const target = document.querySelector('.target-element');
|
|
223
|
-
* const vtlData = findDotCMSVTLData(target);
|
|
224
|
-
* console.log(vtlData);
|
|
145
|
+
* * @example
|
|
146
|
+
* ```html
|
|
147
|
+
* <div onclick="initInlineEditing('BLOCK_EDITOR', { inode, languageId, contentType, fieldName, content })">
|
|
148
|
+
* ${My Content}
|
|
149
|
+
* </div>
|
|
225
150
|
* ```
|
|
226
151
|
*/
|
|
227
|
-
function
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
inode: vltElement.dataset?.['dotInode'],
|
|
235
|
-
name: vltElement.dataset?.['dotUrl']
|
|
236
|
-
};
|
|
152
|
+
function initInlineEditing(type, data) {
|
|
153
|
+
sendMessageToUVE({
|
|
154
|
+
action: types.DotCMSUVEAction.INIT_INLINE_EDITING,
|
|
155
|
+
payload: {
|
|
156
|
+
type,
|
|
157
|
+
data
|
|
158
|
+
}
|
|
237
159
|
});
|
|
238
160
|
}
|
|
239
|
-
/**
|
|
240
|
-
* Check if the scroll position is at the bottom of the page.
|
|
241
|
-
*
|
|
242
|
-
* @export
|
|
243
|
-
* @return {boolean} True if the scroll position is at the bottom, otherwise false.
|
|
244
|
-
* @example
|
|
245
|
-
* ```ts
|
|
246
|
-
* if (dotCMSScrollIsInBottom()) {
|
|
247
|
-
* console.log('Scrolled to the bottom');
|
|
248
|
-
* }
|
|
249
|
-
* ```
|
|
250
|
-
*/
|
|
251
|
-
function computeScrollIsInBottom() {
|
|
252
|
-
const documentHeight = document.documentElement.scrollHeight;
|
|
253
|
-
const viewportHeight = window.innerHeight;
|
|
254
|
-
const scrollY = window.scrollY;
|
|
255
|
-
return scrollY + viewportHeight >= documentHeight;
|
|
256
|
-
}
|
|
257
161
|
|
|
258
|
-
exports.computeScrollIsInBottom = computeScrollIsInBottom;
|
|
259
162
|
exports.createUVESubscription = createUVESubscription;
|
|
260
|
-
exports.
|
|
261
|
-
exports.findDotCMSVTLData = findDotCMSVTLData;
|
|
262
|
-
exports.getClosestDotCMSContainerData = getClosestDotCMSContainerData;
|
|
263
|
-
exports.getDotCMSContainerData = getDotCMSContainerData;
|
|
264
|
-
exports.getDotCMSContentletsBound = getDotCMSContentletsBound;
|
|
265
|
-
exports.getDotCMSPageBounds = getDotCMSPageBounds;
|
|
163
|
+
exports.editContentlet = editContentlet;
|
|
266
164
|
exports.getUVEState = getUVEState;
|
|
165
|
+
exports.initInlineEditing = initInlineEditing;
|
|
166
|
+
exports.reorderMenu = reorderMenu;
|
|
167
|
+
exports.sendMessageToUVE = sendMessageToUVE;
|