@elementor/editor-global-classes 4.0.0-manual → 4.0.0

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.mjs CHANGED
@@ -1,6 +1,3 @@
1
- // src/mcp-integration/classes-resource.ts
2
- import { getMCPByDomain } from "@elementor/editor-mcp";
3
-
4
1
  // src/global-classes-styles-provider.ts
5
2
  import { generateId } from "@elementor/editor-styles";
6
3
  import { createStylesProvider } from "@elementor/editor-styles-repository";
@@ -359,6 +356,41 @@ var getSanitizedData = async (payload) => {
359
356
  return { ...payload, classTitle: getCssClass(payload.classId).label };
360
357
  }
361
358
  break;
359
+ case "classSyncToV3PopupShown":
360
+ return {
361
+ ...payload,
362
+ interaction_type: "popup_shown",
363
+ target_type: "popup",
364
+ target_name: "sync_to_v3_popup",
365
+ interaction_result: "popup_viewed",
366
+ target_location: "widget_panel",
367
+ location_l1: "class_manager"
368
+ };
369
+ case "classSyncToV3": {
370
+ const classLabel = getCssClass(payload.classId).label;
371
+ const isSync = payload.action === "sync";
372
+ return {
373
+ ...payload,
374
+ interaction_type: "click",
375
+ target_type: classLabel,
376
+ target_name: isSync ? "sync_to_v3" : "unsync_to_v3",
377
+ interaction_result: isSync ? "class_is_synced_to_V3" : "class_is_unsynced_from_V3",
378
+ target_location: "widget_panel",
379
+ location_l1: "class_manager",
380
+ interaction_description: isSync ? `user_synced_${classLabel}_to_v3` : `user_unsync_${classLabel}_from_v3`
381
+ };
382
+ }
383
+ case "classSyncToV3PopupClick": {
384
+ const isSyncAction = payload.action === "sync";
385
+ return {
386
+ ...payload,
387
+ interaction_type: "click",
388
+ target_type: "button",
389
+ target_name: isSyncAction ? "sync_to_v3" : "cancel",
390
+ interaction_result: isSyncAction ? "class_is_synced" : "cancel",
391
+ target_location: "sync_to_v3_popup"
392
+ };
393
+ }
362
394
  default:
363
395
  return payload;
364
396
  }
@@ -504,9 +536,7 @@ var updateLocalStorageCache = () => {
504
536
  const classes = globalClassesStylesProvider.actions.all();
505
537
  localStorage.setItem(STORAGE_KEY, JSON.stringify(classes));
506
538
  };
507
- var initClassesResource = () => {
508
- const canvasMcpEntry = getMCPByDomain("canvas");
509
- const classesMcpEntry = getMCPByDomain("classes");
539
+ var initClassesResource = (classesMcpEntry, canvasMcpEntry) => {
510
540
  [canvasMcpEntry, classesMcpEntry].forEach((entry) => {
511
541
  const { mcpServer, resource, waitForReady } = entry;
512
542
  resource(
@@ -538,6 +568,7 @@ import {
538
568
  injectIntoCssClassConvert,
539
569
  registerStyleProviderToColors
540
570
  } from "@elementor/editor-editing-panel";
571
+ import { getMCPByDomain } from "@elementor/editor-mcp";
541
572
  import { __registerPanel as registerPanel } from "@elementor/editor-panels";
542
573
  import { stylesRepository } from "@elementor/editor-styles-repository";
543
574
  import { __registerSlice as registerSlice } from "@elementor/store";
@@ -576,7 +607,7 @@ var PrefetchCssClassUsage = () => {
576
607
 
577
608
  // src/components/class-manager/class-manager-panel.tsx
578
609
  import * as React19 from "react";
579
- import { useCallback, useEffect as useEffect3, useState as useState7 } from "react";
610
+ import { useCallback, useEffect as useEffect4, useState as useState7 } from "react";
580
611
  import { useSuppressedMessage as useSuppressedMessage2 } from "@elementor/editor-current-user";
581
612
  import { getCurrentDocument, getV1DocumentsManager, setDocumentModifiedStatus } from "@elementor/editor-documents";
582
613
  import {
@@ -901,6 +932,7 @@ async function saveGlobalClasses({ context: context2, onApprove }) {
901
932
  changes: calculateChanges(state, currentContext(getState3()))
902
933
  });
903
934
  dispatch2(slice.actions.reset({ context: context2 }));
935
+ window.dispatchEvent(new CustomEvent("classes:updated", { detail: { context: context2 } }));
904
936
  if (response?.data?.data?.code === API_ERROR_CODES.DUPLICATED_LABEL) {
905
937
  dispatch2(slice.actions.updateMultiple(response.data.data.modifiedLabels));
906
938
  trackGlobalClasses({
@@ -1258,8 +1290,7 @@ import * as React15 from "react";
1258
1290
  import { useRef, useState as useState4 } from "react";
1259
1291
  import { validateStyleLabel } from "@elementor/editor-styles-repository";
1260
1292
  import { EditableField, EllipsisWithTooltip as EllipsisWithTooltip3, MenuListItem, useEditable, WarningInfotip } from "@elementor/editor-ui";
1261
- import { isExperimentActive as isExperimentActive2 } from "@elementor/editor-v1-adapters";
1262
- import { DotsVerticalIcon } from "@elementor/icons";
1293
+ import { DotsVerticalIcon, RefreshIcon, RefreshOffIcon } from "@elementor/icons";
1263
1294
  import {
1264
1295
  bindMenu,
1265
1296
  bindTrigger as bindTrigger2,
@@ -1754,7 +1785,7 @@ var ClassItem = ({
1754
1785
  },
1755
1786
  /* @__PURE__ */ React15.createElement(Typography6, { variant: "caption", sx: { color: "text.primary" } }, __11("Rename", "elementor"))
1756
1787
  ),
1757
- isExperimentActive2("e_design_system_sync") && onToggleSync && /* @__PURE__ */ React15.createElement(
1788
+ onToggleSync && /* @__PURE__ */ React15.createElement(
1758
1789
  MenuListItem,
1759
1790
  {
1760
1791
  onClick: () => {
@@ -1762,7 +1793,7 @@ var ClassItem = ({
1762
1793
  onToggleSync(id2, !syncToV3);
1763
1794
  }
1764
1795
  },
1765
- /* @__PURE__ */ React15.createElement(Typography6, { variant: "caption", sx: { color: "text.primary" } }, syncToV3 ? __11("Stop syncing to Version 3", "elementor") : __11("Sync to Version 3", "elementor"))
1796
+ /* @__PURE__ */ React15.createElement(Stack6, { direction: "row", alignItems: "center", gap: 1 }, syncToV3 ? /* @__PURE__ */ React15.createElement(RefreshOffIcon, { fontSize: "tiny" }) : /* @__PURE__ */ React15.createElement(RefreshIcon, { fontSize: "tiny" }), /* @__PURE__ */ React15.createElement(Typography6, { variant: "caption", sx: { color: "text.primary" } }, syncToV3 ? __11("Stop syncing to Global Fonts", "elementor") : __11("Sync to Global Fonts", "elementor")))
1766
1797
  ),
1767
1798
  /* @__PURE__ */ React15.createElement(
1768
1799
  MenuListItem,
@@ -2107,7 +2138,7 @@ function unblockPanelInteractions() {
2107
2138
 
2108
2139
  // src/components/class-manager/start-sync-to-v3-modal.tsx
2109
2140
  import * as React18 from "react";
2110
- import { useState as useState6 } from "react";
2141
+ import { useEffect as useEffect3, useRef as useRef2, useState as useState6 } from "react";
2111
2142
  import {
2112
2143
  Box as Box10,
2113
2144
  Button as Button2,
@@ -2120,17 +2151,38 @@ import {
2120
2151
  } from "@elementor/ui";
2121
2152
  import { __ as __14 } from "@wordpress/i18n";
2122
2153
  var IMAGE_URL = "https://assets.elementor.com/packages/v1/images/class-manager-sync-modal.png";
2123
- var StartSyncToV3Modal = ({ externalOpen, onExternalClose, onConfirm } = {}) => {
2154
+ var StartSyncToV3Modal = ({
2155
+ externalOpen,
2156
+ classId,
2157
+ onExternalClose,
2158
+ onConfirm
2159
+ } = {}) => {
2124
2160
  const [shouldShowAgain, setShouldShowAgain] = useState6(true);
2161
+ const hasTrackedExposure = useRef2(false);
2162
+ useEffect3(() => {
2163
+ if (externalOpen && classId && !hasTrackedExposure.current) {
2164
+ hasTrackedExposure.current = true;
2165
+ trackGlobalClasses({ event: "classSyncToV3PopupShown", classId });
2166
+ }
2167
+ if (!externalOpen) {
2168
+ hasTrackedExposure.current = false;
2169
+ }
2170
+ }, [externalOpen, classId]);
2125
2171
  const handleClose = () => {
2172
+ if (classId) {
2173
+ trackGlobalClasses({ event: "classSyncToV3PopupClick", classId, action: "cancel" });
2174
+ }
2126
2175
  onExternalClose?.();
2127
2176
  };
2128
2177
  const handleConfirm = () => {
2178
+ if (classId) {
2179
+ trackGlobalClasses({ event: "classSyncToV3PopupClick", classId, action: "sync" });
2180
+ }
2129
2181
  onConfirm?.();
2130
2182
  onExternalClose?.();
2131
2183
  };
2132
- return /* @__PURE__ */ React18.createElement(Dialog, { open: !!externalOpen, onClose: handleClose, maxWidth: "sm", fullWidth: true }, /* @__PURE__ */ React18.createElement(DialogContent2, { sx: { p: 0 } }, /* @__PURE__ */ React18.createElement(Box10, { component: "img", src: IMAGE_URL, alt: "", sx: { width: "100%", display: "block" } }), /* @__PURE__ */ React18.createElement(Box10, { sx: { px: 3, pt: 4, pb: 1 } }, /* @__PURE__ */ React18.createElement(Typography9, { variant: "h6" }, __14("Sync class to version 3 Global Fonts", "elementor")), /* @__PURE__ */ React18.createElement(Typography9, { variant: "body2", color: "secondary", sx: { mb: 2, pt: 1 } }, __14(
2133
- "Only typography settings supported in version 3 will be applied, including: font family, responsive font sizes, weight, text transform, decoration, line height, letter spacing, and word spacing. Changes made in the class will automatically apply to version 3.",
2184
+ return /* @__PURE__ */ React18.createElement(Dialog, { open: !!externalOpen, onClose: handleClose, maxWidth: "sm", fullWidth: true }, /* @__PURE__ */ React18.createElement(DialogContent2, { sx: { p: 0 } }, /* @__PURE__ */ React18.createElement(Box10, { component: "img", src: IMAGE_URL, alt: "", sx: { width: "100%", display: "block" } }), /* @__PURE__ */ React18.createElement(Box10, { sx: { px: 3, pt: 4, pb: 1 } }, /* @__PURE__ */ React18.createElement(Typography9, { variant: "h6" }, __14("Sync class to Global Fonts", "elementor")), /* @__PURE__ */ React18.createElement(Typography9, { variant: "body2", color: "secondary", sx: { mb: 2, pt: 1 } }, __14(
2185
+ "Only typography settings supported in Global Fonts will be applied, including: font family, responsive font sizes, weight, text transform, decoration, line height, letter spacing, and word spacing. Changes made in the class will automatically apply to Global Fonts.",
2134
2186
  "elementor"
2135
2187
  )))), /* @__PURE__ */ React18.createElement(DialogActions2, { sx: { justifyContent: "space-between", px: 3, pb: 2 } }, /* @__PURE__ */ React18.createElement(
2136
2188
  FormControlLabel,
@@ -2144,7 +2196,7 @@ var StartSyncToV3Modal = ({ externalOpen, onExternalClose, onConfirm } = {}) =>
2144
2196
  ),
2145
2197
  label: /* @__PURE__ */ React18.createElement(Typography9, { variant: "body2", color: "secondary" }, __14("Don't show again", "elementor"))
2146
2198
  }
2147
- ), /* @__PURE__ */ React18.createElement(Box10, { sx: { display: "flex", gap: 1 } }, /* @__PURE__ */ React18.createElement(Button2, { onClick: handleClose, color: "secondary", size: "small" }, __14("Cancel", "elementor")), /* @__PURE__ */ React18.createElement(Button2, { onClick: handleConfirm, variant: "contained", size: "small" }, __14("Sync to version 3", "elementor")))));
2199
+ ), /* @__PURE__ */ React18.createElement(Box10, { sx: { display: "flex", gap: 1 } }, /* @__PURE__ */ React18.createElement(Button2, { onClick: handleClose, color: "secondary", size: "small" }, __14("Cancel", "elementor")), /* @__PURE__ */ React18.createElement(Button2, { onClick: handleConfirm, variant: "contained", size: "small" }, __14("Sync to Global Fonts", "elementor")))));
2148
2200
  };
2149
2201
 
2150
2202
  // src/components/class-manager/class-manager-panel.tsx
@@ -2196,6 +2248,7 @@ function ClassManagerPanel() {
2196
2248
  }
2197
2249
  })
2198
2250
  );
2251
+ trackGlobalClasses({ event: "classSyncToV3", classId, action: "unsync" });
2199
2252
  setStopSyncConfirmation(null);
2200
2253
  }, []);
2201
2254
  const handleStartSync = useCallback((classId) => {
@@ -2207,6 +2260,7 @@ function ClassManagerPanel() {
2207
2260
  }
2208
2261
  })
2209
2262
  );
2263
+ trackGlobalClasses({ event: "classSyncToV3", classId, action: "sync" });
2210
2264
  setStartSyncConfirmation(null);
2211
2265
  }, []);
2212
2266
  const handleStopSyncRequest = useCallback(
@@ -2278,6 +2332,7 @@ function ClassManagerPanel() {
2278
2332
  StartSyncToV3Modal,
2279
2333
  {
2280
2334
  externalOpen: true,
2335
+ classId: startSyncConfirmation,
2281
2336
  onExternalClose: () => setStartSyncConfirmation(null),
2282
2337
  onConfirm: () => handleStartSync(startSyncConfirmation)
2283
2338
  }
@@ -2314,7 +2369,7 @@ var CloseButton = ({ onClose, ...props }) => /* @__PURE__ */ React19.createEleme
2314
2369
  var ErrorBoundaryFallback = () => /* @__PURE__ */ React19.createElement(Box11, { role: "alert", sx: { minHeight: "100%", p: 2 } }, /* @__PURE__ */ React19.createElement(Alert2, { severity: "error", sx: { mb: 2, maxWidth: 400, textAlign: "center" } }, /* @__PURE__ */ React19.createElement("strong", null, __15("Something went wrong", "elementor"))));
2315
2370
  var usePreventUnload = () => {
2316
2371
  const isDirty2 = useDirtyState();
2317
- useEffect3(() => {
2372
+ useEffect4(() => {
2318
2373
  const handleBeforeUnload = (event) => {
2319
2374
  if (isDirty2) {
2320
2375
  event.preventDefault();
@@ -2350,7 +2405,7 @@ var TotalCssClassCounter = () => {
2350
2405
  };
2351
2406
  var StopSyncConfirmationDialog = ({ open, onClose, onConfirm }) => {
2352
2407
  const [, suppressStopSyncMessage] = useSuppressedMessage2(STOP_SYNC_MESSAGE_KEY);
2353
- return /* @__PURE__ */ React19.createElement(ConfirmationDialog2, { open, onClose }, /* @__PURE__ */ React19.createElement(ConfirmationDialog2.Title, { icon: FlippedColorSwatchIcon, iconColor: "primary" }, __15("Un-sync typography class", "elementor")), /* @__PURE__ */ React19.createElement(ConfirmationDialog2.Content, null, /* @__PURE__ */ React19.createElement(ConfirmationDialog2.ContentText, null, __15("You're about to stop syncing a typography class to version 3.", "elementor")), /* @__PURE__ */ React19.createElement(ConfirmationDialog2.ContentText, { sx: { mt: 1 } }, __15(
2408
+ return /* @__PURE__ */ React19.createElement(ConfirmationDialog2, { open, onClose }, /* @__PURE__ */ React19.createElement(ConfirmationDialog2.Title, { icon: FlippedColorSwatchIcon, iconColor: "primary" }, __15("Un-sync typography class", "elementor")), /* @__PURE__ */ React19.createElement(ConfirmationDialog2.Content, null, /* @__PURE__ */ React19.createElement(ConfirmationDialog2.ContentText, null, __15("You're about to stop syncing a typography class to Global Fonts.", "elementor")), /* @__PURE__ */ React19.createElement(ConfirmationDialog2.ContentText, { sx: { mt: 1 } }, __15(
2354
2409
  "Note that if it's being used anywhere, the affected elements will inherit the default typography.",
2355
2410
  "elementor"
2356
2411
  ))), /* @__PURE__ */ React19.createElement(
@@ -2474,16 +2529,67 @@ function createClassName(prefix) {
2474
2529
  return newClassName;
2475
2530
  }
2476
2531
 
2532
+ // src/components/global-styles-import-listener.tsx
2533
+ import { useEffect as useEffect5 } from "react";
2534
+ import { __useDispatch as useDispatch2 } from "@elementor/store";
2535
+ function GlobalStylesImportListener() {
2536
+ const dispatch5 = useDispatch2();
2537
+ useEffect5(() => {
2538
+ const handleGlobalStylesImported = (event) => {
2539
+ const importedClasses = event.detail?.global_classes;
2540
+ if (importedClasses?.items && importedClasses?.order) {
2541
+ dispatch5(
2542
+ slice.actions.load({
2543
+ preview: {
2544
+ items: importedClasses.items,
2545
+ order: importedClasses.order
2546
+ },
2547
+ frontend: {
2548
+ items: importedClasses.items,
2549
+ order: importedClasses.order
2550
+ }
2551
+ })
2552
+ );
2553
+ }
2554
+ Promise.all([apiClient.all("preview"), apiClient.all("frontend")]).then(([previewRes, frontendRes]) => {
2555
+ const { data: previewData } = previewRes;
2556
+ const { data: frontendData } = frontendRes;
2557
+ dispatch5(
2558
+ slice.actions.load({
2559
+ preview: {
2560
+ items: previewData.data,
2561
+ order: previewData.meta.order
2562
+ },
2563
+ frontend: {
2564
+ items: frontendData.data,
2565
+ order: frontendData.meta.order
2566
+ }
2567
+ })
2568
+ );
2569
+ }).catch(() => {
2570
+ });
2571
+ };
2572
+ window.addEventListener("elementor/global-styles/imported", handleGlobalStylesImported);
2573
+ return () => {
2574
+ window.removeEventListener(
2575
+ "elementor/global-styles/imported",
2576
+ handleGlobalStylesImported
2577
+ );
2578
+ };
2579
+ }, [dispatch5]);
2580
+ return null;
2581
+ }
2582
+
2477
2583
  // src/components/open-panel-from-url.tsx
2478
- import { useEffect as useEffect4, useRef as useRef2 } from "react";
2584
+ import { useEffect as useEffect6, useRef as useRef3 } from "react";
2479
2585
  import { __privateListenTo as listenTo, routeOpenEvent } from "@elementor/editor-v1-adapters";
2480
2586
  var ACTIVE_PANEL_PARAM = "active-panel";
2481
2587
  var PANEL_ID = "global-classes-manager";
2482
2588
  var DEFAULT_PANEL_ROUTE = "panel/elements";
2483
2589
  function OpenPanelFromUrl() {
2484
2590
  const { open } = usePanelActions();
2485
- const hasOpened = useRef2(false);
2486
- useEffect4(() => {
2591
+ const hasOpened = useRef3(false);
2592
+ useEffect6(() => {
2487
2593
  const urlParams = new URLSearchParams(window.location.search);
2488
2594
  const activePanel = urlParams.get(ACTIVE_PANEL_PARAM);
2489
2595
  if (activePanel !== PANEL_ID) {
@@ -2504,11 +2610,11 @@ function OpenPanelFromUrl() {
2504
2610
  }
2505
2611
 
2506
2612
  // src/components/populate-store.tsx
2507
- import { useEffect as useEffect5 } from "react";
2508
- import { __useDispatch as useDispatch2 } from "@elementor/store";
2613
+ import { useEffect as useEffect7 } from "react";
2614
+ import { __useDispatch as useDispatch3 } from "@elementor/store";
2509
2615
  function PopulateStore() {
2510
- const dispatch5 = useDispatch2();
2511
- useEffect5(() => {
2616
+ const dispatch5 = useDispatch3();
2617
+ useEffect7(() => {
2512
2618
  Promise.all([apiClient.all("preview"), apiClient.all("frontend")]).then(
2513
2619
  ([previewRes, frontendRes]) => {
2514
2620
  const { data: previewData } = previewRes;
@@ -2531,9 +2637,6 @@ function PopulateStore() {
2531
2637
  return null;
2532
2638
  }
2533
2639
 
2534
- // src/mcp-integration/index.ts
2535
- import { getMCPByDomain as getMCPByDomain2 } from "@elementor/editor-mcp";
2536
-
2537
2640
  // src/mcp-integration/mcp-apply-unapply-global-classes.ts
2538
2641
  import { doApplyClasses, doGetAppliedClasses, doUnapplyClass } from "@elementor/editor-editing-panel";
2539
2642
  import { z } from "@elementor/schema";
@@ -2962,18 +3065,25 @@ async function attemptDelete(opts) {
2962
3065
  }
2963
3066
 
2964
3067
  // src/mcp-integration/index.ts
2965
- var initMcpIntegration = () => {
2966
- const reg = getMCPByDomain2("classes", {
2967
- instructions: "MCP server for management of Elementor global classes"
2968
- });
3068
+ var initMcpIntegration = (reg, canvasMcpEntry) => {
3069
+ const { setMCPDescription } = reg;
3070
+ setMCPDescription(
3071
+ `Everything related to V4 ( Atomic ) global classes.
3072
+ # Global classes
3073
+ - Create/update/delete global classes
3074
+ - Get list of global classes
3075
+ - Get details of a global class
3076
+ - Get details of a global class
3077
+ `
3078
+ );
2969
3079
  initMcpApplyUnapplyGlobalClasses(reg);
2970
3080
  initMcpApplyGetGlobalClassUsages(reg);
2971
3081
  initManageGlobalClasses(reg);
2972
- initClassesResource();
3082
+ initClassesResource(reg, canvasMcpEntry);
2973
3083
  };
2974
3084
 
2975
3085
  // src/sync-with-document.tsx
2976
- import { useEffect as useEffect6 } from "react";
3086
+ import { useEffect as useEffect8 } from "react";
2977
3087
  import { __privateListenTo as listenTo2, v1ReadyEvent } from "@elementor/editor-v1-adapters";
2978
3088
 
2979
3089
  // src/sync-with-document-save.ts
@@ -2981,9 +3091,11 @@ import { getCurrentUser } from "@elementor/editor-current-user";
2981
3091
  import { setDocumentModifiedStatus as setDocumentModifiedStatus2 } from "@elementor/editor-documents";
2982
3092
  import { registerDataHook } from "@elementor/editor-v1-adapters";
2983
3093
  import { __getState as getState4, __subscribeWithSelector as subscribeWithSelector2 } from "@elementor/store";
3094
+ var pendingSave = null;
2984
3095
  function syncWithDocumentSave(panelActions) {
2985
3096
  const unsubscribe = syncDirtyState();
2986
3097
  bindSaveAction(panelActions);
3098
+ bindBeforeSaveTemplateAction();
2987
3099
  return unsubscribe;
2988
3100
  }
2989
3101
  function syncDirtyState() {
@@ -2994,20 +3106,41 @@ function syncDirtyState() {
2994
3106
  setDocumentModifiedStatus2(true);
2995
3107
  });
2996
3108
  }
3109
+ function triggerSave(panelActions, context2 = "preview") {
3110
+ const user = getCurrentUser();
3111
+ const canEdit = user?.capabilities.includes(UPDATE_CLASS_CAPABILITY_KEY);
3112
+ if (!canEdit) {
3113
+ return null;
3114
+ }
3115
+ if (pendingSave) {
3116
+ return pendingSave;
3117
+ }
3118
+ const promise = saveGlobalClasses({
3119
+ context: context2,
3120
+ onApprove: panelActions?.open
3121
+ });
3122
+ pendingSave = promise;
3123
+ promise.finally(() => {
3124
+ pendingSave = null;
3125
+ });
3126
+ return promise;
3127
+ }
2997
3128
  function bindSaveAction(panelActions) {
2998
3129
  registerDataHook("dependency", "document/save/save", (args) => {
2999
- const user = getCurrentUser();
3000
- const canEdit = user?.capabilities.includes(UPDATE_CLASS_CAPABILITY_KEY);
3001
- if (!canEdit) {
3002
- return true;
3003
- }
3004
- saveGlobalClasses({
3005
- context: args.status === "publish" ? "frontend" : "preview",
3006
- onApprove: panelActions?.open
3007
- });
3130
+ triggerSave(panelActions, args.status === "publish" ? "frontend" : "preview");
3008
3131
  return true;
3009
3132
  });
3010
3133
  }
3134
+ function bindBeforeSaveTemplateAction() {
3135
+ window.addEventListener("elementor/global-styles/before-save", ((event) => {
3136
+ if (!pendingSave && isDirty()) {
3137
+ triggerSave();
3138
+ }
3139
+ if (pendingSave) {
3140
+ event.detail.promises.push(pendingSave);
3141
+ }
3142
+ }));
3143
+ }
3011
3144
  function isDirty() {
3012
3145
  return selectIsDirty(getState4());
3013
3146
  }
@@ -3015,7 +3148,7 @@ function isDirty() {
3015
3148
  // src/sync-with-document.tsx
3016
3149
  function SyncWithDocumentSave() {
3017
3150
  const panelActions = usePanelActions();
3018
- useEffect6(() => {
3151
+ useEffect8(() => {
3019
3152
  listenTo2(v1ReadyEvent(), () => {
3020
3153
  syncWithDocumentSave(panelActions);
3021
3154
  });
@@ -3036,6 +3169,10 @@ function init() {
3036
3169
  id: "global-classes-sync-with-document",
3037
3170
  component: SyncWithDocumentSave
3038
3171
  });
3172
+ injectIntoLogic({
3173
+ id: "global-classes-import-listener",
3174
+ component: GlobalStylesImportListener
3175
+ });
3039
3176
  injectIntoLogic({
3040
3177
  id: "global-classes-prefetch-css-class-usage",
3041
3178
  component: PrefetchCssClassUsage
@@ -3056,7 +3193,10 @@ function init() {
3056
3193
  name: "global",
3057
3194
  getThemeColor: (theme) => theme.palette.global.dark
3058
3195
  });
3059
- initMcpIntegration();
3196
+ initMcpIntegration(
3197
+ getMCPByDomain("classes", { instructions: "MCP server for management of Elementor global classes" }),
3198
+ getMCPByDomain("canvas")
3199
+ );
3060
3200
  }
3061
3201
  export {
3062
3202
  GLOBAL_CLASSES_URI,