@dotcms/uve 1.2.1-next.1 → 1.2.1-next.2

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.
@@ -0,0 +1,71 @@
1
+ import { StyleEditorFormSchema, StyleEditorForm } from './types';
2
+ /**
3
+ * Normalizes a complete form definition into the schema format expected by UVE.
4
+ *
5
+ * This is the main entry point for converting a developer-friendly form definition
6
+ * into the normalized schema structure that UVE (Universal Visual Editor) can consume.
7
+ * The normalization process transforms the entire form hierarchy:
8
+ *
9
+ * **Normalization Process:**
10
+ * 1. Preserves the `contentType` identifier
11
+ * 2. Processes each section using `normalizeSection`, which:
12
+ * - Normalizes all fields in the section using `normalizeField`
13
+ * - Organizes fields into the required multi-dimensional array structure
14
+ * 3. Returns a fully normalized schema with consistent structure across all sections
15
+ *
16
+ * The resulting schema has all field-specific properties moved into `config` objects
17
+ * and all sections using the consistent single-column array structure, regardless
18
+ * of the input format.
19
+ *
20
+ * @experimental This method is experimental and may be subject to change.
21
+ *
22
+ * @param form - The complete form definition to normalize
23
+ * @param form.contentType - The content type identifier this form is associated with
24
+ * @param form.sections - Array of section definitions, each containing a title and fields
25
+ * @returns The normalized form schema ready to be sent to UVE, with all fields and sections normalized
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * const schema = normalizeForm({
30
+ * contentType: 'my-content-type',
31
+ * sections: [
32
+ * {
33
+ * title: 'Typography',
34
+ * fields: [
35
+ * { type: 'input', label: 'Font Size', inputType: 'number', defaultValue: 16 },
36
+ * { type: 'dropdown', label: 'Font Family', options: ['Arial', 'Helvetica'] }
37
+ * ]
38
+ * },
39
+ * {
40
+ * title: 'Colors',
41
+ * fields: [
42
+ * { type: 'input', label: 'Primary Color', inputType: 'text', defaultValue: '#000000' }
43
+ * ]
44
+ * }
45
+ * ]
46
+ * });
47
+ * // Returns: {
48
+ * // contentType: 'my-content-type',
49
+ * // sections: [
50
+ * // {
51
+ * // title: 'Typography',
52
+ * // fields: [
53
+ * // [
54
+ * // { type: 'input', label: 'Font Size', config: { inputType: 'number', defaultValue: 16 } },
55
+ * // { type: 'dropdown', label: 'Font Family', config: { options: [...] } }
56
+ * // ]
57
+ * // ]
58
+ * // },
59
+ * // {
60
+ * // title: 'Colors',
61
+ * // fields: [
62
+ * // [
63
+ * // { type: 'input', label: 'Primary Color', config: { inputType: 'text', defaultValue: '#000000' } }
64
+ * // ]
65
+ * // ]
66
+ * // }
67
+ * // ]
68
+ * // }
69
+ * ```
70
+ */
71
+ export declare function normalizeForm(form: StyleEditorForm): StyleEditorFormSchema;
@@ -0,0 +1,341 @@
1
+ import { StyleEditorFormSchema, StyleEditorForm, StyleEditorInputField, StyleEditorDropdownField, StyleEditorRadioField, StyleEditorCheckboxGroupField, StyleEditorFieldInputType, StyleEditorInputFieldConfig } from './types';
2
+ /**
3
+ * Helper functions for creating style editor field definitions.
4
+ *
5
+ * Provides type-safe factory functions for creating different types of form fields
6
+ * used in the style editor. Each function creates a field definition with the
7
+ * appropriate `type` property automatically set, eliminating the need to manually
8
+ * specify the type discriminator.
9
+ *
10
+ * **Available Field Types:**
11
+ * - `input`: Text or number input fields
12
+ * - `dropdown`: Single-value selection from a dropdown list
13
+ * - `radio`: Single-value selection from radio button options (supports visual options with images)
14
+ * - `checkboxGroup`: Multiple-value selection from checkbox options
15
+ *
16
+ * These factory functions ensure type safety by inferring the correct field type
17
+ * based on the configuration provided, and they automatically set the `type` property
18
+ * to match the factory function used.
19
+ *
20
+ * @experimental This API is experimental and may be subject to change.
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * const form = defineStyleEditorSchema({
25
+ * contentType: 'my-content-type',
26
+ * sections: [
27
+ * {
28
+ * title: 'Typography',
29
+ * fields: [
30
+ * styleEditorField.input({
31
+ * label: 'Font Size',
32
+ * inputType: 'number',
33
+ * defaultValue: 16
34
+ * }),
35
+ * styleEditorField.dropdown({
36
+ * label: 'Font Family',
37
+ * options: ['Arial', 'Helvetica'],
38
+ * defaultValue: 'Arial'
39
+ * }),
40
+ * styleEditorField.radio({
41
+ * label: 'Alignment',
42
+ * options: ['Left', 'Center', 'Right'],
43
+ * defaultValue: 'Left'
44
+ * })
45
+ * ]
46
+ * }
47
+ * ]
48
+ * });
49
+ * ```
50
+ */
51
+ export declare const styleEditorField: {
52
+ /**
53
+ * Creates an input field definition with type-safe default values.
54
+ *
55
+ * Supports both text and number input types. The `defaultValue` type is
56
+ * enforced based on the `inputType` using TypeScript generics:
57
+ * - When `inputType` is `'number'`, `defaultValue` must be a `number`
58
+ * - When `inputType` is `'text'`, `defaultValue` must be a `string`
59
+ *
60
+ * This provides compile-time type checking to prevent mismatched types,
61
+ * such as passing a string when a number is expected.
62
+ *
63
+ * @experimental This method is experimental and may be subject to change.
64
+ *
65
+ * @typeParam T - The input type ('text' or 'number'), inferred from `config.inputType`
66
+ * @param config - Input field configuration
67
+ * @param config.label - The label displayed for this input field
68
+ * @param config.inputType - The type of input ('text' or 'number')
69
+ * @param config.placeholder - Optional placeholder text for the input
70
+ * @param config.defaultValue - Optional default value (type enforced based on inputType)
71
+ * @returns A complete input field definition with type 'input'
72
+ *
73
+ * @example
74
+ * ```typescript
75
+ * // Number input - defaultValue must be a number
76
+ * styleEditorField.input({
77
+ * label: 'Font Size',
78
+ * inputType: 'number',
79
+ * placeholder: 'Enter font size',
80
+ * defaultValue: 16 // ✓ Correct: number
81
+ * })
82
+ *
83
+ * // Text input - defaultValue must be a string
84
+ * styleEditorField.input({
85
+ * label: 'Font Name',
86
+ * inputType: 'text',
87
+ * placeholder: 'Enter font name',
88
+ * defaultValue: 'Arial' // ✓ Correct: string
89
+ * })
90
+ *
91
+ * // TypeScript error - type mismatch
92
+ * styleEditorField.input({
93
+ * label: 'Font Size',
94
+ * inputType: 'number',
95
+ * defaultValue: '16' // ✗ Error: Type 'string' is not assignable to type 'number'
96
+ * })
97
+ * ```
98
+ */
99
+ input: <T extends StyleEditorFieldInputType>(config: StyleEditorInputFieldConfig<T>) => StyleEditorInputField;
100
+ /**
101
+ * Creates a dropdown field definition.
102
+ *
103
+ * Allows users to select a single value from a list of options.
104
+ * Options can be provided as simple strings or as objects with label and value.
105
+ *
106
+ * @experimental This method is experimental and may be subject to change.
107
+ *
108
+ * @param config - Dropdown field configuration (without the 'type' property)
109
+ * @param config.label - The label displayed for this dropdown field
110
+ * @param config.options - Array of options. Can be strings or objects with label and value
111
+ * @param config.defaultValue - Optional default selected value (must match one of the option values)
112
+ * @param config.placeholder - Optional placeholder text shown when no value is selected
113
+ * @returns A complete dropdown field definition with type 'dropdown'
114
+ *
115
+ * @example
116
+ * ```typescript
117
+ * // Simple string options
118
+ * styleEditorField.dropdown({
119
+ * label: 'Font Family',
120
+ * options: ['Arial', 'Helvetica', 'Times New Roman'],
121
+ * defaultValue: 'Arial',
122
+ * placeholder: 'Select a font'
123
+ * })
124
+ *
125
+ * // Object options with custom labels
126
+ * styleEditorField.dropdown({
127
+ * label: 'Theme',
128
+ * options: [
129
+ * { label: 'Light Theme', value: 'light' },
130
+ * { label: 'Dark Theme', value: 'dark' }
131
+ * ],
132
+ * defaultValue: 'light'
133
+ * })
134
+ * ```
135
+ */
136
+ dropdown: (config: Omit<StyleEditorDropdownField, "type">) => StyleEditorDropdownField;
137
+ /**
138
+ * Creates a radio button field definition.
139
+ *
140
+ * Allows users to select a single option from a list. Supports visual
141
+ * options with background images for enhanced UI. Options can be provided
142
+ * as simple strings or as objects with label, value, and optional image properties.
143
+ *
144
+ * **Layout Options:**
145
+ * - `columns: 1` (default): Single column list layout
146
+ * - `columns: 2`: Two-column grid layout, ideal for visual options with images
147
+ *
148
+ * @experimental This method is experimental and may be subject to change.
149
+ *
150
+ * @param config - Radio field configuration (without the 'type' property)
151
+ * @param config.label - The label displayed for this radio group
152
+ * @param config.options - Array of options. Can be strings or objects with label, value, and optional imageURL, width, height
153
+ * @param config.defaultValue - Optional default selected value (must match one of the option values)
154
+ * @param config.columns - Optional number of columns (1 or 2). Defaults to 1 (single column)
155
+ * @returns A complete radio field definition with type 'radio'
156
+ *
157
+ * @example
158
+ * ```typescript
159
+ * // Simple string options (single column)
160
+ * styleEditorField.radio({
161
+ * label: 'Alignment',
162
+ * options: ['Left', 'Center', 'Right'],
163
+ * defaultValue: 'Left'
164
+ * })
165
+ *
166
+ * // Two-column grid layout with images
167
+ * styleEditorField.radio({
168
+ * label: 'Layout',
169
+ * columns: 2,
170
+ * options: [
171
+ * {
172
+ * label: 'Left',
173
+ * value: 'left',
174
+ * imageURL: 'https://example.com/layout-left.png',
175
+ * width: 80,
176
+ * height: 50
177
+ * },
178
+ * {
179
+ * label: 'Right',
180
+ * value: 'right',
181
+ * imageURL: 'https://example.com/layout-right.png',
182
+ * width: 80,
183
+ * height: 50
184
+ * },
185
+ * { label: 'Center', value: 'center' },
186
+ * { label: 'Overlap', value: 'overlap' }
187
+ * ],
188
+ * defaultValue: 'right'
189
+ * })
190
+ * ```
191
+ */
192
+ radio: (config: Omit<StyleEditorRadioField, "type">) => StyleEditorRadioField;
193
+ /**
194
+ * Creates a checkbox group field definition.
195
+ *
196
+ * Allows users to select multiple options simultaneously. Each option
197
+ * can be independently checked or unchecked. The defaultValue is a
198
+ * record mapping option values to their boolean checked state.
199
+ *
200
+ * @experimental This method is experimental and may be subject to change.
201
+ *
202
+ * @param config - Checkbox group field configuration (without the 'type' property)
203
+ * @param config.label - The label displayed for this checkbox group
204
+ * @param config.options - Array of options. Can be strings or objects with label and value
205
+ * @param config.defaultValue - Optional default checked state as a record of option values to boolean
206
+ * @returns A complete checkbox group field definition with type 'checkboxGroup'
207
+ *
208
+ * @example
209
+ * ```typescript
210
+ * styleEditorField.checkboxGroup({
211
+ * label: 'Text Decoration',
212
+ * options: [
213
+ * { label: 'Underline', value: 'underline' },
214
+ * { label: 'Overline', value: 'overline' },
215
+ * { label: 'Line Through', value: 'line-through' }
216
+ * ],
217
+ * defaultValue: {
218
+ * 'underline': true,
219
+ * 'overline': false,
220
+ * 'line-through': false
221
+ * }
222
+ * })
223
+ * ```
224
+ */
225
+ checkboxGroup: (config: Omit<StyleEditorCheckboxGroupField, "type">) => StyleEditorCheckboxGroupField;
226
+ };
227
+ /**
228
+ * Normalizes and validates a style editor form definition.
229
+ *
230
+ * Converts the developer-friendly form structure into the schema format
231
+ * expected by UVE (Universal Visual Editor). This function processes the
232
+ * form definition and transforms it into the normalized schema format where:
233
+ *
234
+ * - All field-specific properties are moved into `config` objects
235
+ * - String options are normalized to `{ label, value }` objects
236
+ * - Sections are organized into the multi-dimensional array structure required by UVE
237
+ *
238
+ * The normalization process ensures consistency and type safety in the schema
239
+ * format sent to UVE. After normalization, use `registerStyleEditorSchemas`
240
+ * to register the schema with the UVE editor.
241
+ *
242
+ * @experimental This method is experimental and may be subject to change.
243
+ *
244
+ * @param form - The style editor form definition containing contentType and sections
245
+ * @param form.contentType - The content type identifier for this form
246
+ * @param form.sections - Array of sections, each containing a title and fields array
247
+ * @returns The normalized form schema ready to be sent to UVE
248
+ *
249
+ * @example
250
+ * ```typescript
251
+ * const formSchema = defineStyleEditorSchema({
252
+ * contentType: 'my-content-type',
253
+ * sections: [
254
+ * {
255
+ * title: 'Typography',
256
+ * fields: [
257
+ * styleEditorField.input({
258
+ * label: 'Font Size',
259
+ * inputType: 'number',
260
+ * defaultValue: 16
261
+ * }),
262
+ * styleEditorField.dropdown({
263
+ * label: 'Font Family',
264
+ * options: ['Arial', 'Helvetica'],
265
+ * defaultValue: 'Arial'
266
+ * })
267
+ * ]
268
+ * },
269
+ * {
270
+ * title: 'Colors',
271
+ * fields: [
272
+ * styleEditorField.input({
273
+ * label: 'Primary Color',
274
+ * inputType: 'text',
275
+ * defaultValue: '#000000'
276
+ * }),
277
+ * styleEditorField.input({
278
+ * label: 'Secondary Color',
279
+ * inputType: 'text',
280
+ * defaultValue: '#FFFFFF'
281
+ * })
282
+ * ]
283
+ * }
284
+ * ]
285
+ * });
286
+ *
287
+ * // Register the schema with UVE
288
+ * registerStyleEditorSchemas([formSchema]);
289
+ * ```
290
+ */
291
+ export declare function defineStyleEditorSchema(form: StyleEditorForm): StyleEditorFormSchema;
292
+ /**
293
+ * Registers style editor form schemas with the UVE editor.
294
+ *
295
+ * Sends normalized style editor schemas to the UVE (Universal Visual Editor)
296
+ * for registration. The schemas must be normalized using `defineStyleEditorSchema`
297
+ * before being passed to this function.
298
+ *
299
+ * **Behavior:**
300
+ * - Only registers schemas when UVE is in EDIT mode
301
+ * - Validates that each schema has a `contentType` property
302
+ * - Skips schemas without `contentType` and logs a warning
303
+ * - Sends the validated schemas to UVE via the `REGISTER_STYLE_SCHEMAS` action
304
+ *
305
+ * **Note:** This function will silently return early if UVE is not in EDIT mode,
306
+ * so it's safe to call even when the editor is not active.
307
+ *
308
+ * @experimental This method is experimental and may be subject to change.
309
+ *
310
+ * @param schemas - Array of normalized style editor form schemas to register with UVE
311
+ * @returns void - This function does not return a value
312
+ *
313
+ * @example
314
+ * ```typescript
315
+ * // Create and normalize a form schema
316
+ * const formSchema = defineStyleEditorSchema({
317
+ * contentType: 'my-content-type',
318
+ * sections: [
319
+ * {
320
+ * title: 'Typography',
321
+ * fields: [
322
+ * styleEditorField.input({
323
+ * label: 'Font Size',
324
+ * inputType: 'number',
325
+ * defaultValue: 16
326
+ * })
327
+ * ]
328
+ * }
329
+ * ]
330
+ * });
331
+ *
332
+ * // Register the schema with UVE
333
+ * registerStyleEditorSchemas([formSchema]);
334
+ *
335
+ * // Register multiple schemas at once
336
+ * const schema1 = defineStyleEditorSchema({ ... });
337
+ * const schema2 = defineStyleEditorSchema({ ... });
338
+ * registerStyleEditorSchemas([schema1, schema2]);
339
+ * ```
340
+ */
341
+ export declare function registerStyleEditorSchemas(schemas: StyleEditorFormSchema[]): void;