@elementor/editor-global-classes 4.1.0-838 → 4.1.0-beta2

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
@@ -263,6 +263,20 @@ var slice = createSlice({
263
263
  state.classLabels[id2] = previewClassData.label;
264
264
  }
265
265
  });
266
+ },
267
+ setOrderWithoutHistory(state, { payload }) {
268
+ state.data.order = payload;
269
+ },
270
+ updateAfterTemplateImport(state, {
271
+ payload
272
+ }) {
273
+ state.initialData.frontend.items = { ...state.initialData.frontend.items, ...payload.addedItems };
274
+ state.initialData.frontend.order = [...state.initialData.frontend.order, ...payload.addedIdsOrder];
275
+ state.initialData.preview.items = { ...state.initialData.preview.items, ...payload.addedItems };
276
+ state.initialData.preview.order = [...state.initialData.preview.order, ...payload.addedIdsOrder];
277
+ state.data.items = { ...state.data.items, ...payload.addedItems };
278
+ state.data.order = [...state.data.order, ...payload.addedIdsOrder];
279
+ state.classLabels = { ...state.classLabels, ...payload.addedClassLabels };
266
280
  }
267
281
  }
268
282
  });
@@ -836,10 +850,12 @@ function calculateChanges(state, initialData) {
836
850
  const initialDataIds = Object.keys(initialData.items);
837
851
  const { order: stateOrder } = state;
838
852
  const { order: initialDataOrder } = initialData;
853
+ const stateOrderIdSet = new Set(stateOrder);
854
+ const deleted = initialDataOrder.filter((id2) => !stateOrderIdSet.has(id2));
839
855
  const order = stateOrder.join(";") !== initialDataOrder.join(";");
840
856
  return {
841
857
  added: stateIds.filter((id2) => !initialDataIds.includes(id2)),
842
- deleted: initialDataIds.filter((id2) => !stateIds.includes(id2)),
858
+ deleted,
843
859
  modified: stateIds.filter((id2) => {
844
860
  return id2 in initialData.items && hash(state.items[id2]) !== hash(initialData.items[id2]);
845
861
  }),
@@ -2060,8 +2076,9 @@ var useFilteredCssClasses = () => {
2060
2076
  [cssClasses]
2061
2077
  );
2062
2078
  const filteredClasses = useMemo3(() => {
2063
- if (searchValue.length > 1) {
2064
- return lowercaseLabels.filter((cssClass) => cssClass.lowerLabel.includes(searchValue.toLowerCase()));
2079
+ const normalizedSearch = searchValue.replace(/[^a-zA-Z0-9_-]/g, "").toLowerCase();
2080
+ if (normalizedSearch.length > 1) {
2081
+ return lowercaseLabels.filter((cssClass) => cssClass.lowerLabel.includes(normalizedSearch));
2065
2082
  }
2066
2083
  return cssClasses;
2067
2084
  }, [searchValue, cssClasses, lowercaseLabels]);
@@ -2574,7 +2591,7 @@ async function fetchAndMergeClasses() {
2574
2591
  }
2575
2592
 
2576
2593
  // src/global-classes-styles-provider.ts
2577
- var MAX_CLASSES = 5e3;
2594
+ var MAX_CLASSES = 1e3;
2578
2595
  var GLOBAL_CLASSES_PROVIDER_KEY = "global-classes";
2579
2596
  var PREGENERATED_LINK_PATTERN = /^global-([0-9]+-)?(preview|frontend)-[a-zA-Z_-]+-css$/;
2580
2597
  var globalClassesStylesProvider = createStylesProvider({
@@ -2872,17 +2889,20 @@ import { __useDispatch as useDispatch2 } from "@elementor/store";
2872
2889
  function GlobalStylesImportListener() {
2873
2890
  const dispatch7 = useDispatch2();
2874
2891
  useEffect5(() => {
2875
- const handleGlobalStylesImported = (event) => {
2876
- const importedClasses = event.detail?.global_classes;
2877
- if (importedClasses?.items && importedClasses?.order) {
2878
- const { items } = importedClasses;
2879
- dispatch7(
2880
- slice.actions.mergeExistingClasses({
2881
- preview: items,
2882
- frontend: items
2883
- })
2884
- );
2892
+ const handleGlobalStylesImported = async (event) => {
2893
+ const customEvent = event;
2894
+ const globalClasses = customEvent.detail?.global_classes;
2895
+ if (!globalClasses?.added_items_order || !globalClasses?.added_items || globalClasses?.added_items_order?.length === 0) {
2896
+ loadCurrentDocumentClasses();
2897
+ return;
2885
2898
  }
2899
+ dispatch7(
2900
+ slice.actions.updateAfterTemplateImport({
2901
+ addedItems: globalClasses.added_items,
2902
+ addedIdsOrder: globalClasses.added_items_order,
2903
+ addedClassLabels: createLabelsForClasses(Object.values(globalClasses.added_items))
2904
+ })
2905
+ );
2886
2906
  };
2887
2907
  window.addEventListener(GLOBAL_STYLES_IMPORTED_EVENT, handleGlobalStylesImported);
2888
2908
  return () => {
@@ -2892,8 +2912,21 @@ function GlobalStylesImportListener() {
2892
2912
  return null;
2893
2913
  }
2894
2914
 
2915
+ // src/components/open-panel-from-event.tsx
2916
+ import { useEffect as useEffect6 } from "react";
2917
+ var EVENT_OPEN_GLOBAL_CLASSES_MANAGER = "elementor/open-global-classes-manager";
2918
+ function OpenPanelFromEvent() {
2919
+ const { open } = usePanelActions();
2920
+ useEffect6(() => {
2921
+ const handler2 = () => open();
2922
+ window.addEventListener(EVENT_OPEN_GLOBAL_CLASSES_MANAGER, handler2);
2923
+ return () => window.removeEventListener(EVENT_OPEN_GLOBAL_CLASSES_MANAGER, handler2);
2924
+ }, [open]);
2925
+ return null;
2926
+ }
2927
+
2895
2928
  // src/components/open-panel-from-url.tsx
2896
- import { useEffect as useEffect6, useRef as useRef3 } from "react";
2929
+ import { useEffect as useEffect7, useRef as useRef3 } from "react";
2897
2930
  import { __privateListenTo as listenTo, routeOpenEvent } from "@elementor/editor-v1-adapters";
2898
2931
  var ACTIVE_PANEL_PARAM = "active-panel";
2899
2932
  var PANEL_ID = "global-classes-manager";
@@ -2901,7 +2934,7 @@ var DEFAULT_PANEL_ROUTE = "panel/elements";
2901
2934
  function OpenPanelFromUrl() {
2902
2935
  const { open } = usePanelActions();
2903
2936
  const hasOpened = useRef3(false);
2904
- useEffect6(() => {
2937
+ useEffect7(() => {
2905
2938
  const urlParams = new URLSearchParams(window.location.search);
2906
2939
  const activePanel = urlParams.get(ACTIVE_PANEL_PARAM);
2907
2940
  if (activePanel !== PANEL_ID) {
@@ -2922,10 +2955,10 @@ function OpenPanelFromUrl() {
2922
2955
  }
2923
2956
 
2924
2957
  // src/components/populate-store.tsx
2925
- import { useEffect as useEffect7 } from "react";
2958
+ import { useEffect as useEffect8 } from "react";
2926
2959
  import { registerDataHook } from "@elementor/editor-v1-adapters";
2927
2960
  function PopulateStore() {
2928
- useEffect7(() => {
2961
+ useEffect8(() => {
2929
2962
  loadCurrentDocumentClasses();
2930
2963
  registerDataHook("after", "editor/documents/attach-preview", async () => {
2931
2964
  await loadCurrentDocumentClasses();
@@ -2937,24 +2970,15 @@ function PopulateStore() {
2937
2970
  // src/mcp-integration/mcp-apply-unapply-global-classes.ts
2938
2971
  import { doApplyClasses, doGetAppliedClasses, doUnapplyClass } from "@elementor/editor-editing-panel";
2939
2972
  import { z } from "@elementor/schema";
2940
- function initMcpApplyUnapplyGlobalClasses(server) {
2941
- server.addTool({
2942
- schema: {
2943
- classId: z.string().describe("The ID of the class to apply"),
2944
- elementId: z.string().describe("The ID of the element to which the class will be applied")
2945
- },
2946
- outputSchema: {
2947
- result: z.string().describe("Result message indicating the success of the apply operation"),
2948
- llm_instructions: z.string().describe("Instructions what to do next, Important to follow these instructions!")
2949
- },
2950
- name: "apply-global-class",
2951
- modelPreferences: {
2952
- intelligencePriority: 0.7,
2953
- speedPriority: 0.8
2954
- },
2955
- description: `Apply a global class to an element, enabling consistent styling through your design system.
2956
2973
 
2957
- ## When to use this tool:
2974
+ // src/mcp-integration/apply-global-class-guide-prompt.ts
2975
+ import { toolPrompts } from "@elementor/editor-mcp";
2976
+ var APPLY_GLOBAL_CLASS_GUIDE_URI = "elementor://global-classes/tools/apply-global-class-guide";
2977
+ var generateApplyGlobalClassGuidePrompt = () => {
2978
+ const prompt = toolPrompts("apply-global-class");
2979
+ prompt.description("Apply a global class to an element, enabling consistent styling through your design system.");
2980
+ prompt.instruction(
2981
+ `## When to use this tool:
2958
2982
  **ALWAYS use this IMMEDIATELY AFTER building compositions** to apply the global classes you created beforehand:
2959
2983
  - After using "build-compositions" tool, apply semantic classes to the created elements
2960
2984
  - When applying consistent typography styles (heading-primary, text-body, etc.)
@@ -2963,18 +2987,59 @@ function initMcpApplyUnapplyGlobalClasses(server) {
2963
2987
 
2964
2988
  **DO NOT use this tool** for:
2965
2989
  - Elements that don't share styles with other elements (use inline styles instead)
2966
- - Layout-specific properties (those should remain inline in stylesConfig)
2967
-
2968
- ## Prerequisites:
2990
+ - Layout-specific properties (those should remain inline in stylesConfig)`
2991
+ );
2992
+ prompt.instruction(
2993
+ `## Prerequisites:
2969
2994
  - **REQUIRED**: Get the list of available global classes from 'elementor://global-classes' resource
2970
2995
  - **REQUIRED**: Get element IDs from the composition XML returned by "build-compositions" tool
2971
2996
  - Ensure you have the most up-to-date list of classes applied to the element to avoid duplicates
2972
- - Make sure you have the correct class ID that you want to apply
2973
-
2974
- ## Best Practices:
2997
+ - Make sure you have the correct class ID that you want to apply`
2998
+ );
2999
+ prompt.instruction(
3000
+ `## Best Practices:
2975
3001
  1. Apply multiple classes to a single element if needed (typography + color + spacing)
2976
3002
  2. After applying, the tool will remind you to remove duplicate inline styles from elementConfig
2977
- 3. Classes should describe purpose, not implementation (e.g., "heading-primary" not "big-red-text")`,
3003
+ 3. Classes should describe purpose, not implementation (e.g., "heading-primary" not "big-red-text")`
3004
+ );
3005
+ return prompt.prompt();
3006
+ };
3007
+
3008
+ // src/mcp-integration/mcp-apply-unapply-global-classes.ts
3009
+ function initMcpApplyUnapplyGlobalClasses(server) {
3010
+ const { addTool, resource } = server;
3011
+ const applyGlobalClassGuideText = generateApplyGlobalClassGuidePrompt();
3012
+ resource(
3013
+ "apply-global-class-guide",
3014
+ APPLY_GLOBAL_CLASS_GUIDE_URI,
3015
+ {
3016
+ description: "Workflow, prerequisites, and best practices for apply-global-class",
3017
+ mimeType: "text/plain",
3018
+ title: "Apply global class tool guide"
3019
+ },
3020
+ async (uri) => ({
3021
+ contents: [{ mimeType: "text/plain", text: applyGlobalClassGuideText, uri: uri.href }]
3022
+ })
3023
+ );
3024
+ addTool({
3025
+ schema: {
3026
+ classId: z.string().describe("The ID of the class to apply"),
3027
+ elementId: z.string().describe("The ID of the element to which the class will be applied")
3028
+ },
3029
+ outputSchema: {
3030
+ result: z.string().describe("Result message indicating the success of the apply operation"),
3031
+ llm_instructions: z.string().describe("Instructions what to do next, Important to follow these instructions!")
3032
+ },
3033
+ name: "apply-global-class",
3034
+ modelPreferences: {
3035
+ intelligencePriority: 0.7,
3036
+ speedPriority: 0.8
3037
+ },
3038
+ description: `Apply a global class to an element for shared design-system styling. Read the full guide at [${APPLY_GLOBAL_CLASS_GUIDE_URI}].`,
3039
+ requiredResources: [
3040
+ { description: "Apply global class tool guide", uri: APPLY_GLOBAL_CLASS_GUIDE_URI },
3041
+ { description: "Global classes list", uri: GLOBAL_CLASSES_URI }
3042
+ ],
2978
3043
  handler: async (params) => {
2979
3044
  const { classId, elementId } = params;
2980
3045
  const appliedClasses = doGetAppliedClasses(elementId);
@@ -2985,7 +3050,7 @@ function initMcpApplyUnapplyGlobalClasses(server) {
2985
3050
  };
2986
3051
  }
2987
3052
  });
2988
- server.addTool({
3053
+ addTool({
2989
3054
  name: "unapply-global-class",
2990
3055
  schema: {
2991
3056
  classId: z.string().describe("The ID of the class to unapply"),
@@ -2998,21 +3063,8 @@ function initMcpApplyUnapplyGlobalClasses(server) {
2998
3063
  intelligencePriority: 0.7,
2999
3064
  speedPriority: 0.8
3000
3065
  },
3001
- description: `Unapply a (global) class from the current element
3002
-
3003
- ## When to use this tool:
3004
- - When a user requests to unapply a global class or a class from an element in the Elementor editor.
3005
- - When you need to remove a specific class from an element's applied classes.
3006
-
3007
- ## Prerequisites:
3008
- - Ensure you have the most up-to-date list of classes applied to the element to avoid errors.
3009
- The list is available at always up-to-date resource 'elementor://global-classes'.
3010
- - Make sure you have the correct class ID that you want to unapply.
3011
-
3012
- <note>
3013
- If the user want to unapply a class by it's name and not ID, retrieve the id from the list, available at uri elementor://global-classes
3014
- </note>
3015
- `,
3066
+ description: `Unapply a global class from an element by class ID. Resolve class names to IDs via [${GLOBAL_CLASSES_URI}].`,
3067
+ requiredResources: [{ description: "Global classes list", uri: GLOBAL_CLASSES_URI }],
3016
3068
  handler: async (params) => {
3017
3069
  const { classId, elementId } = params;
3018
3070
  const ok = doUnapplyClass(elementId, classId);
@@ -3053,19 +3105,15 @@ function initMcpApplyGetGlobalClassUsages(reg) {
3053
3105
  intelligencePriority: 0.6,
3054
3106
  speedPriority: 0.8
3055
3107
  },
3056
- description: `Retrieve the usages of global-classes ACROSS PAGES designed by Elementor editor.
3057
-
3058
- ## Prerequisites: CRITICAL
3059
- - The list of global classes and their applid values is available at resource uri elementor://global-classes
3108
+ description: `Retrieve usages of global classes across all Elementor pages. Heavy operation \u2014 scans every page in the site.
3060
3109
 
3061
- ## When to use this tool:
3062
- - When a user requests to see where a specific global class is being used across the site.
3063
- - When you need to manage or clean up unused global classes.
3064
- - Before deleting a global class, to ensure it is not in use in any other pages.
3110
+ ## When to use:
3111
+ - Before deleting or radically changing a class \u2014 to understand cross-page side effects and decide whether to consult the user.
3112
+ - To identify unused global classes for cleanup.
3065
3113
 
3066
- ## When NOT to use this tool:
3067
- - For getting the list of global classes, refer to the resource at uri elementor://global-classes
3068
- `,
3114
+ ## When NOT to use:
3115
+ - To list global classes themselves \u2014 use the global-classes resource instead (this tool returns usages, not the class list).`,
3116
+ requiredResources: [{ description: "Global classes list", uri: GLOBAL_CLASSES_URI }],
3069
3117
  outputSchema: globalClassesUsageSchema,
3070
3118
  handler: async () => {
3071
3119
  const data = await fetchCssClassUsage();
@@ -3265,15 +3313,7 @@ var initManageGlobalClasses = (reg) => {
3265
3313
  intelligencePriority: 0.85,
3266
3314
  speedPriority: 0.6
3267
3315
  },
3268
- description: `Manages global classes (create/modify) in Elementor editor. Check [elementor://global-classes] and style schemas first.
3269
-
3270
- CREATE: Requires globalClassName, props. Use semantic naming (heading-primary, button-cta, text-muted). Check existing classes to avoid duplicates. ALWAYS create global classes BEFORE compositions for reusable styles.
3271
- MODIFY: Requires classId, props. Get classId from [elementor://global-classes] resource.
3272
-
3273
- Naming pattern: [element-type]-[purpose/variant]-[modifier]
3274
- DO NOT create global classes for: one-off styles, layout-specific properties.
3275
-
3276
- Use style schema at [elementor://styles/schema/{category}] for valid props. Errors include exact schema mismatch details.`,
3316
+ description: `Create or modify global classes for reusable design-system styling. Class names must reflect purpose (e.g. heading-primary, button-cta). Create classes BEFORE compositions. Do NOT create classes for one-off styles or layout-specific properties.`,
3277
3317
  schema,
3278
3318
  outputSchema,
3279
3319
  handler
@@ -3363,16 +3403,6 @@ async function attemptDelete(opts) {
3363
3403
 
3364
3404
  // src/mcp-integration/index.ts
3365
3405
  var initMcpIntegration = (reg, canvasMcpEntry) => {
3366
- const { setMCPDescription } = reg;
3367
- setMCPDescription(
3368
- `Everything related to V4 ( Atomic ) global classes.
3369
- # Global classes
3370
- - Create/update/delete global classes
3371
- - Get list of global classes
3372
- - Get details of a global class
3373
- - Get details of a global class
3374
- `
3375
- );
3376
3406
  initMcpApplyUnapplyGlobalClasses(reg);
3377
3407
  initMcpApplyGetGlobalClassUsages(reg);
3378
3408
  initManageGlobalClasses(reg);
@@ -3380,7 +3410,7 @@ var initMcpIntegration = (reg, canvasMcpEntry) => {
3380
3410
  };
3381
3411
 
3382
3412
  // src/sync-with-document.tsx
3383
- import { useEffect as useEffect8 } from "react";
3413
+ import { useEffect as useEffect9 } from "react";
3384
3414
  import { __privateListenTo as listenTo2, isExperimentActive as isExperimentActive3, v1ReadyEvent } from "@elementor/editor-v1-adapters";
3385
3415
 
3386
3416
  // src/sync-with-document-save.ts
@@ -3445,7 +3475,7 @@ function isDirty() {
3445
3475
  // src/sync-with-document.tsx
3446
3476
  function SyncWithDocumentSave() {
3447
3477
  const { open: openClassPanel } = usePanelActions();
3448
- useEffect8(() => {
3478
+ useEffect9(() => {
3449
3479
  const unsubscribe = listenTo2(v1ReadyEvent(), () => {
3450
3480
  const open = isExperimentActive3("e_editor_design_system_panel") ? () => {
3451
3481
  window.dispatchEvent(new CustomEvent("elementor/open-global-classes-manager"));
@@ -3485,6 +3515,10 @@ function init() {
3485
3515
  id: "global-classes-open-panel-from-url",
3486
3516
  component: OpenPanelFromUrl
3487
3517
  });
3518
+ injectIntoLogic({
3519
+ id: "global-classes-open-panel-from-event",
3520
+ component: OpenPanelFromEvent
3521
+ });
3488
3522
  }
3489
3523
  injectIntoCssClassConvert({
3490
3524
  id: "global-classes-convert-from-local-class",
@@ -3499,7 +3533,15 @@ function init() {
3499
3533
  getThemeColor: (theme) => theme.palette.global.dark
3500
3534
  });
3501
3535
  initMcpIntegration(
3502
- getMCPByDomain("classes", { instructions: "MCP server for management of Elementor global classes" }),
3536
+ getMCPByDomain("classes", {
3537
+ instructions: "MCP server for management of Elementor global classes",
3538
+ docs: `Everything related to V4 ( Atomic ) global classes.
3539
+ # Global classes
3540
+ - Create/update/delete global classes
3541
+ - Get list of global classes
3542
+ - Get details of a global class
3543
+ `
3544
+ }),
3503
3545
  getMCPByDomain("canvas")
3504
3546
  );
3505
3547
  }