@elementor/editor-canvas 4.1.0-736 → 4.1.0-737

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 CHANGED
@@ -586,7 +586,7 @@ function usePortalContainer() {
586
586
 
587
587
  // src/components/style-renderer.tsx
588
588
  var React4 = __toESM(require("react"));
589
- var import_editor_v1_adapters8 = require("@elementor/editor-v1-adapters");
589
+ var import_editor_v1_adapters9 = require("@elementor/editor-v1-adapters");
590
590
  var import_ui3 = require("@elementor/ui");
591
591
 
592
592
  // src/hooks/use-documents-css-links.ts
@@ -641,7 +641,7 @@ var import_react10 = require("react");
641
641
  var import_editor_responsive2 = require("@elementor/editor-responsive");
642
642
  var import_editor_styles4 = require("@elementor/editor-styles");
643
643
  var import_editor_styles_repository2 = require("@elementor/editor-styles-repository");
644
- var import_editor_v1_adapters7 = require("@elementor/editor-v1-adapters");
644
+ var import_editor_v1_adapters8 = require("@elementor/editor-v1-adapters");
645
645
 
646
646
  // src/utils/abort-previous-runs.ts
647
647
  function abortPreviousRuns(cb) {
@@ -655,6 +655,30 @@ function abortPreviousRuns(cb) {
655
655
  };
656
656
  }
657
657
 
658
+ // src/utils/pregenerated-links-removal.ts
659
+ var import_editor_v1_adapters6 = require("@elementor/editor-v1-adapters");
660
+ var removedProviderKeys = /* @__PURE__ */ new Set();
661
+ function removeProviderPregeneratedLinks(providerKey, removePregeneratedLink) {
662
+ if (removedProviderKeys.has(providerKey)) {
663
+ return;
664
+ }
665
+ const iframeDocument = (0, import_editor_v1_adapters6.getCanvasIframeDocument)();
666
+ if (!iframeDocument) {
667
+ return;
668
+ }
669
+ const links = iframeDocument.head.querySelectorAll('link[rel="stylesheet"]');
670
+ links.forEach((link) => {
671
+ const { id, href, media } = link;
672
+ if (removePregeneratedLink({ id, href, media })) {
673
+ link.remove();
674
+ }
675
+ });
676
+ removedProviderKeys.add(providerKey);
677
+ }
678
+ function resetRemovedProviders() {
679
+ removedProviderKeys.clear();
680
+ }
681
+
658
682
  // src/utils/signalized-process.ts
659
683
  function signalizedProcess(signal, steps = []) {
660
684
  return {
@@ -677,7 +701,7 @@ function signalizedProcess(signal, steps = []) {
677
701
  // src/hooks/use-style-prop-resolver.ts
678
702
  var import_react8 = require("react");
679
703
  var import_editor_styles2 = require("@elementor/editor-styles");
680
- var import_editor_v1_adapters6 = require("@elementor/editor-v1-adapters");
704
+ var import_editor_v1_adapters7 = require("@elementor/editor-v1-adapters");
681
705
 
682
706
  // src/renderers/create-props-resolver.ts
683
707
  var import_editor_props2 = require("@elementor/editor-props");
@@ -811,7 +835,7 @@ function useStylePropResolver() {
811
835
  if (key !== "font-family" || typeof value !== "string") {
812
836
  return;
813
837
  }
814
- (0, import_editor_v1_adapters6.enqueueFont)(value);
838
+ (0, import_editor_v1_adapters7.enqueueFont)(value);
815
839
  }
816
840
  });
817
841
  }, []);
@@ -970,7 +994,8 @@ function useStyleItems() {
970
994
  };
971
995
  }, [providerAndSubscribers]);
972
996
  useOnMount(() => {
973
- (0, import_editor_v1_adapters7.registerDataHook)("after", "editor/documents/attach-preview", async () => {
997
+ (0, import_editor_v1_adapters8.registerDataHook)("after", "editor/documents/attach-preview", async () => {
998
+ resetRemovedProviders();
974
999
  const promises = providerAndSubscribers.map(async ({ subscriber }) => subscriber());
975
1000
  await Promise.all(promises);
976
1001
  });
@@ -1004,6 +1029,9 @@ function createProviderSubscriber2({ provider, renderStyles, setStyleItems, cach
1004
1029
  (abortController, previous, current) => signalizedProcess(abortController.signal).then((_, signal) => {
1005
1030
  const hasDiffInfo = current !== void 0 && previous !== void 0;
1006
1031
  const hasCache = cache.orderedIds.length > 0;
1032
+ if (hasCache && provider.isPregeneratedLink) {
1033
+ removeProviderPregeneratedLinks(provider.getKey(), provider.isPregeneratedLink);
1034
+ }
1007
1035
  if (hasDiffInfo && hasCache) {
1008
1036
  return updateItems(previous, current, signal);
1009
1037
  }
@@ -1117,7 +1145,7 @@ function StyleRenderer() {
1117
1145
  return /* @__PURE__ */ React4.createElement(import_ui3.Portal, { container }, filterUniqueStyleDefinitions(styleItems).map((item) => /* @__PURE__ */ React4.createElement("style", { key: `${item.id}-${item.breakpoint}-${item.state ?? "normal"}` }, item.value)), linksAttrs.map((attrs) => /* @__PURE__ */ React4.createElement("link", { ...attrs, key: attrs.id })));
1118
1146
  }
1119
1147
  function usePortalContainer2() {
1120
- return (0, import_editor_v1_adapters8.__privateUseListenTo)((0, import_editor_v1_adapters8.commandEndEvent)("editor/documents/attach-preview"), () => (0, import_editor_v1_adapters8.getCanvasIframeDocument)()?.head);
1148
+ return (0, import_editor_v1_adapters9.__privateUseListenTo)((0, import_editor_v1_adapters9.commandEndEvent)("editor/documents/attach-preview"), () => (0, import_editor_v1_adapters9.getCanvasIframeDocument)()?.head);
1121
1149
  }
1122
1150
  function filterUniqueStyleDefinitions(styleItems) {
1123
1151
  const seen = /* @__PURE__ */ new Map();
@@ -1140,7 +1168,7 @@ function filterUniqueStyleDefinitions(styleItems) {
1140
1168
 
1141
1169
  // src/form-structure/enforce-form-ancestor-commands.ts
1142
1170
  var import_editor_notifications = require("@elementor/editor-notifications");
1143
- var import_editor_v1_adapters9 = require("@elementor/editor-v1-adapters");
1171
+ var import_editor_v1_adapters10 = require("@elementor/editor-v1-adapters");
1144
1172
  var import_i18n = require("@wordpress/i18n");
1145
1173
 
1146
1174
  // src/form-structure/utils.ts
@@ -1200,15 +1228,15 @@ var FORM_FIELDS_OUTSIDE_ALERT = {
1200
1228
  id: "form-fields-outside-form-blocked"
1201
1229
  };
1202
1230
  function initFormAncestorEnforcement() {
1203
- (0, import_editor_v1_adapters9.blockCommand)({
1231
+ (0, import_editor_v1_adapters10.blockCommand)({
1204
1232
  command: "document/elements/create",
1205
1233
  condition: blockFormFieldCreate
1206
1234
  });
1207
- (0, import_editor_v1_adapters9.blockCommand)({
1235
+ (0, import_editor_v1_adapters10.blockCommand)({
1208
1236
  command: "document/elements/move",
1209
1237
  condition: blockFormFieldMove
1210
1238
  });
1211
- (0, import_editor_v1_adapters9.blockCommand)({
1239
+ (0, import_editor_v1_adapters10.blockCommand)({
1212
1240
  command: "document/elements/paste",
1213
1241
  condition: blockFormFieldPaste
1214
1242
  });
@@ -1257,7 +1285,7 @@ function handleBlockedFormField() {
1257
1285
 
1258
1286
  // src/form-structure/prevent-form-nesting-commands.ts
1259
1287
  var import_editor_notifications2 = require("@elementor/editor-notifications");
1260
- var import_editor_v1_adapters10 = require("@elementor/editor-v1-adapters");
1288
+ var import_editor_v1_adapters11 = require("@elementor/editor-v1-adapters");
1261
1289
  var import_i18n2 = require("@wordpress/i18n");
1262
1290
  var FORM_NESTING_ALERT = {
1263
1291
  type: "default",
@@ -1265,15 +1293,15 @@ var FORM_NESTING_ALERT = {
1265
1293
  id: "form-nesting-blocked"
1266
1294
  };
1267
1295
  function initFormNestingPrevention() {
1268
- (0, import_editor_v1_adapters10.blockCommand)({
1296
+ (0, import_editor_v1_adapters11.blockCommand)({
1269
1297
  command: "document/elements/create",
1270
1298
  condition: blockFormCreate
1271
1299
  });
1272
- (0, import_editor_v1_adapters10.blockCommand)({
1300
+ (0, import_editor_v1_adapters11.blockCommand)({
1273
1301
  command: "document/elements/move",
1274
1302
  condition: blockFormMove
1275
1303
  });
1276
- (0, import_editor_v1_adapters10.blockCommand)({
1304
+ (0, import_editor_v1_adapters11.blockCommand)({
1277
1305
  command: "document/elements/paste",
1278
1306
  condition: blockFormPaste
1279
1307
  });
@@ -1778,7 +1806,7 @@ function initStyleTransformers() {
1778
1806
 
1779
1807
  // src/legacy/init-legacy-views.ts
1780
1808
  var import_editor_elements6 = require("@elementor/editor-elements");
1781
- var import_editor_v1_adapters12 = require("@elementor/editor-v1-adapters");
1809
+ var import_editor_v1_adapters13 = require("@elementor/editor-v1-adapters");
1782
1810
 
1783
1811
  // src/renderers/create-dom-renderer.ts
1784
1812
  var import_twing = require("@elementor/twing");
@@ -2326,7 +2354,7 @@ var React6 = __toESM(require("react"));
2326
2354
  var import_client = require("react-dom/client");
2327
2355
  var import_editor_elements5 = require("@elementor/editor-elements");
2328
2356
  var import_editor_props4 = require("@elementor/editor-props");
2329
- var import_editor_v1_adapters11 = require("@elementor/editor-v1-adapters");
2357
+ var import_editor_v1_adapters12 = require("@elementor/editor-v1-adapters");
2330
2358
  var import_i18n3 = require("@wordpress/i18n");
2331
2359
 
2332
2360
  // src/legacy/replacements/base.ts
@@ -2607,7 +2635,7 @@ var InlineEditingReplacement = class extends ReplacementBase {
2607
2635
  return !!this.inlineEditorRoot;
2608
2636
  }
2609
2637
  shouldRenderReplacement() {
2610
- return this.isInlineEditingEligible() && (0, import_editor_v1_adapters11.getCurrentEditMode)() === "edit";
2638
+ return this.isInlineEditingEligible() && (0, import_editor_v1_adapters12.getCurrentEditMode)() === "edit";
2611
2639
  }
2612
2640
  handleRenderInlineEditor = () => {
2613
2641
  if (this.isEditingModeActive() || !this.isInlineEditingEligible()) {
@@ -2685,7 +2713,7 @@ var InlineEditingReplacement = class extends ReplacementBase {
2685
2713
  content: parsed.content ? import_editor_props4.stringPropTypeUtil.create(parsed.content) : null,
2686
2714
  children: parsed.children
2687
2715
  });
2688
- (0, import_editor_v1_adapters11.undoable)(
2716
+ (0, import_editor_v1_adapters12.undoable)(
2689
2717
  {
2690
2718
  do: () => {
2691
2719
  const prevValue = this.getInlineEditablePropValue();
@@ -2727,7 +2755,7 @@ var InlineEditingReplacement = class extends ReplacementBase {
2727
2755
  return null;
2728
2756
  }
2729
2757
  runCommand(key, value) {
2730
- (0, import_editor_v1_adapters11.__privateRunCommandSync)(
2758
+ (0, import_editor_v1_adapters12.__privateRunCommandSync)(
2731
2759
  "document/elements/set-settings",
2732
2760
  {
2733
2761
  container: (0, import_editor_elements5.getContainer)(this.id),
@@ -2737,7 +2765,7 @@ var InlineEditingReplacement = class extends ReplacementBase {
2737
2765
  },
2738
2766
  { internal: true }
2739
2767
  );
2740
- (0, import_editor_v1_adapters11.__privateRunCommandSync)("document/save/set-is-modified", { status: true }, { internal: true });
2768
+ (0, import_editor_v1_adapters12.__privateRunCommandSync)("document/save/set-is-modified", { status: true }, { internal: true });
2741
2769
  }
2742
2770
  getExpectedTag() {
2743
2771
  const tagPropType = this.getTagPropType();
@@ -2889,7 +2917,7 @@ function registerElementType(type, elementTypeGenerator) {
2889
2917
  elementsLegacyTypes[type] = elementTypeGenerator;
2890
2918
  }
2891
2919
  function initLegacyViews() {
2892
- (0, import_editor_v1_adapters12.__privateListenTo)((0, import_editor_v1_adapters12.v1ReadyEvent)(), () => {
2920
+ (0, import_editor_v1_adapters13.__privateListenTo)((0, import_editor_v1_adapters13.v1ReadyEvent)(), () => {
2893
2921
  const widgetsCache = (0, import_editor_elements6.getWidgetsCache)() ?? {};
2894
2922
  const legacyWindow = window;
2895
2923
  const renderer = createDomRenderer();
@@ -2968,7 +2996,7 @@ function initTabsModelExtensions() {
2968
2996
  }
2969
2997
 
2970
2998
  // src/mcp/resources/document-structure-resource.ts
2971
- var import_editor_v1_adapters13 = require("@elementor/editor-v1-adapters");
2999
+ var import_editor_v1_adapters14 = require("@elementor/editor-v1-adapters");
2972
3000
  var DOCUMENT_STRUCTURE_URI = "elementor://document/structure";
2973
3001
  var initDocumentStructureResource = (reg) => {
2974
3002
  const { resource, sendResourceUpdated } = reg;
@@ -2981,14 +3009,14 @@ var initDocumentStructureResource = (reg) => {
2981
3009
  sendResourceUpdated({ uri: DOCUMENT_STRUCTURE_URI });
2982
3010
  }
2983
3011
  };
2984
- (0, import_editor_v1_adapters13.__privateListenTo)(
3012
+ (0, import_editor_v1_adapters14.__privateListenTo)(
2985
3013
  [
2986
- (0, import_editor_v1_adapters13.commandEndEvent)("document/elements/create"),
2987
- (0, import_editor_v1_adapters13.commandEndEvent)("document/elements/delete"),
2988
- (0, import_editor_v1_adapters13.commandEndEvent)("document/elements/move"),
2989
- (0, import_editor_v1_adapters13.commandEndEvent)("document/elements/copy"),
2990
- (0, import_editor_v1_adapters13.commandEndEvent)("document/elements/paste"),
2991
- (0, import_editor_v1_adapters13.commandEndEvent)("editor/documents/attach-preview")
3014
+ (0, import_editor_v1_adapters14.commandEndEvent)("document/elements/create"),
3015
+ (0, import_editor_v1_adapters14.commandEndEvent)("document/elements/delete"),
3016
+ (0, import_editor_v1_adapters14.commandEndEvent)("document/elements/move"),
3017
+ (0, import_editor_v1_adapters14.commandEndEvent)("document/elements/copy"),
3018
+ (0, import_editor_v1_adapters14.commandEndEvent)("document/elements/paste"),
3019
+ (0, import_editor_v1_adapters14.commandEndEvent)("editor/documents/attach-preview")
2992
3020
  ],
2993
3021
  updateDocumentStructure
2994
3022
  );
@@ -4197,14 +4225,14 @@ Note: The "size" property controls image resolution/loading, not visual size. Se
4197
4225
  // src/prevent-link-in-link-commands.ts
4198
4226
  var import_editor_elements12 = require("@elementor/editor-elements");
4199
4227
  var import_editor_notifications3 = require("@elementor/editor-notifications");
4200
- var import_editor_v1_adapters14 = require("@elementor/editor-v1-adapters");
4228
+ var import_editor_v1_adapters15 = require("@elementor/editor-v1-adapters");
4201
4229
  var import_i18n4 = require("@wordpress/i18n");
4202
4230
  function initLinkInLinkPrevention() {
4203
- (0, import_editor_v1_adapters14.blockCommand)({
4231
+ (0, import_editor_v1_adapters15.blockCommand)({
4204
4232
  command: "document/elements/paste",
4205
4233
  condition: blockLinkInLinkPaste
4206
4234
  });
4207
- (0, import_editor_v1_adapters14.blockCommand)({
4235
+ (0, import_editor_v1_adapters15.blockCommand)({
4208
4236
  command: "document/elements/move",
4209
4237
  condition: blockLinkInLinkMove
4210
4238
  });
@@ -4280,7 +4308,7 @@ function shouldBlock(sourceElements, targetElements) {
4280
4308
  // src/style-commands/paste-style.ts
4281
4309
  var import_editor_elements15 = require("@elementor/editor-elements");
4282
4310
  var import_editor_props10 = require("@elementor/editor-props");
4283
- var import_editor_v1_adapters16 = require("@elementor/editor-v1-adapters");
4311
+ var import_editor_v1_adapters17 = require("@elementor/editor-v1-adapters");
4284
4312
 
4285
4313
  // src/utils/command-utils.ts
4286
4314
  var import_editor_elements13 = require("@elementor/editor-elements");
@@ -4327,9 +4355,9 @@ function getTitleForContainers(containers) {
4327
4355
  // src/style-commands/undoable-actions/paste-element-style.ts
4328
4356
  var import_editor_elements14 = require("@elementor/editor-elements");
4329
4357
  var import_editor_styles_repository4 = require("@elementor/editor-styles-repository");
4330
- var import_editor_v1_adapters15 = require("@elementor/editor-v1-adapters");
4358
+ var import_editor_v1_adapters16 = require("@elementor/editor-v1-adapters");
4331
4359
  var import_i18n6 = require("@wordpress/i18n");
4332
- var undoablePasteElementStyle = () => (0, import_editor_v1_adapters15.undoable)(
4360
+ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters16.undoable)(
4333
4361
  {
4334
4362
  do: ({ containers, newStyle }) => {
4335
4363
  return containers.map((container) => {
@@ -4405,12 +4433,12 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters15.undoable)(
4405
4433
  // src/style-commands/paste-style.ts
4406
4434
  function initPasteStyleCommand() {
4407
4435
  const pasteElementStyleCommand = undoablePasteElementStyle();
4408
- (0, import_editor_v1_adapters16.blockCommand)({
4436
+ (0, import_editor_v1_adapters17.blockCommand)({
4409
4437
  command: "document/elements/paste-style",
4410
4438
  condition: hasAtomicWidgets
4411
4439
  });
4412
- (0, import_editor_v1_adapters16.__privateListenTo)(
4413
- (0, import_editor_v1_adapters16.commandStartEvent)("document/elements/paste-style"),
4440
+ (0, import_editor_v1_adapters17.__privateListenTo)(
4441
+ (0, import_editor_v1_adapters17.commandStartEvent)("document/elements/paste-style"),
4414
4442
  (e) => pasteStyles(e.args, pasteElementStyleCommand)
4415
4443
  );
4416
4444
  }
@@ -4461,14 +4489,14 @@ function pasteClasses(containers, classes) {
4461
4489
  }
4462
4490
 
4463
4491
  // src/style-commands/reset-style.ts
4464
- var import_editor_v1_adapters18 = require("@elementor/editor-v1-adapters");
4492
+ var import_editor_v1_adapters19 = require("@elementor/editor-v1-adapters");
4465
4493
 
4466
4494
  // src/style-commands/undoable-actions/reset-element-style.ts
4467
4495
  var import_editor_elements16 = require("@elementor/editor-elements");
4468
4496
  var import_editor_styles_repository5 = require("@elementor/editor-styles-repository");
4469
- var import_editor_v1_adapters17 = require("@elementor/editor-v1-adapters");
4497
+ var import_editor_v1_adapters18 = require("@elementor/editor-v1-adapters");
4470
4498
  var import_i18n7 = require("@wordpress/i18n");
4471
- var undoableResetElementStyle = () => (0, import_editor_v1_adapters17.undoable)(
4499
+ var undoableResetElementStyle = () => (0, import_editor_v1_adapters18.undoable)(
4472
4500
  {
4473
4501
  do: ({ containers }) => {
4474
4502
  return containers.map((container) => {
@@ -4512,12 +4540,12 @@ var undoableResetElementStyle = () => (0, import_editor_v1_adapters17.undoable)(
4512
4540
  // src/style-commands/reset-style.ts
4513
4541
  function initResetStyleCommand() {
4514
4542
  const resetElementStyles = undoableResetElementStyle();
4515
- (0, import_editor_v1_adapters18.blockCommand)({
4543
+ (0, import_editor_v1_adapters19.blockCommand)({
4516
4544
  command: "document/elements/reset-style",
4517
4545
  condition: hasAtomicWidgets
4518
4546
  });
4519
- (0, import_editor_v1_adapters18.__privateListenTo)(
4520
- (0, import_editor_v1_adapters18.commandStartEvent)("document/elements/reset-style"),
4547
+ (0, import_editor_v1_adapters19.__privateListenTo)(
4548
+ (0, import_editor_v1_adapters19.commandStartEvent)("document/elements/reset-style"),
4521
4549
  (e) => resetStyles(e.args, resetElementStyles)
4522
4550
  );
4523
4551
  }
package/dist/index.mjs CHANGED
@@ -543,7 +543,7 @@ import * as React4 from "react";
543
543
  import {
544
544
  __privateUseListenTo as useListenTo4,
545
545
  commandEndEvent as commandEndEvent3,
546
- getCanvasIframeDocument as getCanvasIframeDocument3
546
+ getCanvasIframeDocument as getCanvasIframeDocument4
547
547
  } from "@elementor/editor-v1-adapters";
548
548
  import { Portal as Portal2 } from "@elementor/ui";
549
549
 
@@ -617,6 +617,30 @@ function abortPreviousRuns(cb) {
617
617
  };
618
618
  }
619
619
 
620
+ // src/utils/pregenerated-links-removal.ts
621
+ import { getCanvasIframeDocument as getCanvasIframeDocument3 } from "@elementor/editor-v1-adapters";
622
+ var removedProviderKeys = /* @__PURE__ */ new Set();
623
+ function removeProviderPregeneratedLinks(providerKey, removePregeneratedLink) {
624
+ if (removedProviderKeys.has(providerKey)) {
625
+ return;
626
+ }
627
+ const iframeDocument = getCanvasIframeDocument3();
628
+ if (!iframeDocument) {
629
+ return;
630
+ }
631
+ const links = iframeDocument.head.querySelectorAll('link[rel="stylesheet"]');
632
+ links.forEach((link) => {
633
+ const { id, href, media } = link;
634
+ if (removePregeneratedLink({ id, href, media })) {
635
+ link.remove();
636
+ }
637
+ });
638
+ removedProviderKeys.add(providerKey);
639
+ }
640
+ function resetRemovedProviders() {
641
+ removedProviderKeys.clear();
642
+ }
643
+
620
644
  // src/utils/signalized-process.ts
621
645
  function signalizedProcess(signal, steps = []) {
622
646
  return {
@@ -937,6 +961,7 @@ function useStyleItems() {
937
961
  }, [providerAndSubscribers]);
938
962
  useOnMount(() => {
939
963
  registerDataHook2("after", "editor/documents/attach-preview", async () => {
964
+ resetRemovedProviders();
940
965
  const promises = providerAndSubscribers.map(async ({ subscriber }) => subscriber());
941
966
  await Promise.all(promises);
942
967
  });
@@ -970,6 +995,9 @@ function createProviderSubscriber2({ provider, renderStyles, setStyleItems, cach
970
995
  (abortController, previous, current) => signalizedProcess(abortController.signal).then((_, signal) => {
971
996
  const hasDiffInfo = current !== void 0 && previous !== void 0;
972
997
  const hasCache = cache.orderedIds.length > 0;
998
+ if (hasCache && provider.isPregeneratedLink) {
999
+ removeProviderPregeneratedLinks(provider.getKey(), provider.isPregeneratedLink);
1000
+ }
973
1001
  if (hasDiffInfo && hasCache) {
974
1002
  return updateItems(previous, current, signal);
975
1003
  }
@@ -1083,7 +1111,7 @@ function StyleRenderer() {
1083
1111
  return /* @__PURE__ */ React4.createElement(Portal2, { container }, filterUniqueStyleDefinitions(styleItems).map((item) => /* @__PURE__ */ React4.createElement("style", { key: `${item.id}-${item.breakpoint}-${item.state ?? "normal"}` }, item.value)), linksAttrs.map((attrs) => /* @__PURE__ */ React4.createElement("link", { ...attrs, key: attrs.id })));
1084
1112
  }
1085
1113
  function usePortalContainer2() {
1086
- return useListenTo4(commandEndEvent3("editor/documents/attach-preview"), () => getCanvasIframeDocument3()?.head);
1114
+ return useListenTo4(commandEndEvent3("editor/documents/attach-preview"), () => getCanvasIframeDocument4()?.head);
1087
1115
  }
1088
1116
  function filterUniqueStyleDefinitions(styleItems) {
1089
1117
  const seen = /* @__PURE__ */ new Map();
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.1.0-736",
4
+ "version": "4.1.0-737",
5
5
  "private": false,
6
6
  "author": "Elementor Team",
7
7
  "homepage": "https://elementor.com/",
@@ -37,24 +37,24 @@
37
37
  "react-dom": "^18.3.1"
38
38
  },
39
39
  "dependencies": {
40
- "@elementor/editor": "4.1.0-736",
41
- "@elementor/editor-controls": "4.1.0-736",
42
- "@elementor/editor-documents": "4.1.0-736",
43
- "@elementor/editor-elements": "4.1.0-736",
44
- "@elementor/editor-interactions": "4.1.0-736",
45
- "@elementor/editor-mcp": "4.1.0-736",
46
- "@elementor/editor-notifications": "4.1.0-736",
47
- "@elementor/editor-props": "4.1.0-736",
48
- "@elementor/editor-responsive": "4.1.0-736",
49
- "@elementor/editor-styles": "4.1.0-736",
50
- "@elementor/editor-styles-repository": "4.1.0-736",
51
- "@elementor/editor-ui": "4.1.0-736",
52
- "@elementor/editor-v1-adapters": "4.1.0-736",
53
- "@elementor/schema": "4.1.0-736",
54
- "@elementor/twing": "4.1.0-736",
40
+ "@elementor/editor": "4.1.0-737",
41
+ "@elementor/editor-controls": "4.1.0-737",
42
+ "@elementor/editor-documents": "4.1.0-737",
43
+ "@elementor/editor-elements": "4.1.0-737",
44
+ "@elementor/editor-interactions": "4.1.0-737",
45
+ "@elementor/editor-mcp": "4.1.0-737",
46
+ "@elementor/editor-notifications": "4.1.0-737",
47
+ "@elementor/editor-props": "4.1.0-737",
48
+ "@elementor/editor-responsive": "4.1.0-737",
49
+ "@elementor/editor-styles": "4.1.0-737",
50
+ "@elementor/editor-styles-repository": "4.1.0-737",
51
+ "@elementor/editor-ui": "4.1.0-737",
52
+ "@elementor/editor-v1-adapters": "4.1.0-737",
53
+ "@elementor/schema": "4.1.0-737",
54
+ "@elementor/twing": "4.1.0-737",
55
55
  "@elementor/ui": "1.36.17",
56
- "@elementor/utils": "4.1.0-736",
57
- "@elementor/wp-media": "4.1.0-736",
56
+ "@elementor/utils": "4.1.0-737",
57
+ "@elementor/wp-media": "4.1.0-737",
58
58
  "@floating-ui/react": "^0.27.5",
59
59
  "@wordpress/i18n": "^5.13.0"
60
60
  },
@@ -6,6 +6,7 @@ import { registerDataHook } from '@elementor/editor-v1-adapters';
6
6
 
7
7
  import { type RendererStyleDefinition, type StyleItem, type StyleRenderer } from '../renderers/create-styles-renderer';
8
8
  import { abortPreviousRuns } from '../utils/abort-previous-runs';
9
+ import { removeProviderPregeneratedLinks, resetRemovedProviders } from '../utils/pregenerated-links-removal';
9
10
  import { signalizedProcess } from '../utils/signalized-process';
10
11
  import { useOnMount } from './use-on-mount';
11
12
  import { useStylePropResolver } from './use-style-prop-resolver';
@@ -69,6 +70,8 @@ export function useStyleItems() {
69
70
 
70
71
  useOnMount( () => {
71
72
  registerDataHook( 'after', 'editor/documents/attach-preview', async () => {
73
+ resetRemovedProviders();
74
+
72
75
  const promises = providerAndSubscribers.map( async ( { subscriber } ) => subscriber() );
73
76
 
74
77
  await Promise.all( promises );
@@ -136,6 +139,11 @@ function createProviderSubscriber( { provider, renderStyles, setStyleItems, cach
136
139
  const hasDiffInfo = current !== undefined && previous !== undefined;
137
140
  const hasCache = cache.orderedIds.length > 0;
138
141
 
142
+ if ( hasCache && provider.isPregeneratedLink ) {
143
+ // if styles were rendered already (i.e. hasCache = true), we can safely remove the pregenerated css rules imported via <link /> tags
144
+ removeProviderPregeneratedLinks( provider.getKey(), provider.isPregeneratedLink );
145
+ }
146
+
139
147
  if ( hasDiffInfo && hasCache ) {
140
148
  return updateItems( previous, current, signal );
141
149
  }
@@ -0,0 +1,208 @@
1
+ import { type PregeneratedLinkItem } from '@elementor/editor-styles-repository';
2
+ import { getCanvasIframeDocument } from '@elementor/editor-v1-adapters';
3
+
4
+ import { removeProviderPregeneratedLinks, resetRemovedProviders } from '../pregenerated-links-removal';
5
+
6
+ jest.mock( '@elementor/editor-v1-adapters', () => ( {
7
+ getCanvasIframeDocument: jest.fn(),
8
+ } ) );
9
+
10
+ function createLink( id: string, href: string, media: string = 'all' ): HTMLLinkElement {
11
+ const link = document.createElement( 'link' );
12
+ link.setAttribute( 'rel', 'stylesheet' );
13
+ link.setAttribute( 'id', id );
14
+ link.setAttribute( 'href', href );
15
+ link.setAttribute( 'media', media );
16
+
17
+ return link;
18
+ }
19
+
20
+ describe( 'pregenerated-links-removal', () => {
21
+ const createHead = () => {
22
+ const head = document.createElement( 'head' );
23
+ head.appendChild( createLink( 'base-desktop-css', 'base-desktop.css' ) );
24
+ head.appendChild( createLink( 'base-tablet-css', 'base-tablet.css' ) );
25
+ head.appendChild( createLink( 'global-preview-desktop-css', 'global-preview-desktop.css' ) );
26
+ head.appendChild( createLink( 'global-preview-mobile_extra-css', 'global-preview-mobile_extra.css' ) );
27
+ head.appendChild( createLink( 'local-123-preview-desktop-css', 'local-123-preview-desktop.css' ) );
28
+ head.appendChild( createLink( 'local-456-preview-desktop-css', 'local-456-preview-desktop.css' ) );
29
+ head.appendChild( createLink( 'elementor-post-123-css', 'elementor-post-123.css' ) );
30
+ head.appendChild( createLink( 'other-plugin-css', 'other-plugin.css' ) );
31
+ return head;
32
+ };
33
+
34
+ beforeEach( () => {
35
+ resetRemovedProviders();
36
+ } );
37
+
38
+ describe( 'removeProviderPregeneratedLinks', () => {
39
+ it( 'should remove links matching global pattern', () => {
40
+ // Arrange.
41
+ const head = createHead();
42
+ const mockDocument = { head } as Document;
43
+ jest.mocked( getCanvasIframeDocument ).mockReturnValue( mockDocument );
44
+
45
+ // Act.
46
+ removeProviderPregeneratedLinks( 'global-classes', ( { id } ) =>
47
+ /^global-(preview|frontend)-[a-zA-Z_-]+-css$/.test( id )
48
+ );
49
+
50
+ // Assert.
51
+ const remainingLinkIds = Array.from( head.querySelectorAll( 'link' ) ).map( ( link ) =>
52
+ link.getAttribute( 'id' )
53
+ );
54
+
55
+ expect( remainingLinkIds ).not.toContain( 'global-preview-desktop-css' );
56
+ expect( remainingLinkIds ).not.toContain( 'global-preview-mobile_extra-css' );
57
+ expect( remainingLinkIds ).toContain( 'base-desktop-css' );
58
+ expect( remainingLinkIds ).toContain( 'local-123-preview-desktop-css' );
59
+ expect( remainingLinkIds ).toContain( 'other-plugin-css' );
60
+ } );
61
+
62
+ it( 'should remove links matching local pattern', () => {
63
+ // Arrange.
64
+ const head = createHead();
65
+ const mockDocument = { head } as Document;
66
+ jest.mocked( getCanvasIframeDocument ).mockReturnValue( mockDocument );
67
+
68
+ // Act.
69
+ removeProviderPregeneratedLinks( 'document-elements-123', ( { id } ) =>
70
+ /^local-\d+-(preview|frontend)-[a-zA-Z_-]+-css$/.test( id )
71
+ );
72
+
73
+ // Assert.
74
+ const remainingLinkIds = Array.from( head.querySelectorAll( 'link' ) ).map( ( link ) =>
75
+ link.getAttribute( 'id' )
76
+ );
77
+
78
+ expect( remainingLinkIds ).not.toContain( 'local-123-preview-desktop-css' );
79
+ expect( remainingLinkIds ).not.toContain( 'local-456-preview-desktop-css' );
80
+ expect( remainingLinkIds ).toContain( 'global-preview-desktop-css' );
81
+ expect( remainingLinkIds ).toContain( 'base-desktop-css' );
82
+ } );
83
+
84
+ it( 'should not remove links when provider was already processed', () => {
85
+ // Arrange.
86
+ const head = createHead();
87
+ const mockDocument = { head } as Document;
88
+ jest.mocked( getCanvasIframeDocument ).mockReturnValue( mockDocument );
89
+
90
+ const initialLinkCount = head.querySelectorAll( 'link' ).length;
91
+
92
+ // Act.
93
+ removeProviderPregeneratedLinks( 'global-classes', ( { id } ) =>
94
+ /^global-(preview|frontend)-[a-zA-Z_-]+-css$/.test( id )
95
+ );
96
+ const afterFirstRemoval = head.querySelectorAll( 'link' ).length;
97
+
98
+ removeProviderPregeneratedLinks( 'global-classes', ( { id } ) =>
99
+ /^global-(preview|frontend)-[a-zA-Z_-]+-css$/.test( id )
100
+ );
101
+ const afterSecondCall = head.querySelectorAll( 'link' ).length;
102
+
103
+ // Assert.
104
+ expect( afterFirstRemoval ).toBeLessThan( initialLinkCount );
105
+ expect( afterSecondCall ).toBe( afterFirstRemoval );
106
+ } );
107
+
108
+ it( 'should handle different providers independently', () => {
109
+ // Arrange.
110
+ const head = createHead();
111
+ const mockDocument = { head } as Document;
112
+ jest.mocked( getCanvasIframeDocument ).mockReturnValue( mockDocument );
113
+
114
+ // Act.
115
+ removeProviderPregeneratedLinks( 'global-classes', ( { id } ) =>
116
+ /^global-(preview|frontend)-[a-zA-Z_-]+-css$/.test( id )
117
+ );
118
+ removeProviderPregeneratedLinks( 'document-elements-123', ( { id } ) =>
119
+ /^local-\d+-(preview|frontend)-[a-zA-Z_-]+-css$/.test( id )
120
+ );
121
+
122
+ // Assert.
123
+ const remainingLinkIds = Array.from( head.querySelectorAll( 'link' ) ).map( ( link ) =>
124
+ link.getAttribute( 'id' )
125
+ );
126
+
127
+ expect( remainingLinkIds ).not.toContain( 'global-preview-desktop-css' );
128
+ expect( remainingLinkIds ).not.toContain( 'local-123-preview-desktop-css' );
129
+ expect( remainingLinkIds ).toContain( 'base-desktop-css' );
130
+ expect( remainingLinkIds ).toContain( 'elementor-post-123-css' );
131
+ expect( remainingLinkIds ).toContain( 'other-plugin-css' );
132
+ } );
133
+
134
+ it( 'should do nothing when iframe document is not available', () => {
135
+ // Arrange.
136
+ jest.mocked( getCanvasIframeDocument ).mockReturnValue( null );
137
+
138
+ // Act & Assert - should not throw.
139
+ expect( () => {
140
+ removeProviderPregeneratedLinks( 'global-classes', ( { id } ) =>
141
+ /^global-(preview|frontend)-[a-zA-Z_-]+-css$/.test( id )
142
+ );
143
+ } ).not.toThrow();
144
+ } );
145
+
146
+ it( 'should pass id, path, and media from each link to the predicate', () => {
147
+ const head = document.createElement( 'head' );
148
+
149
+ const link1Params = {
150
+ id: 'test-123',
151
+ href: 'test-123.css',
152
+ media: 'all',
153
+ };
154
+ const link2Params = {
155
+ id: 'test-456',
156
+ href: 'alternative-test-456.css',
157
+ media: 'screen and (max-width: 1024px)',
158
+ };
159
+ const link1 = createLink( link1Params.id, link1Params.href, link1Params.media );
160
+ const link2 = createLink( link2Params.id, link2Params.href, link2Params.media );
161
+ head.appendChild( link1 );
162
+ head.appendChild( link2 );
163
+
164
+ const mockDocument = { head } as Document;
165
+ jest.mocked( getCanvasIframeDocument ).mockReturnValue( mockDocument );
166
+
167
+ const received: PregeneratedLinkItem[] = [];
168
+ removeProviderPregeneratedLinks( 'pregenerated-link-attrs', ( item ) => {
169
+ received.push( item );
170
+ return false;
171
+ } );
172
+
173
+ expect( received ).toMatchObject( [
174
+ { ...link1Params, href: link1.href },
175
+ { ...link2Params, href: link2.href },
176
+ ] );
177
+ } );
178
+ } );
179
+
180
+ describe( 'resetRemovedProviders', () => {
181
+ it( 'should allow re-removal after reset', () => {
182
+ // Arrange.
183
+ const head = createHead();
184
+ const mockDocument = { head } as Document;
185
+ jest.mocked( getCanvasIframeDocument ).mockReturnValue( mockDocument );
186
+
187
+ removeProviderPregeneratedLinks( 'global-classes', ( { id } ) =>
188
+ /^global-(preview|frontend)-[a-zA-Z_-]+-css$/.test( id )
189
+ );
190
+ const countAfterFirstRemoval = head.querySelectorAll( 'link' ).length;
191
+
192
+ head.appendChild( createLink( 'global-preview-widescreen-css', 'global-preview-widescreen.css' ) );
193
+
194
+ const countAfterAddingNewLink = head.querySelectorAll( 'link' ).length;
195
+
196
+ // Act.
197
+ resetRemovedProviders();
198
+ removeProviderPregeneratedLinks( 'global-classes', ( { id } ) =>
199
+ /^global-(preview|frontend)-[a-zA-Z_-]+-css$/.test( id )
200
+ );
201
+
202
+ // Assert.
203
+ const countAfterSecondRemoval = head.querySelectorAll( 'link' ).length;
204
+ expect( countAfterAddingNewLink ).toBe( countAfterFirstRemoval + 1 );
205
+ expect( countAfterSecondRemoval ).toBe( countAfterFirstRemoval );
206
+ } );
207
+ } );
208
+ } );
@@ -0,0 +1,35 @@
1
+ import { type PregeneratedLinkItem } from '@elementor/editor-styles-repository';
2
+ import { getCanvasIframeDocument } from '@elementor/editor-v1-adapters';
3
+
4
+ const removedProviderKeys = new Set< string >();
5
+
6
+ export function removeProviderPregeneratedLinks(
7
+ providerKey: string,
8
+ removePregeneratedLink: ( pregeneratedLinkItem: PregeneratedLinkItem ) => boolean
9
+ ): void {
10
+ if ( removedProviderKeys.has( providerKey ) ) {
11
+ return;
12
+ }
13
+
14
+ const iframeDocument = getCanvasIframeDocument();
15
+
16
+ if ( ! iframeDocument ) {
17
+ return;
18
+ }
19
+
20
+ const links = iframeDocument.head.querySelectorAll< HTMLLinkElement >( 'link[rel="stylesheet"]' );
21
+
22
+ links.forEach( ( link ) => {
23
+ const { id, href, media } = link;
24
+
25
+ if ( removePregeneratedLink( { id, href, media } ) ) {
26
+ link.remove();
27
+ }
28
+ } );
29
+
30
+ removedProviderKeys.add( providerKey );
31
+ }
32
+
33
+ export function resetRemovedProviders(): void {
34
+ removedProviderKeys.clear();
35
+ }