@dotcms/uve 1.2.0 → 1.2.1-next.10

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
@@ -1,10 +1,713 @@
1
1
  'use strict';
2
2
 
3
3
  var _public = require('./public.cjs.js');
4
- require('@dotcms/types');
4
+ var types = require('@dotcms/types');
5
5
  require('@dotcms/types/internal');
6
6
 
7
+ /**
8
+ * Normalizes a field definition into the schema format expected by UVE.
9
+ *
10
+ * Converts developer-friendly field definitions into a normalized structure where
11
+ * all type-specific configuration properties are moved into a `config` object.
12
+ * This transformation ensures consistency in the schema format sent to UVE.
13
+ *
14
+ * **Field Type Handling:**
15
+ * - **Input fields**: Extracts `inputType`, `placeholder`, and `defaultValue` into config
16
+ * - **Dropdown fields**: Normalizes options (strings become `{ label, value }` objects),
17
+ * extracts `placeholder` and `defaultValue` into config
18
+ * - **Radio fields**: Normalizes options (preserves image properties like `imageURL`, `width`, `height`),
19
+ * extracts `defaultValue` into config
20
+ * - **Checkbox group fields**: Normalizes options and derives `defaultValue` from option values
21
+ * (creates Record<string, boolean> mapping option keys to their boolean values)
22
+ *
23
+ * @experimental This method is experimental and may be subject to change.
24
+ *
25
+ * @param field - The field definition to normalize. Must be one of: input, dropdown, radio, or checkboxGroup
26
+ * @returns The normalized field schema with type, label, and config properties ready to be sent to UVE
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * // Input field normalization
31
+ * normalizeField({
32
+ * type: 'input',
33
+ * label: 'Font Size',
34
+ * inputType: 'number',
35
+ * defaultValue: 16,
36
+ * placeholder: 'Enter size'
37
+ * })
38
+ * // Returns: {
39
+ * // type: 'input',
40
+ * // label: 'Font Size',
41
+ * // config: { inputType: 'number', defaultValue: 16, placeholder: 'Enter size' }
42
+ * // }
43
+ *
44
+ * // Dropdown field with string options normalization
45
+ * normalizeField({
46
+ * type: 'dropdown',
47
+ * label: 'Font Family',
48
+ * options: ['Arial', 'Helvetica']
49
+ * })
50
+ * // Returns: {
51
+ * // type: 'dropdown',
52
+ * // label: 'Font Family',
53
+ * // config: { options: [{ label: 'Arial', value: 'Arial' }, { label: 'Helvetica', value: 'Helvetica' }] }
54
+ * // }
55
+ * ```
56
+ */
57
+ function normalizeField(field) {
58
+ const base = {
59
+ type: field.type,
60
+ label: field.label,
61
+ id: field.id
62
+ };
63
+ const config = {};
64
+ // Handle type-specific properties
65
+ if (field.type === 'input') {
66
+ config.inputType = field.inputType;
67
+ config.placeholder = field.placeholder;
68
+ config.defaultValue = field.defaultValue;
69
+ }
70
+ if (field.type === 'dropdown' || field.type === 'radio') {
71
+ // Normalize options to consistent format
72
+ config.options = field.options.map(opt => typeof opt === 'string' ? {
73
+ label: opt,
74
+ value: opt
75
+ } : opt);
76
+ config.defaultValue = field.defaultValue;
77
+ // Handle radio-specific properties
78
+ if (field.type === 'radio') {
79
+ config.columns = field.columns;
80
+ }
81
+ }
82
+ if (field.type === 'checkboxGroup') {
83
+ // Normalize checkbox options - convert to format expected by UVE
84
+ // Options already have label, key, and value (boolean)
85
+ config.options = field.options.map(opt => ({
86
+ label: opt.label,
87
+ value: opt.key // UVE expects 'value' to be the key identifier
88
+ }));
89
+ // Derive defaultValue from options - map key to boolean value
90
+ config.defaultValue = field.options.reduce((acc, opt) => {
91
+ acc[opt.key] = opt.value;
92
+ return acc;
93
+ }, {});
94
+ }
95
+ return {
96
+ ...base,
97
+ config
98
+ };
99
+ }
100
+ /**
101
+ * Normalizes a section definition into the schema format expected by UVE.
102
+ *
103
+ * Converts a section with a flat array of fields into the normalized schema format
104
+ * where fields are organized as a multi-dimensional array (array of column arrays).
105
+ * Currently, all sections are normalized to a single-column layout structure.
106
+ *
107
+ * **Normalization Process:**
108
+ * 1. Normalizes each field in the section using `normalizeField`
109
+ * 2. Wraps the normalized fields array in an outer array to create the column structure
110
+ * 3. Preserves the section title
111
+ *
112
+ * The output format always uses a multi-dimensional array structure (`fields: StyleEditorFieldSchema[][]`),
113
+ * even for single-column layouts, ensuring consistency in the UVE schema format.
114
+ *
115
+ * @experimental This method is experimental and may be subject to change.
116
+ *
117
+ * @param section - The section definition to normalize, containing a title and array of fields
118
+ * @param section.title - The section title displayed to users
119
+ * @param section.fields - Array of field definitions to normalize
120
+ * @returns The normalized section schema with fields organized as a single-column array structure
121
+ *
122
+ * @example
123
+ * ```typescript
124
+ * normalizeSection({
125
+ * title: 'Typography',
126
+ * fields: [
127
+ * { type: 'input', label: 'Font Size', inputType: 'number' },
128
+ * { type: 'dropdown', label: 'Font Family', options: ['Arial'] }
129
+ * ]
130
+ * })
131
+ * // Returns: {
132
+ * // title: 'Typography',
133
+ * // fields: [
134
+ * // [
135
+ * // { type: 'input', label: 'Font Size', config: { inputType: 'number' } },
136
+ * // { type: 'dropdown', label: 'Font Family', config: { options: [...] } }
137
+ * // ]
138
+ * // ]
139
+ * // }
140
+ * ```
141
+ */
142
+ function normalizeSection(section) {
143
+ // Determine if fields is multi-column or single column
144
+ const normalizedFields = section.fields.map(normalizeField);
145
+ return {
146
+ title: section.title,
147
+ fields: normalizedFields
148
+ };
149
+ }
150
+ /**
151
+ * Normalizes a complete form definition into the schema format expected by UVE.
152
+ *
153
+ * This is the main entry point for converting a developer-friendly form definition
154
+ * into the normalized schema structure that UVE (Universal Visual Editor) can consume.
155
+ * The normalization process transforms the entire form hierarchy:
156
+ *
157
+ * **Normalization Process:**
158
+ * 1. Preserves the `contentType` identifier
159
+ * 2. Processes each section using `normalizeSection`, which:
160
+ * - Normalizes all fields in the section using `normalizeField`
161
+ * - Organizes fields into the required multi-dimensional array structure
162
+ * 3. Returns a fully normalized schema with consistent structure across all sections
163
+ *
164
+ * The resulting schema has all field-specific properties moved into `config` objects
165
+ * and all sections using the consistent single-column array structure, regardless
166
+ * of the input format.
167
+ *
168
+ * @experimental This method is experimental and may be subject to change.
169
+ *
170
+ * @param form - The complete form definition to normalize
171
+ * @param form.contentType - The content type identifier this form is associated with
172
+ * @param form.sections - Array of section definitions, each containing a title and fields
173
+ * @returns The normalized form schema ready to be sent to UVE, with all fields and sections normalized
174
+ *
175
+ * @example
176
+ * ```typescript
177
+ * const schema = normalizeForm({
178
+ * contentType: 'my-content-type',
179
+ * sections: [
180
+ * {
181
+ * title: 'Typography',
182
+ * fields: [
183
+ * { type: 'input', label: 'Font Size', inputType: 'number', defaultValue: 16 },
184
+ * { type: 'dropdown', label: 'Font Family', options: ['Arial', 'Helvetica'] }
185
+ * ]
186
+ * },
187
+ * {
188
+ * title: 'Colors',
189
+ * fields: [
190
+ * { type: 'input', label: 'Primary Color', inputType: 'text', defaultValue: '#000000' }
191
+ * ]
192
+ * }
193
+ * ]
194
+ * });
195
+ * // Returns: {
196
+ * // contentType: 'my-content-type',
197
+ * // sections: [
198
+ * // {
199
+ * // title: 'Typography',
200
+ * // fields: [
201
+ * // [
202
+ * // { type: 'input', label: 'Font Size', config: { inputType: 'number', defaultValue: 16 } },
203
+ * // { type: 'dropdown', label: 'Font Family', config: { options: [...] } }
204
+ * // ]
205
+ * // ]
206
+ * // },
207
+ * // {
208
+ * // title: 'Colors',
209
+ * // fields: [
210
+ * // [
211
+ * // { type: 'input', label: 'Primary Color', config: { inputType: 'text', defaultValue: '#000000' } }
212
+ * // ]
213
+ * // ]
214
+ * // }
215
+ * // ]
216
+ * // }
217
+ * ```
218
+ */
219
+ function normalizeForm(form) {
220
+ return {
221
+ contentType: form.contentType,
222
+ sections: form.sections.map(normalizeSection)
223
+ };
224
+ }
7
225
 
226
+ /**
227
+ * Helper functions for creating style editor field definitions.
228
+ *
229
+ * Provides type-safe factory functions for creating different types of form fields
230
+ * used in the style editor. Each function creates a field definition with the
231
+ * appropriate `type` property automatically set, eliminating the need to manually
232
+ * specify the type discriminator.
233
+ *
234
+ * **Available Field Types:**
235
+ * - `input`: Text or number input fields
236
+ * - `dropdown`: Single-value selection from a dropdown list
237
+ * - `radio`: Single-value selection from radio button options (supports visual options with images)
238
+ * - `checkboxGroup`: Multiple-value selection from checkbox options
239
+ *
240
+ * These factory functions ensure type safety by inferring the correct field type
241
+ * based on the configuration provided, and they automatically set the `type` property
242
+ * to match the factory function used.
243
+ *
244
+ * @experimental This API is experimental and may be subject to change.
245
+ *
246
+ * @example
247
+ * ```typescript
248
+ * const form = defineStyleEditorSchema({
249
+ * contentType: 'my-content-type',
250
+ * sections: [
251
+ * {
252
+ * title: 'Typography',
253
+ * fields: [
254
+ * styleEditorField.input({
255
+ * label: 'Font Size',
256
+ * inputType: 'number',
257
+ * defaultValue: 16
258
+ * }),
259
+ * styleEditorField.dropdown({
260
+ * label: 'Font Family',
261
+ * options: ['Arial', 'Helvetica'],
262
+ * defaultValue: 'Arial'
263
+ * }),
264
+ * styleEditorField.radio({
265
+ * label: 'Alignment',
266
+ * options: ['Left', 'Center', 'Right'],
267
+ * defaultValue: 'Left'
268
+ * })
269
+ * ]
270
+ * }
271
+ * ]
272
+ * });
273
+ * ```
274
+ */
275
+ const styleEditorField = {
276
+ /**
277
+ * Creates an input field definition with type-safe default values.
278
+ *
279
+ * Supports both text and number input types. The `defaultValue` type is
280
+ * enforced based on the `inputType` using TypeScript generics:
281
+ * - When `inputType` is `'number'`, `defaultValue` must be a `number`
282
+ * - When `inputType` is `'text'`, `defaultValue` must be a `string`
283
+ *
284
+ * This provides compile-time type checking to prevent mismatched types,
285
+ * such as passing a string when a number is expected.
286
+ *
287
+ * @experimental This method is experimental and may be subject to change.
288
+ *
289
+ * @typeParam T - The input type ('text' or 'number'), inferred from `config.inputType`
290
+ * @param config - Input field configuration
291
+ * @param config.label - The label displayed for this input field
292
+ * @param config.inputType - The type of input ('text' or 'number')
293
+ * @param config.placeholder - Optional placeholder text for the input
294
+ * @param config.defaultValue - Optional default value (type enforced based on inputType)
295
+ * @returns A complete input field definition with type 'input'
296
+ *
297
+ * @example
298
+ * ```typescript
299
+ * // Number input - defaultValue must be a number
300
+ * styleEditorField.input({
301
+ * label: 'Font Size',
302
+ * inputType: 'number',
303
+ * placeholder: 'Enter font size',
304
+ * defaultValue: 16 // ✓ Correct: number
305
+ * })
306
+ *
307
+ * // Text input - defaultValue must be a string
308
+ * styleEditorField.input({
309
+ * label: 'Font Name',
310
+ * inputType: 'text',
311
+ * placeholder: 'Enter font name',
312
+ * defaultValue: 'Arial' // ✓ Correct: string
313
+ * })
314
+ *
315
+ * // TypeScript error - type mismatch
316
+ * styleEditorField.input({
317
+ * label: 'Font Size',
318
+ * inputType: 'number',
319
+ * defaultValue: '16' // ✗ Error: Type 'string' is not assignable to type 'number'
320
+ * })
321
+ * ```
322
+ */
323
+ input: config => ({
324
+ type: 'input',
325
+ ...config
326
+ }),
327
+ /**
328
+ * Creates a dropdown field definition with type-safe default values.
329
+ *
330
+ * Allows users to select a single value from a list of options.
331
+ * Options can be provided as simple strings or as objects with label and value.
332
+ *
333
+ * **Type Safety Tip:** For autocomplete on `defaultValue`, use `as const` when defining options:
334
+ * ```typescript
335
+ * const options = [
336
+ * { label: 'The one', value: 'one' },
337
+ * { label: 'The two', value: 'two' }
338
+ * ] as const;
339
+ *
340
+ * styleEditorField.dropdown({
341
+ * id: 'my-field',
342
+ * label: 'Select option',
343
+ * options,
344
+ * defaultValue: 'one' // ✓ Autocomplete works! TypeScript knows 'one' | 'two'
345
+ * // defaultValue: 'three' // ✗ TypeScript error: not assignable
346
+ * })
347
+ * ```
348
+ *
349
+ * Without `as const`, the function still works but won't provide autocomplete:
350
+ * ```typescript
351
+ * styleEditorField.dropdown({
352
+ * id: 'my-field',
353
+ * label: 'Select option',
354
+ * options: [
355
+ * { label: 'The one', value: 'one' },
356
+ * { label: 'The two', value: 'two' }
357
+ * ],
358
+ * defaultValue: 'one' // Works, but no autocomplete
359
+ * })
360
+ * ```
361
+ *
362
+ * @experimental This method is experimental and may be subject to change.
363
+ *
364
+ * @typeParam TOptions - The options array type (inferred from config, use `as const` for type safety)
365
+ * @param config - Dropdown field configuration (without the 'type' property)
366
+ * @param config.id - The unique identifier for this field
367
+ * @param config.label - The label displayed for this dropdown field
368
+ * @param config.options - Array of options. Use `as const` for type safety and autocomplete
369
+ * @param config.defaultValue - Optional default selected value (type-safe when options are `as const`)
370
+ * @returns A complete dropdown field definition with type 'dropdown'
371
+ *
372
+ * @example
373
+ * ```typescript
374
+ * // With type safety - use 'as const' for autocomplete
375
+ * const options = [
376
+ * { label: 'The one', value: 'one' },
377
+ * { label: 'The two', value: 'two' }
378
+ * ] as const;
379
+ *
380
+ * styleEditorField.dropdown({
381
+ * id: 'my-field',
382
+ * label: 'Select option',
383
+ * options,
384
+ * defaultValue: 'one' // ✓ Autocomplete works!
385
+ * })
386
+ *
387
+ * // Simple string options
388
+ * styleEditorField.dropdown({
389
+ * id: 'font-family',
390
+ * label: 'Font Family',
391
+ * options: ['Arial', 'Helvetica', 'Times New Roman'],
392
+ * defaultValue: 'Arial',
393
+ * placeholder: 'Select a font'
394
+ * })
395
+ *
396
+ * // Object options with custom labels
397
+ * styleEditorField.dropdown({
398
+ * id: 'theme',
399
+ * label: 'Theme',
400
+ * options: [
401
+ * { label: 'Light Theme', value: 'light' },
402
+ * { label: 'Dark Theme', value: 'dark' }
403
+ * ],
404
+ * defaultValue: 'light'
405
+ * })
406
+ * ```
407
+ */
408
+ dropdown: config => ({
409
+ type: 'dropdown',
410
+ ...config,
411
+ options: config.options,
412
+ defaultValue: config.defaultValue
413
+ }),
414
+ /**
415
+ * Creates a radio button field definition with type-safe default values.
416
+ *
417
+ * Allows users to select a single option from a list. Supports visual
418
+ * options with background images for enhanced UI. Options can be provided
419
+ * as simple strings or as objects with label, value, and optional image properties.
420
+ *
421
+ * **Layout Options:**
422
+ * - `columns: 1` (default): Single column list layout
423
+ * - `columns: 2`: Two-column grid layout, ideal for visual options with images
424
+ *
425
+ * **Type Safety Tip:** For autocomplete on `defaultValue`, use `as const` when defining options:
426
+ * ```typescript
427
+ * const options = [
428
+ * { label: 'The one', value: 'one' },
429
+ * { label: 'The two', value: 'two' }
430
+ * ] as const;
431
+ *
432
+ * styleEditorField.radio({
433
+ * id: 'my-field',
434
+ * label: 'Select option',
435
+ * options,
436
+ * defaultValue: 'one' // ✓ Autocomplete works! TypeScript knows 'one' | 'two'
437
+ * // defaultValue: 'three' // ✗ TypeScript error: not assignable
438
+ * })
439
+ * ```
440
+ *
441
+ * Without `as const`, the function still works but won't provide autocomplete:
442
+ * ```typescript
443
+ * styleEditorField.radio({
444
+ * id: 'my-field',
445
+ * label: 'Select option',
446
+ * options: [
447
+ * { label: 'The one', value: 'one' },
448
+ * { label: 'The two', value: 'two' }
449
+ * ],
450
+ * defaultValue: 'one' // Works, but no autocomplete
451
+ * })
452
+ * ```
453
+ *
454
+ * @experimental This method is experimental and may be subject to change.
455
+ *
456
+ * @typeParam TOptions - The options array type (inferred from config, use `as const` for type safety)
457
+ * @param config - Radio field configuration (without the 'type' property)
458
+ * @param config.id - The unique identifier for this field
459
+ * @param config.label - The label displayed for this radio group
460
+ * @param config.options - Array of options. Use `as const` for type safety and autocomplete
461
+ * @param config.defaultValue - Optional default selected value (type-safe when options are `as const`)
462
+ * @param config.columns - Optional number of columns (1 or 2). Defaults to 1 (single column)
463
+ * @returns A complete radio field definition with type 'radio'
464
+ *
465
+ * @example
466
+ * ```typescript
467
+ * // With type safety - use 'as const' for autocomplete
468
+ * const options = [
469
+ * { label: 'The one', value: 'one' },
470
+ * { label: 'The two', value: 'two' }
471
+ * ] as const;
472
+ *
473
+ * styleEditorField.radio({
474
+ * id: 'my-field',
475
+ * label: 'Select option',
476
+ * options,
477
+ * defaultValue: 'one' // ✓ Autocomplete works!
478
+ * })
479
+ *
480
+ * // Simple string options (single column)
481
+ * styleEditorField.radio({
482
+ * id: 'alignment',
483
+ * label: 'Alignment',
484
+ * options: ['Left', 'Center', 'Right'],
485
+ * defaultValue: 'Left'
486
+ * })
487
+ *
488
+ * // Two-column grid layout with images
489
+ * styleEditorField.radio({
490
+ * id: 'layout',
491
+ * label: 'Layout',
492
+ * columns: 2,
493
+ * options: [
494
+ * {
495
+ * label: 'Left',
496
+ * value: 'left',
497
+ * imageURL: 'https://example.com/layout-left.png',
498
+ * },
499
+ * {
500
+ * label: 'Right',
501
+ * value: 'right',
502
+ * imageURL: 'https://example.com/layout-right.png',
503
+ * },
504
+ * { label: 'Center', value: 'center' },
505
+ * { label: 'Overlap', value: 'overlap' }
506
+ * ],
507
+ * defaultValue: 'right'
508
+ * })
509
+ * ```
510
+ */
511
+ radio: config => ({
512
+ type: 'radio',
513
+ ...config,
514
+ options: config.options,
515
+ defaultValue: config.defaultValue
516
+ }),
517
+ /**
518
+ * Creates a checkbox group field definition.
519
+ *
520
+ * Allows users to select multiple options simultaneously. Each option
521
+ * can be independently checked or unchecked. The default checked state
522
+ * is defined directly in each option's `value` property (boolean).
523
+ *
524
+ * **Key Differences from Other Field Types:**
525
+ * - Uses `key` instead of `value` for the identifier (to avoid confusion)
526
+ * - Uses `value` for the default boolean checked state (the actual value)
527
+ * - No separate `defaultValue` property - defaults are embedded in options
528
+ *
529
+ * **Why `key` instead of `value`?**
530
+ * In dropdown and radio fields, `value` represents the actual selected value (string).
531
+ * In checkbox groups, the actual value is boolean (checked/unchecked), so we use
532
+ * `key` for the identifier to avoid confusion. This makes it clear that `value`
533
+ * is the boolean state, not just an identifier.
534
+ *
535
+ * @experimental This method is experimental and may be subject to change.
536
+ *
537
+ * @param config - Checkbox group field configuration (without the 'type' property)
538
+ * @param config.id - The unique identifier for this field
539
+ * @param config.label - The label displayed for this checkbox group
540
+ * @param config.options - Array of checkbox options with label, key, and value (boolean)
541
+ * @returns A complete checkbox group field definition with type 'checkboxGroup'
542
+ *
543
+ * @example
544
+ * ```typescript
545
+ * styleEditorField.checkboxGroup({
546
+ * id: 'text-decoration',
547
+ * label: 'Text Decoration',
548
+ * options: [
549
+ * { label: 'Underline', key: 'underline', value: true },
550
+ * { label: 'Overline', key: 'overline', value: false },
551
+ * { label: 'Line Through', key: 'line-through', value: false }
552
+ * ]
553
+ * // No defaultValue needed - it's automatically derived from options
554
+ * })
555
+ *
556
+ * // Example with type settings
557
+ * styleEditorField.checkboxGroup({
558
+ * id: 'type-settings',
559
+ * label: 'Type settings',
560
+ * options: [
561
+ * { label: 'Bold', key: 'bold', value: true },
562
+ * { label: 'Italic', key: 'italic', value: false },
563
+ * { label: 'Underline', key: 'underline', value: false },
564
+ * { label: 'Strikethrough', key: 'strikethrough', value: false }
565
+ * ]
566
+ * })
567
+ * ```
568
+ */
569
+ checkboxGroup: config => ({
570
+ type: 'checkboxGroup',
571
+ ...config
572
+ })
573
+ };
574
+ /**
575
+ * Normalizes and validates a style editor form definition.
576
+ *
577
+ * Converts the developer-friendly form structure into the schema format
578
+ * expected by UVE (Universal Visual Editor). This function processes the
579
+ * form definition and transforms it into the normalized schema format where:
580
+ *
581
+ * - All field-specific properties are moved into `config` objects
582
+ * - String options are normalized to `{ label, value }` objects
583
+ * - Sections are organized into the multi-dimensional array structure required by UVE
584
+ *
585
+ * The normalization process ensures consistency and type safety in the schema
586
+ * format sent to UVE. After normalization, use `registerStyleEditorSchemas`
587
+ * to register the schema with the UVE editor.
588
+ *
589
+ * @experimental This method is experimental and may be subject to change.
590
+ *
591
+ * @param form - The style editor form definition containing contentType and sections
592
+ * @param form.contentType - The content type identifier for this form
593
+ * @param form.sections - Array of sections, each containing a title and fields array
594
+ * @returns The normalized form schema ready to be sent to UVE
595
+ *
596
+ * @example
597
+ * ```typescript
598
+ * const formSchema = defineStyleEditorSchema({
599
+ * contentType: 'my-content-type',
600
+ * sections: [
601
+ * {
602
+ * title: 'Typography',
603
+ * fields: [
604
+ * styleEditorField.input({
605
+ * label: 'Font Size',
606
+ * inputType: 'number',
607
+ * defaultValue: 16
608
+ * }),
609
+ * styleEditorField.dropdown({
610
+ * label: 'Font Family',
611
+ * options: ['Arial', 'Helvetica'],
612
+ * defaultValue: 'Arial'
613
+ * })
614
+ * ]
615
+ * },
616
+ * {
617
+ * title: 'Colors',
618
+ * fields: [
619
+ * styleEditorField.input({
620
+ * label: 'Primary Color',
621
+ * inputType: 'text',
622
+ * defaultValue: '#000000'
623
+ * }),
624
+ * styleEditorField.input({
625
+ * label: 'Secondary Color',
626
+ * inputType: 'text',
627
+ * defaultValue: '#FFFFFF'
628
+ * })
629
+ * ]
630
+ * }
631
+ * ]
632
+ * });
633
+ *
634
+ * // Register the schema with UVE
635
+ * registerStyleEditorSchemas([formSchema]);
636
+ * ```
637
+ */
638
+ function defineStyleEditorSchema(form) {
639
+ return normalizeForm(form);
640
+ }
641
+ /**
642
+ * Registers style editor form schemas with the UVE editor.
643
+ *
644
+ * Sends normalized style editor schemas to the UVE (Universal Visual Editor)
645
+ * for registration. The schemas must be normalized using `defineStyleEditorSchema`
646
+ * before being passed to this function.
647
+ *
648
+ * **Behavior:**
649
+ * - Only registers schemas when UVE is in EDIT mode
650
+ * - Validates that each schema has a `contentType` property
651
+ * - Skips schemas without `contentType` and logs a warning
652
+ * - Sends the validated schemas to UVE via the `REGISTER_STYLE_SCHEMAS` action
653
+ *
654
+ * **Note:** This function will silently return early if UVE is not in EDIT mode,
655
+ * so it's safe to call even when the editor is not active.
656
+ *
657
+ * @experimental This method is experimental and may be subject to change.
658
+ *
659
+ * @param schemas - Array of normalized style editor form schemas to register with UVE
660
+ * @returns void - This function does not return a value
661
+ *
662
+ * @example
663
+ * ```typescript
664
+ * // Create and normalize a form schema
665
+ * const formSchema = defineStyleEditorSchema({
666
+ * contentType: 'my-content-type',
667
+ * sections: [
668
+ * {
669
+ * title: 'Typography',
670
+ * fields: [
671
+ * styleEditorField.input({
672
+ * label: 'Font Size',
673
+ * inputType: 'number',
674
+ * defaultValue: 16
675
+ * })
676
+ * ]
677
+ * }
678
+ * ]
679
+ * });
680
+ *
681
+ * // Register the schema with UVE
682
+ * registerStyleEditorSchemas([formSchema]);
683
+ *
684
+ * // Register multiple schemas at once
685
+ * const schema1 = defineStyleEditorSchema({ ... });
686
+ * const schema2 = defineStyleEditorSchema({ ... });
687
+ * registerStyleEditorSchemas([schema1, schema2]);
688
+ * ```
689
+ */
690
+ function registerStyleEditorSchemas(schemas) {
691
+ const {
692
+ mode
693
+ } = _public.getUVEState() || {};
694
+ if (!mode || mode !== types.UVE_MODE.EDIT) {
695
+ return;
696
+ }
697
+ const validatedSchemas = schemas.filter((schema, index) => {
698
+ if (!schema.contentType) {
699
+ console.warn(`[registerStyleEditorSchemas] Skipping schema with index [${index}] for not having a contentType`);
700
+ return false;
701
+ }
702
+ return true;
703
+ });
704
+ _public.sendMessageToUVE({
705
+ action: types.DotCMSUVEAction.REGISTER_STYLE_SCHEMAS,
706
+ payload: {
707
+ schemas: validatedSchemas
708
+ }
709
+ });
710
+ }
8
711
 
9
712
  exports.createUVESubscription = _public.createUVESubscription;
10
713
  exports.editContentlet = _public.editContentlet;
@@ -16,3 +719,6 @@ exports.isAnalyticsActive = _public.isAnalyticsActive;
16
719
  exports.reorderMenu = _public.reorderMenu;
17
720
  exports.sendMessageToUVE = _public.sendMessageToUVE;
18
721
  exports.updateNavigation = _public.updateNavigation;
722
+ exports.defineStyleEditorSchema = defineStyleEditorSchema;
723
+ exports.registerStyleEditorSchemas = registerStyleEditorSchemas;
724
+ exports.styleEditorField = styleEditorField;