UNPKG

@dotcms/uve

Version:

Official JavaScript library for interacting with Universal Visual Editor (UVE)

373 lines (368 loc) 12.3 kB
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 };