@elementor/editor-canvas 4.2.0-939 → 4.2.0-940

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/dist/index.d.mts CHANGED
@@ -300,6 +300,8 @@ type CreatePropResolverArgs = {
300
300
  onPropResolve?: (args: {
301
301
  key: string;
302
302
  value: unknown;
303
+ propValue: unknown;
304
+ propType: PropType;
303
305
  }) => void;
304
306
  };
305
307
  type ResolveArgs = {
package/dist/index.d.ts CHANGED
@@ -300,6 +300,8 @@ type CreatePropResolverArgs = {
300
300
  onPropResolve?: (args: {
301
301
  key: string;
302
302
  value: unknown;
303
+ propValue: unknown;
304
+ propType: PropType;
303
305
  }) => void;
304
306
  };
305
307
  type ResolveArgs = {
package/dist/index.js CHANGED
@@ -1443,7 +1443,7 @@ function createPropsResolver({ transformers, schema: initialSchema, onPropResolv
1443
1443
  Object.entries(schema2).map(async ([key, type]) => {
1444
1444
  const value = props[key] ?? type.default;
1445
1445
  const transformed = await transform({ value, key, type, signal, renderContext });
1446
- onPropResolve?.({ key, value: transformed });
1446
+ onPropResolve?.({ key, value: transformed, propValue: value, propType: type });
1447
1447
  if (isMultiProps(transformed)) {
1448
1448
  return getMultiPropsValue(transformed);
1449
1449
  }
@@ -1513,6 +1513,27 @@ function createPropsResolver({ transformers, schema: initialSchema, onPropResolv
1513
1513
  return resolve;
1514
1514
  }
1515
1515
 
1516
+ // src/renderers/enqueue-font-from-style-prop.ts
1517
+ var import_editor_props4 = require("@elementor/editor-props");
1518
+ var maybeEnqueueFontFromStyleProp = (propType, propValue, enqueue) => {
1519
+ if (!(0, import_editor_props4.isTransformable)(propValue) || propValue.disabled) {
1520
+ return;
1521
+ }
1522
+ const typeKey = propType.kind === "union" ? propValue.$$type : propType.key;
1523
+ const propTypeUtil = (0, import_editor_props4.getPropSchemaFromCache)(typeKey);
1524
+ if (!propTypeUtil || !("getEnqueueFontFamily" in propTypeUtil) || typeof propTypeUtil.getEnqueueFontFamily !== "function") {
1525
+ return;
1526
+ }
1527
+ const stored = propValue.value;
1528
+ if (typeof stored !== "string") {
1529
+ return;
1530
+ }
1531
+ const font = propTypeUtil.getEnqueueFontFamily(stored);
1532
+ if (font) {
1533
+ enqueue(font);
1534
+ }
1535
+ };
1536
+
1516
1537
  // src/transformers/create-transformers-registry.ts
1517
1538
  function createTransformersRegistry() {
1518
1539
  const transformers = {};
@@ -1545,11 +1566,8 @@ function useStylePropResolver() {
1545
1566
  return createPropsResolver({
1546
1567
  transformers: styleTransformersRegistry,
1547
1568
  schema: (0, import_editor_styles.getStylesSchema)(),
1548
- onPropResolve: ({ key, value }) => {
1549
- if (key !== "font-family" || typeof value !== "string") {
1550
- return;
1551
- }
1552
- (0, import_editor_v1_adapters8.enqueueFont)(value);
1569
+ onPropResolve: ({ propValue, propType }) => {
1570
+ maybeEnqueueFontFromStyleProp(propType, propValue, import_editor_v1_adapters8.enqueueFont);
1553
1571
  }
1554
1572
  });
1555
1573
  }, []);
@@ -2477,6 +2495,18 @@ var flexTransformer = createTransformer((value) => {
2477
2495
  return null;
2478
2496
  });
2479
2497
 
2498
+ // src/transformers/styles/font-family-transformer.ts
2499
+ var fontFamilyTransformer = createTransformer((value) => {
2500
+ if (typeof value !== "string" || !value.trim()) {
2501
+ return null;
2502
+ }
2503
+ const trimmed = value.trim();
2504
+ if (trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("'") && trimmed.endsWith("'")) {
2505
+ return trimmed;
2506
+ }
2507
+ return `"${trimmed}"`;
2508
+ });
2509
+
2480
2510
  // src/transformers/styles/grid-track-renderer.ts
2481
2511
  var GRID_TRACK_PROPERTIES = /* @__PURE__ */ new Set(["grid-template-columns", "grid-template-rows"]);
2482
2512
  var isGridTrackProperty = (cssProperty) => GRID_TRACK_PROPERTIES.has(cssProperty);
@@ -2628,7 +2658,7 @@ var mapToTransitionString = (value, allowedProperties) => {
2628
2658
 
2629
2659
  // src/init-style-transformers.ts
2630
2660
  function initStyleTransformers() {
2631
- styleTransformersRegistry.register("size", sizeTransformer).register("grid-track-size", gridTrackSizeTransformer).register("shadow", shadowTransformer).register("stroke", strokeTransformer).register(
2661
+ styleTransformersRegistry.register("font-family", fontFamilyTransformer).register("size", sizeTransformer).register("grid-track-size", gridTrackSizeTransformer).register("shadow", shadowTransformer).register("stroke", strokeTransformer).register(
2632
2662
  "dimensions",
2633
2663
  createMultiPropsTransformer(
2634
2664
  ["block-start", "block-end", "inline-start", "inline-end"],
@@ -3346,7 +3376,7 @@ var import_client = require("react-dom/client");
3346
3376
  // src/legacy/replacements/inline-editing/inline-editing-elements.tsx
3347
3377
  var React11 = __toESM(require("react"));
3348
3378
  var import_editor_elements9 = require("@elementor/editor-elements");
3349
- var import_editor_props5 = require("@elementor/editor-props");
3379
+ var import_editor_props6 = require("@elementor/editor-props");
3350
3380
  var import_editor_v1_adapters13 = require("@elementor/editor-v1-adapters");
3351
3381
  var import_i18n3 = require("@wordpress/i18n");
3352
3382
 
@@ -3623,11 +3653,11 @@ var InlineEditingToolbar = ({ anchor, editor, id }) => {
3623
3653
  };
3624
3654
 
3625
3655
  // src/legacy/replacements/inline-editing/inline-editing-eligibility.ts
3626
- var import_editor_props4 = require("@elementor/editor-props");
3656
+ var import_editor_props5 = require("@elementor/editor-props");
3627
3657
  var hasKey = (propType) => {
3628
3658
  return "key" in propType;
3629
3659
  };
3630
- var TEXT_PROP_TYPE_KEYS = /* @__PURE__ */ new Set([import_editor_props4.htmlV3PropTypeUtil.key, import_editor_props4.stringPropTypeUtil.key]);
3660
+ var TEXT_PROP_TYPE_KEYS = /* @__PURE__ */ new Set([import_editor_props5.htmlV3PropTypeUtil.key, import_editor_props5.stringPropTypeUtil.key]);
3631
3661
  var isCoreTextPropTypeKey = (key) => {
3632
3662
  return TEXT_PROP_TYPE_KEYS.has(key);
3633
3663
  };
@@ -3647,7 +3677,7 @@ var isInlineEditingAllowed = ({ rawValue, propTypeFromSchema }) => {
3647
3677
  if (rawValue === null || rawValue === void 0) {
3648
3678
  return isAllowedBySchema(propTypeFromSchema);
3649
3679
  }
3650
- return import_editor_props4.htmlV3PropTypeUtil.isValid(rawValue) || import_editor_props4.stringPropTypeUtil.isValid(rawValue);
3680
+ return import_editor_props5.htmlV3PropTypeUtil.isValid(rawValue) || import_editor_props5.stringPropTypeUtil.isValid(rawValue);
3651
3681
  };
3652
3682
 
3653
3683
  // src/legacy/replacements/inline-editing/inline-editing-elements.tsx
@@ -3732,15 +3762,15 @@ var InlineEditingReplacement = class extends ReplacementBase {
3732
3762
  }
3733
3763
  getExtractedContentValue() {
3734
3764
  const propValue = this.getInlineEditablePropValue();
3735
- const extracted = import_editor_props5.htmlV3PropTypeUtil.extract(propValue);
3736
- return import_editor_props5.stringPropTypeUtil.extract(extracted?.content ?? null) ?? "";
3765
+ const extracted = import_editor_props6.htmlV3PropTypeUtil.extract(propValue);
3766
+ return import_editor_props6.stringPropTypeUtil.extract(extracted?.content ?? null) ?? "";
3737
3767
  }
3738
3768
  setContentValue(value) {
3739
3769
  const settingKey = this.getInlineEditablePropertyName();
3740
3770
  const html = value || "";
3741
- const parsed = (0, import_editor_props5.parseHtmlChildren)(html);
3742
- const valueToSave = import_editor_props5.htmlV3PropTypeUtil.create({
3743
- content: parsed.content ? import_editor_props5.stringPropTypeUtil.create(parsed.content) : null,
3771
+ const parsed = (0, import_editor_props6.parseHtmlChildren)(html);
3772
+ const valueToSave = import_editor_props6.htmlV3PropTypeUtil.create({
3773
+ content: parsed.content ? import_editor_props6.stringPropTypeUtil.create(parsed.content) : null,
3744
3774
  children: parsed.children
3745
3775
  });
3746
3776
  (0, import_editor_v1_adapters13.undoable)(
@@ -3771,7 +3801,7 @@ var InlineEditingReplacement = class extends ReplacementBase {
3771
3801
  return null;
3772
3802
  }
3773
3803
  if (propType.kind === "union") {
3774
- const textKeys = [import_editor_props5.htmlV3PropTypeUtil.key, import_editor_props5.stringPropTypeUtil.key];
3804
+ const textKeys = [import_editor_props6.htmlV3PropTypeUtil.key, import_editor_props6.stringPropTypeUtil.key];
3775
3805
  for (const key of textKeys) {
3776
3806
  if (propType.prop_types[key]) {
3777
3807
  return key;
@@ -3800,7 +3830,7 @@ var InlineEditingReplacement = class extends ReplacementBase {
3800
3830
  getExpectedTag() {
3801
3831
  const tagPropType = this.getTagPropType();
3802
3832
  const tagSettingKey = "tag";
3803
- return import_editor_props5.stringPropTypeUtil.extract(this.getSetting(tagSettingKey) ?? null) ?? import_editor_props5.stringPropTypeUtil.extract(tagPropType?.default ?? null) ?? null;
3833
+ return import_editor_props6.stringPropTypeUtil.extract(this.getSetting(tagSettingKey) ?? null) ?? import_editor_props6.stringPropTypeUtil.extract(tagPropType?.default ?? null) ?? null;
3804
3834
  }
3805
3835
  getTagPropType() {
3806
3836
  const propsSchema = (0, import_editor_elements9.getElementType)(this.type)?.propsSchema;
@@ -4027,7 +4057,7 @@ function createNestedTemplatedType(type, renderer, element) {
4027
4057
  }
4028
4058
 
4029
4059
  // src/legacy/tabs-model-extensions.ts
4030
- var import_editor_props6 = require("@elementor/editor-props");
4060
+ var import_editor_props7 = require("@elementor/editor-props");
4031
4061
  var tabModelExtensions = {
4032
4062
  modifyDefaultChildren(elements) {
4033
4063
  if (!Array.isArray(elements) || elements.length === 0) {
@@ -4043,8 +4073,8 @@ var tabModelExtensions = {
4043
4073
  ...paragraphElement,
4044
4074
  settings: {
4045
4075
  ...paragraphElement.settings,
4046
- paragraph: import_editor_props6.htmlV3PropTypeUtil.create({
4047
- content: import_editor_props6.stringPropTypeUtil.create(`Tab ${position}`),
4076
+ paragraph: import_editor_props7.htmlV3PropTypeUtil.create({
4077
+ content: import_editor_props7.stringPropTypeUtil.create(`Tab ${position}`),
4048
4078
  children: []
4049
4079
  })
4050
4080
  }
@@ -4057,7 +4087,7 @@ function initTabsModelExtensions() {
4057
4087
  }
4058
4088
 
4059
4089
  // src/mcp/canvas-mcp.ts
4060
- var import_editor_props11 = require("@elementor/editor-props");
4090
+ var import_editor_props12 = require("@elementor/editor-props");
4061
4091
 
4062
4092
  // src/mcp/resources/available-widgets-resource.ts
4063
4093
  var import_editor_v1_adapters15 = require("@elementor/editor-v1-adapters");
@@ -4209,7 +4239,7 @@ function extractElementData(element) {
4209
4239
  }
4210
4240
 
4211
4241
  // src/mcp/resources/dynamic-tags-resource.ts
4212
- var import_editor_props7 = require("@elementor/editor-props");
4242
+ var import_editor_props8 = require("@elementor/editor-props");
4213
4243
 
4214
4244
  // src/mcp/utils/resolve-dynamic-tag.ts
4215
4245
  var import_editor_v1_adapters17 = require("@elementor/editor-v1-adapters");
@@ -4277,7 +4307,7 @@ var defaultSettingValue = (propType) => {
4277
4307
  var DYNAMIC_TAGS_URI = "elementor://dynamic-tags";
4278
4308
  var settingsSchema = (propsSchema) => {
4279
4309
  return Object.fromEntries(
4280
- Object.entries(propsSchema ?? {}).filter(([key]) => !OMITTED_DYNAMIC_SETTING_KEYS.includes(key)).map(([key, propType]) => [key, import_editor_props7.Schema.propTypeToJsonSchema(propType)])
4310
+ Object.entries(propsSchema ?? {}).filter(([key]) => !OMITTED_DYNAMIC_SETTING_KEYS.includes(key)).map(([key, propType]) => [key, import_editor_props8.Schema.propTypeToJsonSchema(propType)])
4281
4311
  );
4282
4312
  };
4283
4313
  var buildDynamicTagsList = () => {
@@ -4633,7 +4663,7 @@ var import_editor_elements15 = require("@elementor/editor-elements");
4633
4663
 
4634
4664
  // src/mcp/utils/do-update-element-property.ts
4635
4665
  var import_editor_elements14 = require("@elementor/editor-elements");
4636
- var import_editor_props8 = require("@elementor/editor-props");
4666
+ var import_editor_props9 = require("@elementor/editor-props");
4637
4667
  var import_editor_styles4 = require("@elementor/editor-styles");
4638
4668
  var import_editor_v1_adapters21 = require("@elementor/editor-v1-adapters");
4639
4669
 
@@ -4710,7 +4740,7 @@ var LOCAL_STYLE_META = {
4710
4740
  };
4711
4741
  function resolvePropValue(value, forceKey) {
4712
4742
  const Utils = window.elementorV2.editorVariables.Utils;
4713
- return import_editor_props8.Schema.adjustLlmPropValueSchema(value, {
4743
+ return import_editor_props9.Schema.adjustLlmPropValueSchema(value, {
4714
4744
  forceKey,
4715
4745
  transformers: {
4716
4746
  ...Utils.globalVariablesLLMResolvers,
@@ -4769,7 +4799,7 @@ var doUpdateElementProperty = (params) => {
4769
4799
  }
4770
4800
  if (propertyRawSchema.kind === "plain") {
4771
4801
  if (typeof propertyMapValue[stylePropName] !== "object") {
4772
- const propUtil = (0, import_editor_props8.getPropSchemaFromCache)(propertyRawSchema.key);
4802
+ const propUtil = (0, import_editor_props9.getPropSchemaFromCache)(propertyRawSchema.key);
4773
4803
  if (propUtil) {
4774
4804
  const plainValue = propUtil.create(propertyMapValue[stylePropName]);
4775
4805
  propertyMapValue[stylePropName] = plainValue;
@@ -4822,7 +4852,7 @@ var doUpdateElementProperty = (params) => {
4822
4852
  }
4823
4853
  const propKey = elementPropSchema[propertyName].key;
4824
4854
  const value = resolvePropValue(propertyValue, propKey);
4825
- const { valid, jsonSchema } = import_editor_props8.Schema.validatePropValue(elementPropSchema[propertyName], propertyValue);
4855
+ const { valid, jsonSchema } = import_editor_props9.Schema.validatePropValue(elementPropSchema[propertyName], propertyValue);
4826
4856
  if (!valid) {
4827
4857
  throw new Error(
4828
4858
  `Invalid PropValue for elementId: ${elementId}. PropKey: ${propKey}, PropValue: ${JSON.stringify(
@@ -5531,7 +5561,7 @@ var import_editor_elements18 = require("@elementor/editor-elements");
5531
5561
 
5532
5562
  // src/mcp/utils/validate-input.ts
5533
5563
  var import_editor_elements17 = require("@elementor/editor-elements");
5534
- var import_editor_props9 = require("@elementor/editor-props");
5564
+ var import_editor_props10 = require("@elementor/editor-props");
5535
5565
  var import_editor_styles5 = require("@elementor/editor-styles");
5536
5566
  var _widgetsSchema = null;
5537
5567
  var validateInput = {
@@ -5565,10 +5595,10 @@ var validateInput = {
5565
5595
  if (!propSchema) {
5566
5596
  errors.push(`Property "${propName}" is not defined in the schema.`);
5567
5597
  hasInvalidKey = true;
5568
- } else if (!import_editor_props9.Schema.isPropKeyConfigurable(propName, propSchema)) {
5598
+ } else if (!import_editor_props10.Schema.isPropKeyConfigurable(propName, propSchema)) {
5569
5599
  errors.push(`Property "${propName}" is not configurable.`);
5570
5600
  } else {
5571
- const { valid } = import_editor_props9.Schema.validatePropValue(propSchema, propValue);
5601
+ const { valid } = import_editor_props10.Schema.validatePropValue(propSchema, propValue);
5572
5602
  if (!valid) {
5573
5603
  errors.push(
5574
5604
  `Invalid property "${propName}". Validate input with resource [${STYLE_SCHEMA_URI.replace(
@@ -5881,7 +5911,7 @@ Provide styling as raw CSS via the "style" parameter (a flat map of CSS property
5881
5911
 
5882
5912
  // src/mcp/tools/get-element-config/tool.ts
5883
5913
  var import_editor_elements19 = require("@elementor/editor-elements");
5884
- var import_editor_props10 = require("@elementor/editor-props");
5914
+ var import_editor_props11 = require("@elementor/editor-props");
5885
5915
  var import_schema5 = require("@elementor/schema");
5886
5916
  var schema = {
5887
5917
  elementId: import_schema5.z.string()
@@ -5938,7 +5968,7 @@ var initGetElementConfigTool = (reg) => {
5938
5968
  }
5939
5969
  const propValues = {};
5940
5970
  const stylePropValues = {};
5941
- import_editor_props10.Schema.configurableKeys(propSchema).forEach((key) => {
5971
+ import_editor_props11.Schema.configurableKeys(propSchema).forEach((key) => {
5942
5972
  propValues[key] = structuredClone(elementRawSettings.get(key));
5943
5973
  });
5944
5974
  const elementStyles = (0, import_editor_elements19.getElementStyles)(elementId) || {};
@@ -5974,7 +6004,7 @@ var initGetElementConfigTool = (reg) => {
5974
6004
 
5975
6005
  // src/mcp/canvas-mcp.ts
5976
6006
  var initCanvasMcp = (reg) => {
5977
- import_editor_props11.Schema.setDynamicTagNamesResolver(getDynamicTagNamesByCategories);
6007
+ import_editor_props12.Schema.setDynamicTagNamesResolver(getDynamicTagNamesByCategories);
5978
6008
  initWidgetsSchemaResource(reg);
5979
6009
  initAvailableWidgetsResource(reg);
5980
6010
  initDocumentStructureResource(reg);
@@ -6181,12 +6211,12 @@ function shouldBlock(sourceElements, targetElements) {
6181
6211
 
6182
6212
  // src/style-commands/paste-style.ts
6183
6213
  var import_editor_elements23 = require("@elementor/editor-elements");
6184
- var import_editor_props13 = require("@elementor/editor-props");
6214
+ var import_editor_props14 = require("@elementor/editor-props");
6185
6215
  var import_editor_v1_adapters24 = require("@elementor/editor-v1-adapters");
6186
6216
 
6187
6217
  // src/utils/command-utils.ts
6188
6218
  var import_editor_elements21 = require("@elementor/editor-elements");
6189
- var import_editor_props12 = require("@elementor/editor-props");
6219
+ var import_editor_props13 = require("@elementor/editor-props");
6190
6220
  var import_i18n5 = require("@wordpress/i18n");
6191
6221
  function hasAtomicWidgets(args) {
6192
6222
  const { containers = [args.container] } = args;
@@ -6204,7 +6234,7 @@ function getClassesProp(container) {
6204
6234
  return null;
6205
6235
  }
6206
6236
  const [propKey] = Object.entries(propsSchema).find(
6207
- ([, propType]) => propType.kind === "plain" && propType.key === import_editor_props12.CLASSES_PROP_KEY
6237
+ ([, propType]) => propType.kind === "plain" && propType.key === import_editor_props13.CLASSES_PROP_KEY
6208
6238
  ) ?? [];
6209
6239
  return propKey ?? null;
6210
6240
  }
@@ -6353,8 +6383,8 @@ function pasteClasses(containers, classes) {
6353
6383
  return;
6354
6384
  }
6355
6385
  const classesSetting = (0, import_editor_elements23.getElementSetting)(container.id, classesProp);
6356
- const currentClasses = import_editor_props13.classesPropTypeUtil.extract(classesSetting) ?? [];
6357
- const newClasses = import_editor_props13.classesPropTypeUtil.create(Array.from(/* @__PURE__ */ new Set([...classes, ...currentClasses])));
6386
+ const currentClasses = import_editor_props14.classesPropTypeUtil.extract(classesSetting) ?? [];
6387
+ const newClasses = import_editor_props14.classesPropTypeUtil.create(Array.from(/* @__PURE__ */ new Set([...classes, ...currentClasses])));
6358
6388
  (0, import_editor_elements23.updateElementSettings)({
6359
6389
  id: container.id,
6360
6390
  props: { [classesProp]: newClasses }
package/dist/index.mjs CHANGED
@@ -1396,7 +1396,7 @@ function createPropsResolver({ transformers, schema: initialSchema, onPropResolv
1396
1396
  Object.entries(schema2).map(async ([key, type]) => {
1397
1397
  const value = props[key] ?? type.default;
1398
1398
  const transformed = await transform({ value, key, type, signal, renderContext });
1399
- onPropResolve?.({ key, value: transformed });
1399
+ onPropResolve?.({ key, value: transformed, propValue: value, propType: type });
1400
1400
  if (isMultiProps(transformed)) {
1401
1401
  return getMultiPropsValue(transformed);
1402
1402
  }
@@ -1466,6 +1466,27 @@ function createPropsResolver({ transformers, schema: initialSchema, onPropResolv
1466
1466
  return resolve;
1467
1467
  }
1468
1468
 
1469
+ // src/renderers/enqueue-font-from-style-prop.ts
1470
+ import { getPropSchemaFromCache, isTransformable as isTransformable2 } from "@elementor/editor-props";
1471
+ var maybeEnqueueFontFromStyleProp = (propType, propValue, enqueue) => {
1472
+ if (!isTransformable2(propValue) || propValue.disabled) {
1473
+ return;
1474
+ }
1475
+ const typeKey = propType.kind === "union" ? propValue.$$type : propType.key;
1476
+ const propTypeUtil = getPropSchemaFromCache(typeKey);
1477
+ if (!propTypeUtil || !("getEnqueueFontFamily" in propTypeUtil) || typeof propTypeUtil.getEnqueueFontFamily !== "function") {
1478
+ return;
1479
+ }
1480
+ const stored = propValue.value;
1481
+ if (typeof stored !== "string") {
1482
+ return;
1483
+ }
1484
+ const font = propTypeUtil.getEnqueueFontFamily(stored);
1485
+ if (font) {
1486
+ enqueue(font);
1487
+ }
1488
+ };
1489
+
1469
1490
  // src/transformers/create-transformers-registry.ts
1470
1491
  function createTransformersRegistry() {
1471
1492
  const transformers = {};
@@ -1498,11 +1519,8 @@ function useStylePropResolver() {
1498
1519
  return createPropsResolver({
1499
1520
  transformers: styleTransformersRegistry,
1500
1521
  schema: getStylesSchema(),
1501
- onPropResolve: ({ key, value }) => {
1502
- if (key !== "font-family" || typeof value !== "string") {
1503
- return;
1504
- }
1505
- enqueueFont(value);
1522
+ onPropResolve: ({ propValue, propType }) => {
1523
+ maybeEnqueueFontFromStyleProp(propType, propValue, enqueueFont);
1506
1524
  }
1507
1525
  });
1508
1526
  }, []);
@@ -2432,6 +2450,18 @@ var flexTransformer = createTransformer((value) => {
2432
2450
  return null;
2433
2451
  });
2434
2452
 
2453
+ // src/transformers/styles/font-family-transformer.ts
2454
+ var fontFamilyTransformer = createTransformer((value) => {
2455
+ if (typeof value !== "string" || !value.trim()) {
2456
+ return null;
2457
+ }
2458
+ const trimmed = value.trim();
2459
+ if (trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("'") && trimmed.endsWith("'")) {
2460
+ return trimmed;
2461
+ }
2462
+ return `"${trimmed}"`;
2463
+ });
2464
+
2435
2465
  // src/transformers/styles/grid-track-renderer.ts
2436
2466
  var GRID_TRACK_PROPERTIES = /* @__PURE__ */ new Set(["grid-template-columns", "grid-template-rows"]);
2437
2467
  var isGridTrackProperty = (cssProperty) => GRID_TRACK_PROPERTIES.has(cssProperty);
@@ -2583,7 +2613,7 @@ var mapToTransitionString = (value, allowedProperties) => {
2583
2613
 
2584
2614
  // src/init-style-transformers.ts
2585
2615
  function initStyleTransformers() {
2586
- styleTransformersRegistry.register("size", sizeTransformer).register("grid-track-size", gridTrackSizeTransformer).register("shadow", shadowTransformer).register("stroke", strokeTransformer).register(
2616
+ styleTransformersRegistry.register("font-family", fontFamilyTransformer).register("size", sizeTransformer).register("grid-track-size", gridTrackSizeTransformer).register("shadow", shadowTransformer).register("stroke", strokeTransformer).register(
2587
2617
  "dimensions",
2588
2618
  createMultiPropsTransformer(
2589
2619
  ["block-start", "block-end", "inline-start", "inline-end"],
@@ -4619,7 +4649,7 @@ import {
4619
4649
  updateElementSettings,
4620
4650
  updateElementStyle
4621
4651
  } from "@elementor/editor-elements";
4622
- import { getPropSchemaFromCache, Schema as Schema3 } from "@elementor/editor-props";
4652
+ import { getPropSchemaFromCache as getPropSchemaFromCache2, Schema as Schema3 } from "@elementor/editor-props";
4623
4653
  import { getStylesSchema as getStylesSchema2, getVariantByMeta } from "@elementor/editor-styles";
4624
4654
  import { __privateRunCommandSync as runCommandSync2 } from "@elementor/editor-v1-adapters";
4625
4655
 
@@ -4755,7 +4785,7 @@ var doUpdateElementProperty = (params) => {
4755
4785
  }
4756
4786
  if (propertyRawSchema.kind === "plain") {
4757
4787
  if (typeof propertyMapValue[stylePropName] !== "object") {
4758
- const propUtil = getPropSchemaFromCache(propertyRawSchema.key);
4788
+ const propUtil = getPropSchemaFromCache2(propertyRawSchema.key);
4759
4789
  if (propUtil) {
4760
4790
  const plainValue = propUtil.create(propertyMapValue[stylePropName]);
4761
4791
  propertyMapValue[stylePropName] = plainValue;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@elementor/editor-canvas",
3
3
  "description": "Elementor Editor Canvas",
4
- "version": "4.2.0-939",
4
+ "version": "4.2.0-940",
5
5
  "private": false,
6
6
  "author": "Elementor Team",
7
7
  "homepage": "https://elementor.com/",
@@ -37,26 +37,26 @@
37
37
  "react-dom": "^18.3.1"
38
38
  },
39
39
  "dependencies": {
40
- "@elementor/editor": "4.2.0-939",
40
+ "@elementor/editor": "4.2.0-940",
41
41
  "dompurify": "^3.2.6",
42
- "@elementor/editor-controls": "4.2.0-939",
43
- "@elementor/editor-documents": "4.2.0-939",
44
- "@elementor/editor-elements": "4.2.0-939",
45
- "@elementor/editor-interactions": "4.2.0-939",
46
- "@elementor/editor-mcp": "4.2.0-939",
47
- "@elementor/editor-notifications": "4.2.0-939",
48
- "@elementor/editor-props": "4.2.0-939",
49
- "@elementor/editor-responsive": "4.2.0-939",
50
- "@elementor/editor-styles": "4.2.0-939",
51
- "@elementor/editor-styles-repository": "4.2.0-939",
52
- "@elementor/editor-ui": "4.2.0-939",
53
- "@elementor/editor-v1-adapters": "4.2.0-939",
54
- "@elementor/http-client": "4.2.0-939",
55
- "@elementor/schema": "4.2.0-939",
56
- "@elementor/twing": "4.2.0-939",
42
+ "@elementor/editor-controls": "4.2.0-940",
43
+ "@elementor/editor-documents": "4.2.0-940",
44
+ "@elementor/editor-elements": "4.2.0-940",
45
+ "@elementor/editor-interactions": "4.2.0-940",
46
+ "@elementor/editor-mcp": "4.2.0-940",
47
+ "@elementor/editor-notifications": "4.2.0-940",
48
+ "@elementor/editor-props": "4.2.0-940",
49
+ "@elementor/editor-responsive": "4.2.0-940",
50
+ "@elementor/editor-styles": "4.2.0-940",
51
+ "@elementor/editor-styles-repository": "4.2.0-940",
52
+ "@elementor/editor-ui": "4.2.0-940",
53
+ "@elementor/editor-v1-adapters": "4.2.0-940",
54
+ "@elementor/http-client": "4.2.0-940",
55
+ "@elementor/schema": "4.2.0-940",
56
+ "@elementor/twing": "4.2.0-940",
57
57
  "@elementor/ui": "1.37.5",
58
- "@elementor/utils": "4.2.0-939",
59
- "@elementor/wp-media": "4.2.0-939",
58
+ "@elementor/utils": "4.2.0-940",
59
+ "@elementor/wp-media": "4.2.0-940",
60
60
  "@floating-ui/react": "^0.27.5",
61
61
  "@wordpress/i18n": "^5.13.0"
62
62
  },
@@ -1,51 +1,60 @@
1
1
  import { createMockPropType } from 'test-utils';
2
- import { stringPropTypeUtil } from '@elementor/editor-props';
2
+ import { fontFamilyPropTypeUtil } from '@elementor/editor-props';
3
+ import { type BreakpointsMap } from '@elementor/editor-responsive';
3
4
  import { getStylesSchema } from '@elementor/editor-styles';
4
5
  import { enqueueFont } from '@elementor/editor-v1-adapters';
5
- import { act, renderHook } from '@testing-library/react';
6
+ import { renderHook } from '@testing-library/react';
6
7
 
7
8
  import { initStyleTransformers } from '../../init-style-transformers';
9
+ import { createStylesRenderer } from '../../renderers/create-styles-renderer';
8
10
  import { useStylePropResolver } from '../use-style-prop-resolver';
9
11
 
10
12
  jest.mock( '@elementor/editor-v1-adapters' );
11
- jest.mock( '@elementor/editor-styles' );
13
+ jest.mock( '@elementor/editor-styles', () => ( {
14
+ ...jest.requireActual( '@elementor/editor-styles' ),
15
+ getStylesSchema: jest.fn(),
16
+ } ) );
12
17
 
13
18
  describe( 'useStylePropResolver', () => {
14
- it( 'should call enqueueFont with the correct value when font-family is resolved', async () => {
19
+ it( 'should enqueue fonts from stored props when rendering styles', async () => {
15
20
  // Arrange.
16
21
  initStyleTransformers();
17
22
 
18
23
  jest.mocked( getStylesSchema ).mockReturnValue( {
19
- 'font-family': createMockPropType( { key: 'string', kind: 'plain' } ),
20
- 'another-prop': createMockPropType( { key: 'string', kind: 'plain' } ),
24
+ 'font-family': createMockPropType( { key: 'font-family', kind: 'plain' } ),
25
+ color: createMockPropType( { key: 'string', kind: 'plain' } ),
21
26
  } );
22
27
 
23
28
  const { result } = renderHook( useStylePropResolver );
24
29
 
25
- // Act.
26
- const resolve = result.current;
27
-
28
- await act( () =>
29
- resolve( {
30
- props: {
31
- 'another-prop': stringPropTypeUtil.create( 'value' ),
32
- },
33
- } )
34
- );
35
-
36
- // Assert.
37
- expect( enqueueFont ).not.toHaveBeenCalled();
30
+ const view = createStylesRenderer( {
31
+ resolve: result.current,
32
+ breakpoints: {} as BreakpointsMap,
33
+ } );
38
34
 
39
35
  // Act.
40
- await act( () =>
41
- resolve( {
42
- props: {
43
- 'font-family': stringPropTypeUtil.create( 'arial' ),
36
+ await view( {
37
+ styles: [
38
+ {
39
+ id: 'test-style',
40
+ type: 'class',
41
+ cssName: 'test-style',
42
+ label: 'Test style',
43
+ variants: [
44
+ {
45
+ meta: { breakpoint: null, state: null },
46
+ props: {
47
+ 'font-family': fontFamilyPropTypeUtil.create( 'Open Sans' ),
48
+ },
49
+ custom_css: null,
50
+ },
51
+ ],
44
52
  },
45
- } )
46
- );
53
+ ],
54
+ } );
47
55
 
48
56
  // Assert.
49
- expect( enqueueFont ).toHaveBeenCalledWith( 'arial' );
57
+ expect( enqueueFont ).toHaveBeenCalledWith( 'Open Sans' );
58
+ expect( enqueueFont ).toHaveBeenCalledTimes( 1 );
50
59
  } );
51
60
  } );
@@ -3,6 +3,7 @@ import { getStylesSchema } from '@elementor/editor-styles';
3
3
  import { enqueueFont } from '@elementor/editor-v1-adapters';
4
4
 
5
5
  import { createPropsResolver } from '../renderers/create-props-resolver';
6
+ import { maybeEnqueueFontFromStyleProp } from '../renderers/enqueue-font-from-style-prop';
6
7
  import { styleTransformersRegistry } from '../style-transformers-registry';
7
8
 
8
9
  export function useStylePropResolver() {
@@ -10,12 +11,8 @@ export function useStylePropResolver() {
10
11
  return createPropsResolver( {
11
12
  transformers: styleTransformersRegistry,
12
13
  schema: getStylesSchema(),
13
- onPropResolve: ( { key, value } ) => {
14
- if ( key !== 'font-family' || typeof value !== 'string' ) {
15
- return;
16
- }
17
-
18
- enqueueFont( value );
14
+ onPropResolve: ( { propValue, propType } ) => {
15
+ maybeEnqueueFontFromStyleProp( propType, propValue, enqueueFont );
19
16
  },
20
17
  } );
21
18
  }, [] );
@@ -13,6 +13,7 @@ import { createCombineArrayTransformer } from './transformers/styles/create-comb
13
13
  import { createMultiPropsTransformer } from './transformers/styles/create-multi-props-transformer';
14
14
  import { filterTransformer } from './transformers/styles/filter-transformer';
15
15
  import { flexTransformer } from './transformers/styles/flex-transformer';
16
+ import { fontFamilyTransformer } from './transformers/styles/font-family-transformer';
16
17
  import { gridTrackSizeTransformer } from './transformers/styles/grid-track-size-transformer';
17
18
  import { perspectiveOriginTransformer } from './transformers/styles/perspective-origin-transformer';
18
19
  import { positionTransformer } from './transformers/styles/position-transformer';
@@ -30,6 +31,7 @@ import { transitionTransformer } from './transformers/styles/transition-transfor
30
31
 
31
32
  export function initStyleTransformers() {
32
33
  styleTransformersRegistry
34
+ .register( 'font-family', fontFamilyTransformer )
33
35
  .register( 'size', sizeTransformer )
34
36
  .register( 'grid-track-size', gridTrackSizeTransformer )
35
37
  .register( 'shadow', shadowTransformer )
@@ -287,8 +287,18 @@ describe( 'createPropsResolver', () => {
287
287
 
288
288
  // Assert.
289
289
  expect( onResolve ).toHaveBeenCalledTimes( 2 );
290
- expect( onResolve ).toHaveBeenNthCalledWith( 1, { key: 'int', value: 2 } );
291
- expect( onResolve ).toHaveBeenNthCalledWith( 2, { key: 'int2', value: 4 } );
290
+ expect( onResolve ).toHaveBeenNthCalledWith( 1, {
291
+ key: 'int',
292
+ value: 2,
293
+ propValue: { $$type: 'int', value: 1 },
294
+ propType: createMockPropType( { kind: 'plain', key: 'int' } ),
295
+ } );
296
+ expect( onResolve ).toHaveBeenNthCalledWith( 2, {
297
+ key: 'int2',
298
+ value: 4,
299
+ propValue: { $$type: 'int', value: 3 },
300
+ propType: createMockPropType( { kind: 'plain', key: 'int' } ),
301
+ } );
292
302
  } );
293
303
 
294
304
  it( 'should pass renderContext to transformers', async () => {
@@ -79,6 +79,36 @@ describe( 'renderStyles', () => {
79
79
  expect( resolve ).toHaveBeenNthCalledWith( 5, { props: { 'font-size': '50px' } } );
80
80
  } );
81
81
 
82
+ it.each( [
83
+ [ '"Open Sans"', 'font-family:"Open Sans";' ],
84
+ [ 'Arial', 'font-family:Arial;' ],
85
+ [ 'var(--primary-font)', 'font-family:var(--primary-font);' ],
86
+ ] )( 'should pass through font-family "%s" as-is in CSS output', async ( fontFamily, expected ) => {
87
+ // Arrange.
88
+ const styleDef: RendererStyleDefinition = {
89
+ id: 'test',
90
+ type: 'class',
91
+ cssName: 'test',
92
+ label: 'Test',
93
+ variants: [
94
+ {
95
+ meta: { breakpoint: null, state: null },
96
+ props: { 'font-family': fontFamily },
97
+ custom_css: null,
98
+ },
99
+ ],
100
+ };
101
+
102
+ const resolve = jest.fn( ( { props } ) => props );
103
+ const renderStyles = createStylesRenderer( { breakpoints: {} as BreakpointsMap, resolve } );
104
+
105
+ // Act.
106
+ const result = await renderStyles( { styles: [ styleDef ] } );
107
+
108
+ // Assert.
109
+ expect( result[ 0 ].value ).toContain( expected );
110
+ } );
111
+
82
112
  it( 'should add selector prefix to the output', async () => {
83
113
  // Arrange.
84
114
  const styleDef: RendererStyleDefinition = {
@@ -0,0 +1,29 @@
1
+ import { createMockPropType } from 'test-utils';
2
+ import { fontFamilyPropTypeUtil } from '@elementor/editor-props';
3
+ import { enqueueFont } from '@elementor/editor-v1-adapters';
4
+
5
+ import { maybeEnqueueFontFromStyleProp } from '../enqueue-font-from-style-prop';
6
+
7
+ jest.mock( '@elementor/editor-v1-adapters' );
8
+
9
+ describe( 'maybeEnqueueFontFromStyleProp', () => {
10
+ it( 'should enqueue when prop type implements getEnqueueFontFamily', () => {
11
+ maybeEnqueueFontFromStyleProp(
12
+ createMockPropType( { key: 'font-family', kind: 'plain' } ),
13
+ fontFamilyPropTypeUtil.create( 'Open Sans' ),
14
+ enqueueFont
15
+ );
16
+
17
+ expect( enqueueFont ).toHaveBeenCalledWith( 'Open Sans' );
18
+ } );
19
+
20
+ it( 'should not enqueue when prop type does not implement font enqueue', () => {
21
+ maybeEnqueueFontFromStyleProp(
22
+ createMockPropType( { key: 'string', kind: 'plain' } ),
23
+ { $$type: 'string', value: 'red' },
24
+ enqueueFont
25
+ );
26
+
27
+ expect( enqueueFont ).not.toHaveBeenCalled();
28
+ } );
29
+ } );
@@ -15,7 +15,7 @@ import { getMultiPropsValue, isMultiProps } from './multi-props';
15
15
  type CreatePropResolverArgs = {
16
16
  transformers: TransformersRegistry;
17
17
  schema: PropsSchema;
18
- onPropResolve?: ( args: { key: string; value: unknown } ) => void;
18
+ onPropResolve?: ( args: { key: string; value: unknown; propValue: unknown; propType: PropType } ) => void;
19
19
  };
20
20
 
21
21
  type ResolveArgs = {
@@ -48,7 +48,7 @@ export function createPropsResolver( { transformers, schema: initialSchema, onPr
48
48
  const value = props[ key ] ?? type.default;
49
49
  const transformed = ( await transform( { value, key, type, signal, renderContext } ) ) as PropValue;
50
50
 
51
- onPropResolve?.( { key, value: transformed } );
51
+ onPropResolve?.( { key, value: transformed, propValue: value, propType: type } );
52
52
 
53
53
  if ( isMultiProps( transformed ) ) {
54
54
  return getMultiPropsValue( transformed );
@@ -1,4 +1,4 @@
1
- import type { Props } from '@elementor/editor-props';
1
+ import { type Props } from '@elementor/editor-props';
2
2
  import { type Breakpoint, type BreakpointsMap } from '@elementor/editor-responsive';
3
3
  import {
4
4
  type CustomCss,
@@ -0,0 +1,34 @@
1
+ import { getPropSchemaFromCache, isTransformable, type PropType } from '@elementor/editor-props';
2
+
3
+ export const maybeEnqueueFontFromStyleProp = (
4
+ propType: PropType,
5
+ propValue: unknown,
6
+ enqueue: ( font: string ) => void
7
+ ): void => {
8
+ if ( ! isTransformable( propValue ) || propValue.disabled ) {
9
+ return;
10
+ }
11
+
12
+ const typeKey = propType.kind === 'union' ? propValue.$$type : propType.key;
13
+ const propTypeUtil = getPropSchemaFromCache( typeKey );
14
+
15
+ if (
16
+ ! propTypeUtil ||
17
+ ! ( 'getEnqueueFontFamily' in propTypeUtil ) ||
18
+ typeof propTypeUtil.getEnqueueFontFamily !== 'function'
19
+ ) {
20
+ return;
21
+ }
22
+
23
+ const stored = propValue.value;
24
+
25
+ if ( typeof stored !== 'string' ) {
26
+ return;
27
+ }
28
+
29
+ const font = propTypeUtil.getEnqueueFontFamily( stored );
30
+
31
+ if ( font ) {
32
+ enqueue( font );
33
+ }
34
+ };
@@ -0,0 +1,20 @@
1
+ import { fontFamilyTransformer } from '../font-family-transformer';
2
+
3
+ function run( value: string | null ) {
4
+ return fontFamilyTransformer( value, { key: 'font-family', signal: undefined } );
5
+ }
6
+
7
+ describe( 'fontFamilyTransformer', () => {
8
+ it( 'wraps font names in quotes', () => {
9
+ expect( run( ' Open Sans ' ) ).toBe( '"Open Sans"' );
10
+ expect( run( 'Arial' ) ).toBe( '"Arial"' );
11
+ } );
12
+
13
+ it( 'passes through already quoted values', () => {
14
+ expect( run( '"Open Sans"' ) ).toBe( '"Open Sans"' );
15
+ } );
16
+
17
+ it( 'returns null for non-string values', () => {
18
+ expect( run( null ) ).toBeNull();
19
+ } );
20
+ } );
@@ -0,0 +1,18 @@
1
+ import { createTransformer } from '../create-transformer';
2
+
3
+ export const fontFamilyTransformer = createTransformer( ( value: string | null ) => {
4
+ if ( typeof value !== 'string' || ! value.trim() ) {
5
+ return null;
6
+ }
7
+
8
+ const trimmed = value.trim();
9
+
10
+ if (
11
+ ( trimmed.startsWith( '"' ) && trimmed.endsWith( '"' ) ) ||
12
+ ( trimmed.startsWith( "'" ) && trimmed.endsWith( "'" ) )
13
+ ) {
14
+ return trimmed;
15
+ }
16
+
17
+ return `"${ trimmed }"`;
18
+ } );