@elementor/editor-canvas 4.4.0-1135 → 4.4.0-1137
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.js +114 -83
- package/dist/index.mjs +61 -31
- package/package.json +20 -20
- package/src/form-structure/__tests__/form-structure-utils.test.ts +10 -0
- package/src/form-structure/__tests__/hidden-field-hint.test.ts +137 -0
- package/src/form-structure/hidden-field-hint.ts +29 -0
- package/src/form-structure/utils.ts +2 -0
- package/src/init.tsx +2 -0
- package/src/mcp/utils/convert-css-to-atomic.ts +3 -1
- package/src/transformers/shared/__tests__/icon-transformer.test.ts +65 -15
- package/src/transformers/shared/__tests__/svg-src-transformer.test.ts +12 -3
- package/src/transformers/shared/icon-transformer.ts +15 -10
package/dist/index.js
CHANGED
|
@@ -187,7 +187,9 @@ var SINGLE_BLOCK_KEY = "default";
|
|
|
187
187
|
var convertBlocks = async (blocks) => {
|
|
188
188
|
const { data } = await (0, import_http_client2.httpService)().post(
|
|
189
189
|
CSS_TO_ATOMIC_URL,
|
|
190
|
-
{
|
|
190
|
+
{
|
|
191
|
+
blocks
|
|
192
|
+
}
|
|
191
193
|
);
|
|
192
194
|
return data.data;
|
|
193
195
|
};
|
|
@@ -1795,6 +1797,7 @@ var import_i18n = require("@wordpress/i18n");
|
|
|
1795
1797
|
// src/form-structure/utils.ts
|
|
1796
1798
|
var import_editor_elements4 = require("@elementor/editor-elements");
|
|
1797
1799
|
var FORM_ELEMENT_TYPE = "e-form";
|
|
1800
|
+
var FORM_HIDDEN_FIELD_ELEMENT_TYPE = "e-form-hidden";
|
|
1798
1801
|
var FORM_FIELD_ELEMENT_TYPES = /* @__PURE__ */ new Set([
|
|
1799
1802
|
"e-form-input",
|
|
1800
1803
|
"e-form-textarea",
|
|
@@ -1805,7 +1808,8 @@ var FORM_FIELD_ELEMENT_TYPES = /* @__PURE__ */ new Set([
|
|
|
1805
1808
|
"e-form-radio-button",
|
|
1806
1809
|
"e-form-file-upload",
|
|
1807
1810
|
"e-form-date-picker",
|
|
1808
|
-
"e-form-time-picker"
|
|
1811
|
+
"e-form-time-picker",
|
|
1812
|
+
FORM_HIDDEN_FIELD_ELEMENT_TYPE
|
|
1809
1813
|
]);
|
|
1810
1814
|
function getArgsElementType(args) {
|
|
1811
1815
|
return args.model?.widgetType || args.model?.elType;
|
|
@@ -1922,25 +1926,49 @@ function handleBlockedFormField() {
|
|
|
1922
1926
|
(0, import_editor_notifications.notify)(FORM_FIELDS_OUTSIDE_ALERT);
|
|
1923
1927
|
}
|
|
1924
1928
|
|
|
1925
|
-
// src/form-structure/
|
|
1929
|
+
// src/form-structure/hidden-field-hint.ts
|
|
1926
1930
|
var import_editor_notifications2 = require("@elementor/editor-notifications");
|
|
1927
1931
|
var import_editor_v1_adapters12 = require("@elementor/editor-v1-adapters");
|
|
1928
1932
|
var import_i18n2 = require("@wordpress/i18n");
|
|
1933
|
+
var MOVE_COMMAND = "document/elements/move";
|
|
1934
|
+
var notificationCounter = 0;
|
|
1935
|
+
function createHiddenFieldNotification() {
|
|
1936
|
+
return {
|
|
1937
|
+
type: "default",
|
|
1938
|
+
message: (0, import_i18n2.__)("Hidden field added - invisible on your form. Manage it in the Structure panel.", "elementor"),
|
|
1939
|
+
id: `hidden-field-added-${++notificationCounter}`
|
|
1940
|
+
};
|
|
1941
|
+
}
|
|
1942
|
+
function initHiddenFieldHint() {
|
|
1943
|
+
(0, import_editor_v1_adapters12.registerDataHook)("after", "document/elements/create", (args, _result, options) => {
|
|
1944
|
+
if (options?.commandsCurrentTrace?.includes(MOVE_COMMAND)) {
|
|
1945
|
+
return;
|
|
1946
|
+
}
|
|
1947
|
+
if (getArgsElementType(args) === FORM_HIDDEN_FIELD_ELEMENT_TYPE) {
|
|
1948
|
+
(0, import_editor_notifications2.notify)(createHiddenFieldNotification());
|
|
1949
|
+
}
|
|
1950
|
+
});
|
|
1951
|
+
}
|
|
1952
|
+
|
|
1953
|
+
// src/form-structure/prevent-form-nesting-commands.ts
|
|
1954
|
+
var import_editor_notifications3 = require("@elementor/editor-notifications");
|
|
1955
|
+
var import_editor_v1_adapters13 = require("@elementor/editor-v1-adapters");
|
|
1956
|
+
var import_i18n3 = require("@wordpress/i18n");
|
|
1929
1957
|
var FORM_NESTING_ALERT = {
|
|
1930
1958
|
type: "default",
|
|
1931
|
-
message: (0,
|
|
1959
|
+
message: (0, import_i18n3.__)("Forms can't be nested. Create separate forms instead.", "elementor"),
|
|
1932
1960
|
id: "form-nesting-blocked"
|
|
1933
1961
|
};
|
|
1934
1962
|
function initFormNestingPrevention() {
|
|
1935
|
-
(0,
|
|
1963
|
+
(0, import_editor_v1_adapters13.blockCommand)({
|
|
1936
1964
|
command: "document/elements/create",
|
|
1937
1965
|
condition: blockFormCreate
|
|
1938
1966
|
});
|
|
1939
|
-
(0,
|
|
1967
|
+
(0, import_editor_v1_adapters13.blockCommand)({
|
|
1940
1968
|
command: "document/elements/move",
|
|
1941
1969
|
condition: blockFormMove
|
|
1942
1970
|
});
|
|
1943
|
-
(0,
|
|
1971
|
+
(0, import_editor_v1_adapters13.blockCommand)({
|
|
1944
1972
|
command: "document/elements/paste",
|
|
1945
1973
|
condition: blockFormPaste
|
|
1946
1974
|
});
|
|
@@ -1984,7 +2012,7 @@ function blockFormPaste(args) {
|
|
|
1984
2012
|
return false;
|
|
1985
2013
|
}
|
|
1986
2014
|
function handleBlockedFormField2() {
|
|
1987
|
-
(0,
|
|
2015
|
+
(0, import_editor_notifications3.notify)(FORM_NESTING_ALERT);
|
|
1988
2016
|
}
|
|
1989
2017
|
|
|
1990
2018
|
// src/settings-transformers-registry.ts
|
|
@@ -2180,6 +2208,8 @@ var svgSrcTransformer = createTransformer(async (value, { signal }) => {
|
|
|
2180
2208
|
var EMPTY_ICON_RESULT = { html: null, url: null };
|
|
2181
2209
|
var ICON_SVG_SIZE = "100%";
|
|
2182
2210
|
var ICON_SVG_OVERFLOW = "visible";
|
|
2211
|
+
var FONT_AWESOME_LIBRARY_PREFIX = "fa-";
|
|
2212
|
+
var EICONS_LIBRARY = "eicons";
|
|
2183
2213
|
var DEFAULT_SVG_RELATIVE_PATH = "images/default-svg.svg";
|
|
2184
2214
|
var iconTransformer = createTransformer(async (value, { signal }) => {
|
|
2185
2215
|
const iconValue = typeof value.value === "string" ? value.value : null;
|
|
@@ -2191,14 +2221,14 @@ var iconTransformer = createTransformer(async (value, { signal }) => {
|
|
|
2191
2221
|
if (fontAwesomeHtml) {
|
|
2192
2222
|
return { html: fontAwesomeHtml, url: null };
|
|
2193
2223
|
}
|
|
2194
|
-
if ((
|
|
2195
|
-
return
|
|
2224
|
+
if (library.startsWith(FONT_AWESOME_LIBRARY_PREFIX) || EICONS_LIBRARY === library) {
|
|
2225
|
+
return EMPTY_ICON_RESULT;
|
|
2196
2226
|
}
|
|
2197
|
-
const
|
|
2198
|
-
if (
|
|
2199
|
-
return { html:
|
|
2227
|
+
const providerHtml = await resolveProviderSvg(library, iconValue, signal);
|
|
2228
|
+
if (providerHtml) {
|
|
2229
|
+
return { html: providerHtml, url: null };
|
|
2200
2230
|
}
|
|
2201
|
-
return
|
|
2231
|
+
return resolveDefaultSvg(signal);
|
|
2202
2232
|
});
|
|
2203
2233
|
async function resolveDefaultSvg(signal) {
|
|
2204
2234
|
const assetsUrl = window.elementorCommon?.config?.urls?.assets;
|
|
@@ -2213,8 +2243,8 @@ async function resolveDefaultSvg(signal) {
|
|
|
2213
2243
|
{ key: "svg", signal }
|
|
2214
2244
|
);
|
|
2215
2245
|
}
|
|
2216
|
-
async function
|
|
2217
|
-
const markup = await (0, import_editor_controls.
|
|
2246
|
+
async function resolveProviderSvg(library, iconValue, signal) {
|
|
2247
|
+
const markup = await (0, import_editor_controls.resolveProviderIconSvg)(library, iconValue, signal);
|
|
2218
2248
|
return markup ? processIconSvgContent(markup) : null;
|
|
2219
2249
|
}
|
|
2220
2250
|
async function resolveFontAwesomeSvg(library, iconValue, signal) {
|
|
@@ -2674,7 +2704,7 @@ function initStyleTransformers() {
|
|
|
2674
2704
|
|
|
2675
2705
|
// src/legacy/init-legacy-views.ts
|
|
2676
2706
|
var import_editor_elements8 = require("@elementor/editor-elements");
|
|
2677
|
-
var
|
|
2707
|
+
var import_editor_v1_adapters15 = require("@elementor/editor-v1-adapters");
|
|
2678
2708
|
|
|
2679
2709
|
// src/renderers/create-dom-renderer.ts
|
|
2680
2710
|
var import_twing = require("@elementor/twing");
|
|
@@ -3425,8 +3455,8 @@ var import_client = require("react-dom/client");
|
|
|
3425
3455
|
var React11 = __toESM(require("react"));
|
|
3426
3456
|
var import_editor_elements7 = require("@elementor/editor-elements");
|
|
3427
3457
|
var import_editor_props4 = require("@elementor/editor-props");
|
|
3428
|
-
var
|
|
3429
|
-
var
|
|
3458
|
+
var import_editor_v1_adapters14 = require("@elementor/editor-v1-adapters");
|
|
3459
|
+
var import_i18n4 = require("@wordpress/i18n");
|
|
3430
3460
|
|
|
3431
3461
|
// src/legacy/replacements/base.ts
|
|
3432
3462
|
var TRIGGER_TIMING = {
|
|
@@ -3743,7 +3773,7 @@ var InlineEditingReplacement = class extends ReplacementBase {
|
|
|
3743
3773
|
return this.editing;
|
|
3744
3774
|
}
|
|
3745
3775
|
shouldRenderReplacement() {
|
|
3746
|
-
return this.isInlineEditingEligible() && (0,
|
|
3776
|
+
return this.isInlineEditingEligible() && (0, import_editor_v1_adapters14.getCurrentEditMode)() === "edit";
|
|
3747
3777
|
}
|
|
3748
3778
|
handleRenderInlineEditor = () => {
|
|
3749
3779
|
if (this.isEditingModeActive() || !this.isInlineEditingEligible()) {
|
|
@@ -3830,7 +3860,7 @@ var InlineEditingReplacement = class extends ReplacementBase {
|
|
|
3830
3860
|
setContentValue(value) {
|
|
3831
3861
|
const settingKey = this.getInlineEditablePropertyName();
|
|
3832
3862
|
const valueToSave = this.createContentPropValue(value);
|
|
3833
|
-
(0,
|
|
3863
|
+
(0, import_editor_v1_adapters14.undoable)(
|
|
3834
3864
|
{
|
|
3835
3865
|
do: () => {
|
|
3836
3866
|
const prevValue = this.getInlineEditablePropValue();
|
|
@@ -3844,7 +3874,7 @@ var InlineEditingReplacement = class extends ReplacementBase {
|
|
|
3844
3874
|
{
|
|
3845
3875
|
title: (0, import_editor_elements7.getElementLabel)(this.id),
|
|
3846
3876
|
// translators: %s is the name of the property that was edited.
|
|
3847
|
-
subtitle: (0,
|
|
3877
|
+
subtitle: (0, import_i18n4.__)("%s edited", "elementor").replace(
|
|
3848
3878
|
"%s",
|
|
3849
3879
|
this.getInlineEditablePropTypeKey() ?? "Inline editing"
|
|
3850
3880
|
),
|
|
@@ -3872,7 +3902,7 @@ var InlineEditingReplacement = class extends ReplacementBase {
|
|
|
3872
3902
|
return null;
|
|
3873
3903
|
}
|
|
3874
3904
|
runCommand(key, value) {
|
|
3875
|
-
(0,
|
|
3905
|
+
(0, import_editor_v1_adapters14.__privateRunCommandSync)(
|
|
3876
3906
|
"document/elements/set-settings",
|
|
3877
3907
|
{
|
|
3878
3908
|
container: (0, import_editor_elements7.getContainer)(this.id),
|
|
@@ -3882,7 +3912,7 @@ var InlineEditingReplacement = class extends ReplacementBase {
|
|
|
3882
3912
|
},
|
|
3883
3913
|
{ internal: true }
|
|
3884
3914
|
);
|
|
3885
|
-
(0,
|
|
3915
|
+
(0, import_editor_v1_adapters14.__privateRunCommandSync)("document/save/set-is-modified", { status: true }, { internal: true });
|
|
3886
3916
|
}
|
|
3887
3917
|
getExpectedTag() {
|
|
3888
3918
|
const tagPropType = this.getTagPropType();
|
|
@@ -4047,12 +4077,12 @@ function registerModelExtensions(type, extensions) {
|
|
|
4047
4077
|
}
|
|
4048
4078
|
function registerElementType(type, elementTypeGenerator) {
|
|
4049
4079
|
elementsLegacyTypes[type] = elementTypeGenerator;
|
|
4050
|
-
if ((0,
|
|
4080
|
+
if ((0, import_editor_v1_adapters15.__privateIsReady)()) {
|
|
4051
4081
|
registerElementInLegacyManager(type, createDomRenderer());
|
|
4052
4082
|
}
|
|
4053
4083
|
}
|
|
4054
4084
|
function initLegacyViews() {
|
|
4055
|
-
(0,
|
|
4085
|
+
(0, import_editor_v1_adapters15.__privateListenTo)((0, import_editor_v1_adapters15.v1ReadyEvent)(), () => {
|
|
4056
4086
|
const widgetsCache = (0, import_editor_elements8.getWidgetsCache)() ?? {};
|
|
4057
4087
|
const renderer = createDomRenderer();
|
|
4058
4088
|
registerProPromotionTypes(widgetsCache);
|
|
@@ -4190,9 +4220,9 @@ function initTabsModelExtensions() {
|
|
|
4190
4220
|
var import_editor_props8 = require("@elementor/editor-props");
|
|
4191
4221
|
|
|
4192
4222
|
// src/mcp/icon-library-experiment.ts
|
|
4193
|
-
var
|
|
4223
|
+
var import_editor_v1_adapters16 = require("@elementor/editor-v1-adapters");
|
|
4194
4224
|
var ICON_LIBRARY_EXPERIMENT = "e_svg_library";
|
|
4195
|
-
var isIconLibraryActive = () => (0,
|
|
4225
|
+
var isIconLibraryActive = () => (0, import_editor_v1_adapters16.isExperimentActive)(ICON_LIBRARY_EXPERIMENT);
|
|
4196
4226
|
|
|
4197
4227
|
// src/mcp/resources/available-widgets-resource.ts
|
|
4198
4228
|
var import_http_client3 = require("@elementor/http-client");
|
|
@@ -4270,7 +4300,7 @@ var initBestPracticesResource = (reg) => {
|
|
|
4270
4300
|
|
|
4271
4301
|
// src/mcp/resources/document-structure-resource.ts
|
|
4272
4302
|
var import_editor_elements9 = require("@elementor/editor-elements");
|
|
4273
|
-
var
|
|
4303
|
+
var import_editor_v1_adapters17 = require("@elementor/editor-v1-adapters");
|
|
4274
4304
|
var DOCUMENT_STRUCTURE_URI = "elementor://document/structure";
|
|
4275
4305
|
var initDocumentStructureResource = (reg) => {
|
|
4276
4306
|
const { resource, sendResourceUpdated } = reg;
|
|
@@ -4283,15 +4313,15 @@ var initDocumentStructureResource = (reg) => {
|
|
|
4283
4313
|
sendResourceUpdated({ uri: DOCUMENT_STRUCTURE_URI });
|
|
4284
4314
|
}
|
|
4285
4315
|
};
|
|
4286
|
-
(0,
|
|
4316
|
+
(0, import_editor_v1_adapters17.__privateListenTo)(
|
|
4287
4317
|
[
|
|
4288
|
-
(0,
|
|
4289
|
-
(0,
|
|
4290
|
-
(0,
|
|
4291
|
-
(0,
|
|
4292
|
-
(0,
|
|
4293
|
-
(0,
|
|
4294
|
-
(0,
|
|
4318
|
+
(0, import_editor_v1_adapters17.commandEndEvent)("document/elements/create"),
|
|
4319
|
+
(0, import_editor_v1_adapters17.commandEndEvent)("document/elements/delete"),
|
|
4320
|
+
(0, import_editor_v1_adapters17.commandEndEvent)("document/elements/move"),
|
|
4321
|
+
(0, import_editor_v1_adapters17.commandEndEvent)("document/elements/copy"),
|
|
4322
|
+
(0, import_editor_v1_adapters17.commandEndEvent)("document/elements/paste"),
|
|
4323
|
+
(0, import_editor_v1_adapters17.commandEndEvent)("editor/documents/attach-preview"),
|
|
4324
|
+
(0, import_editor_v1_adapters17.commandEndEvent)("editor/documents/switch")
|
|
4295
4325
|
],
|
|
4296
4326
|
updateDocumentStructure
|
|
4297
4327
|
);
|
|
@@ -4394,7 +4424,7 @@ var initDynamicTagsResource = (reg) => {
|
|
|
4394
4424
|
};
|
|
4395
4425
|
|
|
4396
4426
|
// src/mcp/resources/editor-state-resource.ts
|
|
4397
|
-
var
|
|
4427
|
+
var import_editor_v1_adapters18 = require("@elementor/editor-v1-adapters");
|
|
4398
4428
|
var CURRENTLY_VIEWED_SCREEN = "The user is currently viewing the Elementor editor";
|
|
4399
4429
|
var PAGE_CONTENT_CHARACTER_LIMIT = 500;
|
|
4400
4430
|
var PREVIEW_TEXT_NODE_MIN_LENGTH = 2;
|
|
@@ -4415,8 +4445,8 @@ var initEditorStateResource = (reg) => {
|
|
|
4415
4445
|
lastSerializedState = serialized;
|
|
4416
4446
|
sendResourceUpdated({ uri: EDITOR_STATE_URI });
|
|
4417
4447
|
};
|
|
4418
|
-
(0,
|
|
4419
|
-
[(0,
|
|
4448
|
+
(0, import_editor_v1_adapters18.__privateListenTo)(
|
|
4449
|
+
[(0, import_editor_v1_adapters18.commandEndEvent)("editor/documents/switch"), (0, import_editor_v1_adapters18.commandEndEvent)("editor/documents/attach-preview")],
|
|
4420
4450
|
notifyIfChanged
|
|
4421
4451
|
);
|
|
4422
4452
|
lastSerializedState = JSON.stringify(buildState());
|
|
@@ -4490,7 +4520,7 @@ function getPageTitle() {
|
|
|
4490
4520
|
}
|
|
4491
4521
|
|
|
4492
4522
|
// src/mcp/resources/general-context-resource.ts
|
|
4493
|
-
var
|
|
4523
|
+
var import_editor_v1_adapters19 = require("@elementor/editor-v1-adapters");
|
|
4494
4524
|
var GENERAL_CONTEXT_URI = "elementor://context/general";
|
|
4495
4525
|
var initGeneralContextResource = (reg) => {
|
|
4496
4526
|
const { resource, sendResourceUpdated } = reg;
|
|
@@ -4551,11 +4581,11 @@ var initGeneralContextResource = (reg) => {
|
|
|
4551
4581
|
};
|
|
4552
4582
|
}
|
|
4553
4583
|
);
|
|
4554
|
-
(0,
|
|
4584
|
+
(0, import_editor_v1_adapters19.__privateListenTo)(
|
|
4555
4585
|
[
|
|
4556
|
-
(0,
|
|
4557
|
-
(0,
|
|
4558
|
-
(0,
|
|
4586
|
+
(0, import_editor_v1_adapters19.commandEndEvent)("editor/documents/switch"),
|
|
4587
|
+
(0, import_editor_v1_adapters19.commandEndEvent)("editor/documents/attach-preview"),
|
|
4588
|
+
(0, import_editor_v1_adapters19.commandEndEvent)("document/elements/settings")
|
|
4559
4589
|
],
|
|
4560
4590
|
pushUpdateIfChanged
|
|
4561
4591
|
);
|
|
@@ -4564,7 +4594,7 @@ var initGeneralContextResource = (reg) => {
|
|
|
4564
4594
|
|
|
4565
4595
|
// src/mcp/resources/selected-element-resource.ts
|
|
4566
4596
|
var import_editor_elements10 = require("@elementor/editor-elements");
|
|
4567
|
-
var
|
|
4597
|
+
var import_editor_v1_adapters20 = require("@elementor/editor-v1-adapters");
|
|
4568
4598
|
var SELECTED_ELEMENT_URI = "elementor://context/selected-element";
|
|
4569
4599
|
var initSelectedElementResource = (reg) => {
|
|
4570
4600
|
const { resource, sendResourceUpdated } = reg;
|
|
@@ -4595,11 +4625,11 @@ var initSelectedElementResource = (reg) => {
|
|
|
4595
4625
|
}
|
|
4596
4626
|
publishIfChanged(readSelectionFromEditor());
|
|
4597
4627
|
};
|
|
4598
|
-
(0,
|
|
4628
|
+
(0, import_editor_v1_adapters20.__privateListenTo)(
|
|
4599
4629
|
[
|
|
4600
|
-
(0,
|
|
4601
|
-
(0,
|
|
4602
|
-
(0,
|
|
4630
|
+
(0, import_editor_v1_adapters20.commandEndEvent)("document/elements/select"),
|
|
4631
|
+
(0, import_editor_v1_adapters20.commandEndEvent)("document/elements/deselect-all"),
|
|
4632
|
+
(0, import_editor_v1_adapters20.commandEndEvent)("document/elements/settings")
|
|
4603
4633
|
],
|
|
4604
4634
|
onCommand
|
|
4605
4635
|
);
|
|
@@ -4717,7 +4747,7 @@ var import_editor_props7 = require("@elementor/editor-props");
|
|
|
4717
4747
|
var import_editor_elements12 = require("@elementor/editor-elements");
|
|
4718
4748
|
var import_editor_props6 = require("@elementor/editor-props");
|
|
4719
4749
|
var import_editor_styles4 = require("@elementor/editor-styles");
|
|
4720
|
-
var
|
|
4750
|
+
var import_editor_v1_adapters22 = require("@elementor/editor-v1-adapters");
|
|
4721
4751
|
|
|
4722
4752
|
// src/mcp/utils/merge-custom-css.ts
|
|
4723
4753
|
var CUSTOM_CSS_SEPARATOR = "\n";
|
|
@@ -4786,11 +4816,11 @@ function resolveCanonicalPropKeys(elementType, props) {
|
|
|
4786
4816
|
}
|
|
4787
4817
|
|
|
4788
4818
|
// src/mcp/utils/resolve-dynamic-tag.ts
|
|
4789
|
-
var
|
|
4819
|
+
var import_editor_v1_adapters21 = require("@elementor/editor-v1-adapters");
|
|
4790
4820
|
var DYNAMIC_PROP_TYPE_KEY = "dynamic";
|
|
4791
4821
|
var OMITTED_DYNAMIC_SETTING_KEYS = ["fallback"];
|
|
4792
4822
|
var getAtomicDynamicTags = () => {
|
|
4793
|
-
const config = (0,
|
|
4823
|
+
const config = (0, import_editor_v1_adapters21.getElementorConfig)();
|
|
4794
4824
|
return config.atomicDynamicTags?.tags ?? {};
|
|
4795
4825
|
};
|
|
4796
4826
|
var getDynamicTagNamesByCategories = (categories) => {
|
|
@@ -4991,7 +5021,7 @@ Expected Schema: ${jsonSchema}`
|
|
|
4991
5021
|
},
|
|
4992
5022
|
withHistory: false
|
|
4993
5023
|
});
|
|
4994
|
-
(0,
|
|
5024
|
+
(0, import_editor_v1_adapters22.__privateRunCommandSync)("document/save/set-is-modified", { status: true }, { internal: true });
|
|
4995
5025
|
};
|
|
4996
5026
|
|
|
4997
5027
|
// src/mcp/tools/configure-element/prompt.ts
|
|
@@ -5601,15 +5631,15 @@ Note: The "size" property controls image resolution/loading, not visual size. Se
|
|
|
5601
5631
|
|
|
5602
5632
|
// src/prevent-link-in-link-commands.ts
|
|
5603
5633
|
var import_editor_elements14 = require("@elementor/editor-elements");
|
|
5604
|
-
var
|
|
5605
|
-
var
|
|
5606
|
-
var
|
|
5634
|
+
var import_editor_notifications4 = require("@elementor/editor-notifications");
|
|
5635
|
+
var import_editor_v1_adapters23 = require("@elementor/editor-v1-adapters");
|
|
5636
|
+
var import_i18n5 = require("@wordpress/i18n");
|
|
5607
5637
|
function initLinkInLinkPrevention() {
|
|
5608
|
-
(0,
|
|
5638
|
+
(0, import_editor_v1_adapters23.blockCommand)({
|
|
5609
5639
|
command: "document/elements/paste",
|
|
5610
5640
|
condition: blockLinkInLinkPaste
|
|
5611
5641
|
});
|
|
5612
|
-
(0,
|
|
5642
|
+
(0, import_editor_v1_adapters23.blockCommand)({
|
|
5613
5643
|
command: "document/elements/move",
|
|
5614
5644
|
condition: blockLinkInLinkMove
|
|
5615
5645
|
});
|
|
@@ -5637,7 +5667,7 @@ function blockLinkInLinkPaste(args) {
|
|
|
5637
5667
|
const sourceElements = data.clipboard.elements;
|
|
5638
5668
|
const notification = {
|
|
5639
5669
|
type: "default",
|
|
5640
|
-
message: (0,
|
|
5670
|
+
message: (0, import_i18n5.__)(
|
|
5641
5671
|
"To paste a link to this element, first remove the link from it's parent container.",
|
|
5642
5672
|
"elementor"
|
|
5643
5673
|
),
|
|
@@ -5646,7 +5676,7 @@ function blockLinkInLinkPaste(args) {
|
|
|
5646
5676
|
};
|
|
5647
5677
|
const blocked = shouldBlock(sourceElements, targetElements);
|
|
5648
5678
|
if (blocked) {
|
|
5649
|
-
(0,
|
|
5679
|
+
(0, import_editor_notifications4.notify)(notification);
|
|
5650
5680
|
}
|
|
5651
5681
|
return blocked;
|
|
5652
5682
|
}
|
|
@@ -5656,13 +5686,13 @@ function blockLinkInLinkMove(args) {
|
|
|
5656
5686
|
const targetElement = target;
|
|
5657
5687
|
const notification = {
|
|
5658
5688
|
type: "default",
|
|
5659
|
-
message: (0,
|
|
5689
|
+
message: (0, import_i18n5.__)("To drag a link to this element, first remove the link from it's parent container.", "elementor"),
|
|
5660
5690
|
id: "move-in-link-blocked",
|
|
5661
5691
|
additionalActionProps: [learnMoreActionProps]
|
|
5662
5692
|
};
|
|
5663
5693
|
const isBlocked = shouldBlock(sourceElements, [targetElement]);
|
|
5664
5694
|
if (isBlocked) {
|
|
5665
|
-
(0,
|
|
5695
|
+
(0, import_editor_notifications4.notify)(notification);
|
|
5666
5696
|
}
|
|
5667
5697
|
return isBlocked;
|
|
5668
5698
|
}
|
|
@@ -5685,12 +5715,12 @@ function shouldBlock(sourceElements, targetElements) {
|
|
|
5685
5715
|
// src/style-commands/paste-style.ts
|
|
5686
5716
|
var import_editor_elements17 = require("@elementor/editor-elements");
|
|
5687
5717
|
var import_editor_props10 = require("@elementor/editor-props");
|
|
5688
|
-
var
|
|
5718
|
+
var import_editor_v1_adapters25 = require("@elementor/editor-v1-adapters");
|
|
5689
5719
|
|
|
5690
5720
|
// src/utils/command-utils.ts
|
|
5691
5721
|
var import_editor_elements15 = require("@elementor/editor-elements");
|
|
5692
5722
|
var import_editor_props9 = require("@elementor/editor-props");
|
|
5693
|
-
var
|
|
5723
|
+
var import_i18n6 = require("@wordpress/i18n");
|
|
5694
5724
|
function hasAtomicWidgets(args) {
|
|
5695
5725
|
const { containers = [args.container] } = args;
|
|
5696
5726
|
return containers.some(isAtomicWidget);
|
|
@@ -5726,15 +5756,15 @@ function getClipboardElements(storageKey = "clipboard") {
|
|
|
5726
5756
|
}
|
|
5727
5757
|
}
|
|
5728
5758
|
function getTitleForContainers(containers) {
|
|
5729
|
-
return containers.length > 1 ? (0,
|
|
5759
|
+
return containers.length > 1 ? (0, import_i18n6.__)("Elements", "elementor") : (0, import_editor_elements15.getElementLabel)(containers[0].id);
|
|
5730
5760
|
}
|
|
5731
5761
|
|
|
5732
5762
|
// src/style-commands/undoable-actions/paste-element-style.ts
|
|
5733
5763
|
var import_editor_elements16 = require("@elementor/editor-elements");
|
|
5734
5764
|
var import_editor_styles_repository4 = require("@elementor/editor-styles-repository");
|
|
5735
|
-
var
|
|
5736
|
-
var
|
|
5737
|
-
var undoablePasteElementStyle = () => (0,
|
|
5765
|
+
var import_editor_v1_adapters24 = require("@elementor/editor-v1-adapters");
|
|
5766
|
+
var import_i18n7 = require("@wordpress/i18n");
|
|
5767
|
+
var undoablePasteElementStyle = () => (0, import_editor_v1_adapters24.undoable)(
|
|
5738
5768
|
{
|
|
5739
5769
|
do: ({ containers, newStyle }) => {
|
|
5740
5770
|
return containers.map((container) => {
|
|
@@ -5803,19 +5833,19 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters23.undoable)(
|
|
|
5803
5833
|
},
|
|
5804
5834
|
{
|
|
5805
5835
|
title: ({ containers }) => getTitleForContainers(containers),
|
|
5806
|
-
subtitle: (0,
|
|
5836
|
+
subtitle: (0, import_i18n7.__)("Style Pasted", "elementor")
|
|
5807
5837
|
}
|
|
5808
5838
|
);
|
|
5809
5839
|
|
|
5810
5840
|
// src/style-commands/paste-style.ts
|
|
5811
5841
|
function initPasteStyleCommand() {
|
|
5812
5842
|
const pasteElementStyleCommand = undoablePasteElementStyle();
|
|
5813
|
-
(0,
|
|
5843
|
+
(0, import_editor_v1_adapters25.blockCommand)({
|
|
5814
5844
|
command: "document/elements/paste-style",
|
|
5815
5845
|
condition: hasAtomicWidgets
|
|
5816
5846
|
});
|
|
5817
|
-
(0,
|
|
5818
|
-
(0,
|
|
5847
|
+
(0, import_editor_v1_adapters25.__privateListenTo)(
|
|
5848
|
+
(0, import_editor_v1_adapters25.commandStartEvent)("document/elements/paste-style"),
|
|
5819
5849
|
(e) => pasteStyles(e.args, pasteElementStyleCommand)
|
|
5820
5850
|
);
|
|
5821
5851
|
}
|
|
@@ -5866,14 +5896,14 @@ function pasteClasses(containers, classes) {
|
|
|
5866
5896
|
}
|
|
5867
5897
|
|
|
5868
5898
|
// src/style-commands/reset-style.ts
|
|
5869
|
-
var
|
|
5899
|
+
var import_editor_v1_adapters27 = require("@elementor/editor-v1-adapters");
|
|
5870
5900
|
|
|
5871
5901
|
// src/style-commands/undoable-actions/reset-element-style.ts
|
|
5872
5902
|
var import_editor_elements18 = require("@elementor/editor-elements");
|
|
5873
5903
|
var import_editor_styles_repository5 = require("@elementor/editor-styles-repository");
|
|
5874
|
-
var
|
|
5875
|
-
var
|
|
5876
|
-
var undoableResetElementStyle = () => (0,
|
|
5904
|
+
var import_editor_v1_adapters26 = require("@elementor/editor-v1-adapters");
|
|
5905
|
+
var import_i18n8 = require("@wordpress/i18n");
|
|
5906
|
+
var undoableResetElementStyle = () => (0, import_editor_v1_adapters26.undoable)(
|
|
5877
5907
|
{
|
|
5878
5908
|
do: ({ containers }) => {
|
|
5879
5909
|
return containers.map((container) => {
|
|
@@ -5910,19 +5940,19 @@ var undoableResetElementStyle = () => (0, import_editor_v1_adapters25.undoable)(
|
|
|
5910
5940
|
},
|
|
5911
5941
|
{
|
|
5912
5942
|
title: ({ containers }) => getTitleForContainers(containers),
|
|
5913
|
-
subtitle: (0,
|
|
5943
|
+
subtitle: (0, import_i18n8.__)("Style Reset", "elementor")
|
|
5914
5944
|
}
|
|
5915
5945
|
);
|
|
5916
5946
|
|
|
5917
5947
|
// src/style-commands/reset-style.ts
|
|
5918
5948
|
function initResetStyleCommand() {
|
|
5919
5949
|
const resetElementStyles = undoableResetElementStyle();
|
|
5920
|
-
(0,
|
|
5950
|
+
(0, import_editor_v1_adapters27.blockCommand)({
|
|
5921
5951
|
command: "document/elements/reset-style",
|
|
5922
5952
|
condition: hasAtomicWidgets
|
|
5923
5953
|
});
|
|
5924
|
-
(0,
|
|
5925
|
-
(0,
|
|
5954
|
+
(0, import_editor_v1_adapters27.__privateListenTo)(
|
|
5955
|
+
(0, import_editor_v1_adapters27.commandStartEvent)("document/elements/reset-style"),
|
|
5926
5956
|
(e) => resetStyles(e.args, resetElementStyles)
|
|
5927
5957
|
);
|
|
5928
5958
|
}
|
|
@@ -5948,6 +5978,7 @@ function init() {
|
|
|
5948
5978
|
initLinkInLinkPrevention();
|
|
5949
5979
|
initFormNestingPrevention();
|
|
5950
5980
|
initFormAncestorEnforcement();
|
|
5981
|
+
initHiddenFieldHint();
|
|
5951
5982
|
initViewReplacements();
|
|
5952
5983
|
initLegacyViews();
|
|
5953
5984
|
initSettingsTransformers();
|
|
@@ -6071,9 +6102,9 @@ function getRectClipPath(rect, viewport) {
|
|
|
6071
6102
|
}
|
|
6072
6103
|
|
|
6073
6104
|
// src/hooks/use-canvas-document.ts
|
|
6074
|
-
var
|
|
6105
|
+
var import_editor_v1_adapters28 = require("@elementor/editor-v1-adapters");
|
|
6075
6106
|
function useCanvasDocument() {
|
|
6076
|
-
return (0,
|
|
6107
|
+
return (0, import_editor_v1_adapters28.__privateUseListenTo)((0, import_editor_v1_adapters28.commandEndEvent)("editor/documents/attach-preview"), () => (0, import_editor_v1_adapters28.getCanvasIframeDocument)());
|
|
6077
6108
|
}
|
|
6078
6109
|
|
|
6079
6110
|
// src/hooks/use-escape-on-canvas.ts
|
package/dist/index.mjs
CHANGED
|
@@ -118,7 +118,9 @@ var SINGLE_BLOCK_KEY = "default";
|
|
|
118
118
|
var convertBlocks = async (blocks) => {
|
|
119
119
|
const { data } = await httpService2().post(
|
|
120
120
|
CSS_TO_ATOMIC_URL,
|
|
121
|
-
{
|
|
121
|
+
{
|
|
122
|
+
blocks
|
|
123
|
+
}
|
|
122
124
|
);
|
|
123
125
|
return data.data;
|
|
124
126
|
};
|
|
@@ -1747,6 +1749,7 @@ import { __ } from "@wordpress/i18n";
|
|
|
1747
1749
|
// src/form-structure/utils.ts
|
|
1748
1750
|
import { getAllDescendants } from "@elementor/editor-elements";
|
|
1749
1751
|
var FORM_ELEMENT_TYPE = "e-form";
|
|
1752
|
+
var FORM_HIDDEN_FIELD_ELEMENT_TYPE = "e-form-hidden";
|
|
1750
1753
|
var FORM_FIELD_ELEMENT_TYPES = /* @__PURE__ */ new Set([
|
|
1751
1754
|
"e-form-input",
|
|
1752
1755
|
"e-form-textarea",
|
|
@@ -1757,7 +1760,8 @@ var FORM_FIELD_ELEMENT_TYPES = /* @__PURE__ */ new Set([
|
|
|
1757
1760
|
"e-form-radio-button",
|
|
1758
1761
|
"e-form-file-upload",
|
|
1759
1762
|
"e-form-date-picker",
|
|
1760
|
-
"e-form-time-picker"
|
|
1763
|
+
"e-form-time-picker",
|
|
1764
|
+
FORM_HIDDEN_FIELD_ELEMENT_TYPE
|
|
1761
1765
|
]);
|
|
1762
1766
|
function getArgsElementType(args) {
|
|
1763
1767
|
return args.model?.widgetType || args.model?.elType;
|
|
@@ -1874,13 +1878,37 @@ function handleBlockedFormField() {
|
|
|
1874
1878
|
notify(FORM_FIELDS_OUTSIDE_ALERT);
|
|
1875
1879
|
}
|
|
1876
1880
|
|
|
1877
|
-
// src/form-structure/
|
|
1881
|
+
// src/form-structure/hidden-field-hint.ts
|
|
1878
1882
|
import { notify as notify2 } from "@elementor/editor-notifications";
|
|
1879
|
-
import {
|
|
1883
|
+
import { registerDataHook as registerDataHook3 } from "@elementor/editor-v1-adapters";
|
|
1880
1884
|
import { __ as __2 } from "@wordpress/i18n";
|
|
1885
|
+
var MOVE_COMMAND = "document/elements/move";
|
|
1886
|
+
var notificationCounter = 0;
|
|
1887
|
+
function createHiddenFieldNotification() {
|
|
1888
|
+
return {
|
|
1889
|
+
type: "default",
|
|
1890
|
+
message: __2("Hidden field added - invisible on your form. Manage it in the Structure panel.", "elementor"),
|
|
1891
|
+
id: `hidden-field-added-${++notificationCounter}`
|
|
1892
|
+
};
|
|
1893
|
+
}
|
|
1894
|
+
function initHiddenFieldHint() {
|
|
1895
|
+
registerDataHook3("after", "document/elements/create", (args, _result, options) => {
|
|
1896
|
+
if (options?.commandsCurrentTrace?.includes(MOVE_COMMAND)) {
|
|
1897
|
+
return;
|
|
1898
|
+
}
|
|
1899
|
+
if (getArgsElementType(args) === FORM_HIDDEN_FIELD_ELEMENT_TYPE) {
|
|
1900
|
+
notify2(createHiddenFieldNotification());
|
|
1901
|
+
}
|
|
1902
|
+
});
|
|
1903
|
+
}
|
|
1904
|
+
|
|
1905
|
+
// src/form-structure/prevent-form-nesting-commands.ts
|
|
1906
|
+
import { notify as notify3 } from "@elementor/editor-notifications";
|
|
1907
|
+
import { blockCommand as blockCommand2 } from "@elementor/editor-v1-adapters";
|
|
1908
|
+
import { __ as __3 } from "@wordpress/i18n";
|
|
1881
1909
|
var FORM_NESTING_ALERT = {
|
|
1882
1910
|
type: "default",
|
|
1883
|
-
message:
|
|
1911
|
+
message: __3("Forms can't be nested. Create separate forms instead.", "elementor"),
|
|
1884
1912
|
id: "form-nesting-blocked"
|
|
1885
1913
|
};
|
|
1886
1914
|
function initFormNestingPrevention() {
|
|
@@ -1936,7 +1964,7 @@ function blockFormPaste(args) {
|
|
|
1936
1964
|
return false;
|
|
1937
1965
|
}
|
|
1938
1966
|
function handleBlockedFormField2() {
|
|
1939
|
-
|
|
1967
|
+
notify3(FORM_NESTING_ALERT);
|
|
1940
1968
|
}
|
|
1941
1969
|
|
|
1942
1970
|
// src/settings-transformers-registry.ts
|
|
@@ -2066,9 +2094,8 @@ var timeRangeTransformer = createTransformer((value) => {
|
|
|
2066
2094
|
// src/transformers/shared/icon-transformer.ts
|
|
2067
2095
|
import {
|
|
2068
2096
|
getFontAwesome7IconName,
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
resolveFontAwesome7Icon
|
|
2097
|
+
resolveFontAwesome7Icon,
|
|
2098
|
+
resolveProviderIconSvg
|
|
2072
2099
|
} from "@elementor/editor-controls";
|
|
2073
2100
|
|
|
2074
2101
|
// src/transformers/shared/process-svg-content.ts
|
|
@@ -2137,6 +2164,8 @@ var svgSrcTransformer = createTransformer(async (value, { signal }) => {
|
|
|
2137
2164
|
var EMPTY_ICON_RESULT = { html: null, url: null };
|
|
2138
2165
|
var ICON_SVG_SIZE = "100%";
|
|
2139
2166
|
var ICON_SVG_OVERFLOW = "visible";
|
|
2167
|
+
var FONT_AWESOME_LIBRARY_PREFIX = "fa-";
|
|
2168
|
+
var EICONS_LIBRARY = "eicons";
|
|
2140
2169
|
var DEFAULT_SVG_RELATIVE_PATH = "images/default-svg.svg";
|
|
2141
2170
|
var iconTransformer = createTransformer(async (value, { signal }) => {
|
|
2142
2171
|
const iconValue = typeof value.value === "string" ? value.value : null;
|
|
@@ -2148,14 +2177,14 @@ var iconTransformer = createTransformer(async (value, { signal }) => {
|
|
|
2148
2177
|
if (fontAwesomeHtml) {
|
|
2149
2178
|
return { html: fontAwesomeHtml, url: null };
|
|
2150
2179
|
}
|
|
2151
|
-
if (
|
|
2152
|
-
return
|
|
2180
|
+
if (library.startsWith(FONT_AWESOME_LIBRARY_PREFIX) || EICONS_LIBRARY === library) {
|
|
2181
|
+
return EMPTY_ICON_RESULT;
|
|
2153
2182
|
}
|
|
2154
|
-
const
|
|
2155
|
-
if (
|
|
2156
|
-
return { html:
|
|
2183
|
+
const providerHtml = await resolveProviderSvg(library, iconValue, signal);
|
|
2184
|
+
if (providerHtml) {
|
|
2185
|
+
return { html: providerHtml, url: null };
|
|
2157
2186
|
}
|
|
2158
|
-
return
|
|
2187
|
+
return resolveDefaultSvg(signal);
|
|
2159
2188
|
});
|
|
2160
2189
|
async function resolveDefaultSvg(signal) {
|
|
2161
2190
|
const assetsUrl = window.elementorCommon?.config?.urls?.assets;
|
|
@@ -2170,8 +2199,8 @@ async function resolveDefaultSvg(signal) {
|
|
|
2170
2199
|
{ key: "svg", signal }
|
|
2171
2200
|
);
|
|
2172
2201
|
}
|
|
2173
|
-
async function
|
|
2174
|
-
const markup = await
|
|
2202
|
+
async function resolveProviderSvg(library, iconValue, signal) {
|
|
2203
|
+
const markup = await resolveProviderIconSvg(library, iconValue, signal);
|
|
2175
2204
|
return markup ? processIconSvgContent(markup) : null;
|
|
2176
2205
|
}
|
|
2177
2206
|
async function resolveFontAwesomeSvg(library, iconValue, signal) {
|
|
@@ -3393,7 +3422,7 @@ import {
|
|
|
3393
3422
|
stringPropTypeUtil as stringPropTypeUtil2
|
|
3394
3423
|
} from "@elementor/editor-props";
|
|
3395
3424
|
import { __privateRunCommandSync as runCommandSync, getCurrentEditMode, undoable } from "@elementor/editor-v1-adapters";
|
|
3396
|
-
import { __ as
|
|
3425
|
+
import { __ as __4 } from "@wordpress/i18n";
|
|
3397
3426
|
|
|
3398
3427
|
// src/legacy/replacements/base.ts
|
|
3399
3428
|
var TRIGGER_TIMING = {
|
|
@@ -3815,7 +3844,7 @@ var InlineEditingReplacement = class extends ReplacementBase {
|
|
|
3815
3844
|
{
|
|
3816
3845
|
title: getElementLabel(this.id),
|
|
3817
3846
|
// translators: %s is the name of the property that was edited.
|
|
3818
|
-
subtitle:
|
|
3847
|
+
subtitle: __4("%s edited", "elementor").replace(
|
|
3819
3848
|
"%s",
|
|
3820
3849
|
this.getInlineEditablePropTypeKey() ?? "Inline editing"
|
|
3821
3850
|
),
|
|
@@ -5587,9 +5616,9 @@ import {
|
|
|
5587
5616
|
getAnchoredDescendantId,
|
|
5588
5617
|
isElementAnchored
|
|
5589
5618
|
} from "@elementor/editor-elements";
|
|
5590
|
-
import { notify as
|
|
5619
|
+
import { notify as notify4 } from "@elementor/editor-notifications";
|
|
5591
5620
|
import { blockCommand as blockCommand3 } from "@elementor/editor-v1-adapters";
|
|
5592
|
-
import { __ as
|
|
5621
|
+
import { __ as __5 } from "@wordpress/i18n";
|
|
5593
5622
|
function initLinkInLinkPrevention() {
|
|
5594
5623
|
blockCommand3({
|
|
5595
5624
|
command: "document/elements/paste",
|
|
@@ -5623,7 +5652,7 @@ function blockLinkInLinkPaste(args) {
|
|
|
5623
5652
|
const sourceElements = data.clipboard.elements;
|
|
5624
5653
|
const notification = {
|
|
5625
5654
|
type: "default",
|
|
5626
|
-
message:
|
|
5655
|
+
message: __5(
|
|
5627
5656
|
"To paste a link to this element, first remove the link from it's parent container.",
|
|
5628
5657
|
"elementor"
|
|
5629
5658
|
),
|
|
@@ -5632,7 +5661,7 @@ function blockLinkInLinkPaste(args) {
|
|
|
5632
5661
|
};
|
|
5633
5662
|
const blocked = shouldBlock(sourceElements, targetElements);
|
|
5634
5663
|
if (blocked) {
|
|
5635
|
-
|
|
5664
|
+
notify4(notification);
|
|
5636
5665
|
}
|
|
5637
5666
|
return blocked;
|
|
5638
5667
|
}
|
|
@@ -5642,13 +5671,13 @@ function blockLinkInLinkMove(args) {
|
|
|
5642
5671
|
const targetElement = target;
|
|
5643
5672
|
const notification = {
|
|
5644
5673
|
type: "default",
|
|
5645
|
-
message:
|
|
5674
|
+
message: __5("To drag a link to this element, first remove the link from it's parent container.", "elementor"),
|
|
5646
5675
|
id: "move-in-link-blocked",
|
|
5647
5676
|
additionalActionProps: [learnMoreActionProps]
|
|
5648
5677
|
};
|
|
5649
5678
|
const isBlocked = shouldBlock(sourceElements, [targetElement]);
|
|
5650
5679
|
if (isBlocked) {
|
|
5651
|
-
|
|
5680
|
+
notify4(notification);
|
|
5652
5681
|
}
|
|
5653
5682
|
return isBlocked;
|
|
5654
5683
|
}
|
|
@@ -5680,7 +5709,7 @@ import {
|
|
|
5680
5709
|
// src/utils/command-utils.ts
|
|
5681
5710
|
import { getElementLabel as getElementLabel2, getWidgetsCache as getWidgetsCache7 } from "@elementor/editor-elements";
|
|
5682
5711
|
import { CLASSES_PROP_KEY } from "@elementor/editor-props";
|
|
5683
|
-
import { __ as
|
|
5712
|
+
import { __ as __6 } from "@wordpress/i18n";
|
|
5684
5713
|
function hasAtomicWidgets(args) {
|
|
5685
5714
|
const { containers = [args.container] } = args;
|
|
5686
5715
|
return containers.some(isAtomicWidget);
|
|
@@ -5716,7 +5745,7 @@ function getClipboardElements(storageKey = "clipboard") {
|
|
|
5716
5745
|
}
|
|
5717
5746
|
}
|
|
5718
5747
|
function getTitleForContainers(containers) {
|
|
5719
|
-
return containers.length > 1 ?
|
|
5748
|
+
return containers.length > 1 ? __6("Elements", "elementor") : getElementLabel2(containers[0].id);
|
|
5720
5749
|
}
|
|
5721
5750
|
|
|
5722
5751
|
// src/style-commands/undoable-actions/paste-element-style.ts
|
|
@@ -5728,7 +5757,7 @@ import {
|
|
|
5728
5757
|
} from "@elementor/editor-elements";
|
|
5729
5758
|
import { ELEMENTS_STYLES_RESERVED_LABEL } from "@elementor/editor-styles-repository";
|
|
5730
5759
|
import { undoable as undoable2 } from "@elementor/editor-v1-adapters";
|
|
5731
|
-
import { __ as
|
|
5760
|
+
import { __ as __7 } from "@wordpress/i18n";
|
|
5732
5761
|
var undoablePasteElementStyle = () => undoable2(
|
|
5733
5762
|
{
|
|
5734
5763
|
do: ({ containers, newStyle }) => {
|
|
@@ -5798,7 +5827,7 @@ var undoablePasteElementStyle = () => undoable2(
|
|
|
5798
5827
|
},
|
|
5799
5828
|
{
|
|
5800
5829
|
title: ({ containers }) => getTitleForContainers(containers),
|
|
5801
|
-
subtitle:
|
|
5830
|
+
subtitle: __7("Style Pasted", "elementor")
|
|
5802
5831
|
}
|
|
5803
5832
|
);
|
|
5804
5833
|
|
|
@@ -5871,7 +5900,7 @@ import {
|
|
|
5871
5900
|
import { createElementStyle as createElementStyle3, deleteElementStyle as deleteElementStyle2, getElementStyles as getElementStyles3 } from "@elementor/editor-elements";
|
|
5872
5901
|
import { ELEMENTS_STYLES_RESERVED_LABEL as ELEMENTS_STYLES_RESERVED_LABEL2 } from "@elementor/editor-styles-repository";
|
|
5873
5902
|
import { undoable as undoable3 } from "@elementor/editor-v1-adapters";
|
|
5874
|
-
import { __ as
|
|
5903
|
+
import { __ as __8 } from "@wordpress/i18n";
|
|
5875
5904
|
var undoableResetElementStyle = () => undoable3(
|
|
5876
5905
|
{
|
|
5877
5906
|
do: ({ containers }) => {
|
|
@@ -5909,7 +5938,7 @@ var undoableResetElementStyle = () => undoable3(
|
|
|
5909
5938
|
},
|
|
5910
5939
|
{
|
|
5911
5940
|
title: ({ containers }) => getTitleForContainers(containers),
|
|
5912
|
-
subtitle:
|
|
5941
|
+
subtitle: __8("Style Reset", "elementor")
|
|
5913
5942
|
}
|
|
5914
5943
|
);
|
|
5915
5944
|
|
|
@@ -5947,6 +5976,7 @@ function init() {
|
|
|
5947
5976
|
initLinkInLinkPrevention();
|
|
5948
5977
|
initFormNestingPrevention();
|
|
5949
5978
|
initFormAncestorEnforcement();
|
|
5979
|
+
initHiddenFieldHint();
|
|
5950
5980
|
initViewReplacements();
|
|
5951
5981
|
initLegacyViews();
|
|
5952
5982
|
initSettingsTransformers();
|
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.4.0-
|
|
4
|
+
"version": "4.4.0-1137",
|
|
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.4.0-
|
|
41
|
-
"@elementor/editor-controls": "4.4.0-
|
|
42
|
-
"@elementor/editor-documents": "4.4.0-
|
|
43
|
-
"@elementor/editor-elements": "4.4.0-
|
|
44
|
-
"@elementor/editor-interactions": "4.4.0-
|
|
45
|
-
"@elementor/editor-mcp": "4.4.0-
|
|
46
|
-
"@elementor/editor-notifications": "4.4.0-
|
|
47
|
-
"@elementor/editor-props": "4.4.0-
|
|
48
|
-
"@elementor/editor-responsive": "4.4.0-
|
|
49
|
-
"@elementor/editor-styles": "4.4.0-
|
|
50
|
-
"@elementor/editor-styles-repository": "4.4.0-
|
|
51
|
-
"@elementor/editor-ui": "4.4.0-
|
|
52
|
-
"@elementor/editor-v1-adapters": "4.4.0-
|
|
53
|
-
"@elementor/events": "4.4.0-
|
|
54
|
-
"@elementor/http-client": "4.4.0-
|
|
55
|
-
"@elementor/schema": "4.4.0-
|
|
56
|
-
"@elementor/twing": "4.4.0-
|
|
40
|
+
"@elementor/editor": "4.4.0-1137",
|
|
41
|
+
"@elementor/editor-controls": "4.4.0-1137",
|
|
42
|
+
"@elementor/editor-documents": "4.4.0-1137",
|
|
43
|
+
"@elementor/editor-elements": "4.4.0-1137",
|
|
44
|
+
"@elementor/editor-interactions": "4.4.0-1137",
|
|
45
|
+
"@elementor/editor-mcp": "4.4.0-1137",
|
|
46
|
+
"@elementor/editor-notifications": "4.4.0-1137",
|
|
47
|
+
"@elementor/editor-props": "4.4.0-1137",
|
|
48
|
+
"@elementor/editor-responsive": "4.4.0-1137",
|
|
49
|
+
"@elementor/editor-styles": "4.4.0-1137",
|
|
50
|
+
"@elementor/editor-styles-repository": "4.4.0-1137",
|
|
51
|
+
"@elementor/editor-ui": "4.4.0-1137",
|
|
52
|
+
"@elementor/editor-v1-adapters": "4.4.0-1137",
|
|
53
|
+
"@elementor/events": "4.4.0-1137",
|
|
54
|
+
"@elementor/http-client": "4.4.0-1137",
|
|
55
|
+
"@elementor/schema": "4.4.0-1137",
|
|
56
|
+
"@elementor/twing": "4.4.0-1137",
|
|
57
57
|
"@elementor/ui": "1.41.3",
|
|
58
|
-
"@elementor/utils": "4.4.0-
|
|
59
|
-
"@elementor/wp-media": "4.4.0-
|
|
58
|
+
"@elementor/utils": "4.4.0-1137",
|
|
59
|
+
"@elementor/wp-media": "4.4.0-1137",
|
|
60
60
|
"@floating-ui/react": "^0.27.5",
|
|
61
61
|
"@wordpress/i18n": "^5.13.0",
|
|
62
62
|
"dompurify": "^3.2.6"
|
|
@@ -114,6 +114,16 @@ describe( 'form-structure utils', () => {
|
|
|
114
114
|
expect( errors[ 0 ] ).toContain( 'e-form-input' );
|
|
115
115
|
expect( errors[ 0 ] ).toContain( 'e-form' );
|
|
116
116
|
} );
|
|
117
|
+
it( 'returns an error when a hidden field has no e-form ancestor (invalid)', () => {
|
|
118
|
+
const xml = parseXml( `
|
|
119
|
+
<e-flexbox>
|
|
120
|
+
<e-form-hidden />
|
|
121
|
+
</e-flexbox>
|
|
122
|
+
` );
|
|
123
|
+
const errors = collectFormAncestorErrors( xml );
|
|
124
|
+
expect( errors ).toHaveLength( 1 );
|
|
125
|
+
expect( errors[ 0 ] ).toContain( 'e-form-hidden' );
|
|
126
|
+
} );
|
|
117
127
|
it( 'returns an error for each orphaned form field', () => {
|
|
118
128
|
const xml = parseXml( `
|
|
119
129
|
<e-flexbox>
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { createHooksRegistry, setupHooksRegistry } from 'test-utils';
|
|
2
|
+
import { notify } from '@elementor/editor-notifications';
|
|
3
|
+
|
|
4
|
+
import { initHiddenFieldHint } from '../hidden-field-hint';
|
|
5
|
+
|
|
6
|
+
jest.mock( '@elementor/editor-notifications', () => ( {
|
|
7
|
+
notify: jest.fn(),
|
|
8
|
+
} ) );
|
|
9
|
+
|
|
10
|
+
const CREATE_COMMAND = 'document/elements/create';
|
|
11
|
+
const MOVE_COMMAND = 'document/elements/move';
|
|
12
|
+
const HIDDEN_FIELD_TYPE = 'e-form-hidden';
|
|
13
|
+
|
|
14
|
+
describe( 'hidden field hint', () => {
|
|
15
|
+
const hooksRegistry = createHooksRegistry();
|
|
16
|
+
|
|
17
|
+
beforeEach( () => {
|
|
18
|
+
jest.mocked( notify ).mockClear();
|
|
19
|
+
setupHooksRegistry( hooksRegistry );
|
|
20
|
+
initHiddenFieldHint();
|
|
21
|
+
} );
|
|
22
|
+
|
|
23
|
+
it( 'should notify when a hidden field is added', () => {
|
|
24
|
+
// Arrange
|
|
25
|
+
const hook = hooksRegistry.getByCommand( CREATE_COMMAND );
|
|
26
|
+
|
|
27
|
+
// Act
|
|
28
|
+
hook?.apply( { model: { widgetType: HIDDEN_FIELD_TYPE } } );
|
|
29
|
+
|
|
30
|
+
// Assert
|
|
31
|
+
expect( notify ).toHaveBeenCalledWith(
|
|
32
|
+
expect.objectContaining( {
|
|
33
|
+
message: 'Hidden field added - invisible on your form. Manage it in the Structure panel.',
|
|
34
|
+
} )
|
|
35
|
+
);
|
|
36
|
+
} );
|
|
37
|
+
|
|
38
|
+
it( 'should use unique notification ids for back-to-back adds (not collapsed by the notification system)', () => {
|
|
39
|
+
// Arrange
|
|
40
|
+
const hook = hooksRegistry.getByCommand( CREATE_COMMAND );
|
|
41
|
+
|
|
42
|
+
// Act
|
|
43
|
+
hook?.apply( { model: { widgetType: HIDDEN_FIELD_TYPE } } );
|
|
44
|
+
hook?.apply( { model: { widgetType: HIDDEN_FIELD_TYPE } } );
|
|
45
|
+
|
|
46
|
+
// Assert
|
|
47
|
+
expect( notify ).toHaveBeenCalledTimes( 2 );
|
|
48
|
+
const firstCallId = jest.mocked( notify ).mock.calls[ 0 ][ 0 ].id;
|
|
49
|
+
const secondCallId = jest.mocked( notify ).mock.calls[ 1 ][ 0 ].id;
|
|
50
|
+
expect( firstCallId ).not.toBe( secondCallId );
|
|
51
|
+
} );
|
|
52
|
+
|
|
53
|
+
it( 'should notify again after remove and re-add (simulated by separate create calls)', () => {
|
|
54
|
+
// Arrange
|
|
55
|
+
const hook = hooksRegistry.getByCommand( CREATE_COMMAND );
|
|
56
|
+
|
|
57
|
+
// Act - first add
|
|
58
|
+
hook?.apply( { model: { widgetType: HIDDEN_FIELD_TYPE } } );
|
|
59
|
+
|
|
60
|
+
// simulate removal (no hook for delete affects this)
|
|
61
|
+
|
|
62
|
+
// Act - re-add
|
|
63
|
+
hook?.apply( { model: { widgetType: HIDDEN_FIELD_TYPE } } );
|
|
64
|
+
|
|
65
|
+
// Assert
|
|
66
|
+
expect( notify ).toHaveBeenCalledTimes( 2 );
|
|
67
|
+
} );
|
|
68
|
+
|
|
69
|
+
it( 'should not notify when another element type is created', () => {
|
|
70
|
+
// Arrange
|
|
71
|
+
const hook = hooksRegistry.getByCommand( CREATE_COMMAND );
|
|
72
|
+
|
|
73
|
+
// Act
|
|
74
|
+
hook?.apply( { model: { widgetType: 'e-form-input' } } );
|
|
75
|
+
|
|
76
|
+
// Assert
|
|
77
|
+
expect( notify ).not.toHaveBeenCalled();
|
|
78
|
+
} );
|
|
79
|
+
|
|
80
|
+
it( 'should not notify when the hidden field is created as part of a move', () => {
|
|
81
|
+
// Arrange
|
|
82
|
+
const hook = hooksRegistry.getByCommand( CREATE_COMMAND );
|
|
83
|
+
const eWindow = window as unknown as { $e: { commands?: { currentTrace?: string[] } } };
|
|
84
|
+
eWindow.$e.commands = { currentTrace: [ MOVE_COMMAND, CREATE_COMMAND ] };
|
|
85
|
+
|
|
86
|
+
// Act
|
|
87
|
+
hook?.apply( { model: { widgetType: HIDDEN_FIELD_TYPE } } );
|
|
88
|
+
|
|
89
|
+
// Assert
|
|
90
|
+
expect( notify ).not.toHaveBeenCalled();
|
|
91
|
+
} );
|
|
92
|
+
|
|
93
|
+
it( 'should not notify on selection (selection does not trigger create command)', () => {
|
|
94
|
+
// Arrange - selection uses a different command path, not document/elements/create
|
|
95
|
+
const hook = hooksRegistry.getByCommand( CREATE_COMMAND );
|
|
96
|
+
|
|
97
|
+
// Act - no create call is made for selection
|
|
98
|
+
// Selection triggers commands like document/elements/toggle-selection, not create
|
|
99
|
+
|
|
100
|
+
// Assert
|
|
101
|
+
expect( hook ).toBeDefined();
|
|
102
|
+
expect( notify ).not.toHaveBeenCalled();
|
|
103
|
+
} );
|
|
104
|
+
|
|
105
|
+
it( 'should notify on paste when it triggers create (current behavior: paste triggers toast)', () => {
|
|
106
|
+
// Arrange
|
|
107
|
+
const hook = hooksRegistry.getByCommand( CREATE_COMMAND );
|
|
108
|
+
|
|
109
|
+
// Act - paste internally calls create, so it will trigger the notification
|
|
110
|
+
hook?.apply( { model: { widgetType: HIDDEN_FIELD_TYPE } } );
|
|
111
|
+
|
|
112
|
+
// Assert
|
|
113
|
+
expect( notify ).toHaveBeenCalledTimes( 1 );
|
|
114
|
+
} );
|
|
115
|
+
|
|
116
|
+
it( 'should notify on duplicate when it triggers create (current behavior: duplicate triggers toast)', () => {
|
|
117
|
+
// Arrange
|
|
118
|
+
const hook = hooksRegistry.getByCommand( CREATE_COMMAND );
|
|
119
|
+
|
|
120
|
+
// Act - duplicate internally calls create, so it will trigger the notification
|
|
121
|
+
hook?.apply( { model: { widgetType: HIDDEN_FIELD_TYPE } } );
|
|
122
|
+
|
|
123
|
+
// Assert
|
|
124
|
+
expect( notify ).toHaveBeenCalledTimes( 1 );
|
|
125
|
+
} );
|
|
126
|
+
|
|
127
|
+
it( 'should notify on undo of delete (undo-delete triggers create, so toast shows)', () => {
|
|
128
|
+
// Arrange
|
|
129
|
+
const hook = hooksRegistry.getByCommand( CREATE_COMMAND );
|
|
130
|
+
|
|
131
|
+
// Act - undo of a delete restores via create command
|
|
132
|
+
hook?.apply( { model: { widgetType: HIDDEN_FIELD_TYPE } } );
|
|
133
|
+
|
|
134
|
+
// Assert
|
|
135
|
+
expect( notify ).toHaveBeenCalledTimes( 1 );
|
|
136
|
+
} );
|
|
137
|
+
} );
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type NotificationData, notify } from '@elementor/editor-notifications';
|
|
2
|
+
import { type HookOptions, registerDataHook } from '@elementor/editor-v1-adapters';
|
|
3
|
+
import { __ } from '@wordpress/i18n';
|
|
4
|
+
|
|
5
|
+
import { type CreateArgs, FORM_HIDDEN_FIELD_ELEMENT_TYPE, getArgsElementType } from './utils';
|
|
6
|
+
|
|
7
|
+
const MOVE_COMMAND = 'document/elements/move';
|
|
8
|
+
|
|
9
|
+
let notificationCounter = 0;
|
|
10
|
+
|
|
11
|
+
function createHiddenFieldNotification(): NotificationData {
|
|
12
|
+
return {
|
|
13
|
+
type: 'default',
|
|
14
|
+
message: __( 'Hidden field added - invisible on your form. Manage it in the Structure panel.', 'elementor' ),
|
|
15
|
+
id: `hidden-field-added-${ ++notificationCounter }`,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function initHiddenFieldHint() {
|
|
20
|
+
registerDataHook( 'after', 'document/elements/create', ( args: CreateArgs, _result, options?: HookOptions ) => {
|
|
21
|
+
if ( options?.commandsCurrentTrace?.includes( MOVE_COMMAND ) ) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if ( getArgsElementType( args ) === FORM_HIDDEN_FIELD_ELEMENT_TYPE ) {
|
|
26
|
+
notify( createHiddenFieldNotification() );
|
|
27
|
+
}
|
|
28
|
+
} );
|
|
29
|
+
}
|
|
@@ -35,6 +35,7 @@ export type StorageContent = {
|
|
|
35
35
|
};
|
|
36
36
|
|
|
37
37
|
export const FORM_ELEMENT_TYPE = 'e-form';
|
|
38
|
+
export const FORM_HIDDEN_FIELD_ELEMENT_TYPE = 'e-form-hidden';
|
|
38
39
|
export const FORM_FIELD_ELEMENT_TYPES = new Set( [
|
|
39
40
|
'e-form-input',
|
|
40
41
|
'e-form-textarea',
|
|
@@ -46,6 +47,7 @@ export const FORM_FIELD_ELEMENT_TYPES = new Set( [
|
|
|
46
47
|
'e-form-file-upload',
|
|
47
48
|
'e-form-date-picker',
|
|
48
49
|
'e-form-time-picker',
|
|
50
|
+
FORM_HIDDEN_FIELD_ELEMENT_TYPE,
|
|
49
51
|
] );
|
|
50
52
|
|
|
51
53
|
export function getArgsElementType( args: CreateArgs ): string | undefined {
|
package/src/init.tsx
CHANGED
|
@@ -6,6 +6,7 @@ import { ElementsOverlays } from './components/elements-overlays';
|
|
|
6
6
|
import { InteractionsRenderer } from './components/interactions-renderer';
|
|
7
7
|
import { StyleRenderer } from './components/style-renderer';
|
|
8
8
|
import { initFormAncestorEnforcement } from './form-structure/enforce-form-ancestor-commands';
|
|
9
|
+
import { initHiddenFieldHint } from './form-structure/hidden-field-hint';
|
|
9
10
|
import { initFormNestingPrevention } from './form-structure/prevent-form-nesting-commands';
|
|
10
11
|
import { initSettingsTransformers } from './init-settings-transformers';
|
|
11
12
|
import { initStyleTransformers } from './init-style-transformers';
|
|
@@ -25,6 +26,7 @@ export function init() {
|
|
|
25
26
|
initLinkInLinkPrevention();
|
|
26
27
|
initFormNestingPrevention();
|
|
27
28
|
initFormAncestorEnforcement();
|
|
29
|
+
initHiddenFieldHint();
|
|
28
30
|
|
|
29
31
|
initViewReplacements();
|
|
30
32
|
|
|
@@ -22,7 +22,9 @@ const convertBlocks = async (
|
|
|
22
22
|
): Promise< Record< string, CssConversionResult > > => {
|
|
23
23
|
const { data } = await httpService().post< HttpResponse< Record< string, CssConversionResult > > >(
|
|
24
24
|
CSS_TO_ATOMIC_URL,
|
|
25
|
-
{
|
|
25
|
+
{
|
|
26
|
+
blocks,
|
|
27
|
+
}
|
|
26
28
|
);
|
|
27
29
|
|
|
28
30
|
return data.data;
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
import { resetFontAwesome7IconsCache } from '@elementor/editor-controls';
|
|
1
|
+
import {
|
|
2
|
+
registerIconLibraryProvider,
|
|
3
|
+
resetFontAwesome7IconsCache,
|
|
4
|
+
unregisterIconLibraryProvider,
|
|
5
|
+
} from '@elementor/editor-controls';
|
|
8
6
|
import { iconPropTypeUtil, stringPropTypeUtil } from '@elementor/editor-props';
|
|
9
7
|
|
|
10
8
|
import { iconPropType } from '../../../__tests__/prop-types';
|
|
@@ -186,15 +184,12 @@ describe( 'iconTransformer', () => {
|
|
|
186
184
|
expect( result ).toEqual( { html: null, url: null } );
|
|
187
185
|
} );
|
|
188
186
|
|
|
189
|
-
it( 'falls back to the default svg when
|
|
187
|
+
it( 'falls back to the default svg when no provider resolves a non-native library', async () => {
|
|
190
188
|
// Arrange.
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
},
|
|
196
|
-
},
|
|
197
|
-
} as typeof window.elementor;
|
|
189
|
+
registerIconLibraryProvider( {
|
|
190
|
+
id: 'test-provider',
|
|
191
|
+
useIcons: () => ( { data: [], isLoading: false } ),
|
|
192
|
+
} );
|
|
198
193
|
const defaultSvg =
|
|
199
194
|
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50"><path d="M24.9999 4.31543"></path></svg>';
|
|
200
195
|
global.fetch = jest.fn().mockResolvedValue( {
|
|
@@ -206,6 +201,8 @@ describe( 'iconTransformer', () => {
|
|
|
206
201
|
// Act.
|
|
207
202
|
const result = await resolveSavedIcon( 'missing-set missing-set-ghost', 'missing-set' );
|
|
208
203
|
|
|
204
|
+
unregisterIconLibraryProvider( 'test-provider' );
|
|
205
|
+
|
|
209
206
|
// Assert.
|
|
210
207
|
expect( global.fetch ).toHaveBeenCalledWith(
|
|
211
208
|
'https://example.com/assets/images/default-svg.svg',
|
|
@@ -217,6 +214,59 @@ describe( 'iconTransformer', () => {
|
|
|
217
214
|
} );
|
|
218
215
|
} );
|
|
219
216
|
|
|
217
|
+
it( 'falls back to the default svg for a non-native library when no provider is registered', async () => {
|
|
218
|
+
// Arrange.
|
|
219
|
+
const defaultSvg =
|
|
220
|
+
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50"><path d="M24.9999 4.31543"></path></svg>';
|
|
221
|
+
global.fetch = jest.fn().mockResolvedValue( {
|
|
222
|
+
ok: true,
|
|
223
|
+
headers: new Headers( { 'content-type': 'image/svg+xml' } ),
|
|
224
|
+
text: () => Promise.resolve( defaultSvg ),
|
|
225
|
+
} );
|
|
226
|
+
|
|
227
|
+
// Act.
|
|
228
|
+
const result = await resolveSavedIcon( 'my-set my-set-star', 'my-set' );
|
|
229
|
+
|
|
230
|
+
// Assert.
|
|
231
|
+
expect( result ).toEqual( {
|
|
232
|
+
html: expect.stringContaining( 'M24.9999 4.31543' ),
|
|
233
|
+
url: 'https://example.com/assets/images/default-svg.svg',
|
|
234
|
+
} );
|
|
235
|
+
} );
|
|
236
|
+
|
|
237
|
+
it( 'does not replace PHP-managed eicons with the default svg', async () => {
|
|
238
|
+
// Arrange.
|
|
239
|
+
global.fetch = jest.fn();
|
|
240
|
+
|
|
241
|
+
// Act.
|
|
242
|
+
const result = await resolveSavedIcon( 'eicon-edit', 'eicons' );
|
|
243
|
+
|
|
244
|
+
// Assert.
|
|
245
|
+
expect( result ).toEqual( { html: null, url: null } );
|
|
246
|
+
expect( global.fetch ).not.toHaveBeenCalled();
|
|
247
|
+
} );
|
|
248
|
+
|
|
249
|
+
it( 'renders and sanitizes svg returned by a provider', async () => {
|
|
250
|
+
// Arrange.
|
|
251
|
+
registerIconLibraryProvider( {
|
|
252
|
+
id: 'test-provider',
|
|
253
|
+
useIcons: () => ( { data: [], isLoading: false } ),
|
|
254
|
+
resolveSvg: () =>
|
|
255
|
+
Promise.resolve(
|
|
256
|
+
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10"><script>alert(1)</script><path d="M1 1h8v8H1z"></path></svg>'
|
|
257
|
+
),
|
|
258
|
+
} );
|
|
259
|
+
|
|
260
|
+
// Act.
|
|
261
|
+
const result = ( await resolveSavedIcon( 'my-set my-set-star', 'my-set' ) ) as { html: string };
|
|
262
|
+
|
|
263
|
+
unregisterIconLibraryProvider( 'test-provider' );
|
|
264
|
+
|
|
265
|
+
// Assert.
|
|
266
|
+
expect( result.html ).toContain( 'M1 1h8v8H1z' );
|
|
267
|
+
expect( result.html ).not.toContain( 'script' );
|
|
268
|
+
} );
|
|
269
|
+
|
|
220
270
|
it( 'returns null html when value or library is missing', async () => {
|
|
221
271
|
// Act.
|
|
222
272
|
const resolve = createPropsResolver( {
|
|
@@ -47,7 +47,10 @@ describe( 'svgSrcTransformer', () => {
|
|
|
47
47
|
const result = ( await svgSrcTransformer(
|
|
48
48
|
{ id: null, url: 'https://example.com/icon.svg' },
|
|
49
49
|
{ key: 'svg' }
|
|
50
|
-
) ) as {
|
|
50
|
+
) ) as {
|
|
51
|
+
html: string;
|
|
52
|
+
url: string;
|
|
53
|
+
};
|
|
51
54
|
|
|
52
55
|
// Assert.
|
|
53
56
|
expect( result.html ).toContain( 'width: 100%' );
|
|
@@ -91,7 +94,10 @@ describe( 'svgSrcTransformer', () => {
|
|
|
91
94
|
const result = ( await svgSrcTransformer(
|
|
92
95
|
{ id: 99, url: 'https://example.com/fallback.svg' },
|
|
93
96
|
{ key: 'svg' }
|
|
94
|
-
) ) as {
|
|
97
|
+
) ) as {
|
|
98
|
+
html: string;
|
|
99
|
+
url: string;
|
|
100
|
+
};
|
|
95
101
|
|
|
96
102
|
// Assert.
|
|
97
103
|
expect( result.url ).toBe( 'https://example.com/fallback.svg' );
|
|
@@ -146,7 +152,10 @@ describe( 'svgSrcTransformer', () => {
|
|
|
146
152
|
const result = ( await svgSrcTransformer(
|
|
147
153
|
{ id: null, url: 'https://example.com/styled.svg' },
|
|
148
154
|
{ key: 'svg' }
|
|
149
|
-
) ) as {
|
|
155
|
+
) ) as {
|
|
156
|
+
html: string;
|
|
157
|
+
url: string;
|
|
158
|
+
};
|
|
150
159
|
|
|
151
160
|
// Assert.
|
|
152
161
|
expect( result.html ).toContain( 'display: block' );
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type FontAwesome7IconDefinition,
|
|
3
3
|
getFontAwesome7IconName,
|
|
4
|
-
isDeletedCustomIconLibrary,
|
|
5
|
-
resolveCustomIconSvg,
|
|
6
4
|
resolveFontAwesome7Icon,
|
|
5
|
+
resolveProviderIconSvg,
|
|
7
6
|
} from '@elementor/editor-controls';
|
|
8
7
|
|
|
9
8
|
import { createTransformer } from '../create-transformer';
|
|
@@ -14,6 +13,8 @@ import { svgSrcTransformer } from './svg-src-transformer';
|
|
|
14
13
|
const EMPTY_ICON_RESULT = { html: null, url: null };
|
|
15
14
|
const ICON_SVG_SIZE = '100%';
|
|
16
15
|
const ICON_SVG_OVERFLOW = 'visible';
|
|
16
|
+
const FONT_AWESOME_LIBRARY_PREFIX = 'fa-';
|
|
17
|
+
const EICONS_LIBRARY = 'eicons';
|
|
17
18
|
const DEFAULT_SVG_RELATIVE_PATH = 'images/default-svg.svg';
|
|
18
19
|
|
|
19
20
|
type IconValue = {
|
|
@@ -35,17 +36,17 @@ export const iconTransformer = createTransformer( async ( value: IconValue, { si
|
|
|
35
36
|
return { html: fontAwesomeHtml, url: null };
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
if (
|
|
39
|
-
return
|
|
39
|
+
if ( library.startsWith( FONT_AWESOME_LIBRARY_PREFIX ) || EICONS_LIBRARY === library ) {
|
|
40
|
+
return EMPTY_ICON_RESULT;
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
const
|
|
43
|
+
const providerHtml = await resolveProviderSvg( library, iconValue, signal );
|
|
43
44
|
|
|
44
|
-
if (
|
|
45
|
-
return { html:
|
|
45
|
+
if ( providerHtml ) {
|
|
46
|
+
return { html: providerHtml, url: null };
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
return
|
|
49
|
+
return resolveDefaultSvg( signal );
|
|
49
50
|
} );
|
|
50
51
|
|
|
51
52
|
async function resolveDefaultSvg( signal?: AbortSignal ) {
|
|
@@ -64,8 +65,12 @@ async function resolveDefaultSvg( signal?: AbortSignal ) {
|
|
|
64
65
|
);
|
|
65
66
|
}
|
|
66
67
|
|
|
67
|
-
async function
|
|
68
|
-
|
|
68
|
+
async function resolveProviderSvg(
|
|
69
|
+
library: string,
|
|
70
|
+
iconValue: string,
|
|
71
|
+
signal?: AbortSignal
|
|
72
|
+
): Promise< string | null > {
|
|
73
|
+
const markup = await resolveProviderIconSvg( library, iconValue, signal );
|
|
69
74
|
|
|
70
75
|
return markup ? processIconSvgContent( markup ) : null;
|
|
71
76
|
}
|