@elementor/editor-global-classes 4.3.0-998 → 4.3.0-beta1

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
@@ -144,12 +144,16 @@ var slice = createSlice({
144
144
  state.isDirty = true;
145
145
  },
146
146
  update(state, { payload }) {
147
+ const oldLabel = state.classLabels[payload.style.id];
147
148
  localHistory.next(state.data);
148
149
  const style = state.data.items[payload.style.id];
149
150
  const mergedData = {
150
151
  ...style,
151
152
  ...payload.style
152
153
  };
154
+ if (oldLabel && payload.style.label && payload.style.label !== oldLabel) {
155
+ state.classLabels[payload.style.id] = payload.style.label;
156
+ }
153
157
  state.data.items[payload.style.id] = mergedData;
154
158
  state.isDirty = true;
155
159
  },
@@ -251,9 +255,15 @@ var slice = createSlice({
251
255
  updateAfterTemplateImport(state, {
252
256
  payload
253
257
  }) {
254
- state.initialData.frontend.items = { ...state.initialData.frontend.items, ...payload.addedItems };
258
+ state.initialData.frontend.items = {
259
+ ...state.initialData.frontend.items,
260
+ ...payload.addedItems
261
+ };
255
262
  state.initialData.frontend.order = [...state.initialData.frontend.order, ...payload.addedIdsOrder];
256
- state.initialData.preview.items = { ...state.initialData.preview.items, ...payload.addedItems };
263
+ state.initialData.preview.items = {
264
+ ...state.initialData.preview.items,
265
+ ...payload.addedItems
266
+ };
257
267
  state.initialData.preview.order = [...state.initialData.preview.order, ...payload.addedIdsOrder];
258
268
  state.data.items = { ...state.data.items, ...payload.addedItems };
259
269
  state.data.order = [...state.data.order, ...payload.addedIdsOrder];
@@ -1988,7 +1998,7 @@ var GlobalClassesList = ({
1988
1998
  search: { debouncedValue: searchValue }
1989
1999
  } = useSearchAndFilters();
1990
2000
  const cssClasses = useOrderedClasses();
1991
- const dispatch7 = useDispatch();
2001
+ const dispatch8 = useDispatch();
1992
2002
  const filters = useFilters();
1993
2003
  const [draggedItemId, setDraggedItemId] = useState5(null);
1994
2004
  const [loading, setLoading] = useState5({});
@@ -2021,22 +2031,22 @@ var GlobalClassesList = ({
2021
2031
  }
2022
2032
  });
2023
2033
  useEffect2(() => {
2024
- const handler2 = (event) => {
2034
+ const handler = (event) => {
2025
2035
  if (event.key === "z" && (event.ctrlKey || event.metaKey)) {
2026
2036
  event.stopImmediatePropagation();
2027
2037
  event.preventDefault();
2028
2038
  if (event.shiftKey) {
2029
- dispatch7(slice.actions.redo());
2039
+ dispatch8(slice.actions.redo());
2030
2040
  return;
2031
2041
  }
2032
- dispatch7(slice.actions.undo());
2042
+ dispatch8(slice.actions.undo());
2033
2043
  }
2034
2044
  };
2035
- window.addEventListener("keydown", handler2, {
2045
+ window.addEventListener("keydown", handler, {
2036
2046
  capture: true
2037
2047
  });
2038
- return () => window.removeEventListener("keydown", handler2);
2039
- }, [dispatch7]);
2048
+ return () => window.removeEventListener("keydown", handler);
2049
+ }, [dispatch8]);
2040
2050
  if (!cssClasses?.length) {
2041
2051
  return /* @__PURE__ */ React17.createElement(EmptyState, null);
2042
2052
  }
@@ -2096,7 +2106,7 @@ var GlobalClassesList = ({
2096
2106
  source: "class-manager"
2097
2107
  });
2098
2108
  void await loadExistingClasses([cssClass.id]);
2099
- dispatch7(
2109
+ dispatch8(
2100
2110
  slice.actions.update({
2101
2111
  style: {
2102
2112
  id: cssClass.id,
@@ -2122,7 +2132,7 @@ var GlobalClassesList = ({
2122
2132
  } else if (newValue && onStartSyncRequest) {
2123
2133
  onStartSyncRequest(id);
2124
2134
  } else {
2125
- dispatch7(
2135
+ dispatch8(
2126
2136
  slice.actions.update({
2127
2137
  style: {
2128
2138
  id,
@@ -2149,10 +2159,10 @@ var StyledHeader = styled6(Typography8)(({ theme, variant }) => ({
2149
2159
  }
2150
2160
  }));
2151
2161
  var useReorder = (draggedItemId, setDraggedItemId, draggedItemLabel) => {
2152
- const dispatch7 = useDispatch();
2162
+ const dispatch8 = useDispatch();
2153
2163
  const order = useClassesOrder();
2154
2164
  const reorder = (newIds) => {
2155
- dispatch7(slice.actions.setOrder(newIds));
2165
+ dispatch8(slice.actions.setOrder(newIds));
2156
2166
  if (draggedItemId) {
2157
2167
  trackGlobalClasses({
2158
2168
  event: "classManagerReorder",
@@ -2523,19 +2533,14 @@ import {
2523
2533
  import { __ as __15 } from "@wordpress/i18n";
2524
2534
 
2525
2535
  // src/capabilities.ts
2526
- import { isExperimentActive } from "@elementor/editor-v1-adapters";
2527
- var EXPERIMENT_KEY = "global_classes_should_enforce_capabilities";
2528
2536
  var UPDATE_CLASS_CAPABILITY_KEY = "elementor_global_classes_update_class";
2529
2537
  var getCapabilities = () => {
2530
- const shouldEnforceCapabilities = isExperimentActive(EXPERIMENT_KEY);
2531
- if (shouldEnforceCapabilities) {
2532
- return {
2533
- update: UPDATE_CLASS_CAPABILITY_KEY,
2534
- create: UPDATE_CLASS_CAPABILITY_KEY,
2535
- delete: UPDATE_CLASS_CAPABILITY_KEY,
2536
- updateProps: UPDATE_CLASS_CAPABILITY_KEY
2537
- };
2538
- }
2538
+ return {
2539
+ update: UPDATE_CLASS_CAPABILITY_KEY,
2540
+ create: UPDATE_CLASS_CAPABILITY_KEY,
2541
+ delete: UPDATE_CLASS_CAPABILITY_KEY,
2542
+ updateProps: UPDATE_CLASS_CAPABILITY_KEY
2543
+ };
2539
2544
  };
2540
2545
 
2541
2546
  // src/global-classes-styles-provider.ts
@@ -2788,7 +2793,7 @@ import { useEffect as useEffect5 } from "react";
2788
2793
  import { GLOBAL_STYLES_IMPORTED_EVENT } from "@elementor/editor-canvas";
2789
2794
  import { __useDispatch as useDispatch2 } from "@elementor/store";
2790
2795
  function GlobalStylesImportListener() {
2791
- const dispatch7 = useDispatch2();
2796
+ const dispatch8 = useDispatch2();
2792
2797
  useEffect5(() => {
2793
2798
  const handleGlobalStylesImported = async (event) => {
2794
2799
  const customEvent = event;
@@ -2797,7 +2802,7 @@ function GlobalStylesImportListener() {
2797
2802
  loadCurrentDocumentClasses();
2798
2803
  return;
2799
2804
  }
2800
- dispatch7(
2805
+ dispatch8(
2801
2806
  slice.actions.updateAfterTemplateImport({
2802
2807
  addedItems: globalClasses.added_items,
2803
2808
  addedIdsOrder: globalClasses.added_items_order,
@@ -2809,7 +2814,7 @@ function GlobalStylesImportListener() {
2809
2814
  return () => {
2810
2815
  window.removeEventListener(GLOBAL_STYLES_IMPORTED_EVENT, handleGlobalStylesImported);
2811
2816
  };
2812
- }, [dispatch7]);
2817
+ }, [dispatch8]);
2813
2818
  return null;
2814
2819
  }
2815
2820
 
@@ -2826,9 +2831,78 @@ function PopulateStore() {
2826
2831
  return null;
2827
2832
  }
2828
2833
 
2834
+ // src/mcp-integration/manage-classes-tool.ts
2835
+ import { httpService as httpService2 } from "@elementor/http-client";
2836
+ import { z } from "@elementor/schema";
2837
+ import { __dispatch as dispatch7 } from "@elementor/store";
2838
+ var MCP_PROXY_URL = "elementor/v1/mcp-proxy";
2839
+ var TOOL_NAME = "manage-classes";
2840
+ var initManageClassesTool = (reg) => {
2841
+ const { addTool } = reg;
2842
+ addTool({
2843
+ name: TOOL_NAME,
2844
+ description: "Manage V4 global CSS classes on the active kit. Bulk create, update, or delete using raw CSS declarations (up to 50 operations). Duplicate labels are auto-renamed with a DUP_ prefix.",
2845
+ schema: {
2846
+ action: z.enum(["create", "update", "delete"]),
2847
+ id: z.string().optional().describe("Class id \u2014 required for update/delete. Get from the global-classes resource."),
2848
+ label: z.string().optional().describe("Class label (lowercase, dash-separated) \u2014 required for create/update."),
2849
+ css: z.string().optional().describe(
2850
+ 'Plain CSS string. Supports &:hover/&:focus/&:active nesting and @media(--breakpoint) blocks. font-family must be a single Google Font name (no fallback stacks). In patch mode: "prop: null" removes that prop; "all: null" wipes the variant.'
2851
+ ),
2852
+ mode: z.enum(["patch", "replace"]).optional().describe(
2853
+ "Merge strategy for update \u2014 patch (default): merge incoming props with existing; replace: discard all existing variants for the affected breakpoints."
2854
+ )
2855
+ },
2856
+ outputSchema: {
2857
+ status: z.enum(["ok"]).describe("Operation status"),
2858
+ id: z.string().optional().describe("ID of the affected class \u2014 use for subsequent update/delete calls."),
2859
+ label: z.string().optional().describe("Final label of the class after any auto-rename.")
2860
+ },
2861
+ requiredResources: [
2862
+ {
2863
+ uri: GLOBAL_CLASSES_URI,
2864
+ description: "Current global classes \u2014 check before creating to avoid duplicates"
2865
+ }
2866
+ ],
2867
+ isDestructive: true,
2868
+ handler: async (params) => {
2869
+ const { data } = await httpService2().post(MCP_PROXY_URL, {
2870
+ tool: TOOL_NAME,
2871
+ input: { operations: [params] }
2872
+ });
2873
+ const result = data.data.results?.[0];
2874
+ const { create, update, delete: del } = globalClassesStylesProvider.actions;
2875
+ switch (params.action) {
2876
+ case "create":
2877
+ if (result && create) {
2878
+ create(result.label, result.variants, result.id);
2879
+ }
2880
+ break;
2881
+ case "update":
2882
+ if (result && update) {
2883
+ update(result);
2884
+ }
2885
+ break;
2886
+ case "delete":
2887
+ if (params.id && del) {
2888
+ del(params.id);
2889
+ }
2890
+ break;
2891
+ }
2892
+ dispatch7(slice.actions.reset({ context: "frontend" }));
2893
+ window.dispatchEvent(new CustomEvent("classes:updated", { detail: { context: "frontend" } }));
2894
+ return {
2895
+ status: "ok",
2896
+ id: result?.id,
2897
+ label: result?.label
2898
+ };
2899
+ }
2900
+ });
2901
+ };
2902
+
2829
2903
  // src/mcp-integration/mcp-apply-unapply-global-classes.ts
2830
2904
  import { doApplyClasses, doGetAppliedClasses, doUnapplyClass } from "@elementor/editor-editing-panel";
2831
- import { z } from "@elementor/schema";
2905
+ import { z as z2 } from "@elementor/schema";
2832
2906
 
2833
2907
  // src/mcp-integration/apply-global-class-guide-prompt.ts
2834
2908
  import { toolPrompts } from "@elementor/editor-mcp";
@@ -2838,8 +2912,8 @@ var generateApplyGlobalClassGuidePrompt = () => {
2838
2912
  prompt.description("Apply a global class to an element, enabling consistent styling through your design system.");
2839
2913
  prompt.instruction(
2840
2914
  `## When to use this tool:
2841
- **ALWAYS use this IMMEDIATELY AFTER building compositions** to apply the global classes you created beforehand:
2842
- - After using "build-compositions" tool, apply semantic classes to the created elements
2915
+ **ALWAYS use this IMMEDIATELY AFTER creating or updating elements** to apply the global classes you created beforehand:
2916
+ - After adding elements to the canvas, apply semantic classes to them
2843
2917
  - When applying consistent typography styles (heading-primary, text-body, etc.)
2844
2918
  - When applying theme colors or brand styles (bg-brand, button-cta, etc.)
2845
2919
  - When ensuring spacing consistency (spacing-section-large, etc.)
@@ -2851,7 +2925,7 @@ var generateApplyGlobalClassGuidePrompt = () => {
2851
2925
  prompt.instruction(
2852
2926
  `## Prerequisites:
2853
2927
  - **REQUIRED**: Get the list of available global classes from 'elementor://global-classes' resource
2854
- - **REQUIRED**: Get element IDs from the composition XML returned by "build-compositions" tool
2928
+ - **REQUIRED**: Get element IDs from the page structure or selected element resources
2855
2929
  - Ensure you have the most up-to-date list of classes applied to the element to avoid duplicates
2856
2930
  - Make sure you have the correct class ID that you want to apply`
2857
2931
  );
@@ -2882,12 +2956,12 @@ function initMcpApplyUnapplyGlobalClasses(server) {
2882
2956
  );
2883
2957
  addTool({
2884
2958
  schema: {
2885
- classId: z.string().describe("The ID of the class to apply"),
2886
- elementId: z.string().describe("The ID of the element to which the class will be applied")
2959
+ classId: z2.string().describe("The ID of the class to apply"),
2960
+ elementId: z2.string().describe("The ID of the element to which the class will be applied")
2887
2961
  },
2888
2962
  outputSchema: {
2889
- result: z.string().describe("Result message indicating the success of the apply operation"),
2890
- llm_instructions: z.string().describe("Instructions what to do next, Important to follow these instructions!")
2963
+ result: z2.string().describe("Result message indicating the success of the apply operation"),
2964
+ llm_instructions: z2.string().describe("Instructions what to do next, Important to follow these instructions!")
2891
2965
  },
2892
2966
  name: "apply-global-class",
2893
2967
  description: `Apply a global class to an element for shared design-system styling. Read the full guide at [${APPLY_GLOBAL_CLASS_GUIDE_URI}].`,
@@ -2913,11 +2987,11 @@ function initMcpApplyUnapplyGlobalClasses(server) {
2913
2987
  addTool({
2914
2988
  name: "unapply-global-class",
2915
2989
  schema: {
2916
- classId: z.string().describe("The ID of the class to unapply"),
2917
- elementId: z.string().describe("The ID of the element from which the class will be unapplied")
2990
+ classId: z2.string().describe("The ID of the class to unapply"),
2991
+ elementId: z2.string().describe("The ID of the element from which the class will be unapplied")
2918
2992
  },
2919
2993
  outputSchema: {
2920
- result: z.string().describe("Result message indicating the success of the unapply operation")
2994
+ result: z2.string().describe("Result message indicating the success of the unapply operation")
2921
2995
  },
2922
2996
  description: `Unapply a global class from an element by class ID. Resolve class names to IDs via [${GLOBAL_CLASSES_URI}].`,
2923
2997
  requiredResources: [{ description: "Global classes list", uri: GLOBAL_CLASSES_URI }],
@@ -2935,21 +3009,21 @@ function initMcpApplyUnapplyGlobalClasses(server) {
2935
3009
  }
2936
3010
 
2937
3011
  // src/mcp-integration/mcp-get-global-class-usages.ts
2938
- import { z as z2 } from "@elementor/schema";
3012
+ import { z as z3 } from "@elementor/schema";
2939
3013
  function initMcpApplyGetGlobalClassUsages(reg) {
2940
3014
  const { addTool } = reg;
2941
3015
  const globalClassesUsageSchema = {
2942
- usages: z2.array(
2943
- z2.object({
2944
- classId: z2.string().describe(
3016
+ usages: z3.array(
3017
+ z3.object({
3018
+ classId: z3.string().describe(
2945
3019
  'The ID of the class, not visible to the user. To retrieve the name of the class, use the "list-global-classes" tool'
2946
3020
  ),
2947
- usages: z2.array(
2948
- z2.object({
2949
- pageId: z2.string().describe("The ID of the page where the class is used"),
2950
- title: z2.string().describe("The title of the page where the class is used"),
2951
- total: z2.number().describe("The number of times the class is used on this page"),
2952
- elements: z2.array(z2.string()).describe("List of element IDs using this class on the page")
3021
+ usages: z3.array(
3022
+ z3.object({
3023
+ pageId: z3.string().describe("The ID of the page where the class is used"),
3024
+ title: z3.string().describe("The title of the page where the class is used"),
3025
+ total: z3.number().describe("The number of times the class is used on this page"),
3026
+ elements: z3.array(z3.string()).describe("List of element IDs using this class on the page")
2953
3027
  })
2954
3028
  )
2955
3029
  })
@@ -2997,270 +3071,11 @@ function initMcpApplyGetGlobalClassUsages(reg) {
2997
3071
  });
2998
3072
  }
2999
3073
 
3000
- // src/mcp-integration/mcp-manage-global-classes.ts
3001
- import { BREAKPOINTS_SCHEMA_FULL_URI, convertStyleBlocksToAtomic } from "@elementor/editor-canvas";
3002
- import { dispatchMcpStylesAppliedEvent } from "@elementor/editor-mcp";
3003
- import { z as z3 } from "@elementor/schema";
3004
- var schema = {
3005
- action: z3.enum(["create", "modify", "delete"]).describe("Operation to perform"),
3006
- classId: z3.string().optional().describe("Global class ID (required for modify). Get from elementor://global-classes resource."),
3007
- globalClassName: z3.string().optional().describe("Global class name (required for create)"),
3008
- style: z3.object({
3009
- default: z3.string().describe("Plaintext CSS for the default state. MUST be non-empty \u2014 blank strings are rejected."),
3010
- hover: z3.string().describe("Plaintext CSS for the :hover state. optional").optional(),
3011
- focus: z3.string().describe("Plaintext CSS for the :focus state. optional").optional(),
3012
- active: z3.string().describe("Plaintext CSS for the :active state. optional").optional()
3013
- }).describe(
3014
- "Plaintext CSS per pseudo-state. All states are converted in one bulk request; unconvertible declarations are stored as custom CSS."
3015
- ),
3016
- breakpoint: z3.nullable(z3.string().describe("Responsive breakpoint name for styles. Defaults to desktop (null).")).default(null).describe("Responsive breakpoint name for styles. Defaults to desktop (null).")
3017
- };
3018
- var outputSchema = {
3019
- status: z3.enum(["ok", "error"]).describe("Operation status"),
3020
- classId: z3.string().optional().describe("Class ID (returned on create success)"),
3021
- message: z3.string().optional().describe("Error details if status is error")
3022
- };
3023
- var handler = async (input) => {
3024
- const { action, classId: rawClassId, globalClassName, style: rawStyle, breakpoint } = input;
3025
- let classId = rawClassId;
3026
- if (action === "create" && !globalClassName) {
3027
- return {
3028
- status: "error",
3029
- message: "Create requires globalClassName"
3030
- };
3031
- }
3032
- if (action === "modify" && !classId) {
3033
- return {
3034
- status: "error",
3035
- message: "Modify requires classId"
3036
- };
3037
- }
3038
- if (action === "delete" && !classId) {
3039
- return {
3040
- status: "error",
3041
- message: "Delete requires classId"
3042
- };
3043
- }
3044
- const { create, update, delete: deleteClass2 } = globalClassesStylesProvider.actions;
3045
- if (!create || !update || !deleteClass2) {
3046
- return {
3047
- status: "error",
3048
- message: "Required actions not available"
3049
- };
3050
- }
3051
- const styleBlocks = collectNonEmptyStyleBlocks(rawStyle);
3052
- if (action !== "delete" && Object.keys(styleBlocks).length === 0) {
3053
- throw new Error(
3054
- 'Style must not be empty. Provide plaintext CSS per state.\n\nExample: style.default = "display: flex; flex-direction: column; gap: 1rem;"'
3055
- );
3056
- }
3057
- let convertedByState = {};
3058
- if (action !== "delete") {
3059
- const conversionResults = await convertStyleBlocksToAtomic(styleBlocks);
3060
- convertedByState = Object.fromEntries(
3061
- Object.entries(conversionResults).map(([state, { props, customCss }]) => [
3062
- state,
3063
- { props, customCss: toStoredCustomCss(customCss) }
3064
- ])
3065
- );
3066
- }
3067
- const breakpointValue = breakpoint ?? "desktop";
3068
- let result = {
3069
- status: "error",
3070
- classId: "",
3071
- message: "unknown error"
3072
- };
3073
- try {
3074
- if (action === "delete") {
3075
- const deleted = await attemptDelete({
3076
- classId,
3077
- stylesProvider: globalClassesStylesProvider
3078
- });
3079
- if (deleted) {
3080
- return { status: "ok", message: `deleted global class with ID ${classId}` };
3081
- }
3082
- throw new Error("error deleting class");
3083
- }
3084
- let currentAction = action;
3085
- for await (const [state, { props, customCss }] of Object.entries(convertedByState)) {
3086
- switch (currentAction) {
3087
- case "create":
3088
- const newClassId = await attemptCreate({
3089
- props,
3090
- customCss,
3091
- className: globalClassName,
3092
- stylesProvider: globalClassesStylesProvider,
3093
- breakpoint: breakpointValue,
3094
- state
3095
- });
3096
- if (newClassId && currentAction === "create") {
3097
- currentAction = "modify";
3098
- classId = newClassId;
3099
- result = {
3100
- status: "ok",
3101
- message: `created global class with ID ${newClassId}`
3102
- };
3103
- globalClassesStylesProvider.actions.tracking?.({
3104
- event: "classCreated",
3105
- executedBy: "mcp_tool",
3106
- classId: newClassId
3107
- });
3108
- dispatchMcpStylesAppliedEvent({ styleValue: props });
3109
- } else {
3110
- throw new Error("error creating class");
3111
- }
3112
- break;
3113
- case "modify":
3114
- const updated = await attemptUpdate({
3115
- classId,
3116
- props,
3117
- customCss,
3118
- stylesProvider: globalClassesStylesProvider,
3119
- breakpoint: breakpointValue,
3120
- state
3121
- });
3122
- if (updated) {
3123
- result = { status: "ok", classId };
3124
- dispatchMcpStylesAppliedEvent({ styleValue: props });
3125
- } else {
3126
- throw new Error("error modifying class");
3127
- }
3128
- break;
3129
- default:
3130
- throw new Error(`Unsupported action ${action}`);
3131
- }
3132
- }
3133
- } catch (error) {
3134
- return {
3135
- status: "error",
3136
- message: `${action} failed: ${error.message || "Unknown error"}`
3137
- };
3138
- }
3139
- return result;
3140
- };
3141
- var initManageGlobalClasses = (reg) => {
3142
- const { addTool } = reg;
3143
- addTool({
3144
- name: "manage-global-classes",
3145
- requiredResources: [
3146
- { uri: GLOBAL_CLASSES_URI, description: "Global classes list" },
3147
- { uri: BREAKPOINTS_SCHEMA_FULL_URI, description: "Breakpoints list" }
3148
- ],
3149
- 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 applying them. Do NOT create classes for one-off styles.
3150
-
3151
- IMPORTANT: style must contain plaintext CSS rules per state \u2014 never pass empty strings.
3152
- CSS is converted server-side in one bulk request; any declaration that cannot be converted is stored as the class custom CSS.
3153
-
3154
- Example \u2014 creating a flex column class:
3155
- style.default = "display: flex; flex-direction: column; gap: 1rem;"
3156
-
3157
- Example \u2014 hover state:
3158
- style.hover = "opacity: 0.85;"`,
3159
- schema,
3160
- outputSchema,
3161
- handler
3162
- });
3163
- };
3164
- async function attemptCreate(opts) {
3165
- const { props, customCss, breakpoint, className, stylesProvider, state } = opts;
3166
- const { create, delete: deleteClass2 } = stylesProvider.actions;
3167
- if (!className) {
3168
- throw new Error("Global class name is a required for creation");
3169
- }
3170
- if (!create || !deleteClass2) {
3171
- throw new Error("User is unable to create global classes");
3172
- }
3173
- const newClassId = create(className, [
3174
- {
3175
- meta: {
3176
- breakpoint,
3177
- state: state === "default" ? null : state
3178
- },
3179
- custom_css: customCss,
3180
- props
3181
- }
3182
- ]);
3183
- try {
3184
- await saveGlobalClasses2({ context: "frontend" });
3185
- return newClassId;
3186
- } catch {
3187
- deleteClass2(newClassId);
3188
- throw new Error("error creating class");
3189
- }
3190
- }
3191
- async function attemptUpdate(opts) {
3192
- const { props, customCss, breakpoint, classId, stylesProvider, state } = opts;
3193
- const { updateProps, update } = stylesProvider.actions;
3194
- if (!classId) {
3195
- throw new Error("Class ID is required for modification");
3196
- }
3197
- if (!updateProps || !update) {
3198
- throw new Error("User is unable to update global classes");
3199
- }
3200
- await loadExistingClasses([classId]);
3201
- const snapshot = structuredClone(stylesProvider.actions.all());
3202
- try {
3203
- updateProps({
3204
- id: classId,
3205
- props,
3206
- custom_css: customCss,
3207
- meta: {
3208
- breakpoint,
3209
- state: state === "default" ? null : state
3210
- }
3211
- });
3212
- await saveGlobalClasses2({ context: "frontend" });
3213
- return true;
3214
- } catch {
3215
- snapshot.forEach((style) => {
3216
- update({
3217
- id: style.id,
3218
- variants: style.variants
3219
- });
3220
- });
3221
- await saveGlobalClasses2({ context: "frontend" });
3222
- throw new Error("error updating class");
3223
- }
3224
- }
3225
- async function attemptDelete(opts) {
3226
- const { classId, stylesProvider } = opts;
3227
- const { delete: deleteClass2, create } = stylesProvider.actions;
3228
- if (!classId) {
3229
- throw new Error("Class ID is required for deletion");
3230
- }
3231
- if (!deleteClass2 || !create) {
3232
- throw new Error("User is unable to delete global classes");
3233
- }
3234
- const snapshot = structuredClone(stylesProvider.actions.all());
3235
- const targetClass = snapshot.find((style) => style.id === classId);
3236
- if (!targetClass) {
3237
- throw new Error(`Class with ID "${classId}" not found`);
3238
- }
3239
- deleteClass2(classId);
3240
- await saveGlobalClasses2({ context: "frontend" });
3241
- return true;
3242
- }
3243
- function collectNonEmptyStyleBlocks(style) {
3244
- const blocks = {};
3245
- Object.entries(style).forEach(([state, cssText]) => {
3246
- if (cssText?.trim()) {
3247
- blocks[state] = cssText.trim();
3248
- }
3249
- });
3250
- return blocks;
3251
- }
3252
- function toStoredCustomCss(customCss) {
3253
- if (!customCss?.trim()) {
3254
- return null;
3255
- }
3256
- return { raw: btoa(customCss) };
3257
- }
3258
-
3259
3074
  // src/mcp-integration/index.ts
3260
3075
  var initMcpIntegration = (reg, canvasMcpEntry) => {
3261
3076
  initMcpApplyUnapplyGlobalClasses(reg);
3262
3077
  initMcpApplyGetGlobalClassUsages(reg);
3263
- initManageGlobalClasses(reg);
3078
+ initManageClassesTool(reg);
3264
3079
  initClassesResource(reg, canvasMcpEntry);
3265
3080
  };
3266
3081