@dotcms/uve
Version:
Official JavaScript library for interacting with Universal Visual Editor (UVE)
373 lines (368 loc) • 12.3 kB
JavaScript
import { g as getUVEState, s as sendMessageToUVE } from './public.esm.js';
export { C as CUSTOM_NO_COMPONENT, D as DEVELOPMENT_MODE, f as DOT_SECTION_ID_PREFIX, E as EMPTY_CONTAINER_STYLE_ANGULAR, h as EMPTY_CONTAINER_STYLE_REACT, j as END_CLASS, P as PRODUCTION_MODE, S as START_CLASS, T as TEMP_EMPTY_CONTENTLET, k as TEMP_EMPTY_CONTENTLET_TYPE, _ as __UVE_EVENTS__, l as __UVE_EVENT_ERROR_FALLBACK__, m as combineClasses, n as computeScrollIsInBottom, a as createUVESubscription, o as findDotCMSElement, p as findDotCMSVTLData, q as getClosestDotCMSContainerData, t as getColumnPositionClasses, v as getContainersData, w as getContentletsInContainer, x as getDotCMSContainerData, y as getDotCMSContentletsBound, z as getDotCMSPageBounds, A as getDotContainerAttributes, B as getDotContentletAttributes, F as isValidBlocks, G as readContentletDataset, H as setBounds } from './public.esm.js';
import { UVE_MODE, DotCMSUVEAction } from '@dotcms/types';
import '@dotcms/types/internal';
/**
* TinyMCE default config across all versions
*
* @internal
*/
const __DEFAULT_TINYMCE_CONFIG__ = {
menubar: false,
inline: true,
valid_styles: {
'*': 'font-size,font-family,color,text-decoration,text-align'
},
powerpaste_word_import: 'clean',
powerpaste_html_import: 'clean',
suffix: '.min' // Suffix to use when loading resources
};
/**
* TinyMCE config to use per mode
*
* @internal
*/
const __BASE_TINYMCE_CONFIG_WITH_NO_DEFAULT__ = {
full: {
plugins: 'link lists autolink charmap',
toolbar: ['styleselect undo redo | bold italic underline | forecolor backcolor | alignleft aligncenter alignright alignfull | numlist bullist outdent indent | hr charmap removeformat | link'],
style_formats: [{
title: 'Paragraph',
format: 'p'
}, {
title: 'Header 1',
format: 'h1'
}, {
title: 'Header 2',
format: 'h2'
}, {
title: 'Header 3',
format: 'h3'
}, {
title: 'Header 4',
format: 'h4'
}, {
title: 'Header 5',
format: 'h5'
}, {
title: 'Header 6',
format: 'h6'
}, {
title: 'Pre',
format: 'pre'
}, {
title: 'Code',
format: 'code'
}]
},
plain: {
plugins: '',
toolbar: ''
},
minimal: {
plugins: 'link autolink',
toolbar: 'bold italic underline | link',
valid_elements: 'strong,em,span[style],a[href]'
}
};
/**
* TinyMCE path
*
* @internal
*/
const __TINYMCE_PATH_ON_DOTCMS__ = '/ext/tinymcev7/tinymce.min.js';
/**
* Normalizes a field definition into the schema format expected by UVE.
*
* Converts developer-friendly field definitions into a normalized structure where
* all type-specific configuration properties are moved into a `config` object.
* This transformation ensures consistency in the schema format sent to UVE.
*
* **Field Type Handling:**
* - **Input fields**: Extracts `inputType` and `placeholder` into config
* - **Dropdown fields**: Normalizes options (strings become `{ label, value }` objects)
* - **Radio fields**: Normalizes options (preserves image properties like `imageURL`, `width`, `height`),
* extracts `columns` into config
* - **Checkbox group fields**: Normalizes options (converts to format expected by UVE)
*
* @experimental This method is experimental and may be subject to change.
*
* @param field - The field definition to normalize. Must be one of: input, dropdown, radio, or checkboxGroup
* @returns The normalized field schema with type, label, and config properties ready to be sent to UVE
*
* @example
* ```typescript
* // Input field normalization
* normalizeField({
* type: 'input',
* id: 'font-size',
* label: 'Font Size',
* inputType: 'number',
* placeholder: 'Enter size'
* })
* // Returns: {
* // type: 'input',
* // id: 'font-size',
* // label: 'Font Size',
* // config: { inputType: 'number', placeholder: 'Enter size' }
* // }
*
* // Dropdown field with string options normalization
* normalizeField({
* type: 'dropdown',
* label: 'Font Family',
* options: ['Arial', 'Helvetica']
* })
* // Returns: {
* // type: 'dropdown',
* // label: 'Font Family',
* // config: { options: [{ label: 'Arial', value: 'Arial' }, { label: 'Helvetica', value: 'Helvetica' }] }
* // }
* ```
*/
function normalizeField(field) {
const base = {
type: field.type,
label: field.label,
id: field.id
};
const config = {};
// Handle type-specific properties
if (field.type === 'input') {
config.inputType = field.inputType;
config.placeholder = field.placeholder;
}
if (field.type === 'dropdown' || field.type === 'radio') {
// Normalize options to consistent format
config.options = field.options.map(opt => typeof opt === 'string' ? {
label: opt,
value: opt
} : opt);
// Handle radio-specific properties
if (field.type === 'radio') {
config.columns = field.columns;
}
}
if (field.type === 'checkboxGroup') {
// Normalize checkbox options - convert to format expected by UVE
// Options have label and key - convert key to 'value' for UVE format
config.options = field.options.map(opt => ({
label: opt.label,
value: opt.key // UVE expects 'value' to be the key identifier
}));
}
return {
...base,
config
};
}
/**
* Normalizes a section definition into the schema format expected by UVE.
*
* Converts a section with a flat array of fields into the normalized schema format
* where fields are organized as a multi-dimensional array (array of column arrays).
* Currently, all sections are normalized to a single-column layout structure.
*
* **Normalization Process:**
* 1. Normalizes each field in the section using `normalizeField`
* 2. Wraps the normalized fields array in an outer array to create the column structure
* 3. Preserves the section title
*
* The output format always uses a multi-dimensional array structure (`fields: StyleEditorFieldSchema[][]`),
* even for single-column layouts, ensuring consistency in the UVE schema format.
*
* @experimental This method is experimental and may be subject to change.
*
* @param section - The section definition to normalize, containing a title and array of fields
* @param section.title - The section title displayed to users
* @param section.fields - Array of field definitions to normalize
* @returns The normalized section schema with fields organized as a single-column array structure
*
* @example
* ```typescript
* normalizeSection({
* title: 'Typography',
* fields: [
* { type: 'input', label: 'Font Size', inputType: 'number' },
* { type: 'dropdown', label: 'Font Family', options: ['Arial'] }
* ]
* })
* // Returns: {
* // title: 'Typography',
* // fields: [
* // [
* // { type: 'input', label: 'Font Size', config: { inputType: 'number' } },
* // { type: 'dropdown', label: 'Font Family', config: { options: [...] } }
* // ]
* // ]
* // }
* ```
*/
function normalizeSection(section) {
// Determine if fields is multi-column or single column
const normalizedFields = section.fields.map(normalizeField);
return {
title: section.title,
fields: normalizedFields
};
}
/**
* Normalizes a complete form definition into the schema format expected by UVE.
*
* This is the main entry point for converting a developer-friendly form definition
* into the normalized schema structure that UVE (Universal Visual Editor) can consume.
* The normalization process transforms the entire form hierarchy:
*
* **Normalization Process:**
* 1. Preserves the `contentType` identifier
* 2. Processes each section using `normalizeSection`, which:
* - Normalizes all fields in the section using `normalizeField`
* - Organizes fields into the required multi-dimensional array structure
* 3. Returns a fully normalized schema with consistent structure across all sections
*
* The resulting schema has all field-specific properties moved into `config` objects
* and all sections using the consistent single-column array structure, regardless
* of the input format.
*
* @experimental This method is experimental and may be subject to change.
*
* @param form - The complete form definition to normalize
* @param form.contentType - The content type identifier this form is associated with
* @param form.sections - Array of section definitions, each containing a title and fields
* @returns The normalized form schema ready to be sent to UVE, with all fields and sections normalized
*
* @example
* ```typescript
* const schema = normalizeForm({
* contentType: 'my-content-type',
* sections: [
* {
* title: 'Typography',
* fields: [
* { type: 'input', id: 'font-size', label: 'Font Size', inputType: 'number' },
* { type: 'dropdown', id: 'font-family', label: 'Font Family', options: ['Arial', 'Helvetica'] }
* ]
* },
* {
* title: 'Colors',
* fields: [
* { type: 'input', id: 'primary-color', label: 'Primary Color', inputType: 'text' }
* ]
* }
* ]
* });
* // Returns: {
* // contentType: 'my-content-type',
* // sections: [
* // {
* // title: 'Typography',
* // fields: [
* // [
* // { type: 'input', id: 'font-size', label: 'Font Size', config: { inputType: 'number' } },
* // { type: 'dropdown', id: 'font-family', label: 'Font Family', config: { options: [...] } }
* // ]
* // ]
* // },
* // {
* // title: 'Colors',
* // fields: [
* // [
* // { type: 'input', id: 'primary-color', label: 'Primary Color', config: { inputType: 'text' } }
* // ]
* // ]
* // }
* // ]
* // }
* ```
*/
function normalizeForm(form) {
return {
contentType: form.contentType,
sections: form.sections.map(normalizeSection)
};
}
/**
* Normalizes and validates a style editor form definition into the schema format
* expected by UVE. Used internally by the schema builder.
*
* @internal
*/
function defineStyleEditorSchema(form) {
return normalizeForm(form);
}
/**
* Registers style editor form schemas with the UVE editor.
*
* Sends normalized style editor schemas to UVE for registration.
* Only registers schemas when UVE is in EDIT mode.
*
* @internal — called automatically by useEditableDotCMSPage and DotCMSEditablePageService
*/
function registerStyleEditorSchemas(schemas) {
const {
mode
} = getUVEState() || {};
if (!mode || mode !== UVE_MODE.EDIT) {
return;
}
const validatedSchemas = schemas.filter((schema, index) => {
if (!schema.contentType) {
console.warn(`[registerStyleEditorSchemas] Skipping schema with index [${index}] for not having a contentType`);
return false;
}
return true;
});
sendMessageToUVE({
action: DotCMSUVEAction.REGISTER_STYLE_SCHEMAS,
payload: {
schemas: validatedSchemas
}
});
}
/**
* Helper functions for creating style editor field definitions.
* Used by the dotCMS schema builder UI.
*
* @experimental This API is experimental and may be subject to change.
*/
const styleEditorField = {
/**
* Creates an input field definition.
*
* @experimental This method is experimental and may be subject to change.
*/
input: config => ({
type: 'input',
...config
}),
/**
* Creates a dropdown field definition.
*
* @experimental This method is experimental and may be subject to change.
*/
dropdown: config => ({
type: 'dropdown',
...config,
options: config.options
}),
/**
* Creates a radio button field definition.
*
* @experimental This method is experimental and may be subject to change.
*/
radio: config => ({
type: 'radio',
...config,
options: config.options
}),
/**
* Creates a checkbox group field definition.
*
* @experimental This method is experimental and may be subject to change.
*/
checkboxGroup: config => ({
type: 'checkboxGroup',
...config
})
};
export { __BASE_TINYMCE_CONFIG_WITH_NO_DEFAULT__, __DEFAULT_TINYMCE_CONFIG__, __TINYMCE_PATH_ON_DOTCMS__, defineStyleEditorSchema, getUVEState, normalizeForm, registerStyleEditorSchemas, styleEditorField };