@elementor/editor-props 3.33.0-99 → 3.35.0-325

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,190 @@
1
+ import { type PropsSchema, type PropType } from '../types';
2
+ import { type JsonSchema7 } from './prop-json-schema';
3
+
4
+ export function jsonSchemaToPropType( schema: JsonSchema7, key = < string >schema.key ): PropType {
5
+ const meta: Record< string, unknown > = {};
6
+
7
+ if ( schema.description ) {
8
+ meta.description = schema.description;
9
+ }
10
+
11
+ // Handle union types (anyOf)
12
+ if ( schema.anyOf && Array.isArray( schema.anyOf ) ) {
13
+ return convertJsonSchemaToUnionPropType( schema, meta );
14
+ }
15
+
16
+ // Handle object types
17
+ if ( schema.type === 'object' && schema.properties ) {
18
+ return convertJsonSchemaToObjectPropType( schema, meta, key );
19
+ }
20
+
21
+ // Handle array types
22
+ if ( schema.type === 'array' && schema.items ) {
23
+ return convertJsonSchemaToArrayPropType( schema, meta, key );
24
+ }
25
+
26
+ // Handle plain types (string, number, boolean)
27
+ return convertJsonSchemaToPlainPropType( schema, meta, key );
28
+ }
29
+
30
+ function convertJsonSchemaToPlainPropType(
31
+ schema: JsonSchema7,
32
+ meta: Record< string, unknown >,
33
+ key = < string >schema.key
34
+ ): PropType {
35
+ const settings: Record< string, unknown > = {};
36
+
37
+ // Determine the key based on type
38
+ let propKey = key || 'string';
39
+
40
+ if ( schema.type === 'number' ) {
41
+ propKey = 'number';
42
+ } else if ( schema.type === 'boolean' ) {
43
+ propKey = 'boolean';
44
+ } else if ( schema.type === 'string' ) {
45
+ propKey = 'string';
46
+ }
47
+
48
+ // Handle enum values
49
+ if ( Array.isArray( schema.enum ) ) {
50
+ settings.enum = schema.enum;
51
+ }
52
+
53
+ return {
54
+ kind: 'plain',
55
+ key: propKey,
56
+ settings,
57
+ meta,
58
+ } as PropType;
59
+ }
60
+
61
+ /**
62
+ * Converts a JSON Schema anyOf to a union PropType
63
+ * @param schema
64
+ * @param meta
65
+ */
66
+ function convertJsonSchemaToUnionPropType( schema: JsonSchema7, meta: Record< string, unknown > ): PropType {
67
+ const propTypes: Record< string, PropType > = {};
68
+
69
+ if ( ! schema.anyOf || ! Array.isArray( schema.anyOf ) ) {
70
+ throw new Error( 'Invalid anyOf schema' );
71
+ }
72
+
73
+ // Process each variant in the anyOf array
74
+ for ( const variantSchema of schema.anyOf ) {
75
+ // Each variant should be an object with $$type and value properties
76
+ if (
77
+ variantSchema.type === 'object' &&
78
+ variantSchema.properties &&
79
+ variantSchema.properties.$$type &&
80
+ variantSchema.properties.value
81
+ ) {
82
+ const typeProperty = variantSchema.properties.$$type;
83
+
84
+ // Extract the type key from the enum
85
+ let typeKey: string;
86
+ if ( typeProperty.enum && Array.isArray( typeProperty.enum ) && typeProperty.enum.length > 0 ) {
87
+ typeKey = typeProperty.enum[ 0 ] as string;
88
+ } else {
89
+ continue;
90
+ }
91
+
92
+ // Convert the value schema to a PropType
93
+ const valuePropType = convertJsonSchemaToPropType( variantSchema.properties.value );
94
+ propTypes[ typeKey ] = valuePropType;
95
+ }
96
+ }
97
+
98
+ return {
99
+ kind: 'union',
100
+ prop_types: propTypes,
101
+ settings: {},
102
+ meta,
103
+ } as PropType;
104
+ }
105
+
106
+ function convertJsonSchemaToObjectPropType(
107
+ schema: JsonSchema7,
108
+ meta: Record< string, unknown >,
109
+ key = < string >schema.key
110
+ ): PropType {
111
+ const shape: Record< string, PropType > = {};
112
+
113
+ if ( ! schema.properties ) {
114
+ return {
115
+ kind: 'object',
116
+ key,
117
+ shape: {},
118
+ settings: {},
119
+ meta,
120
+ } as PropType;
121
+ }
122
+
123
+ const requiredFields = Array.isArray( schema.required ) ? schema.required : [];
124
+
125
+ // Convert each property
126
+ for ( const [ propKey, propSchema ] of Object.entries( schema.properties ) ) {
127
+ const subPropType = convertJsonSchemaToPropType( propSchema, key );
128
+
129
+ // Mark as required if it's in the required array
130
+ if ( requiredFields.includes( propKey ) ) {
131
+ subPropType.settings = {
132
+ ...subPropType.settings,
133
+ required: true,
134
+ };
135
+ }
136
+
137
+ shape[ propKey ] = subPropType;
138
+ }
139
+
140
+ return {
141
+ kind: 'object',
142
+ key: key || 'object',
143
+ shape,
144
+ settings: {},
145
+ meta,
146
+ } as PropType;
147
+ }
148
+
149
+ function convertJsonSchemaToArrayPropType(
150
+ schema: JsonSchema7,
151
+ meta: Record< string, unknown >,
152
+ key = < string >schema.key
153
+ ): PropType {
154
+ if ( ! schema.items ) {
155
+ throw new Error( 'Array schema must have items property' );
156
+ }
157
+
158
+ const itemPropType = convertJsonSchemaToPropType( schema.items );
159
+
160
+ return {
161
+ kind: 'array',
162
+ key: key || 'array',
163
+ item_prop_type: itemPropType,
164
+ settings: {},
165
+ meta,
166
+ } as PropType;
167
+ }
168
+
169
+ function convertJsonSchemaToPropType( schema: JsonSchema7, key?: string ): PropType {
170
+ return jsonSchemaToPropType( schema, key );
171
+ }
172
+
173
+ /**
174
+ * Converts a complete JSON Schema object back to a PropsSchema
175
+ *
176
+ * @param jsonSchema The JSON Schema to convert
177
+ */
178
+ export function jsonSchemaToPropsSchema( jsonSchema: JsonSchema7 ): PropsSchema {
179
+ const propsSchema: PropsSchema = {};
180
+
181
+ if ( jsonSchema.type !== 'object' || ! jsonSchema.properties ) {
182
+ throw new Error( 'Root schema must be an object with properties' );
183
+ }
184
+
185
+ for ( const [ key, propSchema ] of Object.entries( jsonSchema.properties ) ) {
186
+ propsSchema[ key ] = convertJsonSchemaToPropType( propSchema, key );
187
+ }
188
+
189
+ return propsSchema;
190
+ }
@@ -1,7 +1,12 @@
1
1
  import type { Props } from '../types';
2
2
 
3
3
  export function mergeProps( current: Props, updates: Props ) {
4
- const props = structuredClone( current );
4
+ // edge case, the server returns an array instead of an object when empty props because of PHP array / object conversion
5
+ let props: Props = {};
6
+
7
+ if ( ! Array.isArray( current ) ) {
8
+ props = structuredClone( current );
9
+ }
5
10
 
6
11
  Object.entries( updates ).forEach( ( [ key, value ] ) => {
7
12
  if ( value === null || value === undefined ) {
@@ -11,19 +11,32 @@ type ParsedTerm = DependencyTerm;
11
11
 
12
12
  type Relation = Dependency[ 'relation' ];
13
13
 
14
- export function isDependencyMet( dependency: Dependency | undefined, values: PropValue ): boolean {
14
+ export function isDependencyMet(
15
+ dependency: Dependency | undefined,
16
+ values: PropValue
17
+ ): { isMet: true } | { isMet: false; failingDependencies: DependencyTerm[] } {
15
18
  if ( ! dependency?.terms.length ) {
16
- return true;
19
+ return { isMet: true };
17
20
  }
18
21
 
19
22
  const { relation, terms } = dependency;
20
23
  const method = getRelationMethod( relation );
21
24
 
22
- return terms[ method ]( ( term: ParsedTerm | Dependency ) =>
23
- isDependency( term )
24
- ? isDependencyMet( term, values )
25
- : evaluateTerm( term, extractValue( term.path, values )?.value )
26
- );
25
+ const failingDependencies: DependencyTerm[] = [];
26
+ const isMet = terms[ method ]( ( term: ParsedTerm | Dependency ) => {
27
+ const isNestedDependency = isDependency( term );
28
+ const result = isNestedDependency
29
+ ? isDependencyMet( term, values ).isMet
30
+ : evaluateTerm( term, extractValue( term.path, values )?.value );
31
+
32
+ if ( ! result && ! isNestedDependency ) {
33
+ failingDependencies.push( term );
34
+ }
35
+
36
+ return result;
37
+ } );
38
+
39
+ return { isMet, failingDependencies };
27
40
  }
28
41
 
29
42
  export function evaluateTerm( term: DependencyTerm, actualValue: unknown ) {
@@ -0,0 +1,17 @@
1
+ export type JsonSchema7 = {
2
+ type?: string | string[];
3
+ properties?: Record< string, JsonSchema7 >;
4
+ items?: JsonSchema7;
5
+ enum?: unknown[];
6
+ anyOf?: JsonSchema7[];
7
+ oneOf?: JsonSchema7[];
8
+ allOf?: JsonSchema7[];
9
+ required?: string[];
10
+ description?: string;
11
+ default?: unknown;
12
+ if?: JsonSchema7;
13
+ then?: JsonSchema7;
14
+ else?: JsonSchema7;
15
+ key?: string;
16
+ [ key: string ]: unknown;
17
+ };
@@ -0,0 +1,177 @@
1
+ import { type PropsSchema, type PropType } from '../types';
2
+ import { type JsonSchema7 } from './prop-json-schema';
3
+
4
+ export function propTypeToJsonSchema( propType: PropType ): JsonSchema7 {
5
+ const description = propType.meta?.description;
6
+
7
+ const schema: JsonSchema7 = {};
8
+
9
+ if ( description ) {
10
+ schema.description = description;
11
+ }
12
+
13
+ // Handle different kinds of prop types
14
+ switch ( propType.kind ) {
15
+ case 'plain':
16
+ return convertPlainPropType( propType, schema );
17
+ case 'union':
18
+ return convertUnionPropType( propType, schema );
19
+ case 'object':
20
+ return convertObjectPropType( propType, schema );
21
+ case 'array':
22
+ return convertArrayPropType( propType, schema );
23
+ default:
24
+ return convertPlainPropType( propType, schema );
25
+ }
26
+
27
+ return schema;
28
+ }
29
+
30
+ function convertPlainPropType( propType: PropType & { kind: 'plain' }, baseSchema: JsonSchema7 ): JsonSchema7 {
31
+ const schema = { ...baseSchema };
32
+
33
+ // Determine type based on key
34
+ const key = propType.key.toLowerCase();
35
+
36
+ switch ( key ) {
37
+ case 'number':
38
+ schema.type = 'number';
39
+ break;
40
+ case 'boolean':
41
+ schema.type = 'boolean';
42
+ break;
43
+ default:
44
+ schema.type = 'string';
45
+ }
46
+
47
+ // Handle enum from settings
48
+ if ( Array.isArray( propType.settings?.enum ) ) {
49
+ schema.enum = propType.settings.enum;
50
+ }
51
+
52
+ return schema;
53
+ }
54
+
55
+ /**
56
+ * Converts a union prop type to JSON Schema ( электричество anyOf)
57
+ *
58
+ * @param propType The union prop type to convert
59
+ * @param baseSchema Base schema to extend
60
+ */
61
+ function convertUnionPropType( propType: PropType & { kind: 'union' }, baseSchema: JsonSchema7 ): JsonSchema7 {
62
+ const schema = structuredClone( baseSchema );
63
+
64
+ const propTypes = propType.prop_types || {};
65
+ const schemas: JsonSchema7[] = [];
66
+
67
+ // Convert each prop type in the union
68
+ for ( const [ typeKey, subPropType ] of Object.entries( propTypes ) ) {
69
+ const subSchema = convertPropTypeToJsonSchema( subPropType );
70
+
71
+ schemas.push( {
72
+ type: 'object',
73
+ required: [ '$$type', 'value' ],
74
+ properties: {
75
+ $$type: {
76
+ type: 'string',
77
+ const: typeKey,
78
+ description: subPropType.meta?.description,
79
+ $comment: `Discriminator for union type variant: ${ typeKey }`,
80
+ },
81
+ value: subSchema,
82
+ },
83
+ } );
84
+ }
85
+
86
+ if ( schemas.length > 0 ) {
87
+ schema.anyOf = schemas;
88
+ }
89
+
90
+ const propTypeDescription = propType.meta?.description;
91
+ if ( propTypeDescription ) {
92
+ schema.description = propTypeDescription;
93
+ }
94
+ return schema;
95
+ }
96
+
97
+ function convertObjectPropType( propType: PropType & { kind: 'object' }, baseSchema: JsonSchema7 ): JsonSchema7 {
98
+ const schema = structuredClone( baseSchema );
99
+
100
+ schema.type = 'object';
101
+ schema.properties = {};
102
+
103
+ const required: string[] = [];
104
+
105
+ const shape = propType.shape || {};
106
+
107
+ // Convert each property in the object shape
108
+ for ( const [ key, subPropType ] of Object.entries( shape ) ) {
109
+ const propSchema = convertPropTypeToJsonSchema( subPropType );
110
+
111
+ // Check if this property is required
112
+ if ( subPropType.settings?.required === true ) {
113
+ required.push( key );
114
+ }
115
+
116
+ schema.properties[ key ] = propSchema;
117
+ }
118
+
119
+ // Add required array if there are required fields
120
+ if ( required.length > 0 ) {
121
+ schema.required = required;
122
+ }
123
+
124
+ return schema;
125
+ }
126
+
127
+ function convertArrayPropType( propType: PropType & { kind: 'array' }, baseSchema: JsonSchema7 ): JsonSchema7 {
128
+ const schema = structuredClone( baseSchema );
129
+
130
+ schema.type = 'array';
131
+
132
+ const itemPropType = propType.item_prop_type;
133
+
134
+ if ( itemPropType ) {
135
+ schema.items = convertPropTypeToJsonSchema( itemPropType );
136
+ }
137
+
138
+ return schema;
139
+ }
140
+
141
+ function convertPropTypeToJsonSchema( propType: PropType ): JsonSchema7 {
142
+ return propTypeToJsonSchema( propType );
143
+ }
144
+
145
+ export function propsSchemaToJsonSchema( schema: PropsSchema ): JsonSchema7 {
146
+ const jsonSchema: JsonSchema7 = {
147
+ type: 'object',
148
+ properties: {},
149
+ };
150
+
151
+ for ( const [ key, propType ] of Object.entries( schema ) ) {
152
+ // Skip internal properties
153
+ if ( ! isPropKeyConfigurable( key ) ) {
154
+ continue;
155
+ }
156
+
157
+ const propSchema = convertPropTypeToJsonSchema( propType );
158
+ if ( jsonSchema.properties ) {
159
+ jsonSchema.properties[ key ] = propSchema;
160
+ }
161
+
162
+ // Handle required fields at root level if needed
163
+ // (typically props are optional unless specified)
164
+ }
165
+
166
+ return jsonSchema;
167
+ }
168
+
169
+ export const nonConfigurablePropKeys = [ '_cssid', 'classes', 'attributes' ] as readonly string[];
170
+
171
+ export function isPropKeyConfigurable( propKey: string ): boolean {
172
+ return ! nonConfigurablePropKeys.includes( propKey );
173
+ }
174
+
175
+ export function configurableKeys( schema: PropsSchema ): string[] {
176
+ return Object.keys( schema ).filter( isPropKeyConfigurable );
177
+ }