@dotcms/uve 0.0.1-beta.11 → 0.0.1-beta.12

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 CHANGED
@@ -58,209 +58,110 @@ function getUVEState() {
58
58
  /**
59
59
  * Creates a subscription to a UVE event.
60
60
  *
61
- * @param {string} event - The event to subscribe to.
62
- * @param {UVECallback} callback - The callback to call when the event is triggered.
63
- * @return {UnsubscribeUVE | undefined} The unsubscribe function if the event is valid, undefined otherwise.
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
- * const unsubscribeChanges = createUVESubscription('changes', (payload) => {
68
- * console.log(payload);
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(event, callback) {
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__(event);
79
+ return internal.__UVE_EVENT_ERROR_FALLBACK__(eventType);
76
80
  }
77
- const eventCallback = internal.__UVE_EVENTS__[event];
81
+ const eventCallback = internal.__UVE_EVENTS__[eventType];
78
82
  if (!eventCallback) {
79
- console.error(`UVE Subscription: Event ${event} not found`);
80
- return internal.__UVE_EVENT_ERROR_FALLBACK__(event);
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
- * Calculates the bounding information for each page element within the given containers.
90
+ * Post message to dotcms page editor
87
91
  *
88
92
  * @export
89
- * @param {HTMLDivElement[]} containers - An array of HTMLDivElement representing the containers.
90
- * @return {DotCMSContainerBound[]} An array of objects containing the bounding information for each page element.
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 getDotCMSPageBounds(containers) {
99
- return containers.map(container => {
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 sendMessageToEditor(message) {
97
+ window.parent.postMessage(message, '*');
113
98
  }
114
99
  /**
115
- * Calculates the bounding information for each contentlet inside a container.
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
- * @param {DOMRect} containerRect - The bounding rectangle of the container.
119
- * @param {HTMLDivElement[]} contentlets - An array of HTMLDivElement representing the contentlets.
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 getDotCMSContentletsBound(containerRect, contentlets) {
130
- return contentlets.map(contentlet => {
131
- const contentletRect = contentlet.getBoundingClientRect();
132
- return {
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
+ sendMessageToEditor({
110
+ action: types.DotCMSUVEAction.EDIT_CONTENTLET,
111
+ payload: contentlet
147
112
  });
148
113
  }
149
- /**
150
- * Get container data from VTLS.
114
+ /*
115
+ * Reorders the menu based on the provided configuration.
151
116
  *
152
- * @export
153
- * @param {HTMLElement} container - The container element.
154
- * @return {object} An object containing the container data.
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
- * @export
174
- * @param {Element} element - The contentlet element.
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 getClosestDotCMSContainerData(element) {
184
- // Find the closest ancestor element with data-dot-object="container" attribute
185
- const container = element.closest('[data-dot-object="container"]');
186
- // If a container element is found
187
- if (container) {
188
- // Return the dataset of the container element
189
- return getDotCMSContainerData(container);
190
- } else {
191
- // If no container element is found, return null
192
- console.warn('No container found for the contentlet');
193
- return null;
194
- }
124
+ function reorderMenu(config) {
125
+ const {
126
+ startLevel = 1,
127
+ depth = 2
128
+ } = config || {};
129
+ sendMessageToEditor({
130
+ action: types.DotCMSUVEAction.REORDER_MENU,
131
+ payload: {
132
+ startLevel,
133
+ depth
134
+ }
135
+ });
195
136
  }
196
137
  /**
197
- * Find the closest contentlet element based on HTMLElement.
138
+ * Initializes the inline editing in the editor.
198
139
  *
199
140
  * @export
200
- * @param {HTMLElement | null} element - The starting element.
201
- * @return {HTMLElement | null} The closest contentlet element or null if not found.
202
- * @example
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
- * @export
218
- * @param {HTMLElement} target - The target element to search within.
219
- * @return {Array<{ inode: string, name: string }> | null} An array of objects containing VTL data or null if none found.
220
- * @example
221
- * ```ts
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 findDotCMSVTLData(target) {
228
- const vltElements = target.querySelectorAll('[data-dot-object="vtl-file"]');
229
- if (!vltElements.length) {
230
- return null;
231
- }
232
- return Array.from(vltElements).map(vltElement => {
233
- return {
234
- inode: vltElement.dataset?.['dotInode'],
235
- name: vltElement.dataset?.['dotUrl']
236
- };
152
+ function initInlineEditing(type, data) {
153
+ sendMessageToEditor({
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.findDotCMSElement = findDotCMSElement;
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.sendMessageToEditor = sendMessageToEditor;
package/index.esm.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { __UVE_EVENT_ERROR_FALLBACK__, __UVE_EVENTS__ } from './internal.esm.js';
2
- import { UVE_MODE } from './types.esm.js';
2
+ import { UVE_MODE, DotCMSUVEAction } from './types.esm.js';
3
3
 
4
4
  /**
5
5
  * Gets the current state of the Universal Visual Editor (UVE).
@@ -56,201 +56,105 @@ function getUVEState() {
56
56
  /**
57
57
  * Creates a subscription to a UVE event.
58
58
  *
59
- * @param {string} event - The event to subscribe to.
60
- * @param {UVECallback} callback - The callback to call when the event is triggered.
61
- * @return {UnsubscribeUVE | undefined} The unsubscribe function if the event is valid, undefined otherwise.
59
+ * @param eventType - The type of event to subscribe to
60
+ * @param callback - The callback function that will be called when the event occurs
61
+ * @returns An event subscription that can be used to unsubscribe
62
62
  *
63
63
  * @example
64
64
  * ```ts
65
- * const unsubscribeChanges = createUVESubscription('changes', (payload) => {
66
- * console.log(payload);
65
+ * // Subscribe to page changes
66
+ * const subscription = createUVESubscription(UVEEventType.CONTENT_CHANGES, (changes) => {
67
+ * console.log('Content changes:', changes);
67
68
  * });
69
+ *
70
+ * // Later, unsubscribe when no longer needed
71
+ * subscription.unsubscribe();
68
72
  * ```
69
73
  */
70
- function createUVESubscription(event, callback) {
74
+ function createUVESubscription(eventType, callback) {
71
75
  if (!getUVEState()) {
72
76
  console.warn('UVE Subscription: Not running inside UVE');
73
- return __UVE_EVENT_ERROR_FALLBACK__(event);
77
+ return __UVE_EVENT_ERROR_FALLBACK__(eventType);
74
78
  }
75
- const eventCallback = __UVE_EVENTS__[event];
79
+ const eventCallback = __UVE_EVENTS__[eventType];
76
80
  if (!eventCallback) {
77
- console.error(`UVE Subscription: Event ${event} not found`);
78
- return __UVE_EVENT_ERROR_FALLBACK__(event);
81
+ console.error(`UVE Subscription: Event ${eventType} not found`);
82
+ return __UVE_EVENT_ERROR_FALLBACK__(eventType);
79
83
  }
80
84
  return eventCallback(callback);
81
85
  }
82
86
 
83
87
  /**
84
- * Calculates the bounding information for each page element within the given containers.
88
+ * Post message to dotcms page editor
85
89
  *
86
90
  * @export
87
- * @param {HTMLDivElement[]} containers - An array of HTMLDivElement representing the containers.
88
- * @return {DotCMSContainerBound[]} An array of objects containing the bounding information for each page element.
89
- * @example
90
- * ```ts
91
- * const containers = document.querySelectorAll('.container');
92
- * const bounds = getDotCMSPageBounds(containers);
93
- * console.log(bounds);
94
- * ```
91
+ * @template T
92
+ * @param {DotCMSUVEMessage<T>} message
95
93
  */
96
- function getDotCMSPageBounds(containers) {
97
- return containers.map(container => {
98
- const containerRect = container.getBoundingClientRect();
99
- const contentlets = Array.from(container.querySelectorAll('[data-dot-object="contentlet"]'));
100
- return {
101
- x: containerRect.x,
102
- y: containerRect.y,
103
- width: containerRect.width,
104
- height: containerRect.height,
105
- payload: JSON.stringify({
106
- container: getDotCMSContainerData(container)
107
- }),
108
- contentlets: getDotCMSContentletsBound(containerRect, contentlets)
109
- };
110
- });
94
+ function sendMessageToEditor(message) {
95
+ window.parent.postMessage(message, '*');
111
96
  }
112
97
  /**
113
- * Calculates the bounding information for each contentlet inside a container.
98
+ * You can use this function to edit a contentlet in the editor.
99
+ *
100
+ * Calling this function inside the editor, will prompt the UVE to open a dialog to edit the contentlet.
114
101
  *
115
102
  * @export
116
- * @param {DOMRect} containerRect - The bounding rectangle of the container.
117
- * @param {HTMLDivElement[]} contentlets - An array of HTMLDivElement representing the contentlets.
118
- * @return {DotCMSContentletBound[]} An array of objects containing the bounding information for each contentlet.
119
- * @example
120
- * ```ts
121
- * const containerRect = container.getBoundingClientRect();
122
- * const contentlets = container.querySelectorAll('.contentlet');
123
- * const bounds = getDotCMSContentletsBound(containerRect, contentlets);
124
- * console.log(bounds); // Element bounds within the container
125
- * ```
103
+ * @template T
104
+ * @param {Contentlet<T>} contentlet - The contentlet to edit.
126
105
  */
127
- function getDotCMSContentletsBound(containerRect, contentlets) {
128
- return contentlets.map(contentlet => {
129
- const contentletRect = contentlet.getBoundingClientRect();
130
- return {
131
- x: 0,
132
- y: contentletRect.y - containerRect.y,
133
- width: contentletRect.width,
134
- height: contentletRect.height,
135
- payload: JSON.stringify({
136
- container: contentlet.dataset?.['dotContainer'] ? JSON.parse(contentlet.dataset?.['dotContainer']) : getClosestDotCMSContainerData(contentlet),
137
- contentlet: {
138
- identifier: contentlet.dataset?.['dotIdentifier'],
139
- title: contentlet.dataset?.['dotTitle'],
140
- inode: contentlet.dataset?.['dotInode'],
141
- contentType: contentlet.dataset?.['dotType']
142
- }
143
- })
144
- };
106
+ function editContentlet(contentlet) {
107
+ sendMessageToEditor({
108
+ action: DotCMSUVEAction.EDIT_CONTENTLET,
109
+ payload: contentlet
145
110
  });
146
111
  }
147
- /**
148
- * Get container data from VTLS.
112
+ /*
113
+ * Reorders the menu based on the provided configuration.
149
114
  *
150
- * @export
151
- * @param {HTMLElement} container - The container element.
152
- * @return {object} An object containing the container data.
153
- * @example
154
- * ```ts
155
- * const container = document.querySelector('.container');
156
- * const data = getContainerData(container);
157
- * console.log(data);
158
- * ```
159
- */
160
- function getDotCMSContainerData(container) {
161
- return {
162
- acceptTypes: container.dataset?.['dotAcceptTypes'] || '',
163
- identifier: container.dataset?.['dotIdentifier'] || '',
164
- maxContentlets: container.dataset?.['maxContentlets'] || '',
165
- uuid: container.dataset?.['dotUuid'] || ''
166
- };
167
- }
168
- /**
169
- * Get the closest container data from the contentlet.
115
+ * @param {ReorderMenuConfig} [config] - Optional configuration for reordering the menu.
116
+ * @param {number} [config.startLevel=1] - The starting level of the menu to reorder.
117
+ * @param {number} [config.depth=2] - The depth of the menu to reorder.
170
118
  *
171
- * @export
172
- * @param {Element} element - The contentlet element.
173
- * @return {object | null} An object containing the closest container data or null if no container is found.
174
- * @example
175
- * ```ts
176
- * const contentlet = document.querySelector('.contentlet');
177
- * const data = getClosestDotCMSContainerData(contentlet);
178
- * console.log(data);
179
- * ```
119
+ * This function constructs a URL for the reorder menu page with the specified
120
+ * start level and depth, and sends a message to the editor to perform the reorder action.
180
121
  */
181
- function getClosestDotCMSContainerData(element) {
182
- // Find the closest ancestor element with data-dot-object="container" attribute
183
- const container = element.closest('[data-dot-object="container"]');
184
- // If a container element is found
185
- if (container) {
186
- // Return the dataset of the container element
187
- return getDotCMSContainerData(container);
188
- } else {
189
- // If no container element is found, return null
190
- console.warn('No container found for the contentlet');
191
- return null;
192
- }
122
+ function reorderMenu(config) {
123
+ const {
124
+ startLevel = 1,
125
+ depth = 2
126
+ } = config || {};
127
+ sendMessageToEditor({
128
+ action: DotCMSUVEAction.REORDER_MENU,
129
+ payload: {
130
+ startLevel,
131
+ depth
132
+ }
133
+ });
193
134
  }
194
135
  /**
195
- * Find the closest contentlet element based on HTMLElement.
136
+ * Initializes the inline editing in the editor.
196
137
  *
197
138
  * @export
198
- * @param {HTMLElement | null} element - The starting element.
199
- * @return {HTMLElement | null} The closest contentlet element or null if not found.
200
- * @example
201
- * const element = document.querySelector('.some-element');
202
- * const contentlet = findDotCMSElement(element);
203
- * console.log(contentlet);
204
- */
205
- function findDotCMSElement(element) {
206
- if (!element) return null;
207
- if (element?.dataset?.['dotObject'] === 'contentlet' || element?.dataset?.['dotObject'] === 'container' && element.children.length === 0) {
208
- return element;
209
- }
210
- return findDotCMSElement(element?.['parentElement']);
211
- }
212
- /**
213
- * Find VTL data within a target element.
139
+ * @param {INLINE_EDITING_EVENT_KEY} type
140
+ * @param {InlineEditEventData} eventData
141
+ * @return {*}
214
142
  *
215
- * @export
216
- * @param {HTMLElement} target - The target element to search within.
217
- * @return {Array<{ inode: string, name: string }> | null} An array of objects containing VTL data or null if none found.
218
- * @example
219
- * ```ts
220
- * const target = document.querySelector('.target-element');
221
- * const vtlData = findDotCMSVTLData(target);
222
- * console.log(vtlData);
143
+ * * @example
144
+ * ```html
145
+ * <div onclick="initInlineEditing('BLOCK_EDITOR', { inode, languageId, contentType, fieldName, content })">
146
+ * ${My Content}
147
+ * </div>
223
148
  * ```
224
149
  */
225
- function findDotCMSVTLData(target) {
226
- const vltElements = target.querySelectorAll('[data-dot-object="vtl-file"]');
227
- if (!vltElements.length) {
228
- return null;
229
- }
230
- return Array.from(vltElements).map(vltElement => {
231
- return {
232
- inode: vltElement.dataset?.['dotInode'],
233
- name: vltElement.dataset?.['dotUrl']
234
- };
150
+ function initInlineEditing(type, data) {
151
+ sendMessageToEditor({
152
+ action: DotCMSUVEAction.INIT_INLINE_EDITING,
153
+ payload: {
154
+ type,
155
+ data
156
+ }
235
157
  });
236
158
  }
237
- /**
238
- * Check if the scroll position is at the bottom of the page.
239
- *
240
- * @export
241
- * @return {boolean} True if the scroll position is at the bottom, otherwise false.
242
- * @example
243
- * ```ts
244
- * if (dotCMSScrollIsInBottom()) {
245
- * console.log('Scrolled to the bottom');
246
- * }
247
- * ```
248
- */
249
- function computeScrollIsInBottom() {
250
- const documentHeight = document.documentElement.scrollHeight;
251
- const viewportHeight = window.innerHeight;
252
- const scrollY = window.scrollY;
253
- return scrollY + viewportHeight >= documentHeight;
254
- }
255
159
 
256
- export { computeScrollIsInBottom, createUVESubscription, findDotCMSElement, findDotCMSVTLData, getClosestDotCMSContainerData, getDotCMSContainerData, getDotCMSContentletsBound, getDotCMSPageBounds, getUVEState };
160
+ export { createUVESubscription, editContentlet, getUVEState, initInlineEditing, reorderMenu, sendMessageToEditor };