@elementor/editor-props 4.2.0-924 → 4.2.0-926

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.
@@ -1,7 +1,25 @@
1
1
  import { type PropsSchema, type PropType } from '../types';
2
2
  import { type JsonSchema7 } from './prop-json-schema';
3
3
 
4
- export function propTypeToJsonSchema( propType: PropType ): JsonSchema7 {
4
+ const DYNAMIC_PROP_TYPE_KEY = 'dynamic';
5
+ const OVERRIDABLE_PROP_TYPE_KEY = 'overridable';
6
+
7
+ type DynamicTagNamesResolver = ( categories: string[] ) => string[];
8
+
9
+ // Host (editor-canvas) injects a resolver that maps a prop's accepted categories to the names of the
10
+ // dynamic tags allowed for it. Keeping it injectable preserves this lib's purity: without a host the
11
+ // `name` field stays an open string instead of an enum.
12
+ let dynamicTagNamesResolver: DynamicTagNamesResolver | null = null;
13
+
14
+ export function setDynamicTagNamesResolver( resolver: DynamicTagNamesResolver | null ): void {
15
+ dynamicTagNamesResolver = resolver;
16
+ }
17
+
18
+ // A dynamic value replaces the value of the exact node it is attached to, which may be a nested
19
+ // field (e.g. an image's `src`) rather than the property root. It is advertised once per branch, at
20
+ // the outermost prop type that supports it, and suppressed for descendants of that node to avoid
21
+ // offering the same dynamic option twice on a single branch.
22
+ export function propTypeToJsonSchema( propType: PropType, suppressDynamic: boolean = false ): JsonSchema7 {
5
23
  const description = propType.meta?.description;
6
24
 
7
25
  const schema: JsonSchema7 = {};
@@ -18,11 +36,11 @@ export function propTypeToJsonSchema( propType: PropType ): JsonSchema7 {
18
36
  // Handle different kinds of prop types
19
37
  switch ( propType.kind ) {
20
38
  case 'union':
21
- return convertUnionPropType( propType, schema );
39
+ return convertUnionPropType( propType, schema, suppressDynamic );
22
40
  case 'object':
23
- return convertObjectPropType( propType, schema );
41
+ return convertObjectPropType( propType, schema, suppressDynamic );
24
42
  case 'array':
25
- return convertArrayPropType( propType, schema );
43
+ return convertArrayPropType( propType, schema, suppressDynamic );
26
44
  default:
27
45
  return convertPlainPropType( propType, schema );
28
46
  }
@@ -73,24 +91,36 @@ function convertPlainPropType(
73
91
  }
74
92
 
75
93
  /**
76
- * Converts a union prop type to JSON Schema ( электричество anyOf)
94
+ * Converts a union prop type to JSON Schema (anyOf).
77
95
  *
78
- * @param propType The union prop type to convert
79
- * @param baseSchema Base schema to extend
96
+ * @param propType The union prop type to convert
97
+ * @param baseSchema Base schema to extend
98
+ * @param suppressDynamic When true, an ancestor already offered the dynamic option for this branch
80
99
  */
81
- function convertUnionPropType( propType: PropType & { kind: 'union' }, baseSchema: JsonSchema7 ): JsonSchema7 {
100
+ function convertUnionPropType(
101
+ propType: PropType & { kind: 'union' },
102
+ baseSchema: JsonSchema7,
103
+ suppressDynamic: boolean
104
+ ): JsonSchema7 {
82
105
  const schema = structuredClone( baseSchema );
83
106
 
84
107
  const propTypes = propType.prop_types || {};
108
+ const offersDynamic = ! suppressDynamic && Boolean( propTypes[ DYNAMIC_PROP_TYPE_KEY ] );
109
+ const suppressNestedDynamic = suppressDynamic || offersDynamic;
85
110
  const schemas: JsonSchema7[] = [];
86
111
 
87
112
  // Convert each prop type in the union
88
113
  for ( const [ typeKey, subPropType ] of Object.entries( propTypes ) ) {
89
- if ( typeKey === 'dynamic' || typeKey === 'overridable' ) {
114
+ if ( typeKey === OVERRIDABLE_PROP_TYPE_KEY ) {
115
+ continue;
116
+ }
117
+ if ( typeKey === DYNAMIC_PROP_TYPE_KEY ) {
118
+ if ( offersDynamic ) {
119
+ schemas.push( convertDynamicPropType( subPropType ) );
120
+ }
90
121
  continue;
91
122
  }
92
- const subSchema = convertPropTypeToJsonSchema( subPropType );
93
- schemas.push( subSchema );
123
+ schemas.push( propTypeToJsonSchema( subPropType, suppressNestedDynamic ) );
94
124
  }
95
125
 
96
126
  if ( schemas.length > 0 ) {
@@ -104,7 +134,50 @@ function convertUnionPropType( propType: PropType & { kind: 'union' }, baseSchem
104
134
  return schema;
105
135
  }
106
136
 
107
- function convertObjectPropType( propType: PropType & { kind: 'object' }, baseSchema: JsonSchema7 ): JsonSchema7 {
137
+ // Emits a compact representation of the `dynamic` union member. It is offered as one option of THIS
138
+ // node's value (e.g. a property root, or a nested field such as an image's `src`): put the dynamic
139
+ // object exactly here, in place of the sibling static variant. Only `name` is required from the LLM
140
+ // (constrained to the tags allowed here); `group` is filled by the host resolver, and `settings` are
141
+ // described per-tag in the dynamic-tags resource, so the full tag catalog is never inlined.
142
+ function convertDynamicPropType( propType: PropType ): JsonSchema7 {
143
+ const categories = Array.isArray( propType.settings?.categories )
144
+ ? ( propType.settings.categories as string[] )
145
+ : [];
146
+ const allowedTagNames = dynamicTagNamesResolver?.( categories ) ?? [];
147
+
148
+ return {
149
+ type: 'object',
150
+ description:
151
+ 'Bind THIS value to a dynamic tag instead of a static value (this may be a nested field, ' +
152
+ 'e.g. an image\'s "src"). Look up the chosen tag in the "elementor://dynamic-tags" resource ' +
153
+ 'and populate "settings" exactly as its schema requires.',
154
+ properties: {
155
+ $$type: { type: 'string', const: DYNAMIC_PROP_TYPE_KEY },
156
+ value: {
157
+ type: 'object',
158
+ properties: {
159
+ name: {
160
+ type: 'string',
161
+ description: 'Dynamic tag name from "elementor://dynamic-tags".',
162
+ ...( allowedTagNames.length ? { enum: allowedTagNames } : {} ),
163
+ },
164
+ settings: {
165
+ type: 'object',
166
+ description: "Tag settings matching the chosen tag's schema in the resource.",
167
+ },
168
+ },
169
+ required: [ 'name' ],
170
+ },
171
+ },
172
+ required: [ '$$type', 'value' ],
173
+ };
174
+ }
175
+
176
+ function convertObjectPropType(
177
+ propType: PropType & { kind: 'object' },
178
+ baseSchema: JsonSchema7,
179
+ suppressDynamic: boolean
180
+ ): JsonSchema7 {
108
181
  const schema = structuredClone( baseSchema );
109
182
 
110
183
  schema.type = 'object';
@@ -134,7 +207,7 @@ function convertObjectPropType( propType: PropType & { kind: 'object' }, baseSch
134
207
 
135
208
  // Convert each property in the object shape
136
209
  for ( const [ key, subPropType ] of Object.entries( shape ) ) {
137
- const propSchema = propTypeToJsonSchema( subPropType );
210
+ const propSchema = propTypeToJsonSchema( subPropType, suppressDynamic );
138
211
 
139
212
  // Check if this property is required
140
213
  if ( subPropType.settings?.required === true ) {
@@ -157,7 +230,11 @@ function convertObjectPropType( propType: PropType & { kind: 'object' }, baseSch
157
230
  };
158
231
  }
159
232
 
160
- function convertArrayPropType( propType: PropType & { kind: 'array' }, baseSchema: JsonSchema7 ): JsonSchema7 {
233
+ function convertArrayPropType(
234
+ propType: PropType & { kind: 'array' },
235
+ baseSchema: JsonSchema7,
236
+ suppressDynamic: boolean
237
+ ): JsonSchema7 {
161
238
  const schema = structuredClone( baseSchema );
162
239
 
163
240
  schema.type = 'object';
@@ -166,7 +243,7 @@ function convertArrayPropType( propType: PropType & { kind: 'array' }, baseSchem
166
243
  const itemPropType = propType.item_prop_type;
167
244
 
168
245
  if ( itemPropType ) {
169
- items = convertPropTypeToJsonSchema( itemPropType );
246
+ items = propTypeToJsonSchema( itemPropType, suppressDynamic );
170
247
  }
171
248
 
172
249
  schema.properties = {
@@ -182,10 +259,6 @@ function convertArrayPropType( propType: PropType & { kind: 'array' }, baseSchem
182
259
  return schema;
183
260
  }
184
261
 
185
- function convertPropTypeToJsonSchema( propType: PropType ): JsonSchema7 {
186
- return propTypeToJsonSchema( propType );
187
- }
188
-
189
262
  export const nonConfigurablePropKeys = [ '_cssid', 'classes', 'attributes' ] as readonly string[];
190
263
 
191
264
  export function isPropKeyConfigurable( propKey: string, propType?: PropType ): boolean {
@@ -50,6 +50,173 @@ export const STUBS = {
50
50
  value: 'rgba(0, 0, 0, 1)',
51
51
  },
52
52
  },
53
+ dynamicText: {
54
+ kind: 'union',
55
+ default: null,
56
+ meta: {
57
+ description: 'A text value that also supports dynamic tags',
58
+ },
59
+ settings: {},
60
+ prop_types: {
61
+ string: {
62
+ kind: 'string',
63
+ key: 'string',
64
+ default: null,
65
+ meta: {},
66
+ settings: {},
67
+ dependencies: undefined,
68
+ initial_value: null,
69
+ },
70
+ dynamic: {
71
+ kind: 'plain',
72
+ key: 'dynamic',
73
+ default: null,
74
+ meta: {},
75
+ settings: {
76
+ categories: [ 'text' ],
77
+ },
78
+ dependencies: undefined,
79
+ initial_value: null,
80
+ },
81
+ overridable: {
82
+ kind: 'plain',
83
+ key: 'overridable',
84
+ default: null,
85
+ meta: {},
86
+ settings: {},
87
+ dependencies: undefined,
88
+ initial_value: null,
89
+ },
90
+ },
91
+ dependencies: undefined,
92
+ initial_value: null,
93
+ },
94
+ htmlV3Title: {
95
+ kind: 'union',
96
+ default: null,
97
+ meta: {},
98
+ settings: {},
99
+ prop_types: {
100
+ 'html-v3': {
101
+ kind: 'object',
102
+ key: 'html-v3',
103
+ default: null,
104
+ meta: {},
105
+ settings: {},
106
+ shape: {
107
+ content: {
108
+ kind: 'union',
109
+ default: null,
110
+ meta: {},
111
+ settings: {},
112
+ prop_types: {
113
+ string: {
114
+ kind: 'string',
115
+ key: 'string',
116
+ default: null,
117
+ meta: {},
118
+ settings: {},
119
+ dependencies: undefined,
120
+ initial_value: null,
121
+ },
122
+ dynamic: {
123
+ kind: 'plain',
124
+ key: 'dynamic',
125
+ default: null,
126
+ meta: {},
127
+ settings: { categories: [ 'text' ] },
128
+ dependencies: undefined,
129
+ initial_value: null,
130
+ },
131
+ },
132
+ dependencies: undefined,
133
+ initial_value: null,
134
+ },
135
+ },
136
+ dependencies: undefined,
137
+ initial_value: null,
138
+ },
139
+ dynamic: {
140
+ kind: 'plain',
141
+ key: 'dynamic',
142
+ default: null,
143
+ meta: {},
144
+ settings: { categories: [ 'text' ] },
145
+ dependencies: undefined,
146
+ initial_value: null,
147
+ },
148
+ },
149
+ dependencies: undefined,
150
+ initial_value: null,
151
+ },
152
+ dynamicImage: {
153
+ kind: 'object',
154
+ key: 'image',
155
+ default: null,
156
+ meta: {},
157
+ settings: {},
158
+ shape: {
159
+ src: {
160
+ kind: 'union',
161
+ default: null,
162
+ meta: {},
163
+ settings: {},
164
+ prop_types: {
165
+ 'image-src': {
166
+ kind: 'object',
167
+ key: 'image-src',
168
+ default: null,
169
+ meta: {},
170
+ settings: {},
171
+ shape: {
172
+ id: {
173
+ kind: 'number',
174
+ key: 'image-attachment-id',
175
+ default: null,
176
+ meta: {},
177
+ settings: {},
178
+ dependencies: undefined,
179
+ initial_value: null,
180
+ },
181
+ url: {
182
+ kind: 'string',
183
+ key: 'url',
184
+ default: null,
185
+ meta: {},
186
+ settings: {},
187
+ dependencies: undefined,
188
+ initial_value: null,
189
+ },
190
+ },
191
+ dependencies: undefined,
192
+ initial_value: null,
193
+ },
194
+ dynamic: {
195
+ kind: 'plain',
196
+ key: 'dynamic',
197
+ default: null,
198
+ meta: {},
199
+ settings: { categories: [ 'image' ] },
200
+ dependencies: undefined,
201
+ initial_value: null,
202
+ },
203
+ },
204
+ dependencies: undefined,
205
+ initial_value: null,
206
+ },
207
+ size: {
208
+ kind: 'string',
209
+ key: 'string',
210
+ default: null,
211
+ meta: {},
212
+ settings: {},
213
+ dependencies: undefined,
214
+ initial_value: null,
215
+ },
216
+ },
217
+ dependencies: undefined,
218
+ initial_value: null,
219
+ },
53
220
  alignContent: {
54
221
  kind: 'string',
55
222
  key: 'string',