@dotcms/uve 0.0.1-beta.33 → 0.0.1-beta.35

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 CHANGED
@@ -1,324 +1,589 @@
1
- # DotCMS UVE SDK
1
+ # dotCMS UVE SDK
2
2
 
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.
3
+ The `@dotcms/uve` SDK adds live editing to your JavaScript app using the dotCMS Universal Visual Editor (UVE). It provides low-level tools that power our framework-specific SDKs, such as [`@dotcms/react`](https://github.com/dotCMS/core/blob/main/core-web/libs/sdk/react/README.md) and [`@dotcms/angular`](https://github.com/dotCMS/core/blob/main/core-web/libs/sdk/angular/README.md).
4
4
 
5
- > **BETA VERSION NOTICE:** This SDK is currently in beta. APIs, functionality, and documentation may change significantly in the stable release.
5
+ > ⚠️ We **do not recommend using this SDK directly** for most use cases, you should use a [framework SDK that handles setup](#Getting Started: Recommended Examples), rendering, and event wiring for you.
6
+
7
+ With `@dotcms/uve`, framework SDKs are able to:
8
+ - Make pages and contentlets editable
9
+ - Respond to editor events (content updates, mode changes)
10
+ - Trigger modal or inline editing experiences
11
+ - Sync app routing with the dotCMS editor
6
12
 
7
13
  ## Table of Contents
8
14
 
9
- - [Installation](#installation)
10
- - [Entry Points](#entry-points)
11
- - [Getting Started](#getting-started)
12
- - [API Reference](#api-reference)
13
- - [Editor State](#editor-state)
14
- - [Event Subscriptions](#event-subscriptions)
15
- - [Content Editing](#content-editing)
16
- - [Navigation & UI](#navigation--ui)
17
- - [Messaging](#messaging)
18
- - [Types Reference](#types-reference)
19
- - [Examples](#examples)
20
- - [Contributing](#contributing)
21
- - [License](#license)
15
+ - [Before You Use @dotcms/uve](#before-you-use-dotcmsuve)
16
+ - [Getting Started: Recommended Examples](#getting-started-recommended-examples)
17
+ - [🚩 Custom Setup: Manual Rendering (Not Recommended)](#-custom-setup-manual-rendering-not-recommended)
18
+ - [Prerequisites & Setup](#prerequisites--setup)
19
+ - [Get a dotCMS Environment](#get-a-dotcms-environment)
20
+ - [Create a dotCMS API Key](#create-a-dotcms-api-key)
21
+ - [Installation](#installation)
22
+ - [Using the SDK with TypeScript](#using-the-sdk-with-typescript)
23
+ - [SDK Reference](#sdk-reference)
24
+ - [`initUVE()`](#inituveconfig-dotcmsuveconfig)
25
+ - [`getUVEState()`](#getuvestate)
26
+ - [`createUVESubscription()`](#createuvesubscriptioneventtype-callback)
27
+ - [`editContentlet()`](#editcontentletcontentlet)
28
+ - [`initInlineEditing()`](#initinlineeditingtype-data)
29
+ - [`enableBlockEditorInline()`](#enableblockeditorinlinecontentlet-fieldname)
30
+ - [`updateNavigation()`](#updatenavigationpathname)
31
+ - [`reorderMenu()`](#reordermenuconfig)
32
+ - [`sendMessageToUVE()`](#sendmessagetouvemessage)
33
+ - [Troubleshooting](#troubleshooting)
34
+ - [Common Issues & Solutions](#common-issues--solutions)
35
+ - [Debugging Tips](#debugging-tips)
36
+ - [Still Having Issues?](#still-having-issues)
37
+ - [dotCMS Support](#dotcms-support)
38
+ - [How To Contribute](#how-to-contribute)
39
+ - [Licensing Information](#licensing-information)
40
+ - [Troubleshooting](#troubleshooting)
41
+
42
+ ## Before You Use @dotcms/uve
43
+
44
+ ### Getting Started: Recommended Examples
45
+
46
+ We strongly recommend using one of our official framework SDKs, which are designed to handle UVE integration, routing, rendering, and more—out of the box. These examples are the best way to get started:
47
+
48
+ - [dotCMS Angular SDK: Angular Example](https://github.com/dotCMS/core/tree/main/examples/angular) – Ideal for Angular apps 🅰️
49
+ - [dotCMS React SDK: NextJS Example](https://github.com/dotCMS/core/tree/main/examples/react) – Ideal for NextJS projects ⚛️
50
+ - [dotCMS React SDK: Astro Example](https://github.com/dotCMS/core/tree/main/examples/astro) – Ideal for Astro projects 🌌
51
+
52
+ These examples handle UVE integration, routing, rendering, and more—out of the box. **If you're building a headless dotCMS front-end, start there.**
53
+
54
+ ### 🚩 Custom Setup: Manual Rendering (Not Recommended)
55
+
56
+ > 💡 We recommend using one of our official framework SDKs, which are designed to handle UVE integration, routing, rendering, and more—out of the box.
57
+
58
+ You can use `@dotcms/uve` directly, but **it’s not recommended or supported** unless you’re building a highly custom integration. Here’s how the pieces fit together:
59
+
60
+ 1. **You must use `@dotcms/client` to fetch content and page data.**
61
+ 2. **You must render pages based on dotCMS’s layout schema.**
62
+ 3. **You must apply the correct `data-dot-*` attributes to containers and contentlets.**
63
+
64
+ Here's a minimal setup using `@dotcms/client` and `@dotcms/uve`:
65
+
66
+ 1. Initializa the Client and get the page response:
67
+
68
+ ```ts
69
+ // getPage.ts
70
+ import { createDotCMSClient } from '@dotcms/client/next';
71
+ import { initUVE, createUVESubscription } from '@dotcms/uve/next';
72
+
73
+ const dotCMSClient = createDotCMSClient({
74
+ dotcmsUrl: 'https://your-dotcms-instance.com',
75
+ authToken: 'your-api-key',
76
+ siteId: 'your-site-id'
77
+ });
22
78
 
23
- ## Installation
79
+ const getPage = async () => {
80
+ const pageResponse = await dotCMSClient.page.get('/', {
81
+ languageId: '1'
82
+ });
24
83
 
25
- The UVE SDK is automatically included in DotCMS installations. For external usage:
84
+ return pageResponse;
85
+ };
86
+ ```
26
87
 
27
- ```bash
28
- # Using npm
29
- npm install @dotcms/uve-sdk
88
+ 2. Initialize the UVE and subscribe to changes:
30
89
 
31
- # Using yarn
32
- yarn add @dotcms/uve-sdk
33
- ```
90
+ > ⚠️ The `initUVE()` function only works with a `PageResponse` returned by `@dotcms/client`. If you try to pass in data from another source or build your own structure, it won't initialize properly.
91
+
92
+ ```ts
93
+ import { initUVE, createUVESubscription } from '@dotcms/uve/next';
94
+ import { getPage } from './getPage';
34
95
 
35
- ## Entry Points
96
+ const pageResponse = await getPage();
36
97
 
37
- The library exposes three main entry points:
98
+ initUVE(pageResponse);
99
+ createUVESubscription('changes', (newPageResponse) => {
100
+ // Handle page updates (e.g. re-render)
101
+ });
102
+ ```
38
103
 
39
- - **`@dotcms/uve`**: Provides everything developers need to communicate with UVE.
104
+ > ⚠️ This only sets up the editor connection. You are responsible for rendering the page structure (rows, columns, containers, contentlets) using your own UI components.
40
105
 
41
- - **`@dotcms/uve/types`**: Offers TypeScript types, interfaces, and other structures to help users organize their code properly.
106
+ 3. Create a custom render for the page:
42
107
 
43
- ## Getting Started
108
+ ```tsx
109
+ // 🔧 Render the page layout (you must implement this component)
110
+ <MyDotCMSPage pageAsset={pageResponse.pageAsset} />
111
+ ```
44
112
 
45
- To use the UVE SDK in your project, import the necessary functions:
113
+ > ⚠️ Below is a simplified breakdown of how dotCMS layouts are structured and how you might render them manually.
114
+
115
+ #### 🔄 How to Render a dotCMS Page
116
+
117
+ > 📚 For a complete guide, here is a full tutorial:
118
+ > 👉 [dotCMS Page Rendering Architecture]( https://dev.dotcms.com/docs/dotcms-page-rendering-architecture)
119
+
120
+ dotCMS pages are structured as nested layout objects:
121
+
122
+ - A `PageAsset` contains a `layout` object
123
+ - The `layout` includes rows, columns, containers, and contentlets
124
+
125
+ Here’s a basic pseudocode outline:
126
+
127
+ ```jsx
128
+ <Page>
129
+ {layout.body.rows.map(row => (
130
+ <Row>
131
+ {row.columns.map(column => (
132
+ <Column>
133
+ {column.containers.map(container => (
134
+ <Container data-dot-object="container" ...>
135
+ {container.contentlets.map(contentlet => (
136
+ <Contentlet data-dot-object="contentlet" ...>
137
+ {renderContentletByType(contentlet)}
138
+ </Contentlet>
139
+ ))}
140
+ </Container>
141
+ ))}
142
+ </Column>
143
+ ))}
144
+ </Row>
145
+ ))}
146
+ </Page>
147
+ ```
46
148
 
47
- ```typescript
48
- import { getUVEState, createUVESubscription, editContentlet } from '@dotcms/uve';
49
- import { UVEEventType, UVE_MODE } from '@dotcms/uve/types';
50
-
51
- // Check if we're in the editor
52
- const uveState = getUVEState();
53
- if (uveState?.mode === UVE_MODE.EDIT) {
54
- console.log('Running in edit mode!');
55
-
56
- // Subscribe to content changes
57
- const subscription = createUVESubscription(UVEEventType.CONTENT_CHANGES, (changes) => {
58
- console.log('Content updated:', changes);
59
- // Update your UI with the new content
60
- });
61
-
62
- // Later, when no longer needed
63
- subscription.unsubscribe();
149
+ Each contentlet is rendered according to its content type:
150
+
151
+ ```ts
152
+ function renderContentletByType(contentlet) {
153
+ switch(contentlet.contentType) {
154
+ case 'text': return <TextBlock contentlet={contentlet} />;
155
+ case 'image': return <ImageBlock contentlet={contentlet} />;
156
+ case 'video': return <VideoBlock contentlet={contentlet} />;
157
+ default: return null;
158
+ }
64
159
  }
65
160
  ```
66
161
 
67
- ## API Reference
162
+ To make the layout editable, be sure to apply all required `data-dot-*` attributes on containers and contentlets.
68
163
 
69
- ### Editor State
164
+ ## Prerequisites & Setup
70
165
 
71
- #### `getUVEState`
166
+ ### Get a dotCMS Environment
72
167
 
73
- Retrieves the current UVE state.
168
+ #### Version Compatibility
74
169
 
75
- **Returns:**
76
- - A `UVEState` object if running inside the editor, or `undefined` otherwise.
170
+ - **Recommended**: dotCMS Evergreen
171
+ - **Minimum**: dotCMS v25.05
172
+ - **Best Experience**: Latest Evergreen release
77
173
 
78
- The state includes:
79
- - `mode`: The current editor mode (preview, edit, live).
80
- - `languageId`: The language ID of the current page set in the UVE.
81
- - `persona`: The persona of the current page set in the UVE.
82
- - `variantName`: The name of the current variant.
83
- - `experimentId`: The ID of the current experiment.
84
- - `publishDate`: The publish date of the current page set in the UVE.
174
+ #### Environment Setup
85
175
 
86
- > **Note:** If any of these properties are absent, it means the value is the default one.
176
+ **For Production Use:**
87
177
 
88
- **Example:**
89
- ```typescript
90
- const editorState = getUVEState();
91
- if (editorState?.mode === 'edit') {
92
- // Enable editing features
93
- }
94
- ```
178
+ - ☁️ [Cloud hosting options](https://www.dotcms.com/pricing) - managed solutions with SLA
179
+ - 🛠️ [Self-hosted options](https://dev.dotcms.com/docs/current-releases) - deploy on your infrastructure
95
180
 
96
- ### Event Subscriptions
181
+ **For Testing & Development:**
97
182
 
98
- #### `createUVESubscription`
183
+ - 🧑🏻‍💻 [dotCMS demo site](https://demo.dotcms.com/dotAdmin/#/public/login) - perfect for trying out the SDK
184
+ - 📘 [Learn how to use the demo site](https://dev.dotcms.com/docs/demo-site)
185
+ - 📝 Read-only access, ideal for building proof-of-concepts
99
186
 
100
- Subscribe to page changes and other UVE events. Receive a callback that will be called with the updated content of the page.
187
+ **For Local Development:**
101
188
 
102
- **Parameters:**
103
- - `eventType` - The type of event to subscribe to.
104
- - `callback` - The callback function that will be called when the event occurs.
189
+ - 🐳 [Docker setup guide](https://github.com/dotCMS/core/tree/main/docker/docker-compose-examples/single-node-demo-site)
190
+ - 💻 [Local installation guide](https://dev.dotcms.com/docs/quick-start-guide)
105
191
 
106
- **Returns:**
107
- - An event subscription that can be used to unsubscribe.
192
+ ### Configure The Universal Visual Editor App
108
193
 
109
- **Example:**
110
- ```typescript
111
- // Subscribe to page changes
112
- const subscription = createUVESubscription(UVEEventType.CONTENT_CHANGES, (changes) => {
113
- console.log('Content changes:', changes);
114
- });
194
+ For a step-by-step guide on setting up the Universal Visual Editor, check out our [easy-to-follow instructions](https://dev.dotcms.com/docs/uve-headless-config) and get started in no time!
195
+
196
+ ### Installation
115
197
 
116
- // Later, unsubscribe when no longer needed
117
- subscription.unsubscribe();
198
+ ```bash
199
+ npm install @dotcms/uve@next
118
200
  ```
119
201
 
120
- ### Content Editing
202
+ ### Using the SDK with TypeScript
121
203
 
122
- #### `editContentlet`
204
+ All interfaces and types are available through the `@dotcms/types` package:
123
205
 
124
- Allows you to edit a contentlet in the editor.
206
+ ```bash
207
+ npm install @dotcms/types@next --save-dev
208
+ ```
125
209
 
126
- Calling this function within the editor prompts the UVE to open a dialog to edit the specified contentlet.
210
+ #### Common Types
127
211
 
128
- **Parameters:**
129
- - `contentlet<T>` - The contentlet to edit.
212
+ The SDK uses several key types from `@dotcms/types`:
130
213
 
131
- **Example:**
132
214
  ```typescript
133
- // Edit a contentlet
134
- editContentlet(myContentlet);
215
+ import {
216
+ DotCMSContentlet,
217
+ DotCMSPageResponse,
218
+ DotCMSUVEConfig,
219
+ DotCMSInlineEditingType,
220
+ UVEEventType,
221
+ UVEState
222
+ } from '@dotcms/types';
135
223
  ```
136
224
 
137
- #### `initInlineEditing`
225
+ For a complete reference of all available types and interfaces, please refer to the [@dotcms/types documentation](https://www.npmjs.com/package/@dotcms/types).
138
226
 
139
- Initializes inline editing in the editor.
227
+ ## SDK Reference
140
228
 
141
- **Parameters:**
142
- - `type` - The type of inline editing ('BLOCK_EDITOR' or 'WYSIWYG').
143
- - `data` - (Optional) Data for the inline editing session.
229
+ ### `initUVE(config?: DotCMSUVEConfig)`
144
230
 
145
- **Example:**
146
- ```typescript
147
- // Initialize block editor
148
- initInlineEditing('BLOCK_EDITOR', {
149
- inode: 'abc123',
150
- language: 1,
151
- contentType: 'Blog',
152
- fieldName: 'body',
153
- content: { /* content data */ }
154
- });
231
+ `initUVE` is a function that initializes the Universal Visual Editor (UVE). It sets up the necessary communication between your app and the editor, enabling seamless integration and interaction.
232
+
233
+ | Input | Type | Required | Description |
234
+ | -------- | -------------------- | -------- | ------------------------------------------- |
235
+ | `config` | `DotCMSPageResponse` | ✅ | The page Response from the `@dotcms/client` |
236
+
237
+ #### Usage
238
+
239
+ ```ts
240
+ const { destroyUVESubscriptions } = initUVE(pageResponse);
155
241
  ```
156
242
 
157
- ### Navigation & UI
243
+ > ⚠️ If you don't provide a `pageResponse`, we can't assure that the UVE will be initialized correctly.
158
244
 
159
- #### `reorderMenu`
245
+ ### `getUVEState()`
160
246
 
161
- Reorders the menu based on the provided configuration.
247
+ `getUVEState` is a function that returns the [UVE state](#uve-state) if UVE is active.
162
248
 
163
- **Parameters:**
164
- - `config` (optional): Configuration for reordering the menu.
165
- - `startLevel` (default: `1`): The starting level of the menu to reorder.
166
- - `depth` (default: `2`): The depth of the menu to reorder.
249
+ #### Usage
167
250
 
168
- 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.
251
+ ```tsx
252
+ import { getUVEState } from '@dotcms/uve';
253
+ import { UVE_MODE } from '@dotcms/types';
169
254
 
170
- **Example:**
171
- ```typescript
172
- // Reorder menu starting from level 2 with depth of 3
173
- reorderMenu({ startLevel: 2, depth: 3 });
255
+ const myEditButton = () => {
256
+ const uveState = getUVEState();
257
+
258
+ if (uveState?.mode === UVE_MODE.EDIT) {
259
+ return <button>Edit</button>;
260
+ }
261
+
262
+ return null;
263
+ };
174
264
  ```
175
265
 
176
- ### Messaging
266
+ #### UVE State
177
267
 
178
- #### `sendMessageToUVE`
268
+ - `dotCMSHost`: The host URL of the DotCMS instance
269
+ - `experimentId`: The ID of the current experiment
270
+ - `languageId`: The language ID of the current page set on the UVE
271
+ - `mode`: The current editor mode (`'preview'`, `'edit'`, `'live'`)
272
+ - `persona`: The persona of the current page set on the UVE
273
+ - `publishDate`: The publish date of the current page set on the UVE
274
+ - `variantName`: The name of the current variant
179
275
 
180
- 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.
276
+ ### `createUVESubscription(eventType, callback)`
181
277
 
182
- This function is primarily used within other library functions but can be helpful if you need to trigger specific behavior by sending a message to the UVE.
278
+ `createUVESubscription` is a function that allows your application to dynamically interact with UVE by subscribing to events such as content changes or navigation updates. This enables your app to respond in real-time to user actions and editor events, enhancing the interactive experience.
183
279
 
184
- **Example:**
185
- ```typescript
186
- sendMessageToUVE({
187
- action: DotCMSUVEAction.CUSTOM_MESSAGE,
188
- payload: { key: 'value' }
280
+ | Input | Type | Required | Description |
281
+ | ----------- | -------------- | -------- | ----------------------------------------- |
282
+ | `eventType` | `UVEEventType` | ✅ | [The event to subscribe to](#event-types) |
283
+ | `callback` | `Function` | ✅ | Called when the event is triggered |
284
+
285
+ #### Usage
286
+
287
+ ```ts
288
+ import { createUVESubscription } from '@dotcms/uve';
289
+ import { UVEEventType } from '@dotcms/types';
290
+
291
+ const sub = createUVESubscription(UVEEventType.CONTENT_CHANGES, (newPageResponse) => {
292
+ // do something when the content changes
189
293
  });
294
+
295
+ // Later, when you want to unsubscribe
296
+ sub.unsubscribe();
190
297
  ```
191
298
 
192
- ### Available Message Types (DotCMSUVEAction)
299
+ #### Event Types
193
300
 
194
- | **Type** | **Description** |
195
- |--------------------------------------|---------------------------------------------------------------------------------------------------|
196
- | `NAVIGATION_UPDATE` | Notifies the dotCMS editor that the page has changed. |
197
- | `SET_BOUNDS` | Sends the position of rows, columns, containers, and contentlets to the editor. |
198
- | `SET_CONTENTLET` | Sends information about the currently hovered contentlet. |
199
- | `IFRAME_SCROLL` | Informs the editor that the page is being scrolled. |
200
- | `IFRAME_SCROLL_END` | Notifies the editor that scrolling has stopped. |
201
- | `PING_EDITOR` | Pings the editor to check if the page is inside the editor. |
202
- | `INIT_INLINE_EDITING` | Initializes the inline editing mode in the editor. |
203
- | `COPY_CONTENTLET_INLINE_EDITING` | Opens the "Copy Contentlet" dialog to duplicate and edit a contentlet inline. |
204
- | `UPDATE_CONTENTLET_INLINE_EDITING` | Triggers the save action for inline-edited contentlets. |
205
- | `REORDER_MENU` | Triggers the menu reorder action with a specified configuration. |
206
- | `GET_PAGE_DATA` | Requests the current page information from the editor. |
207
- | `CLIENT_READY` | Indicates that the client has completed initialization. |
208
- | `EDIT_CONTENTLET` | Opens the contentlet editing dialog in the editor. |
301
+ - `UVEEventType.CONTENT_CHANGES`: Triggered when the content of the page changes.
302
+ - `UVEEventType.PAGE_RELOAD`: Triggered when the page is reloaded.
303
+ - `UVEEventType.REQUEST_BOUNDS`: Triggered when the editor requests the bounds of the page.
304
+ - `UVEEventType.IFRAME_SCROLL`: Triggered when the iframe is scrolled.
305
+ - `UVEEventType.IFRAME_SCROLL_END`: Triggered when the iframe has stopped scrolling.
306
+ - `UVEEventType.CONTENTLET_HOVERED`: Triggered when a contentlet is hovered.
209
307
 
210
- ## Types Reference
308
+ ### `editContentlet(contentlet)`
211
309
 
212
- The SDK provides TypeScript types to assist in development:
310
+ `editContentlet` is a function that opens the dotCMS modal editor for any contentlet in or out of page area.
213
311
 
214
- ### UVE State and Modes
312
+ | Input | Type | Required | Description |
313
+ | ------------ | ------------------ | -------- | -------------------------------- |
314
+ | `contentlet` | `Contentlet<T>` | ✅ | The contentlet you want to edit. |
215
315
 
216
- ```typescript
217
- // UVE State Interface
218
- interface UVEState {
219
- mode: UVE_MODE;
220
- persona: string | null;
221
- variantName: string | null;
222
- experimentId: string | null;
223
- publishDate: string | null;
224
- languageId: string | null;
225
- }
316
+ #### Usage
226
317
 
227
- // UVE Mode Enum
228
- enum UVE_MODE {
229
- EDIT = 'EDIT_MODE',
230
- PREVIEW = 'PREVIEW_MODE',
231
- LIVE = 'LIVE',
232
- UNKNOWN = 'UNKNOWN'
233
- }
318
+ ```tsx
319
+ import { editContentlet, getUVEState } from '@dotcms/uve';
320
+ import { UVE_MODE } from '@dotcms/types';
321
+
322
+ const myEditButton = ({ contentlet }) => {
323
+ const uveState = getUVEState();
324
+
325
+ if (uveState?.mode === UVE_MODE.EDIT) {
326
+ return <button onClick={() => editContentlet(contentlet)}>Edit</button>;
327
+ }
328
+
329
+ return null;
330
+ };
234
331
  ```
235
332
 
236
- ### UVE Events
333
+ ### `initInlineEditing(type, data)`
334
+
335
+ `initInlineEditing` is a function that triggers inline editing for supported field types (WYSIWYG or Block Editor).
336
+
337
+ | Input | Type | Required | Description |
338
+ | ----------- | ---------------------------- | -------- | ------------------------------------------------------------------------------ |
339
+ | `type` | `DotCMSInlineEditingType` | ✅ | `'BLOCK_EDITOR'` or `'WYSIWYG'` |
340
+ | `fieldData` | `DotCMSInlineEditingPayload` | ✅ | [Field content required to enable inline editing](#dotcmsinlineeditingpayload) |
341
+
342
+ #### Usage
343
+
344
+ ```ts
345
+ import { initInlineEditing, getUVEState } from "@dotcms/uve";
346
+ import { UVE_MODE } from "@dotcms/types";
347
+
348
+ const MyBanner = ({ contentlet }) => {
349
+ const uveState = getUVEState();
350
+
351
+ const handleClick = () => {
352
+ if (uveState?.mode === UVE_MODE.EDIT) {
353
+ const { inode, contentType, title } = contentlet;
354
+ initInlineEditing("BLOCK_EDITOR", {
355
+ inode,
356
+ contentType,
357
+ content: title,
358
+ fieldName: "title",
359
+ });
360
+ }
361
+ };
362
+ return (
363
+ <div>
364
+ <h1 onClick={handleClick}>{contentlet.title}</h1>
365
+ <p>{contentlet.description}</p>
366
+ </div>
367
+ );
368
+ };
369
+ ```
237
370
 
238
- ```typescript
239
- // Event Types Enum
240
- enum UVEEventType {
241
- CONTENT_CHANGES = 'changes',
242
- PAGE_RELOAD = 'page-reload',
243
- REQUEST_BOUNDS = 'request-bounds',
244
- IFRAME_SCROLL = 'iframe-scroll',
245
- CONTENTLET_HOVERED = 'contentlet-hovered'
246
- }
371
+ #### DotCMSInlineEditingPayload
247
372
 
248
- // Event Subscription Interface
249
- interface UVEEventSubscription {
250
- unsubscribe: () => void;
251
- event: string;
252
- }
373
+ - `inode` (string): The inode of the contentlet to edit.
374
+ - `contentType` (string): The content type of the contentlet to edit.
375
+ - `fieldName` (string): The name of the field to edit.
376
+ - `content` (string): The content of the field to edit.
377
+
378
+ ### `enableBlockEditorInline(contentlet, fieldName)`
379
+
380
+ `enableBlockEditorInline` is a shortcut to [enable inline block editing](https://dev.dotcms.com/docs/block-editor#BlockInlineEditor) for a field.
381
+
382
+ | Input | Type | Required | Description |
383
+ | ------------ | ----------------------- | -------- | -------------------------------------------------------------- |
384
+ | `contentlet` | `DotCMSBasicContentlet` | ✅ | The target contentlet |
385
+ | `fieldName` | `string` | ✅ | [Name of the block field to edit](#dotcmsinlineeditingpayload) |
386
+
387
+ #### Usage
388
+
389
+ ```tsx
390
+ import { enableBlockEditorInline, getUVEState } from '@dotcms/uve';
391
+ import { UVE_MODE } from '@dotcms/types';
392
+
393
+ const MyBanner = ({ contentlet }) => {
394
+ const uveState = getUVEState();
395
+
396
+ const handleClick = () => {
397
+ if (uveState?.mode === UVE_MODE.EDIT) {
398
+ enableBlockEditorInline(contentlet, 'blockContent');
399
+ }
400
+ };
401
+
402
+ return <MyBlockEditorRender onClick={handleClick} />;
403
+ };
253
404
  ```
254
405
 
255
- ## Examples
406
+ ### `updateNavigation(pathname)`
256
407
 
257
- ### Basic Usage
408
+ `updateNavigation` is a function that notifies UVE that navigation has changed (e.g., in SPAs).
258
409
 
259
- ```typescript
260
- import { getUVEState, createUVESubscription } from '@dotcms/uve';
261
- import { UVEEventType, UVE_MODE } from '@dotcms/uve/types';
262
-
263
- // Check if we're in the editor
264
- const uveState = getUVEState();
265
- if (uveState) {
266
- console.log(`Running in ${uveState.mode} mode`);
267
-
268
- // Initialize components based on editor state
269
- if (uveState.mode === UVE_MODE.EDIT) {
270
- enableEditFeatures();
271
- }
272
- }
410
+ | Input | Type | Required | Description |
411
+ | ---------- | -------- | -------- | -------------------------- |
412
+ | `pathname` | `string` | ✅ | The new pathname to update |
413
+
414
+ #### Usage
415
+
416
+ ```tsx
417
+ import { updateNavigation } from '@dotcms/uve';
418
+
419
+ updateNavigation('/navigate-to-this-new-page');
273
420
  ```
274
421
 
275
- ### Content Updates
422
+ ### `reorderMenu(config?)`
276
423
 
277
- ```typescript
278
- import { createUVESubscription } from '@dotcms/uve';
279
- import { UVEEventType } from '@dotcms/uve/types';
424
+ `reorderMenu` is a function that opens the UVE menu editor to reorder navigation links.
280
425
 
281
- // Subscribe to content changes
282
- const subscription = createUVESubscription(UVEEventType.CONTENT_CHANGES, (changes) => {
283
- // Update your UI with the new content
284
- updateUI(changes);
285
- });
426
+ | Input | Type | Required | Description |
427
+ | --------- | ------------------------- | -------- | ---------------------------------------------------------- |
428
+ | `config?` | `DotCMSReorderMenuConfig` | ❌ | [Optional config for reordering](#dotcmsreordermenuconfig) |
286
429
 
287
- // Clean up when component unmounts
288
- function cleanup() {
289
- subscription.unsubscribe();
290
- }
430
+ #### Usage
431
+
432
+ ```ts
433
+ import { reorderMenu } from '@dotcms/uve';
434
+
435
+ reorderMenu({ startLevel: 2, depth: 3 });
291
436
  ```
292
437
 
293
- ### Inline Editing Integration
438
+ #### DotCMSReorderMenuConfig
294
439
 
295
- ```typescript
296
- import { initInlineEditing } from '@dotcms/uve';
297
-
298
- // Integrate with a block editor component
299
- function setupBlockEditor(element, contentData) {
300
- element.addEventListener('click', () => {
301
- initInlineEditing('BLOCK_EDITOR', {
302
- inode: contentData.inode,
303
- language: contentData.languageId,
304
- contentType: contentData.contentType,
305
- fieldName: 'body',
306
- content: contentData.content
307
- });
308
- });
309
- }
440
+ - `startLevel` (number): The level to start reordering from
441
+ - `depth` (number): The depth of the menu to reorder
442
+
443
+ ### `sendMessageToUVE(message)`
444
+
445
+ `sendMessageToUVE` is a low-level function to send custom messages to UVE.
446
+
447
+ | Input | Type | Required | Description |
448
+ | --------- | ------------------------------------------ | -------- | ---------------------------- |
449
+ | `message` | [`DotCMSUVEMessage<T>`](#dotcmsuvemessage) | ✅ | Object with action + payload |
450
+
451
+ #### Usage
452
+
453
+ ```ts
454
+ sendMessageToUVE({
455
+ action: DotCMSUVEAction.CUSTOM_EVENT,
456
+ payload: { type: 'MyEvent', data: {...} }
457
+ });
310
458
  ```
311
459
 
312
- ## Contributing
460
+ #### DotCMSUVEMessage<T>
461
+
462
+ | Event (DotCMSUVEAction) | Payload (T) |
463
+ | ---------------------------------- | ------------------------------------------------------------- | ------- |
464
+ | `NAVIGATION_UPDATE` | `{ url: string }` |
465
+ | `SET_BOUNDS` | `DotCMSContainerBound[]` |
466
+ | `SET_CONTENTLET` | `DotCMSBasicContentlet` |
467
+ | `IFRAME_SCROLL` | `'up' | 'down'` |
468
+ | `IFRAME_SCROLL_END` | --- |
469
+ | `REORDER_MENU` | `DotCMSReorderMenuConfig` |
470
+ | `INIT_INLINE_EDITING` | `DotCMSInlineEditingPayload` |
471
+ | `COPY_CONTENTLET_INLINE_EDITING` | `{ dataset: { inode, language, fieldName: this.fieldName } }` |
472
+ | `UPDATE_CONTENTLET_INLINE_EDITING` | `{ content: string, dataset: { inode, langId, fieldName } }` |
473
+ | `GET_PAGE_DATA` | --- |
474
+ | `CLIENT_READY` | --- |
475
+ | `EDIT_CONTENTLET` | `DotCMSBasicContentlet` |
476
+
477
+ ## Troubleshooting
478
+
479
+ ### Common Issues & Solutions
313
480
 
314
- We welcome contributions to the UVE SDK! Please follow these steps:
481
+ #### Memory Management
315
482
 
316
- 1. Fork the repository
483
+ 1. **Memory Leaks**: Application experiences memory leaks
484
+ - **Possible Causes**:
485
+ - Failing to call `destroyUVESubscriptions()` on unmount
486
+ - **Solutions**:
487
+ - Always call `destroyUVESubscriptions()` when your component unmounts to clean up subscriptions
488
+
489
+ #### Editor State
490
+
491
+ 1. **Undefined State**: `getUVEState()` returns undefined
492
+ - **Possible Causes**:
493
+ - Application not running inside the dotCMS editor
494
+ - **Solutions**:
495
+ - Ensure your application is running within the dotCMS environment when calling `getUVEState()`
496
+
497
+ #### Event Handling
498
+
499
+ 1. **Unsubscribed Events**: Events not unsubscribed leading to unexpected behavior
500
+ - **Possible Causes**:
501
+ - Not unsubscribing from events
502
+ - **Solutions**:
503
+ - Always unsubscribe from events using the `unsubscribe()` method to prevent memory leaks
504
+
505
+ #### Inline Editing
506
+
507
+ 1. **Invalid Contentlet or Field**: `initInlineEditing()` requires valid contentlet and field name
508
+ - **Possible Causes**:
509
+ - Incorrect contentlet or field name
510
+ - **Solutions**:
511
+ - Verify that the contentlet and field name are correct and exist in the dotCMS instance
512
+
513
+ #### Non-existent Page Navigation
514
+
515
+ 1. **Navigation to a non-existent page**: May break content sync in UVE and make the editor redirect to the home page
516
+ - **Possible Causes**:
517
+ - Navigation to a non-existent page
518
+ - **Solutions**:
519
+ - Ensure the page exists in the dotCMS instance
520
+
521
+ #### Menu Reordering
522
+
523
+ 1. **UI Action Requirement**: `reorderMenu()` must be called from a UI action
524
+ - **Possible Causes**:
525
+ - Attempting to auto-trigger `reorderMenu()`
526
+ - **Solutions**:
527
+ - Ensure `reorderMenu()` is triggered by a user action within the UI
528
+
529
+ ### Debugging Tips
530
+
531
+ 1. **Ensure you are in the UVE Context**
532
+ - Check if you are in the UVE context by calling `getUVEState()`
533
+ - If you are not in the UVE context, you will not be able to use the UVE SDK correctly
534
+ 2. **Check Browser Console**
535
+ - Check for errors in the browser console
536
+ - Check for errors in the browser network tab
537
+ 3. **Network Monitoring**
538
+ - Use browser dev tools to monitor API calls
539
+ - Check for 401/403 errors (auth issues)
540
+ - Verify asset loading paths
541
+
542
+ ### Still Having Issues?
543
+
544
+ If you're still experiencing problems after trying these solutions:
545
+
546
+ 1. Search existing [GitHub issues](https://github.com/dotCMS/core/issues)
547
+ 2. Check our [community forum](https://community.dotcms.com/)
548
+ 3. Create a new issue with:
549
+ - Detailed reproduction steps
550
+ - Environment information
551
+ - Error messages
552
+ - Code samples
553
+
554
+ ## dotCMS Support
555
+
556
+ We offer multiple channels to get help with the dotCMS UVE SDK:
557
+
558
+ - **GitHub Issues**: For bug reports and feature requests, please [open an issue](https://github.com/dotCMS/core/issues/new/choose) in the GitHub repository.
559
+ - **Community Forum**: Join our [community discussions](https://community.dotcms.com/) to ask questions and share solutions.
560
+ - **Stack Overflow**: Use the tag `dotcms-uve` when posting questions.
561
+
562
+ When reporting issues, please include:
563
+
564
+ - SDK version you're using
565
+ - dotCMS version
566
+ - Minimal reproduction steps
567
+ - Expected vs. actual behavior
568
+
569
+ Enterprise customers can access premium support through the [dotCMS Support Portal](https://dev.dotcms.com/docs/help).
570
+
571
+ ## How To Contribute
572
+
573
+ GitHub pull requests are the preferred method to contribute code to dotCMS. We welcome contributions to the DotCMS UVE SDK! If you'd like to contribute, please follow these steps:
574
+
575
+ 1. Fork the repository [dotCMS/core](https://github.com/dotCMS/core)
317
576
  2. Create a feature branch (`git checkout -b feature/amazing-feature`)
318
577
  3. Commit your changes (`git commit -m 'Add some amazing feature'`)
319
578
  4. Push to the branch (`git push origin feature/amazing-feature`)
320
579
  5. Open a Pull Request
321
580
 
322
- ## License
581
+ Please ensure your code follows the existing style and includes appropriate tests.
582
+
583
+ ## Licensing Information
584
+
585
+ dotCMS comes in multiple editions and as such is dual-licensed. The dotCMS Community Edition is licensed under the GPL 3.0 and is freely available for download, customization, and deployment for use within organizations of all stripes. dotCMS Enterprise Editions (EE) adds several enterprise features and is available via a supported, indemnified commercial license from dotCMS. For the differences between the editions, see [the feature page](http://www.dotcms.com/cms-platform/features).
586
+
587
+ This SDK is part of dotCMS's dual-licensed platform (GPL 3.0 for Community, commercial license for Enterprise).
323
588
 
324
- This project is licensed under the MIT License - see the LICENSE file for details.
589
+ [Learn more ](https://www.dotcms.com)at [dotcms.com](https://www.dotcms.com).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dotcms/uve",
3
- "version": "0.0.1-beta.33",
3
+ "version": "0.0.1-beta.35",
4
4
  "description": "Official JavaScript library for interacting with Universal Visual Editor (UVE)",
5
5
  "repository": {
6
6
  "type": "git",
package/public.cjs.js CHANGED
@@ -127,7 +127,8 @@ function getClosestDotCMSContainerData(element) {
127
127
  */
128
128
  function findDotCMSElement(element) {
129
129
  if (!element) return null;
130
- if (element?.dataset?.['dotObject'] === 'contentlet' || element?.dataset?.['dotObject'] === 'container' && element.children.length === 0) {
130
+ const emptyContent = element.querySelector('[data-dot-object="empty-content"]');
131
+ if (element?.dataset?.['dotObject'] === 'contentlet' || element?.dataset?.['dotObject'] === 'container' && emptyContent) {
131
132
  return element;
132
133
  }
133
134
  return findDotCMSElement(element?.['parentElement']);
package/public.esm.js CHANGED
@@ -125,7 +125,8 @@ function getClosestDotCMSContainerData(element) {
125
125
  */
126
126
  function findDotCMSElement(element) {
127
127
  if (!element) return null;
128
- if (element?.dataset?.['dotObject'] === 'contentlet' || element?.dataset?.['dotObject'] === 'container' && element.children.length === 0) {
128
+ const emptyContent = element.querySelector('[data-dot-object="empty-content"]');
129
+ if (element?.dataset?.['dotObject'] === 'contentlet' || element?.dataset?.['dotObject'] === 'container' && emptyContent) {
129
130
  return element;
130
131
  }
131
132
  return findDotCMSElement(element?.['parentElement']);