@elementor/editor-global-classes 3.33.0-99 → 3.34.2

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.
Files changed (37) hide show
  1. package/dist/index.js +1000 -430
  2. package/dist/index.js.map +1 -1
  3. package/dist/index.mjs +940 -366
  4. package/dist/index.mjs.map +1 -1
  5. package/package.json +21 -18
  6. package/src/api.ts +4 -0
  7. package/src/components/class-manager/class-manager-button.tsx +15 -1
  8. package/src/components/class-manager/class-manager-panel.tsx +2 -2
  9. package/src/components/class-manager/delete-class.ts +9 -3
  10. package/src/components/class-manager/delete-confirmation-dialog.tsx +2 -2
  11. package/src/components/class-manager/duplicate-label-dialog.tsx +159 -0
  12. package/src/components/class-manager/global-classes-list.tsx +53 -22
  13. package/src/components/convert-local-class-to-global-class.tsx +7 -0
  14. package/src/components/css-class-usage/components/css-class-usage-popover.tsx +10 -1
  15. package/src/components/css-class-usage/components/css-class-usage-trigger.tsx +22 -7
  16. package/src/components/search-and-filter/components/filter/active-filters.tsx +8 -0
  17. package/src/components/search-and-filter/components/filter/clear-icon-button.tsx +12 -3
  18. package/src/components/search-and-filter/components/filter/css-class-filter.tsx +10 -0
  19. package/src/components/search-and-filter/components/filter/filter-list.tsx +7 -0
  20. package/src/components/search-and-filter/components/search/class-manager-search.tsx +6 -0
  21. package/src/components/search-and-filter/context.tsx +12 -2
  22. package/src/errors.ts +5 -0
  23. package/src/global-classes-styles-provider.ts +13 -3
  24. package/src/hooks/use-css-class-by-id.ts +8 -0
  25. package/src/hooks/use-prefetch-css-class-usage.ts +6 -0
  26. package/src/init.ts +14 -5
  27. package/src/mcp-integration/classes-resource.ts +20 -0
  28. package/src/mcp-integration/index.ts +15 -0
  29. package/src/mcp-integration/mcp-apply-unapply-global-classes.ts +117 -0
  30. package/src/mcp-integration/mcp-get-global-class-usages.ts +72 -0
  31. package/src/save-global-classes.tsx +55 -0
  32. package/src/store.ts +32 -1
  33. package/src/sync-with-document-save.ts +9 -6
  34. package/src/sync-with-document.tsx +19 -0
  35. package/src/utils/tracking.ts +204 -0
  36. package/src/components/class-manager/save-changes-dialog.tsx +0 -92
  37. package/src/save-global-classes.ts +0 -42
package/dist/index.mjs CHANGED
@@ -6,26 +6,26 @@ import {
6
6
  registerStyleProviderToColors
7
7
  } from "@elementor/editor-editing-panel";
8
8
  import { __registerPanel as registerPanel } from "@elementor/editor-panels";
9
- import { stylesRepository } from "@elementor/editor-styles-repository";
10
- import { __privateListenTo as listenTo, v1ReadyEvent } from "@elementor/editor-v1-adapters";
9
+ import { stylesRepository as stylesRepository2 } from "@elementor/editor-styles-repository";
11
10
  import { __registerSlice as registerSlice } from "@elementor/store";
12
11
 
13
12
  // src/components/class-manager/class-manager-button.tsx
14
- import * as React18 from "react";
13
+ import * as React19 from "react";
15
14
  import {
16
15
  __useActiveDocument as useActiveDocument2,
17
16
  __useActiveDocumentActions as useActiveDocumentActions
18
17
  } from "@elementor/editor-documents";
19
18
  import { useUserStylesCapability } from "@elementor/editor-styles-repository";
19
+ import { SaveChangesDialog as SaveChangesDialog2, useDialog as useDialog2 } from "@elementor/editor-ui";
20
20
  import { IconButton as IconButton5, Tooltip as Tooltip6 } from "@elementor/ui";
21
- import { __ as __14 } from "@wordpress/i18n";
21
+ import { __ as __15 } from "@wordpress/i18n";
22
22
 
23
23
  // src/global-classes-styles-provider.ts
24
24
  import { generateId } from "@elementor/editor-styles";
25
25
  import { createStylesProvider } from "@elementor/editor-styles-repository";
26
26
  import {
27
27
  __dispatch as dispatch,
28
- __getState as getState,
28
+ __getState as getState2,
29
29
  __subscribeWithSelector as subscribeWithSelector
30
30
  } from "@elementor/store";
31
31
  import { __ } from "@wordpress/i18n";
@@ -56,9 +56,12 @@ var GlobalClassLabelAlreadyExistsError = createError({
56
56
  code: "global_class_label_already_exists",
57
57
  message: "Class with this name already exists."
58
58
  });
59
+ var GlobalClassTrackingError = createError({
60
+ code: "global_class_tracking_error",
61
+ message: "Error tracking global classes event."
62
+ });
59
63
 
60
64
  // src/store.ts
61
- import { mergeProps } from "@elementor/editor-props";
62
65
  import {
63
66
  getVariantByMeta
64
67
  } from "@elementor/editor-styles";
@@ -179,6 +182,13 @@ var slice = createSlice({
179
182
  state.data.items[payload.style.id] = mergedData;
180
183
  state.isDirty = true;
181
184
  },
185
+ updateMultiple(state, { payload }) {
186
+ localHistory.next(state.data);
187
+ Object.entries(payload).forEach(([id2, { modified }]) => {
188
+ state.data.items[id2].label = modified;
189
+ });
190
+ state.isDirty = false;
191
+ },
182
192
  updateProps(state, {
183
193
  payload
184
194
  }) {
@@ -236,6 +246,17 @@ var slice = createSlice({
236
246
  }
237
247
  }
238
248
  });
249
+ var mergeProps = (current, updates) => {
250
+ const props = Array.isArray(current) ? {} : current;
251
+ Object.entries(updates).forEach(([key, value]) => {
252
+ if (value === null || value === void 0) {
253
+ delete props[key];
254
+ } else {
255
+ props[key] = value;
256
+ }
257
+ });
258
+ return props;
259
+ };
239
260
  var getNonEmptyVariants = (style) => {
240
261
  return style.variants.filter(
241
262
  ({ props, custom_css: customCss }) => Object.keys(props).length || customCss?.raw
@@ -258,8 +279,159 @@ var selectEmptyCssClass = createSelector(
258
279
  ({ items }) => Object.values(items).filter((cssClass) => cssClass.variants.length === 0)
259
280
  );
260
281
 
282
+ // src/utils/tracking.ts
283
+ import { getMixpanel } from "@elementor/mixpanel";
284
+ import { __getState as getState } from "@elementor/store";
285
+
286
+ // src/api.ts
287
+ import { httpService } from "@elementor/http-client";
288
+ var RESOURCE_URL = "/global-classes";
289
+ var BASE_URL = "elementor/v1";
290
+ var RESOURCE_USAGE_URL = `${RESOURCE_URL}/usage`;
291
+ var apiClient = {
292
+ usage: () => httpService().get(`${BASE_URL}${RESOURCE_USAGE_URL}`),
293
+ all: (context2 = "preview") => httpService().get(`${BASE_URL}${RESOURCE_URL}`, {
294
+ params: { context: context2 }
295
+ }),
296
+ publish: (payload) => httpService().put("elementor/v1" + RESOURCE_URL, payload, {
297
+ params: {
298
+ context: "frontend"
299
+ }
300
+ }),
301
+ saveDraft: (payload) => httpService().put("elementor/v1" + RESOURCE_URL, payload, {
302
+ params: {
303
+ context: "preview"
304
+ }
305
+ })
306
+ };
307
+ var API_ERROR_CODES = {
308
+ DUPLICATED_LABEL: "DUPLICATED_LABEL"
309
+ };
310
+
311
+ // src/components/css-class-usage/utils.ts
312
+ var transformData = (data) => Object.entries(data).reduce((acc, [key, value]) => {
313
+ acc[key] = {
314
+ content: value || [],
315
+ total: value.reduce((total, val) => total + (val?.total || 0), 0)
316
+ };
317
+ return acc;
318
+ }, {});
319
+
320
+ // service/css-class-usage-service.ts
321
+ var fetchCssClassUsage = async () => {
322
+ const response = await apiClient.usage();
323
+ return transformData(response?.data?.data || {});
324
+ };
325
+
326
+ // src/utils/tracking.ts
327
+ var trackGlobalClasses = async (payload) => {
328
+ const { runAction } = payload;
329
+ const data = await getSanitizedData(payload);
330
+ if (data) {
331
+ track(data);
332
+ if (data.event === "classCreated" && "classId" in data) {
333
+ fireClassApplied(data.classId);
334
+ }
335
+ }
336
+ runAction?.();
337
+ };
338
+ var fireClassApplied = async (classId) => {
339
+ const appliedInfo = await getAppliedInfo(classId);
340
+ track({
341
+ event: "classApplied",
342
+ classId,
343
+ ...appliedInfo,
344
+ totalInstancesAfterApply: 1
345
+ });
346
+ };
347
+ var getSanitizedData = async (payload) => {
348
+ switch (payload.event) {
349
+ case "classApplied":
350
+ if ("classId" in payload && payload.classId) {
351
+ const appliedInfo = await getAppliedInfo(payload.classId);
352
+ return { ...payload, ...appliedInfo };
353
+ }
354
+ break;
355
+ case "classRemoved":
356
+ if ("classId" in payload && payload.classId) {
357
+ const deleteInfo = getRemovedInfo(payload.classId);
358
+ return { ...payload, ...deleteInfo };
359
+ }
360
+ break;
361
+ case "classDeleted":
362
+ if ("classId" in payload && payload.classId) {
363
+ const deleteInfo = await trackDeleteClass(payload.classId);
364
+ return { ...payload, ...deleteInfo };
365
+ }
366
+ break;
367
+ case "classCreated":
368
+ if ("source" in payload && payload.source !== "created") {
369
+ if ("classId" in payload && payload.classId) {
370
+ return { ...payload, classTitle: getCssClass(payload.classId).label };
371
+ }
372
+ }
373
+ return payload;
374
+ case "classStateClicked":
375
+ if ("classId" in payload && payload.classId) {
376
+ return { ...payload, classTitle: getCssClass(payload.classId).label };
377
+ }
378
+ break;
379
+ default:
380
+ return payload;
381
+ }
382
+ };
383
+ var track = (data) => {
384
+ const { dispatchEvent, config } = getMixpanel();
385
+ if (!config?.names?.global_classes?.[data.event]) {
386
+ console.error("Global class tracking event not found", { event: data.event });
387
+ return;
388
+ }
389
+ const name = config.names.global_classes[data.event];
390
+ const { event, ...eventData } = data;
391
+ try {
392
+ dispatchEvent?.(name, {
393
+ event,
394
+ ...eventData
395
+ });
396
+ } catch (error) {
397
+ throw new GlobalClassTrackingError({ cause: error });
398
+ }
399
+ };
400
+ var extractCssClassData = (classId) => {
401
+ const cssClass = getCssClass(classId);
402
+ const classTitle = cssClass.label;
403
+ return { classTitle };
404
+ };
405
+ var getCssClass = (classId) => {
406
+ const cssClass = selectClass(getState(), classId);
407
+ if (!cssClass) {
408
+ throw new Error(`CSS class with ID ${classId} not found`);
409
+ }
410
+ return cssClass;
411
+ };
412
+ var trackDeleteClass = async (classId) => {
413
+ const totalInstances = await getTotalInstancesByCssClassID(classId);
414
+ const classTitle = getCssClass(classId).label;
415
+ return { totalInstances, classTitle };
416
+ };
417
+ var getTotalInstancesByCssClassID = async (classId) => {
418
+ const cssClassUsage = await fetchCssClassUsage();
419
+ return cssClassUsage[classId]?.total ?? 1;
420
+ };
421
+ var getAppliedInfo = async (classId) => {
422
+ const { classTitle } = extractCssClassData(classId);
423
+ const totalInstancesAfterApply = await getTotalInstancesByCssClassID(classId) + 1;
424
+ return { classTitle, totalInstancesAfterApply };
425
+ };
426
+ var getRemovedInfo = (classId) => {
427
+ const { classTitle } = extractCssClassData(classId);
428
+ return {
429
+ classTitle
430
+ };
431
+ };
432
+
261
433
  // src/global-classes-styles-provider.ts
262
- var MAX_CLASSES = 50;
434
+ var MAX_CLASSES = 100;
263
435
  var GLOBAL_CLASSES_PROVIDER_KEY = "global-classes";
264
436
  var globalClassesStylesProvider = createStylesProvider({
265
437
  key: GLOBAL_CLASSES_PROVIDER_KEY,
@@ -272,13 +444,17 @@ var globalClassesStylesProvider = createStylesProvider({
272
444
  subscribe: (cb) => subscribeWithStates(cb),
273
445
  capabilities: getCapabilities(),
274
446
  actions: {
275
- all: () => selectOrderedClasses(getState()),
276
- get: (id2) => selectClass(getState(), id2),
447
+ all: () => {
448
+ const selectAllClasses = selectOrderedClasses(getState2());
449
+ localStorage.setItem("elementor-global-classes", JSON.stringify(selectAllClasses));
450
+ return selectAllClasses;
451
+ },
452
+ get: (id2) => selectClass(getState2(), id2),
277
453
  resolveCssName: (id2) => {
278
- return selectClass(getState(), id2)?.label ?? id2;
454
+ return selectClass(getState2(), id2)?.label ?? id2;
279
455
  },
280
456
  create: (label, variants = []) => {
281
- const classes = selectGlobalClasses(getState());
457
+ const classes = selectGlobalClasses(getState2());
282
458
  const existingLabels = Object.values(classes).map((style) => style.label);
283
459
  if (existingLabels.includes(label)) {
284
460
  throw new GlobalClassLabelAlreadyExistsError({ context: { label } });
@@ -323,11 +499,16 @@ var globalClassesStylesProvider = createStylesProvider({
323
499
  props: {}
324
500
  })
325
501
  );
502
+ },
503
+ tracking: (data) => {
504
+ trackGlobalClasses(data).catch((error) => {
505
+ throw new GlobalClassTrackingError({ cause: error });
506
+ });
326
507
  }
327
508
  }
328
509
  });
329
510
  var subscribeWithStates = (cb) => {
330
- let previousState = selectData(getState());
511
+ let previousState = selectData(getState2());
331
512
  return subscribeWithSelector(
332
513
  (state) => state.globalClasses,
333
514
  (currentState) => {
@@ -340,43 +521,6 @@ var subscribeWithStates = (cb) => {
340
521
  // src/hooks/use-prefetch-css-class-usage.ts
341
522
  import { useQueryClient } from "@elementor/query";
342
523
 
343
- // src/api.ts
344
- import { httpService } from "@elementor/http-client";
345
- var RESOURCE_URL = "/global-classes";
346
- var BASE_URL = "elementor/v1";
347
- var RESOURCE_USAGE_URL = `${RESOURCE_URL}/usage`;
348
- var apiClient = {
349
- usage: () => httpService().get(`${BASE_URL}${RESOURCE_USAGE_URL}`),
350
- all: (context2 = "preview") => httpService().get(`${BASE_URL}${RESOURCE_URL}`, {
351
- params: { context: context2 }
352
- }),
353
- publish: (payload) => httpService().put("elementor/v1" + RESOURCE_URL, payload, {
354
- params: {
355
- context: "frontend"
356
- }
357
- }),
358
- saveDraft: (payload) => httpService().put("elementor/v1" + RESOURCE_URL, payload, {
359
- params: {
360
- context: "preview"
361
- }
362
- })
363
- };
364
-
365
- // src/components/css-class-usage/utils.ts
366
- var transformData = (data) => Object.entries(data).reduce((acc, [key, value]) => {
367
- acc[key] = {
368
- content: value || [],
369
- total: value.reduce((total, val) => total + (val?.total || 0), 0)
370
- };
371
- return acc;
372
- }, {});
373
-
374
- // service/css-class-usage-service.ts
375
- var fetchCssClassUsage = async () => {
376
- const response = await apiClient.usage();
377
- return transformData(response.data.data);
378
- };
379
-
380
524
  // src/components/css-class-usage/types.ts
381
525
  var QUERY_KEY = "css-classes-usage";
382
526
 
@@ -389,10 +533,15 @@ function usePrefetchCssClassUsage() {
389
533
  });
390
534
  return { prefetchClassesUsage };
391
535
  }
536
+ var PrefetchCssClassUsage = () => {
537
+ const { prefetchClassesUsage } = usePrefetchCssClassUsage();
538
+ prefetchClassesUsage();
539
+ return null;
540
+ };
392
541
 
393
542
  // src/components/class-manager/class-manager-panel.tsx
394
- import * as React17 from "react";
395
- import { useEffect as useEffect2 } from "react";
543
+ import * as React18 from "react";
544
+ import { useEffect as useEffect3 } from "react";
396
545
  import { setDocumentModifiedStatus } from "@elementor/editor-documents";
397
546
  import {
398
547
  __createPanel as createPanel,
@@ -402,23 +551,23 @@ import {
402
551
  PanelHeader,
403
552
  PanelHeaderTitle
404
553
  } from "@elementor/editor-panels";
405
- import { ThemeProvider } from "@elementor/editor-ui";
554
+ import { SaveChangesDialog, ThemeProvider, useDialog } from "@elementor/editor-ui";
406
555
  import { changeEditMode } from "@elementor/editor-v1-adapters";
407
556
  import { XIcon } from "@elementor/icons";
408
557
  import { useMutation } from "@elementor/query";
409
558
  import { __dispatch as dispatch4 } from "@elementor/store";
410
559
  import {
411
- Alert,
412
- Box as Box9,
560
+ Alert as Alert2,
561
+ Box as Box10,
413
562
  Button as Button3,
414
563
  Chip as Chip4,
415
- DialogHeader,
416
- Divider as Divider3,
564
+ DialogHeader as DialogHeader2,
565
+ Divider as Divider4,
417
566
  ErrorBoundary,
418
567
  IconButton as IconButton4,
419
- Stack as Stack8
568
+ Stack as Stack9
420
569
  } from "@elementor/ui";
421
- import { __ as __13 } from "@wordpress/i18n";
570
+ import { __ as __14 } from "@wordpress/i18n";
422
571
 
423
572
  // src/hooks/use-classes-order.ts
424
573
  import { __useSelector as useSelector } from "@elementor/store";
@@ -447,9 +596,17 @@ var INIT_CHECKED_FILTERS = {
447
596
  };
448
597
  var SearchAndFilterProvider = ({ children }) => {
449
598
  const [filters, setFilters] = React.useState(INIT_CHECKED_FILTERS);
599
+ const getInitialSearchValue = () => {
600
+ const storedValue = localStorage.getItem("elementor-global-classes-search");
601
+ if (storedValue) {
602
+ localStorage.removeItem("elementor-global-classes-search");
603
+ return storedValue;
604
+ }
605
+ return "";
606
+ };
450
607
  const { debouncedValue, inputValue, handleChange } = useDebounceState({
451
608
  delay: 300,
452
- initialValue: ""
609
+ initialValue: getInitialSearchValue()
453
610
  });
454
611
  const onClearSearch = () => {
455
612
  handleChange("");
@@ -580,25 +737,150 @@ var useFilters = () => {
580
737
  }, [filters, allFilters]);
581
738
  };
582
739
 
583
- // src/save-global-classes.ts
584
- import { __dispatch as dispatch2, __getState as getState2 } from "@elementor/store";
740
+ // src/save-global-classes.tsx
741
+ import * as React3 from "react";
742
+ import { openDialog } from "@elementor/editor-ui";
743
+ import { __dispatch as dispatch2, __getState as getState3 } from "@elementor/store";
585
744
  import { hash } from "@elementor/utils";
586
- async function saveGlobalClasses({ context: context2 }) {
587
- const state = selectData(getState2());
588
- if (context2 === "preview") {
589
- await apiClient.saveDraft({
590
- items: state.items,
591
- order: state.order,
592
- changes: calculateChanges(state, selectPreviewInitialData(getState2()))
745
+
746
+ // src/components/class-manager/duplicate-label-dialog.tsx
747
+ import * as React2 from "react";
748
+ import { closeDialog, EllipsisWithTooltip } from "@elementor/editor-ui";
749
+ import { InfoCircleFilledIcon } from "@elementor/icons";
750
+ import {
751
+ Alert,
752
+ Box,
753
+ Button,
754
+ DialogActions,
755
+ DialogContent,
756
+ DialogHeader,
757
+ Divider,
758
+ Icon,
759
+ Stack,
760
+ Typography
761
+ } from "@elementor/ui";
762
+ import { __ as __2 } from "@wordpress/i18n";
763
+ var DUP_PREFIX = "DUP_";
764
+ var DuplicateLabelDialog = ({
765
+ modifiedLabels,
766
+ onApprove
767
+ }) => {
768
+ const handleButtonClick = () => {
769
+ localStorage.setItem("elementor-global-classes-search", DUP_PREFIX);
770
+ onApprove?.();
771
+ closeDialog();
772
+ };
773
+ return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(DialogHeader, { logo: false }, /* @__PURE__ */ React2.createElement(Box, { display: "flex", alignItems: "center", gap: 1 }, /* @__PURE__ */ React2.createElement(Icon, { color: "secondary" }, /* @__PURE__ */ React2.createElement(InfoCircleFilledIcon, { fontSize: "medium" })), /* @__PURE__ */ React2.createElement(Typography, { variant: "subtitle1" }, __2("We've published your page and updated class names.", "elementor")))), /* @__PURE__ */ React2.createElement(DialogContent, null, /* @__PURE__ */ React2.createElement(Stack, { spacing: 2, direction: "column" }, /* @__PURE__ */ React2.createElement(Typography, { variant: "body2" }, __2(
774
+ "Some new classes used the same names as existing ones. To prevent conflicts, we added the prefix",
775
+ "elementor"
776
+ ), /* @__PURE__ */ React2.createElement("strong", null, " ", DUP_PREFIX)), /* @__PURE__ */ React2.createElement(Box, null, /* @__PURE__ */ React2.createElement(
777
+ Box,
778
+ {
779
+ sx: {
780
+ width: "100%",
781
+ display: "flex",
782
+ gap: 2,
783
+ alignItems: "flex-start"
784
+ }
785
+ },
786
+ /* @__PURE__ */ React2.createElement(
787
+ Typography,
788
+ {
789
+ variant: "subtitle2",
790
+ sx: {
791
+ fontWeight: "bold",
792
+ flex: 1,
793
+ flexShrink: 1,
794
+ flexGrow: 1,
795
+ minWidth: 0
796
+ }
797
+ },
798
+ __2("Before", "elementor")
799
+ ),
800
+ /* @__PURE__ */ React2.createElement(
801
+ Typography,
802
+ {
803
+ variant: "subtitle2",
804
+ sx: {
805
+ minWidth: "200px",
806
+ fontWeight: "bold",
807
+ flexShrink: 0,
808
+ flexGrow: 0,
809
+ width: "200px",
810
+ maxWidth: "200px"
811
+ }
812
+ },
813
+ __2("After", "elementor")
814
+ )
815
+ ), /* @__PURE__ */ React2.createElement(Divider, { sx: { mt: 0.5, mb: 0.5 } }), /* @__PURE__ */ React2.createElement(Stack, { direction: "column", gap: 0.5, sx: { pb: 2 } }, Object.values(modifiedLabels).map(({ original, modified }, index) => /* @__PURE__ */ React2.createElement(
816
+ Box,
817
+ {
818
+ key: index,
819
+ sx: {
820
+ width: "100%",
821
+ display: "flex",
822
+ gap: 2,
823
+ alignItems: "flex-start"
824
+ }
825
+ },
826
+ /* @__PURE__ */ React2.createElement(
827
+ Box,
828
+ {
829
+ sx: {
830
+ flex: 1,
831
+ flexShrink: 1,
832
+ flexGrow: 1,
833
+ minWidth: 0
834
+ }
835
+ },
836
+ /* @__PURE__ */ React2.createElement(EllipsisWithTooltip, { title: original }, /* @__PURE__ */ React2.createElement(Typography, { variant: "body2", sx: { color: "text.secondary" } }, original))
837
+ ),
838
+ /* @__PURE__ */ React2.createElement(
839
+ Box,
840
+ {
841
+ sx: {
842
+ minWidth: "200px",
843
+ flexShrink: 0,
844
+ flexGrow: 0,
845
+ width: "200px",
846
+ maxWidth: "200px"
847
+ }
848
+ },
849
+ /* @__PURE__ */ React2.createElement(EllipsisWithTooltip, { title: modified }, /* @__PURE__ */ React2.createElement(Typography, { variant: "body2", sx: { color: "text.primary" } }, modified))
850
+ )
851
+ ))), /* @__PURE__ */ React2.createElement(Box, null, /* @__PURE__ */ React2.createElement(Alert, { severity: "info", size: "small", color: "secondary" }, /* @__PURE__ */ React2.createElement("strong", null, __2("Your designs and classes are safe.", "elementor")), __2(
852
+ "Only the prefixes were added. Find them in Class Manager by searching",
853
+ "elementor"
854
+ ), /* @__PURE__ */ React2.createElement("strong", null, DUP_PREFIX)))))), /* @__PURE__ */ React2.createElement(DialogActions, null, /* @__PURE__ */ React2.createElement(Button, { color: "secondary", variant: "text", onClick: handleButtonClick }, __2("Go to Class Manager", "elementor")), /* @__PURE__ */ React2.createElement(Button, { color: "secondary", variant: "contained", onClick: closeDialog }, __2("Done", "elementor"))));
855
+ };
856
+
857
+ // src/save-global-classes.tsx
858
+ async function saveGlobalClasses({ context: context2, onApprove }) {
859
+ const state = selectData(getState3());
860
+ const apiAction = context2 === "preview" ? apiClient.saveDraft : apiClient.publish;
861
+ const currentContext = context2 === "preview" ? selectPreviewInitialData : selectFrontendInitialData;
862
+ const response = await apiAction({
863
+ items: state.items,
864
+ order: state.order,
865
+ changes: calculateChanges(state, currentContext(getState3()))
866
+ });
867
+ dispatch2(slice.actions.reset({ context: context2 }));
868
+ if (response?.data?.data?.code === API_ERROR_CODES.DUPLICATED_LABEL) {
869
+ dispatch2(slice.actions.updateMultiple(response.data.data.modifiedLabels));
870
+ trackGlobalClasses({
871
+ event: "classPublishConflict",
872
+ numOfConflicts: Object.keys(response.data.data.modifiedLabels).length
593
873
  });
594
- } else {
595
- await apiClient.publish({
596
- items: state.items,
597
- order: state.order,
598
- changes: calculateChanges(state, selectFrontendInitialData(getState2()))
874
+ openDialog({
875
+ component: /* @__PURE__ */ React3.createElement(
876
+ DuplicateLabelDialog,
877
+ {
878
+ modifiedLabels: response.data.data.modifiedLabels || [],
879
+ onApprove
880
+ }
881
+ )
599
882
  });
600
883
  }
601
- dispatch2(slice.actions.reset({ context: context2 }));
602
884
  }
603
885
  function calculateChanges(state, initialData) {
604
886
  const stateIds = Object.keys(state.items);
@@ -613,19 +895,26 @@ function calculateChanges(state, initialData) {
613
895
  }
614
896
 
615
897
  // src/components/search-and-filter/components/filter/active-filters.tsx
616
- import * as React4 from "react";
617
- import { Chip as Chip2, Stack as Stack2 } from "@elementor/ui";
618
- import { __ as __3 } from "@wordpress/i18n";
898
+ import * as React6 from "react";
899
+ import { Chip as Chip2, Stack as Stack3 } from "@elementor/ui";
900
+ import { __ as __4 } from "@wordpress/i18n";
619
901
 
620
902
  // src/components/search-and-filter/components/filter/clear-icon-button.tsx
621
- import * as React2 from "react";
903
+ import * as React4 from "react";
622
904
  import { BrushBigIcon } from "@elementor/icons";
623
- import { Box, IconButton, styled, Tooltip } from "@elementor/ui";
624
- var ClearIconButton = ({ tooltipText, sx }) => {
905
+ import { Box as Box2, IconButton, styled, Tooltip } from "@elementor/ui";
906
+ var ClearIconButton = ({ tooltipText, sx, trigger }) => {
625
907
  const {
626
908
  filters: { onClearFilter }
627
909
  } = useSearchAndFilters();
628
- return /* @__PURE__ */ React2.createElement(Tooltip, { title: tooltipText, placement: "top", disableInteractive: true }, /* @__PURE__ */ React2.createElement(Box, null, /* @__PURE__ */ React2.createElement(CustomIconButton, { "aria-label": tooltipText, size: "tiny", onClick: onClearFilter, sx }, /* @__PURE__ */ React2.createElement(BrushBigIcon, { fontSize: "tiny" }))));
910
+ const handleClearFilters = () => {
911
+ onClearFilter(trigger);
912
+ trackGlobalClasses({
913
+ event: "classManagerFilterCleared",
914
+ trigger
915
+ });
916
+ };
917
+ return /* @__PURE__ */ React4.createElement(Tooltip, { title: tooltipText, placement: "top", disableInteractive: true }, /* @__PURE__ */ React4.createElement(Box2, null, /* @__PURE__ */ React4.createElement(CustomIconButton, { "aria-label": tooltipText, size: "tiny", onClick: handleClearFilters, sx }, /* @__PURE__ */ React4.createElement(BrushBigIcon, { fontSize: "tiny" }))));
629
918
  };
630
919
  var CustomIconButton = styled(IconButton)(({ theme }) => ({
631
920
  "&.Mui-disabled": {
@@ -637,13 +926,13 @@ var CustomIconButton = styled(IconButton)(({ theme }) => ({
637
926
  }));
638
927
 
639
928
  // src/components/search-and-filter/components/filter/filter-list.tsx
640
- import * as React3 from "react";
641
- import { Checkbox, Chip, MenuItem, MenuList, Stack, Typography } from "@elementor/ui";
642
- import { __ as __2 } from "@wordpress/i18n";
929
+ import * as React5 from "react";
930
+ import { Checkbox, Chip, MenuItem, MenuList, Stack as Stack2, Typography as Typography2 } from "@elementor/ui";
931
+ import { __ as __3 } from "@wordpress/i18n";
643
932
  var filterConfig = {
644
- unused: __2("Unused", "elementor"),
645
- empty: __2("Empty", "elementor"),
646
- onThisPage: __2("On this page", "elementor")
933
+ unused: __3("Unused", "elementor"),
934
+ empty: __3("Empty", "elementor"),
935
+ onThisPage: __3("On this page", "elementor")
647
936
  };
648
937
  var FilterList = () => {
649
938
  const {
@@ -652,31 +941,37 @@ var FilterList = () => {
652
941
  const filteredCssClass = useFilteredCssClassUsage();
653
942
  const handleOnClick = (value) => {
654
943
  setFilters((prev) => ({ ...prev, [value]: !prev[value] }));
944
+ trackGlobalClasses({
945
+ event: "classManagerFilterUsed",
946
+ action: filters[value] ? "remove" : "apply",
947
+ type: value,
948
+ trigger: "menu"
949
+ });
655
950
  };
656
- return /* @__PURE__ */ React3.createElement(MenuList, null, /* @__PURE__ */ React3.createElement(MenuItem, { onClick: () => handleOnClick("unused") }, /* @__PURE__ */ React3.createElement(
951
+ return /* @__PURE__ */ React5.createElement(MenuList, null, /* @__PURE__ */ React5.createElement(MenuItem, { onClick: () => handleOnClick("unused") }, /* @__PURE__ */ React5.createElement(
657
952
  LabeledCheckbox,
658
953
  {
659
954
  label: filterConfig.unused,
660
955
  checked: filters.unused,
661
- suffix: /* @__PURE__ */ React3.createElement(Chip, { size: "tiny", sx: { ml: "auto" }, label: filteredCssClass.unused.length })
956
+ suffix: /* @__PURE__ */ React5.createElement(Chip, { size: "tiny", sx: { ml: "auto" }, label: filteredCssClass.unused.length })
662
957
  }
663
- )), /* @__PURE__ */ React3.createElement(MenuItem, { onClick: () => handleOnClick("empty") }, /* @__PURE__ */ React3.createElement(
958
+ )), /* @__PURE__ */ React5.createElement(MenuItem, { onClick: () => handleOnClick("empty") }, /* @__PURE__ */ React5.createElement(
664
959
  LabeledCheckbox,
665
960
  {
666
961
  label: filterConfig.empty,
667
962
  checked: filters.empty,
668
- suffix: /* @__PURE__ */ React3.createElement(Chip, { size: "tiny", sx: { ml: "auto" }, label: filteredCssClass.empty.length })
963
+ suffix: /* @__PURE__ */ React5.createElement(Chip, { size: "tiny", sx: { ml: "auto" }, label: filteredCssClass.empty.length })
669
964
  }
670
- )), /* @__PURE__ */ React3.createElement(MenuItem, { onClick: () => handleOnClick("onThisPage") }, /* @__PURE__ */ React3.createElement(
965
+ )), /* @__PURE__ */ React5.createElement(MenuItem, { onClick: () => handleOnClick("onThisPage") }, /* @__PURE__ */ React5.createElement(
671
966
  LabeledCheckbox,
672
967
  {
673
968
  label: filterConfig.onThisPage,
674
969
  checked: filters.onThisPage,
675
- suffix: /* @__PURE__ */ React3.createElement(Chip, { size: "tiny", sx: { ml: "auto" }, label: filteredCssClass.onThisPage.length })
970
+ suffix: /* @__PURE__ */ React5.createElement(Chip, { size: "tiny", sx: { ml: "auto" }, label: filteredCssClass.onThisPage.length })
676
971
  }
677
972
  )));
678
973
  };
679
- var LabeledCheckbox = ({ label, suffix, checked }) => /* @__PURE__ */ React3.createElement(Stack, { direction: "row", alignItems: "center", gap: 0.5, flex: 1 }, /* @__PURE__ */ React3.createElement(
974
+ var LabeledCheckbox = ({ label, suffix, checked }) => /* @__PURE__ */ React5.createElement(Stack2, { direction: "row", alignItems: "center", gap: 0.5, flex: 1 }, /* @__PURE__ */ React5.createElement(
680
975
  Checkbox,
681
976
  {
682
977
  size: "small",
@@ -689,7 +984,7 @@ var LabeledCheckbox = ({ label, suffix, checked }) => /* @__PURE__ */ React3.cre
689
984
  }
690
985
  }
691
986
  }
692
- ), /* @__PURE__ */ React3.createElement(Typography, { variant: "caption", sx: { color: "text.secondary" } }, label), suffix);
987
+ ), /* @__PURE__ */ React5.createElement(Typography2, { variant: "caption", sx: { color: "text.secondary" } }, label), suffix);
693
988
 
694
989
  // src/components/search-and-filter/components/filter/active-filters.tsx
695
990
  var ActiveFilters = () => {
@@ -698,10 +993,16 @@ var ActiveFilters = () => {
698
993
  } = useSearchAndFilters();
699
994
  const handleRemove = (key) => {
700
995
  setFilters((prev) => ({ ...prev, [key]: false }));
996
+ trackGlobalClasses({
997
+ event: "classManagerFilterUsed",
998
+ action: "remove",
999
+ type: key,
1000
+ trigger: "header"
1001
+ });
701
1002
  };
702
1003
  const activeKeys = Object.keys(filters).filter((key) => filters[key]);
703
1004
  const showClearIcon = activeKeys.length > 0;
704
- return /* @__PURE__ */ React4.createElement(Stack2, { direction: "row", alignItems: "center", justifyContent: "space-between" }, /* @__PURE__ */ React4.createElement(Stack2, { direction: "row", gap: 0.5, alignItems: "center", flexWrap: "wrap" }, activeKeys.map((key) => /* @__PURE__ */ React4.createElement(
1005
+ return /* @__PURE__ */ React6.createElement(Stack3, { direction: "row", alignItems: "center", justifyContent: "space-between" }, /* @__PURE__ */ React6.createElement(Stack3, { direction: "row", gap: 0.5, alignItems: "center", flexWrap: "wrap" }, activeKeys.map((key) => /* @__PURE__ */ React6.createElement(
705
1006
  Chip2,
706
1007
  {
707
1008
  key,
@@ -710,10 +1011,11 @@ var ActiveFilters = () => {
710
1011
  sx: chipSx,
711
1012
  size: "tiny"
712
1013
  }
713
- ))), showClearIcon && /* @__PURE__ */ React4.createElement(
1014
+ ))), showClearIcon && /* @__PURE__ */ React6.createElement(
714
1015
  ClearIconButton,
715
1016
  {
716
- tooltipText: __3("Clear Filters", "elementor"),
1017
+ trigger: "header",
1018
+ tooltipText: __4("Clear Filters", "elementor"),
717
1019
  sx: { margin: "0 0 auto auto" }
718
1020
  }
719
1021
  ));
@@ -729,11 +1031,11 @@ var chipSx = {
729
1031
  };
730
1032
 
731
1033
  // src/components/search-and-filter/components/filter/css-class-filter.tsx
732
- import * as React5 from "react";
1034
+ import * as React7 from "react";
733
1035
  import { PopoverBody, PopoverHeader } from "@elementor/editor-ui";
734
1036
  import { FilterIcon } from "@elementor/icons";
735
- import { bindPopover, bindToggle, Divider, Popover, ToggleButton, Tooltip as Tooltip2, usePopupState } from "@elementor/ui";
736
- import { __ as __4 } from "@wordpress/i18n";
1037
+ import { bindPopover, bindToggle, Divider as Divider2, Popover, ToggleButton, Tooltip as Tooltip2, usePopupState } from "@elementor/ui";
1038
+ import { __ as __5 } from "@wordpress/i18n";
737
1039
  var CssClassFilter = () => {
738
1040
  const {
739
1041
  filters: { filters }
@@ -742,8 +1044,15 @@ var CssClassFilter = () => {
742
1044
  variant: "popover",
743
1045
  disableAutoFocus: true
744
1046
  });
1047
+ React7.useEffect(() => {
1048
+ if (popupState.isOpen) {
1049
+ trackGlobalClasses({
1050
+ event: "classManagerFiltersOpened"
1051
+ });
1052
+ }
1053
+ }, [popupState.isOpen]);
745
1054
  const showCleanIcon = Object.values(filters).some((value) => value);
746
- return /* @__PURE__ */ React5.createElement(React5.Fragment, null, /* @__PURE__ */ React5.createElement(Tooltip2, { title: __4("Filters", "elementor"), placement: "top" }, /* @__PURE__ */ React5.createElement(
1055
+ return /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement(Tooltip2, { title: __5("Filters", "elementor"), placement: "top" }, /* @__PURE__ */ React7.createElement(
747
1056
  ToggleButton,
748
1057
  {
749
1058
  value: "filter",
@@ -751,8 +1060,8 @@ var CssClassFilter = () => {
751
1060
  selected: popupState.isOpen,
752
1061
  ...bindToggle(popupState)
753
1062
  },
754
- /* @__PURE__ */ React5.createElement(FilterIcon, { fontSize: "tiny" })
755
- )), /* @__PURE__ */ React5.createElement(
1063
+ /* @__PURE__ */ React7.createElement(FilterIcon, { fontSize: "tiny" })
1064
+ )), /* @__PURE__ */ React7.createElement(
756
1065
  Popover,
757
1066
  {
758
1067
  sx: {
@@ -768,76 +1077,82 @@ var CssClassFilter = () => {
768
1077
  },
769
1078
  ...bindPopover(popupState)
770
1079
  },
771
- /* @__PURE__ */ React5.createElement(
1080
+ /* @__PURE__ */ React7.createElement(
772
1081
  PopoverHeader,
773
1082
  {
774
1083
  actions: showCleanIcon ? [
775
- /* @__PURE__ */ React5.createElement(
1084
+ /* @__PURE__ */ React7.createElement(
776
1085
  ClearIconButton,
777
1086
  {
1087
+ trigger: "menu",
778
1088
  key: "clear-all-button",
779
- tooltipText: __4("Clear all", "elementor")
1089
+ tooltipText: __5("Clear all", "elementor")
780
1090
  }
781
1091
  )
782
1092
  ] : [],
783
1093
  onClose: popupState.close,
784
- title: __4("Filters", "elementor"),
785
- icon: /* @__PURE__ */ React5.createElement(FilterIcon, { fontSize: "tiny" })
1094
+ title: __5("Filters", "elementor"),
1095
+ icon: /* @__PURE__ */ React7.createElement(FilterIcon, { fontSize: "tiny" })
786
1096
  }
787
1097
  ),
788
- /* @__PURE__ */ React5.createElement(
789
- Divider,
1098
+ /* @__PURE__ */ React7.createElement(
1099
+ Divider2,
790
1100
  {
791
1101
  sx: {
792
1102
  borderWidth: "1px 0 0 0"
793
1103
  }
794
1104
  }
795
1105
  ),
796
- /* @__PURE__ */ React5.createElement(PopoverBody, { width: 344, height: 125 }, /* @__PURE__ */ React5.createElement(FilterList, null))
1106
+ /* @__PURE__ */ React7.createElement(PopoverBody, { width: 344, height: 125 }, /* @__PURE__ */ React7.createElement(FilterList, null))
797
1107
  ));
798
1108
  };
799
1109
 
800
1110
  // src/components/search-and-filter/components/search/class-manager-search.tsx
801
- import * as React6 from "react";
1111
+ import * as React8 from "react";
802
1112
  import { SearchIcon } from "@elementor/icons";
803
- import { Box as Box2, InputAdornment, Stack as Stack3, TextField } from "@elementor/ui";
804
- import { __ as __5 } from "@wordpress/i18n";
1113
+ import { Box as Box3, InputAdornment, Stack as Stack4, TextField } from "@elementor/ui";
1114
+ import { __ as __6 } from "@wordpress/i18n";
805
1115
  var ClassManagerSearch = () => {
806
1116
  const {
807
1117
  search: { inputValue, handleChange }
808
1118
  } = useSearchAndFilters();
809
- return /* @__PURE__ */ React6.createElement(Stack3, { direction: "row", gap: 0.5, sx: { width: "100%" } }, /* @__PURE__ */ React6.createElement(Box2, { sx: { flexGrow: 1 } }, /* @__PURE__ */ React6.createElement(
1119
+ return /* @__PURE__ */ React8.createElement(Stack4, { direction: "row", gap: 0.5, sx: { width: "100%" } }, /* @__PURE__ */ React8.createElement(Box3, { sx: { flexGrow: 1 } }, /* @__PURE__ */ React8.createElement(
810
1120
  TextField,
811
1121
  {
812
1122
  role: "search",
813
1123
  fullWidth: true,
814
1124
  size: "tiny",
815
1125
  value: inputValue,
816
- placeholder: __5("Search", "elementor"),
1126
+ onFocus: () => {
1127
+ trackGlobalClasses({
1128
+ event: "classManagerSearched"
1129
+ });
1130
+ },
1131
+ placeholder: __6("Search", "elementor"),
817
1132
  onChange: (e) => handleChange(e.target.value),
818
1133
  InputProps: {
819
- startAdornment: /* @__PURE__ */ React6.createElement(InputAdornment, { position: "start" }, /* @__PURE__ */ React6.createElement(SearchIcon, { fontSize: "tiny" }))
1134
+ startAdornment: /* @__PURE__ */ React8.createElement(InputAdornment, { position: "start" }, /* @__PURE__ */ React8.createElement(SearchIcon, { fontSize: "tiny" }))
820
1135
  }
821
1136
  }
822
1137
  )));
823
1138
  };
824
1139
 
825
1140
  // src/components/class-manager/class-manager-introduction.tsx
826
- import * as React7 from "react";
1141
+ import * as React9 from "react";
827
1142
  import { useState as useState2 } from "react";
828
1143
  import { useSuppressedMessage } from "@elementor/editor-current-user";
829
1144
  import { IntroductionModal } from "@elementor/editor-ui";
830
- import { Box as Box3, Image, Typography as Typography2 } from "@elementor/ui";
831
- import { __ as __6 } from "@wordpress/i18n";
1145
+ import { Box as Box4, Image, Typography as Typography3 } from "@elementor/ui";
1146
+ import { __ as __7 } from "@wordpress/i18n";
832
1147
  var MESSAGE_KEY = "global-class-manager";
833
1148
  var ClassManagerIntroduction = () => {
834
1149
  const [isMessageSuppressed, suppressMessage] = useSuppressedMessage(MESSAGE_KEY);
835
1150
  const [shouldShowIntroduction, setShouldShowIntroduction] = useState2(!isMessageSuppressed);
836
- return /* @__PURE__ */ React7.createElement(
1151
+ return /* @__PURE__ */ React9.createElement(
837
1152
  IntroductionModal,
838
1153
  {
839
1154
  open: shouldShowIntroduction,
840
- title: __6("Class Manager", "elementor"),
1155
+ title: __7("Class Manager", "elementor"),
841
1156
  handleClose: (shouldShowAgain) => {
842
1157
  if (!shouldShowAgain) {
843
1158
  suppressMessage();
@@ -845,7 +1160,7 @@ var ClassManagerIntroduction = () => {
845
1160
  setShouldShowIntroduction(false);
846
1161
  }
847
1162
  },
848
- /* @__PURE__ */ React7.createElement(
1163
+ /* @__PURE__ */ React9.createElement(
849
1164
  Image,
850
1165
  {
851
1166
  sx: { width: "100%", aspectRatio: "16 / 9" },
@@ -853,14 +1168,14 @@ var ClassManagerIntroduction = () => {
853
1168
  alt: ""
854
1169
  }
855
1170
  ),
856
- /* @__PURE__ */ React7.createElement(IntroductionContent, null)
1171
+ /* @__PURE__ */ React9.createElement(IntroductionContent, null)
857
1172
  );
858
1173
  };
859
1174
  var IntroductionContent = () => {
860
- return /* @__PURE__ */ React7.createElement(Box3, { p: 3 }, /* @__PURE__ */ React7.createElement(Typography2, { variant: "body2" }, __6(
1175
+ return /* @__PURE__ */ React9.createElement(Box4, { p: 3 }, /* @__PURE__ */ React9.createElement(Typography3, { variant: "body2" }, __7(
861
1176
  "The Class Manager lets you see all the classes you've created, plus adjust their priority, rename them, and delete unused classes to keep your CSS structured.",
862
1177
  "elementor"
863
- )), /* @__PURE__ */ React7.createElement("br", null), /* @__PURE__ */ React7.createElement(Typography2, { variant: "body2" }, __6(
1178
+ )), /* @__PURE__ */ React9.createElement("br", null), /* @__PURE__ */ React9.createElement(Typography3, { variant: "body2" }, __7(
864
1179
  "Remember, when editing an item within a specific class, any changes you make will apply across all elements in that class.",
865
1180
  "elementor"
866
1181
  )));
@@ -872,8 +1187,14 @@ import { __privateRunCommand as runCommand } from "@elementor/editor-v1-adapters
872
1187
  import { __dispatch as dispatch3 } from "@elementor/store";
873
1188
  var isDeleted = false;
874
1189
  var deleteClass = (id2) => {
875
- dispatch3(slice.actions.delete(id2));
876
- isDeleted = true;
1190
+ trackGlobalClasses({
1191
+ event: "classDeleted",
1192
+ classId: id2,
1193
+ runAction: () => {
1194
+ dispatch3(slice.actions.delete(id2));
1195
+ isDeleted = true;
1196
+ }
1197
+ });
877
1198
  };
878
1199
  var onDelete = async () => {
879
1200
  await reloadDocument();
@@ -892,16 +1213,16 @@ var reloadDocument = () => {
892
1213
  };
893
1214
 
894
1215
  // src/components/class-manager/flipped-color-swatch-icon.tsx
895
- import * as React8 from "react";
1216
+ import * as React10 from "react";
896
1217
  import { ColorSwatchIcon } from "@elementor/icons";
897
- var FlippedColorSwatchIcon = ({ sx, ...props }) => /* @__PURE__ */ React8.createElement(ColorSwatchIcon, { sx: { transform: "rotate(90deg)", ...sx }, ...props });
1218
+ var FlippedColorSwatchIcon = ({ sx, ...props }) => /* @__PURE__ */ React10.createElement(ColorSwatchIcon, { sx: { transform: "rotate(90deg)", ...sx }, ...props });
898
1219
 
899
1220
  // src/components/class-manager/global-classes-list.tsx
900
- import * as React15 from "react";
901
- import { useEffect, useMemo as useMemo3 } from "react";
1221
+ import * as React17 from "react";
1222
+ import { useEffect as useEffect2, useMemo as useMemo3 } from "react";
902
1223
  import { __useDispatch as useDispatch } from "@elementor/store";
903
- import { List, Stack as Stack7, styled as styled6, Typography as Typography7 } from "@elementor/ui";
904
- import { __ as __12 } from "@wordpress/i18n";
1224
+ import { List, Stack as Stack8, styled as styled6, Typography as Typography8 } from "@elementor/ui";
1225
+ import { __ as __13 } from "@wordpress/i18n";
905
1226
 
906
1227
  // src/hooks/use-ordered-classes.ts
907
1228
  import { __useSelector as useSelector3 } from "@elementor/store";
@@ -910,31 +1231,31 @@ var useOrderedClasses = () => {
910
1231
  };
911
1232
 
912
1233
  // src/components/class-manager/class-item.tsx
913
- import * as React13 from "react";
1234
+ import * as React15 from "react";
914
1235
  import { useRef, useState as useState4 } from "react";
915
1236
  import { validateStyleLabel } from "@elementor/editor-styles-repository";
916
- import { EditableField, EllipsisWithTooltip as EllipsisWithTooltip2, MenuListItem, useEditable, WarningInfotip } from "@elementor/editor-ui";
1237
+ import { EditableField, EllipsisWithTooltip as EllipsisWithTooltip3, MenuListItem, useEditable, WarningInfotip } from "@elementor/editor-ui";
917
1238
  import { DotsVerticalIcon } from "@elementor/icons";
918
1239
  import {
919
1240
  bindMenu,
920
1241
  bindTrigger as bindTrigger2,
921
- Box as Box7,
1242
+ Box as Box8,
922
1243
  IconButton as IconButton3,
923
1244
  ListItemButton,
924
1245
  Menu,
925
- Stack as Stack5,
1246
+ Stack as Stack6,
926
1247
  styled as styled5,
927
1248
  Tooltip as Tooltip5,
928
- Typography as Typography5,
1249
+ Typography as Typography6,
929
1250
  usePopupState as usePopupState3
930
1251
  } from "@elementor/ui";
931
- import { __ as __10 } from "@wordpress/i18n";
1252
+ import { __ as __11 } from "@wordpress/i18n";
932
1253
 
933
1254
  // src/components/css-class-usage/components/css-class-usage-popover.tsx
934
- import * as React9 from "react";
1255
+ import * as React11 from "react";
935
1256
  import { __useOpenDocumentInNewTab as useOpenDocumentInNewTab } from "@elementor/editor-documents";
936
1257
  import {
937
- EllipsisWithTooltip,
1258
+ EllipsisWithTooltip as EllipsisWithTooltip2,
938
1259
  PopoverBody as PopoverBody2,
939
1260
  PopoverHeader as PopoverHeader2,
940
1261
  PopoverMenuList
@@ -948,8 +1269,8 @@ import {
948
1269
  PopupTemplateIcon,
949
1270
  PostTypeIcon
950
1271
  } from "@elementor/icons";
951
- import { Box as Box4, Chip as Chip3, Divider as Divider2, Icon, MenuList as MenuList2, Stack as Stack4, styled as styled2, Tooltip as Tooltip3, Typography as Typography3 } from "@elementor/ui";
952
- import { __ as __7 } from "@wordpress/i18n";
1272
+ import { Box as Box5, Chip as Chip3, Divider as Divider3, Icon as Icon2, MenuList as MenuList2, Stack as Stack5, styled as styled2, Tooltip as Tooltip3, Typography as Typography4 } from "@elementor/ui";
1273
+ import { __ as __8 } from "@wordpress/i18n";
953
1274
 
954
1275
  // src/hooks/use-css-class-usage-by-id.ts
955
1276
  var EMPTY_CLASS_USAGE = {
@@ -965,24 +1286,24 @@ var useCssClassUsageByID = (id2) => {
965
1286
  // src/components/css-class-usage/components/css-class-usage-popover.tsx
966
1287
  var iconMapper = {
967
1288
  "wp-post": {
968
- label: __7("Post", "elementor"),
969
- icon: /* @__PURE__ */ React9.createElement(PostTypeIcon, { fontSize: "inherit" })
1289
+ label: __8("Post", "elementor"),
1290
+ icon: /* @__PURE__ */ React11.createElement(PostTypeIcon, { fontSize: "inherit" })
970
1291
  },
971
1292
  "wp-page": {
972
- label: __7("Page", "elementor"),
973
- icon: /* @__PURE__ */ React9.createElement(PagesIcon, { fontSize: "inherit" })
1293
+ label: __8("Page", "elementor"),
1294
+ icon: /* @__PURE__ */ React11.createElement(PagesIcon, { fontSize: "inherit" })
974
1295
  },
975
1296
  popup: {
976
- label: __7("Popup", "elementor"),
977
- icon: /* @__PURE__ */ React9.createElement(PopupTemplateIcon, { fontSize: "inherit" })
1297
+ label: __8("Popup", "elementor"),
1298
+ icon: /* @__PURE__ */ React11.createElement(PopupTemplateIcon, { fontSize: "inherit" })
978
1299
  },
979
1300
  header: {
980
- label: __7("Header", "elementor"),
981
- icon: /* @__PURE__ */ React9.createElement(HeaderTemplateIcon, { fontSize: "inherit" })
1301
+ label: __8("Header", "elementor"),
1302
+ icon: /* @__PURE__ */ React11.createElement(HeaderTemplateIcon, { fontSize: "inherit" })
982
1303
  },
983
1304
  footer: {
984
- label: __7("Footer", "elementor"),
985
- icon: /* @__PURE__ */ React9.createElement(FooterTemplateIcon, { fontSize: "inherit" })
1305
+ label: __8("Footer", "elementor"),
1306
+ icon: /* @__PURE__ */ React11.createElement(FooterTemplateIcon, { fontSize: "inherit" })
986
1307
  }
987
1308
  };
988
1309
  var CssClassUsagePopover = ({
@@ -1000,41 +1321,48 @@ var CssClassUsagePopover = ({
1000
1321
  docType: type
1001
1322
  })
1002
1323
  ) ?? [];
1003
- return /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(
1324
+ const handleSelect = (value) => {
1325
+ onNavigate(+value);
1326
+ trackGlobalClasses({
1327
+ event: "classUsageLocate",
1328
+ classId: cssClassID
1329
+ });
1330
+ };
1331
+ return /* @__PURE__ */ React11.createElement(React11.Fragment, null, /* @__PURE__ */ React11.createElement(
1004
1332
  PopoverHeader2,
1005
1333
  {
1006
- icon: /* @__PURE__ */ React9.createElement(CurrentLocationIcon, { fontSize: "tiny" }),
1007
- title: /* @__PURE__ */ React9.createElement(Stack4, { flexDirection: "row", gap: 1, alignItems: "center" }, /* @__PURE__ */ React9.createElement(Box4, { "aria-label": "header-title" }, __7("Locator", "elementor")), /* @__PURE__ */ React9.createElement(Box4, null, /* @__PURE__ */ React9.createElement(Chip3, { sx: { lineHeight: 1 }, size: "tiny", label: classUsage.total }))),
1334
+ icon: /* @__PURE__ */ React11.createElement(CurrentLocationIcon, { fontSize: "tiny" }),
1335
+ title: /* @__PURE__ */ React11.createElement(Stack5, { flexDirection: "row", gap: 1, alignItems: "center" }, /* @__PURE__ */ React11.createElement(Box5, { "aria-label": "header-title" }, __8("Locator", "elementor")), /* @__PURE__ */ React11.createElement(Box5, null, /* @__PURE__ */ React11.createElement(Chip3, { sx: { lineHeight: 1 }, size: "tiny", label: classUsage.total }))),
1008
1336
  onClose
1009
1337
  }
1010
- ), /* @__PURE__ */ React9.createElement(Divider2, null), /* @__PURE__ */ React9.createElement(PopoverBody2, { width: 300 }, /* @__PURE__ */ React9.createElement(
1338
+ ), /* @__PURE__ */ React11.createElement(Divider3, null), /* @__PURE__ */ React11.createElement(PopoverBody2, { width: 300 }, /* @__PURE__ */ React11.createElement(
1011
1339
  PopoverMenuList,
1012
1340
  {
1013
- onSelect: (value) => onNavigate(+value),
1341
+ onSelect: handleSelect,
1014
1342
  items: cssClassUsageRecords,
1015
1343
  onClose: () => {
1016
1344
  },
1017
1345
  menuListTemplate: StyledCssClassUsageItem,
1018
- menuItemContentTemplate: (cssClassUsageRecord) => /* @__PURE__ */ React9.createElement(Stack4, { flexDirection: "row", flex: 1, alignItems: "center" }, /* @__PURE__ */ React9.createElement(Box4, { display: "flex", sx: { pr: 1 } }, /* @__PURE__ */ React9.createElement(
1346
+ menuItemContentTemplate: (cssClassUsageRecord) => /* @__PURE__ */ React11.createElement(Stack5, { flexDirection: "row", flex: 1, alignItems: "center" }, /* @__PURE__ */ React11.createElement(Box5, { display: "flex", sx: { pr: 1 } }, /* @__PURE__ */ React11.createElement(
1019
1347
  Tooltip3,
1020
1348
  {
1021
1349
  disableInteractive: true,
1022
1350
  title: iconMapper?.[cssClassUsageRecord.docType]?.label ?? cssClassUsageRecord.docType,
1023
1351
  placement: "top"
1024
1352
  },
1025
- /* @__PURE__ */ React9.createElement(Icon, { fontSize: "small" }, iconMapper?.[cssClassUsageRecord.docType]?.icon || /* @__PURE__ */ React9.createElement(PagesIcon, { fontSize: "inherit" }))
1026
- )), /* @__PURE__ */ React9.createElement(Box4, { sx: { pr: 0.5, maxWidth: "173px" }, display: "flex" }, /* @__PURE__ */ React9.createElement(
1027
- EllipsisWithTooltip,
1353
+ /* @__PURE__ */ React11.createElement(Icon2, { fontSize: "small" }, iconMapper?.[cssClassUsageRecord.docType]?.icon || /* @__PURE__ */ React11.createElement(PagesIcon, { fontSize: "inherit" }))
1354
+ )), /* @__PURE__ */ React11.createElement(Box5, { sx: { pr: 0.5, maxWidth: "173px" }, display: "flex" }, /* @__PURE__ */ React11.createElement(
1355
+ EllipsisWithTooltip2,
1028
1356
  {
1029
1357
  title: cssClassUsageRecord.label,
1030
- as: Typography3,
1358
+ as: Typography4,
1031
1359
  variant: "caption",
1032
1360
  maxWidth: "173px",
1033
1361
  sx: {
1034
1362
  lineHeight: 1
1035
1363
  }
1036
1364
  }
1037
- )), /* @__PURE__ */ React9.createElement(ExternalLinkIcon, { className: "hover-only-icon", fontSize: "tiny" }), /* @__PURE__ */ React9.createElement(
1365
+ )), /* @__PURE__ */ React11.createElement(ExternalLinkIcon, { className: "hover-only-icon", fontSize: "tiny" }), /* @__PURE__ */ React11.createElement(
1038
1366
  Chip3,
1039
1367
  {
1040
1368
  sx: {
@@ -1081,13 +1409,13 @@ var StyledCssClassUsageItem = styled2(MenuList2)(({ theme }) => ({
1081
1409
  }));
1082
1410
 
1083
1411
  // src/components/css-class-usage/components/css-class-usage-trigger.tsx
1084
- import * as React10 from "react";
1412
+ import * as React12 from "react";
1085
1413
  import { InfoAlert } from "@elementor/editor-ui";
1086
1414
  import { CurrentLocationIcon as CurrentLocationIcon2 } from "@elementor/icons";
1087
1415
  import {
1088
1416
  bindPopover as bindPopover2,
1089
1417
  bindTrigger,
1090
- Box as Box5,
1418
+ Box as Box6,
1091
1419
  IconButton as IconButton2,
1092
1420
  Infotip,
1093
1421
  Popover as Popover2,
@@ -1095,7 +1423,7 @@ import {
1095
1423
  Tooltip as Tooltip4,
1096
1424
  usePopupState as usePopupState2
1097
1425
  } from "@elementor/ui";
1098
- import { __ as __8 } from "@wordpress/i18n";
1426
+ import { __ as __9 } from "@wordpress/i18n";
1099
1427
  var CssClassUsageTrigger = ({ id: id2, onClick }) => {
1100
1428
  const {
1101
1429
  data: { total },
@@ -1106,21 +1434,33 @@ var CssClassUsageTrigger = ({ id: id2, onClick }) => {
1106
1434
  return null;
1107
1435
  }
1108
1436
  const WrapperComponent = total !== 0 ? TooltipWrapper : InfoAlertMessage;
1109
- return /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(Box5, { position: "relative" }, /* @__PURE__ */ React10.createElement(WrapperComponent, { total }, /* @__PURE__ */ React10.createElement(
1437
+ const handleMouseEnter = () => {
1438
+ trackGlobalClasses({
1439
+ event: "classUsageHovered",
1440
+ classId: id2,
1441
+ usage: total
1442
+ });
1443
+ };
1444
+ const handleClick = (e) => {
1445
+ if (total !== 0) {
1446
+ bindTrigger(cssClassUsagePopover).onClick(e);
1447
+ onClick(id2);
1448
+ trackGlobalClasses({
1449
+ event: "classUsageClicked",
1450
+ classId: id2
1451
+ });
1452
+ }
1453
+ };
1454
+ return /* @__PURE__ */ React12.createElement(React12.Fragment, null, /* @__PURE__ */ React12.createElement(Box6, { position: "relative", onMouseEnter: handleMouseEnter }, /* @__PURE__ */ React12.createElement(WrapperComponent, { total }, /* @__PURE__ */ React12.createElement(
1110
1455
  CustomIconButton2,
1111
1456
  {
1112
1457
  disabled: total === 0,
1113
1458
  size: "tiny",
1114
1459
  ...bindTrigger(cssClassUsagePopover),
1115
- onClick: (e) => {
1116
- if (total !== 0) {
1117
- bindTrigger(cssClassUsagePopover).onClick(e);
1118
- onClick(id2);
1119
- }
1120
- }
1460
+ onClick: handleClick
1121
1461
  },
1122
- /* @__PURE__ */ React10.createElement(CurrentLocationIcon2, { fontSize: "tiny" })
1123
- ))), /* @__PURE__ */ React10.createElement(Box5, null, /* @__PURE__ */ React10.createElement(
1462
+ /* @__PURE__ */ React12.createElement(CurrentLocationIcon2, { fontSize: "tiny" })
1463
+ ))), /* @__PURE__ */ React12.createElement(Box6, null, /* @__PURE__ */ React12.createElement(
1124
1464
  Popover2,
1125
1465
  {
1126
1466
  anchorOrigin: {
@@ -1137,7 +1477,7 @@ var CssClassUsageTrigger = ({ id: id2, onClick }) => {
1137
1477
  onClick("");
1138
1478
  }
1139
1479
  },
1140
- /* @__PURE__ */ React10.createElement(
1480
+ /* @__PURE__ */ React12.createElement(
1141
1481
  CssClassUsagePopover,
1142
1482
  {
1143
1483
  onClose: cssClassUsagePopover.close,
@@ -1159,80 +1499,80 @@ var CustomIconButton2 = styled3(IconButton2)(({ theme }) => ({
1159
1499
  height: "22px",
1160
1500
  width: "22px"
1161
1501
  }));
1162
- var TooltipWrapper = ({ children, total }) => /* @__PURE__ */ React10.createElement(
1502
+ var TooltipWrapper = ({ children, total }) => /* @__PURE__ */ React12.createElement(
1163
1503
  Tooltip4,
1164
1504
  {
1165
1505
  disableInteractive: true,
1166
1506
  placement: "top",
1167
- title: `${__8("Show {{number}} {{locations}}", "elementor").replace("{{number}}", total.toString()).replace(
1507
+ title: `${__9("Show {{number}} {{locations}}", "elementor").replace("{{number}}", total.toString()).replace(
1168
1508
  "{{locations}}",
1169
- total === 1 ? __8("location", "elementor") : __8("locations", "elementor")
1509
+ total === 1 ? __9("location", "elementor") : __9("locations", "elementor")
1170
1510
  )}`
1171
1511
  },
1172
- /* @__PURE__ */ React10.createElement("span", null, children)
1512
+ /* @__PURE__ */ React12.createElement("span", null, children)
1173
1513
  );
1174
- var InfoAlertMessage = ({ children }) => /* @__PURE__ */ React10.createElement(
1514
+ var InfoAlertMessage = ({ children }) => /* @__PURE__ */ React12.createElement(
1175
1515
  Infotip,
1176
1516
  {
1177
1517
  disableInteractive: true,
1178
1518
  placement: "top",
1179
1519
  color: "secondary",
1180
- content: /* @__PURE__ */ React10.createElement(InfoAlert, { sx: { mt: 1 } }, __8("This class isn\u2019t being used yet.", "elementor"))
1520
+ content: /* @__PURE__ */ React12.createElement(InfoAlert, { sx: { mt: 1 } }, __9("This class isn\u2019t being used yet.", "elementor"))
1181
1521
  },
1182
- /* @__PURE__ */ React10.createElement("span", null, children)
1522
+ /* @__PURE__ */ React12.createElement("span", null, children)
1183
1523
  );
1184
1524
 
1185
1525
  // src/components/class-manager/delete-confirmation-dialog.tsx
1186
- import * as React11 from "react";
1526
+ import * as React13 from "react";
1187
1527
  import { createContext as createContext2, useContext as useContext2, useState as useState3 } from "react";
1188
1528
  import { AlertOctagonFilledIcon } from "@elementor/icons";
1189
1529
  import {
1190
- Button,
1530
+ Button as Button2,
1191
1531
  Dialog,
1192
- DialogActions,
1193
- DialogContent,
1532
+ DialogActions as DialogActions2,
1533
+ DialogContent as DialogContent2,
1194
1534
  DialogContentText,
1195
1535
  DialogTitle,
1196
- Typography as Typography4
1536
+ Typography as Typography5
1197
1537
  } from "@elementor/ui";
1198
- import { __ as __9 } from "@wordpress/i18n";
1538
+ import { __ as __10 } from "@wordpress/i18n";
1199
1539
  var context = createContext2(null);
1200
1540
  var DeleteConfirmationProvider = ({ children }) => {
1201
1541
  const [dialogProps, setDialogProps] = useState3(null);
1202
- const openDialog = (props) => {
1542
+ const openDialog2 = (props) => {
1203
1543
  setDialogProps(props);
1204
1544
  };
1205
- const closeDialog = () => {
1545
+ const closeDialog2 = () => {
1206
1546
  setDialogProps(null);
1207
1547
  };
1208
- return /* @__PURE__ */ React11.createElement(context.Provider, { value: { openDialog, closeDialog, dialogProps } }, children, !!dialogProps && /* @__PURE__ */ React11.createElement(DeleteConfirmationDialog, { ...dialogProps }));
1548
+ return /* @__PURE__ */ React13.createElement(context.Provider, { value: { openDialog: openDialog2, closeDialog: closeDialog2, dialogProps } }, children, !!dialogProps && /* @__PURE__ */ React13.createElement(DeleteConfirmationDialog, { ...dialogProps }));
1209
1549
  };
1210
1550
  var TITLE_ID = "delete-class-dialog";
1211
1551
  var DeleteConfirmationDialog = ({ label, id: id2 }) => {
1212
- const { closeDialog } = useDeleteConfirmation();
1552
+ const { closeDialog: closeDialog2 } = useDeleteConfirmation();
1213
1553
  const {
1214
1554
  data: { total, content }
1215
1555
  } = useCssClassUsageByID(id2);
1216
1556
  const onConfirm = () => {
1557
+ closeDialog2();
1217
1558
  deleteClass(id2);
1218
- closeDialog();
1219
1559
  };
1220
- const text = total && content.length ? __9(
1560
+ const text = total && content.length ? __10(
1221
1561
  "Will permanently remove it from your project and may affect the design across all elements using it. Used %1 times across %2 pages. This action cannot be undone.",
1222
1562
  "elementor"
1223
- ).replace("%1", total.toString()).replace("%2", content.length.toString()) : __9(
1563
+ ).replace("%1", total.toString()).replace("%2", content.length.toString()) : __10(
1224
1564
  "Will permanently remove it from your project and may affect the design across all elements using it. This action cannot be undone.",
1225
1565
  "elementor"
1226
1566
  );
1227
- return /* @__PURE__ */ React11.createElement(Dialog, { open: true, onClose: closeDialog, "aria-labelledby": TITLE_ID, maxWidth: "xs" }, /* @__PURE__ */ React11.createElement(DialogTitle, { id: TITLE_ID, display: "flex", alignItems: "center", gap: 1, sx: { lineHeight: 1 } }, /* @__PURE__ */ React11.createElement(AlertOctagonFilledIcon, { color: "error" }), __9("Delete this class?", "elementor")), /* @__PURE__ */ React11.createElement(DialogContent, null, /* @__PURE__ */ React11.createElement(DialogContentText, { variant: "body2", color: "textPrimary" }, __9("Deleting", "elementor"), /* @__PURE__ */ React11.createElement(Typography4, { variant: "subtitle2", component: "span" }, "\xA0", label, "\xA0"), text)), /* @__PURE__ */ React11.createElement(DialogActions, null, /* @__PURE__ */ React11.createElement(Button, { color: "secondary", onClick: closeDialog }, __9("Not now", "elementor")), /* @__PURE__ */ React11.createElement(
1228
- Button,
1567
+ return /* @__PURE__ */ React13.createElement(Dialog, { open: true, onClose: closeDialog2, "aria-labelledby": TITLE_ID, maxWidth: "xs" }, /* @__PURE__ */ React13.createElement(DialogTitle, { id: TITLE_ID, display: "flex", alignItems: "center", gap: 1, sx: { lineHeight: 1 } }, /* @__PURE__ */ React13.createElement(AlertOctagonFilledIcon, { color: "error" }), __10("Delete this class?", "elementor")), /* @__PURE__ */ React13.createElement(DialogContent2, null, /* @__PURE__ */ React13.createElement(DialogContentText, { variant: "body2", color: "textPrimary" }, __10("Deleting", "elementor"), /* @__PURE__ */ React13.createElement(Typography5, { variant: "subtitle2", component: "span" }, "\xA0", label, "\xA0"), text)), /* @__PURE__ */ React13.createElement(DialogActions2, null, /* @__PURE__ */ React13.createElement(Button2, { color: "secondary", onClick: closeDialog2 }, __10("Not now", "elementor")), /* @__PURE__ */ React13.createElement(
1568
+ Button2,
1229
1569
  {
1230
1570
  autoFocus: true,
1231
1571
  variant: "contained",
1232
1572
  color: "error",
1233
1573
  onClick: onConfirm
1234
1574
  },
1235
- __9("Delete", "elementor")
1575
+ __10("Delete", "elementor")
1236
1576
  )));
1237
1577
  };
1238
1578
  var useDeleteConfirmation = () => {
@@ -1244,18 +1584,18 @@ var useDeleteConfirmation = () => {
1244
1584
  };
1245
1585
 
1246
1586
  // src/components/class-manager/sortable.tsx
1247
- import * as React12 from "react";
1587
+ import * as React14 from "react";
1248
1588
  import { GripVerticalIcon } from "@elementor/icons";
1249
1589
  import {
1250
- Box as Box6,
1590
+ Box as Box7,
1251
1591
  styled as styled4,
1252
1592
  UnstableSortableItem,
1253
1593
  UnstableSortableProvider
1254
1594
  } from "@elementor/ui";
1255
- var SortableProvider = (props) => /* @__PURE__ */ React12.createElement(UnstableSortableProvider, { restrictAxis: true, variant: "static", dragPlaceholderStyle: { opacity: "1" }, ...props });
1256
- var SortableTrigger = (props) => /* @__PURE__ */ React12.createElement(StyledSortableTrigger, { ...props, role: "button", className: "class-item-sortable-trigger", "aria-label": "sort" }, /* @__PURE__ */ React12.createElement(GripVerticalIcon, { fontSize: "tiny" }));
1595
+ var SortableProvider = (props) => /* @__PURE__ */ React14.createElement(UnstableSortableProvider, { restrictAxis: true, variant: "static", dragPlaceholderStyle: { opacity: "1" }, ...props });
1596
+ var SortableTrigger = (props) => /* @__PURE__ */ React14.createElement(StyledSortableTrigger, { ...props, role: "button", className: "class-item-sortable-trigger", "aria-label": "sort" }, /* @__PURE__ */ React14.createElement(GripVerticalIcon, { fontSize: "tiny" }));
1257
1597
  var SortableItem = ({ children, id: id2, ...props }) => {
1258
- return /* @__PURE__ */ React12.createElement(
1598
+ return /* @__PURE__ */ React14.createElement(
1259
1599
  UnstableSortableItem,
1260
1600
  {
1261
1601
  ...props,
@@ -1271,8 +1611,8 @@ var SortableItem = ({ children, id: id2, ...props }) => {
1271
1611
  isDragOverlay,
1272
1612
  isDragPlaceholder
1273
1613
  }) => {
1274
- return /* @__PURE__ */ React12.createElement(
1275
- Box6,
1614
+ return /* @__PURE__ */ React14.createElement(
1615
+ Box7,
1276
1616
  {
1277
1617
  ...itemProps,
1278
1618
  style: itemStyle,
@@ -1290,7 +1630,7 @@ var SortableItem = ({ children, id: id2, ...props }) => {
1290
1630
  triggerStyle,
1291
1631
  isDragPlaceholder
1292
1632
  }),
1293
- showDropIndication && /* @__PURE__ */ React12.createElement(SortableItemIndicator, { style: dropIndicationStyle })
1633
+ showDropIndication && /* @__PURE__ */ React14.createElement(SortableItemIndicator, { style: dropIndicationStyle })
1294
1634
  );
1295
1635
  }
1296
1636
  }
@@ -1303,7 +1643,7 @@ var StyledSortableTrigger = styled4("div")(({ theme }) => ({
1303
1643
  transform: `translate( -${theme.spacing(1.5)}, -50% )`,
1304
1644
  color: theme.palette.action.active
1305
1645
  }));
1306
- var SortableItemIndicator = styled4(Box6)`
1646
+ var SortableItemIndicator = styled4(Box7)`
1307
1647
  width: 100%;
1308
1648
  height: 1px;
1309
1649
  background-color: ${({ theme }) => theme.palette.text.primary};
@@ -1332,13 +1672,13 @@ var ClassItem = ({
1332
1672
  validation: validateLabel
1333
1673
  });
1334
1674
  const [selectedCssUsage, setSelectedCssUsage] = useState4("");
1335
- const { openDialog } = useDeleteConfirmation();
1675
+ const { openDialog: openDialog2 } = useDeleteConfirmation();
1336
1676
  const popupState = usePopupState3({
1337
1677
  variant: "popover",
1338
1678
  disableAutoFocus: true
1339
1679
  });
1340
1680
  const isSelected = (selectedCssUsage === id2 || selected || popupState.isOpen) && !disabled;
1341
- return /* @__PURE__ */ React13.createElement(React13.Fragment, null, /* @__PURE__ */ React13.createElement(Stack5, { p: 0 }, /* @__PURE__ */ React13.createElement(
1681
+ return /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(Stack6, { p: 0 }, /* @__PURE__ */ React15.createElement(
1342
1682
  WarningInfotip,
1343
1683
  {
1344
1684
  open: Boolean(error),
@@ -1347,7 +1687,7 @@ var ClassItem = ({
1347
1687
  width: itemRef.current?.getBoundingClientRect().width,
1348
1688
  offset: [0, -15]
1349
1689
  },
1350
- /* @__PURE__ */ React13.createElement(
1690
+ /* @__PURE__ */ React15.createElement(
1351
1691
  StyledListItemButton,
1352
1692
  {
1353
1693
  ref: itemRef,
@@ -1361,28 +1701,28 @@ var ClassItem = ({
1361
1701
  disabled,
1362
1702
  focusVisibleClassName: "visible-class-item"
1363
1703
  },
1364
- /* @__PURE__ */ React13.createElement(SortableTrigger, { ...sortableTriggerProps }),
1365
- /* @__PURE__ */ React13.createElement(Indicator, { isActive: isEditing, isError: !!error }, isEditing ? /* @__PURE__ */ React13.createElement(
1704
+ /* @__PURE__ */ React15.createElement(SortableTrigger, { ...sortableTriggerProps }),
1705
+ /* @__PURE__ */ React15.createElement(Indicator, { isActive: isEditing, isError: !!error }, isEditing ? /* @__PURE__ */ React15.createElement(
1366
1706
  EditableField,
1367
1707
  {
1368
1708
  ref: editableRef,
1369
- as: Typography5,
1709
+ as: Typography6,
1370
1710
  variant: "caption",
1371
1711
  ...getEditableProps()
1372
1712
  }
1373
- ) : /* @__PURE__ */ React13.createElement(EllipsisWithTooltip2, { title: label, as: Typography5, variant: "caption" })),
1374
- /* @__PURE__ */ React13.createElement(Box7, { className: "class-item-locator" }, /* @__PURE__ */ React13.createElement(CssClassUsageTrigger, { id: id2, onClick: setSelectedCssUsage })),
1375
- /* @__PURE__ */ React13.createElement(
1713
+ ) : /* @__PURE__ */ React15.createElement(EllipsisWithTooltip3, { title: label, as: Typography6, variant: "caption" })),
1714
+ /* @__PURE__ */ React15.createElement(Box8, { className: "class-item-locator" }, /* @__PURE__ */ React15.createElement(CssClassUsageTrigger, { id: id2, onClick: setSelectedCssUsage })),
1715
+ /* @__PURE__ */ React15.createElement(
1376
1716
  Tooltip5,
1377
1717
  {
1378
1718
  placement: "top",
1379
1719
  className: "class-item-more-actions",
1380
- title: __10("More actions", "elementor")
1720
+ title: __11("More actions", "elementor")
1381
1721
  },
1382
- /* @__PURE__ */ React13.createElement(IconButton3, { size: "tiny", ...bindTrigger2(popupState), "aria-label": "More actions" }, /* @__PURE__ */ React13.createElement(DotsVerticalIcon, { fontSize: "tiny" }))
1722
+ /* @__PURE__ */ React15.createElement(IconButton3, { size: "tiny", ...bindTrigger2(popupState), "aria-label": "More actions" }, /* @__PURE__ */ React15.createElement(DotsVerticalIcon, { fontSize: "tiny" }))
1383
1723
  )
1384
1724
  )
1385
- )), /* @__PURE__ */ React13.createElement(
1725
+ )), /* @__PURE__ */ React15.createElement(
1386
1726
  Menu,
1387
1727
  {
1388
1728
  ...bindMenu(popupState),
@@ -1395,7 +1735,7 @@ var ClassItem = ({
1395
1735
  horizontal: "right"
1396
1736
  }
1397
1737
  },
1398
- /* @__PURE__ */ React13.createElement(
1738
+ /* @__PURE__ */ React15.createElement(
1399
1739
  MenuListItem,
1400
1740
  {
1401
1741
  sx: { minWidth: "160px" },
@@ -1404,17 +1744,17 @@ var ClassItem = ({
1404
1744
  openEditMode();
1405
1745
  }
1406
1746
  },
1407
- /* @__PURE__ */ React13.createElement(Typography5, { variant: "caption", sx: { color: "text.primary" } }, __10("Rename", "elementor"))
1747
+ /* @__PURE__ */ React15.createElement(Typography6, { variant: "caption", sx: { color: "text.primary" } }, __11("Rename", "elementor"))
1408
1748
  ),
1409
- /* @__PURE__ */ React13.createElement(
1749
+ /* @__PURE__ */ React15.createElement(
1410
1750
  MenuListItem,
1411
1751
  {
1412
1752
  onClick: () => {
1413
1753
  popupState.close();
1414
- openDialog({ id: id2, label });
1754
+ openDialog2({ id: id2, label });
1415
1755
  }
1416
1756
  },
1417
- /* @__PURE__ */ React13.createElement(Typography5, { variant: "caption", sx: { color: "error.light" } }, __10("Delete", "elementor"))
1757
+ /* @__PURE__ */ React15.createElement(Typography6, { variant: "caption", sx: { color: "error.light" } }, __11("Delete", "elementor"))
1418
1758
  )
1419
1759
  ));
1420
1760
  };
@@ -1447,7 +1787,7 @@ var StyledListItemButton = styled5(ListItemButton, {
1447
1787
  }
1448
1788
  `
1449
1789
  );
1450
- var Indicator = styled5(Box7, {
1790
+ var Indicator = styled5(Box8, {
1451
1791
  shouldForwardProp: (prop) => !["isActive", "isError"].includes(prop)
1452
1792
  })(({ theme, isActive, isError }) => ({
1453
1793
  display: "flex",
@@ -1477,10 +1817,10 @@ var validateLabel = (newLabel) => {
1477
1817
  };
1478
1818
 
1479
1819
  // src/components/class-manager/not-found.tsx
1480
- import * as React14 from "react";
1820
+ import * as React16 from "react";
1481
1821
  import { ColorSwatchIcon as ColorSwatchIcon2, PhotoIcon } from "@elementor/icons";
1482
- import { Box as Box8, Link, Stack as Stack6, Typography as Typography6 } from "@elementor/ui";
1483
- import { __ as __11 } from "@wordpress/i18n";
1822
+ import { Box as Box9, Link, Stack as Stack7, Typography as Typography7 } from "@elementor/ui";
1823
+ import { __ as __12 } from "@wordpress/i18n";
1484
1824
  var getNotFoundType = (searchValue, filters, filteredClasses) => {
1485
1825
  const searchNotFound = filteredClasses.length <= 0 && searchValue.length > 1;
1486
1826
  const filterNotFound = filters && filters.length === 0;
@@ -1498,19 +1838,19 @@ var getNotFoundType = (searchValue, filters, filteredClasses) => {
1498
1838
  };
1499
1839
  var notFound = {
1500
1840
  filterAndSearch: {
1501
- mainText: __11("Sorry, nothing matched.", "elementor"),
1502
- sceneryText: __11("Try something else.", "elementor"),
1503
- icon: /* @__PURE__ */ React14.createElement(PhotoIcon, { color: "inherit", fontSize: "large" })
1841
+ mainText: __12("Sorry, nothing matched.", "elementor"),
1842
+ sceneryText: __12("Try something else.", "elementor"),
1843
+ icon: /* @__PURE__ */ React16.createElement(PhotoIcon, { color: "inherit", fontSize: "large" })
1504
1844
  },
1505
1845
  search: {
1506
- mainText: __11("Sorry, nothing matched", "elementor"),
1507
- sceneryText: __11("Clear your input and try something else.", "elementor"),
1508
- icon: /* @__PURE__ */ React14.createElement(PhotoIcon, { color: "inherit", fontSize: "large" })
1846
+ mainText: __12("Sorry, nothing matched", "elementor"),
1847
+ sceneryText: __12("Clear your input and try something else.", "elementor"),
1848
+ icon: /* @__PURE__ */ React16.createElement(PhotoIcon, { color: "inherit", fontSize: "large" })
1509
1849
  },
1510
1850
  filter: {
1511
- mainText: __11("Sorry, nothing matched that search.", "elementor"),
1512
- sceneryText: __11("Clear the filters and try something else.", "elementor"),
1513
- icon: /* @__PURE__ */ React14.createElement(ColorSwatchIcon2, { color: "inherit", fontSize: "large" })
1851
+ mainText: __12("Sorry, nothing matched that search.", "elementor"),
1852
+ sceneryText: __12("Clear the filters and try something else.", "elementor"),
1853
+ icon: /* @__PURE__ */ React16.createElement(ColorSwatchIcon2, { color: "inherit", fontSize: "large" })
1514
1854
  }
1515
1855
  };
1516
1856
  var NotFound = ({ notFoundType }) => {
@@ -1520,11 +1860,11 @@ var NotFound = ({ notFoundType }) => {
1520
1860
  } = useSearchAndFilters();
1521
1861
  switch (notFoundType) {
1522
1862
  case "filter":
1523
- return /* @__PURE__ */ React14.createElement(NotFoundLayout, { ...notFound.filter, onClear: onClearFilter });
1863
+ return /* @__PURE__ */ React16.createElement(NotFoundLayout, { ...notFound.filter, onClear: onClearFilter });
1524
1864
  case "search":
1525
- return /* @__PURE__ */ React14.createElement(NotFoundLayout, { ...notFound.search, searchValue: inputValue, onClear: onClearSearch });
1865
+ return /* @__PURE__ */ React16.createElement(NotFoundLayout, { ...notFound.search, searchValue: inputValue, onClear: onClearSearch });
1526
1866
  case "filterAndSearch":
1527
- return /* @__PURE__ */ React14.createElement(
1867
+ return /* @__PURE__ */ React16.createElement(
1528
1868
  NotFoundLayout,
1529
1869
  {
1530
1870
  ...notFound.filterAndSearch,
@@ -1536,8 +1876,8 @@ var NotFound = ({ notFoundType }) => {
1536
1876
  );
1537
1877
  }
1538
1878
  };
1539
- var NotFoundLayout = ({ onClear, searchValue, mainText, sceneryText, icon }) => /* @__PURE__ */ React14.createElement(
1540
- Stack6,
1879
+ var NotFoundLayout = ({ onClear, searchValue, mainText, sceneryText, icon }) => /* @__PURE__ */ React16.createElement(
1880
+ Stack7,
1541
1881
  {
1542
1882
  color: "text.secondary",
1543
1883
  pt: 5,
@@ -1547,16 +1887,16 @@ var NotFoundLayout = ({ onClear, searchValue, mainText, sceneryText, icon }) =>
1547
1887
  justifySelf: "center"
1548
1888
  },
1549
1889
  icon,
1550
- /* @__PURE__ */ React14.createElement(
1551
- Box8,
1890
+ /* @__PURE__ */ React16.createElement(
1891
+ Box9,
1552
1892
  {
1553
1893
  sx: {
1554
1894
  width: "100%"
1555
1895
  }
1556
1896
  },
1557
- /* @__PURE__ */ React14.createElement(Typography6, { align: "center", variant: "subtitle2", color: "inherit" }, mainText),
1558
- searchValue && /* @__PURE__ */ React14.createElement(
1559
- Typography6,
1897
+ /* @__PURE__ */ React16.createElement(Typography7, { align: "center", variant: "subtitle2", color: "inherit" }, mainText),
1898
+ searchValue && /* @__PURE__ */ React16.createElement(
1899
+ Typography7,
1560
1900
  {
1561
1901
  variant: "subtitle2",
1562
1902
  color: "inherit",
@@ -1566,8 +1906,8 @@ var NotFoundLayout = ({ onClear, searchValue, mainText, sceneryText, icon }) =>
1566
1906
  justifyContent: "center"
1567
1907
  }
1568
1908
  },
1569
- /* @__PURE__ */ React14.createElement("span", null, "\u201C"),
1570
- /* @__PURE__ */ React14.createElement(
1909
+ /* @__PURE__ */ React16.createElement("span", null, "\u201C"),
1910
+ /* @__PURE__ */ React16.createElement(
1571
1911
  "span",
1572
1912
  {
1573
1913
  style: {
@@ -1578,11 +1918,11 @@ var NotFoundLayout = ({ onClear, searchValue, mainText, sceneryText, icon }) =>
1578
1918
  },
1579
1919
  searchValue
1580
1920
  ),
1581
- /* @__PURE__ */ React14.createElement("span", null, "\u201D.")
1921
+ /* @__PURE__ */ React16.createElement("span", null, "\u201D.")
1582
1922
  )
1583
1923
  ),
1584
- /* @__PURE__ */ React14.createElement(Typography6, { align: "center", variant: "caption", color: "inherit" }, sceneryText),
1585
- /* @__PURE__ */ React14.createElement(Typography6, { align: "center", variant: "caption", color: "inherit" }, /* @__PURE__ */ React14.createElement(Link, { color: "secondary", variant: "caption", component: "button", onClick: onClear }, __11("Clear & try again", "elementor")))
1924
+ /* @__PURE__ */ React16.createElement(Typography7, { align: "center", variant: "caption", color: "inherit" }, sceneryText),
1925
+ /* @__PURE__ */ React16.createElement(Typography7, { align: "center", variant: "caption", color: "inherit" }, /* @__PURE__ */ React16.createElement(Link, { color: "secondary", variant: "caption", component: "button", onClick: onClear }, __12("Clear & try again", "elementor")))
1586
1926
  );
1587
1927
 
1588
1928
  // src/components/class-manager/global-classes-list.tsx
@@ -1593,9 +1933,11 @@ var GlobalClassesList = ({ disabled }) => {
1593
1933
  const cssClasses = useOrderedClasses();
1594
1934
  const dispatch5 = useDispatch();
1595
1935
  const filters = useFilters();
1596
- const [classesOrder, reorderClasses] = useReorder();
1936
+ const [draggedItemId, setDraggedItemId] = React17.useState(null);
1937
+ const draggedItemLabel = cssClasses.find((cssClass) => cssClass.id === draggedItemId)?.label ?? "";
1938
+ const [classesOrder, reorderClasses] = useReorder(draggedItemId, setDraggedItemId, draggedItemLabel ?? "");
1597
1939
  const filteredCssClasses = useFilteredCssClasses();
1598
- useEffect(() => {
1940
+ useEffect2(() => {
1599
1941
  const handler = (event) => {
1600
1942
  if (event.key === "z" && (event.ctrlKey || event.metaKey)) {
1601
1943
  event.stopImmediatePropagation();
@@ -1613,58 +1955,81 @@ var GlobalClassesList = ({ disabled }) => {
1613
1955
  return () => window.removeEventListener("keydown", handler);
1614
1956
  }, [dispatch5]);
1615
1957
  if (!cssClasses?.length) {
1616
- return /* @__PURE__ */ React15.createElement(EmptyState, null);
1958
+ return /* @__PURE__ */ React17.createElement(EmptyState, null);
1617
1959
  }
1618
1960
  const notFoundType = getNotFoundType(searchValue, filters, filteredCssClasses);
1619
1961
  if (notFoundType) {
1620
- return /* @__PURE__ */ React15.createElement(NotFound, { notFoundType });
1962
+ return /* @__PURE__ */ React17.createElement(NotFound, { notFoundType });
1621
1963
  }
1622
1964
  const isFiltersApplied = filters?.length || searchValue;
1623
1965
  const allowSorting = filteredCssClasses.length > 1 && !isFiltersApplied;
1624
- return /* @__PURE__ */ React15.createElement(DeleteConfirmationProvider, null, /* @__PURE__ */ React15.createElement(List, { sx: { display: "flex", flexDirection: "column", gap: 0.5 } }, /* @__PURE__ */ React15.createElement(
1966
+ return /* @__PURE__ */ React17.createElement(DeleteConfirmationProvider, null, /* @__PURE__ */ React17.createElement(List, { sx: { display: "flex", flexDirection: "column", gap: 0.5 } }, /* @__PURE__ */ React17.createElement(
1625
1967
  SortableProvider,
1626
1968
  {
1627
1969
  value: classesOrder,
1628
1970
  onChange: reorderClasses,
1629
1971
  disableDragOverlay: !allowSorting
1630
1972
  },
1631
- filteredCssClasses?.map(({ id: id2, label }) => /* @__PURE__ */ React15.createElement(SortableItem, { key: id2, id: id2 }, ({ isDragged, isDragPlaceholder, triggerProps, triggerStyle }) => /* @__PURE__ */ React15.createElement(
1632
- ClassItem,
1633
- {
1634
- id: id2,
1635
- label,
1636
- renameClass: (newLabel) => {
1637
- dispatch5(
1638
- slice.actions.update({
1639
- style: {
1640
- id: id2,
1641
- label: newLabel
1642
- }
1643
- })
1644
- );
1645
- },
1646
- selected: isDragged,
1647
- disabled: disabled || isDragPlaceholder,
1648
- sortableTriggerProps: { ...triggerProps, style: triggerStyle },
1649
- showSortIndicator: allowSorting
1973
+ filteredCssClasses?.map(({ id: id2, label }) => /* @__PURE__ */ React17.createElement(SortableItem, { key: id2, id: id2 }, ({ isDragged, isDragPlaceholder, triggerProps, triggerStyle }) => {
1974
+ if (isDragged && !draggedItemId) {
1975
+ setDraggedItemId(id2);
1650
1976
  }
1651
- )))
1977
+ return /* @__PURE__ */ React17.createElement(
1978
+ ClassItem,
1979
+ {
1980
+ id: id2,
1981
+ label,
1982
+ renameClass: (newLabel) => {
1983
+ trackGlobalClasses({
1984
+ event: "classRenamed",
1985
+ classId: id2,
1986
+ oldValue: label,
1987
+ newValue: newLabel,
1988
+ source: "class-manager"
1989
+ });
1990
+ dispatch5(
1991
+ slice.actions.update({
1992
+ style: {
1993
+ id: id2,
1994
+ label: newLabel
1995
+ }
1996
+ })
1997
+ );
1998
+ },
1999
+ selected: isDragged,
2000
+ disabled: disabled || isDragPlaceholder,
2001
+ sortableTriggerProps: {
2002
+ ...triggerProps,
2003
+ style: triggerStyle
2004
+ },
2005
+ showSortIndicator: allowSorting
2006
+ }
2007
+ );
2008
+ }))
1652
2009
  )));
1653
2010
  };
1654
- var EmptyState = () => /* @__PURE__ */ React15.createElement(Stack7, { alignItems: "center", gap: 1.5, pt: 10, px: 0.5, maxWidth: "260px", margin: "auto" }, /* @__PURE__ */ React15.createElement(FlippedColorSwatchIcon, { fontSize: "large" }), /* @__PURE__ */ React15.createElement(StyledHeader, { variant: "subtitle2", component: "h2", color: "text.secondary" }, __12("There are no global classes yet.", "elementor")), /* @__PURE__ */ React15.createElement(Typography7, { align: "center", variant: "caption", color: "text.secondary" }, __12(
2011
+ var EmptyState = () => /* @__PURE__ */ React17.createElement(Stack8, { alignItems: "center", gap: 1.5, pt: 10, px: 0.5, maxWidth: "260px", margin: "auto" }, /* @__PURE__ */ React17.createElement(FlippedColorSwatchIcon, { fontSize: "large" }), /* @__PURE__ */ React17.createElement(StyledHeader, { variant: "subtitle2", component: "h2", color: "text.secondary" }, __13("There are no global classes yet.", "elementor")), /* @__PURE__ */ React17.createElement(Typography8, { align: "center", variant: "caption", color: "text.secondary" }, __13(
1655
2012
  "CSS classes created in the editor panel will appear here. Once they are available, you can arrange their hierarchy, rename them, or delete them as needed.",
1656
2013
  "elementor"
1657
2014
  )));
1658
- var StyledHeader = styled6(Typography7)(({ theme, variant }) => ({
2015
+ var StyledHeader = styled6(Typography8)(({ theme, variant }) => ({
1659
2016
  "&.MuiTypography-root": {
1660
2017
  ...theme.typography[variant]
1661
2018
  }
1662
2019
  }));
1663
- var useReorder = () => {
2020
+ var useReorder = (draggedItemId, setDraggedItemId, draggedItemLabel) => {
1664
2021
  const dispatch5 = useDispatch();
1665
2022
  const order = useClassesOrder();
1666
2023
  const reorder = (newIds) => {
1667
2024
  dispatch5(slice.actions.setOrder(newIds));
2025
+ if (draggedItemId) {
2026
+ trackGlobalClasses({
2027
+ event: "classManagerReorder",
2028
+ classId: draggedItemId,
2029
+ classTitle: draggedItemLabel
2030
+ });
2031
+ setDraggedItemId(null);
2032
+ }
1668
2033
  };
1669
2034
  return [order, reorder];
1670
2035
  };
@@ -1705,44 +2070,6 @@ function unblockPanelInteractions() {
1705
2070
  extendedWindow.$e?.components?.get?.("panel")?.unblockUserInteractions?.();
1706
2071
  }
1707
2072
 
1708
- // src/components/class-manager/save-changes-dialog.tsx
1709
- import * as React16 from "react";
1710
- import { useState as useState5 } from "react";
1711
- import { AlertTriangleFilledIcon } from "@elementor/icons";
1712
- import {
1713
- Button as Button2,
1714
- Dialog as Dialog2,
1715
- DialogActions as DialogActions2,
1716
- DialogContent as DialogContent2,
1717
- DialogContentText as DialogContentText2,
1718
- DialogTitle as DialogTitle2
1719
- } from "@elementor/ui";
1720
- var TITLE_ID2 = "save-changes-dialog";
1721
- var SaveChangesDialog = ({ children, onClose }) => /* @__PURE__ */ React16.createElement(Dialog2, { open: true, onClose, "aria-labelledby": TITLE_ID2, maxWidth: "xs" }, children);
1722
- var SaveChangesDialogTitle = ({ children }) => /* @__PURE__ */ React16.createElement(DialogTitle2, { id: TITLE_ID2, display: "flex", alignItems: "center", gap: 1, sx: { lineHeight: 1 } }, /* @__PURE__ */ React16.createElement(AlertTriangleFilledIcon, { color: "secondary" }), children);
1723
- var SaveChangesDialogContent = ({ children }) => /* @__PURE__ */ React16.createElement(DialogContent2, null, children);
1724
- var SaveChangesDialogContentText = (props) => /* @__PURE__ */ React16.createElement(DialogContentText2, { variant: "body2", color: "textPrimary", display: "flex", flexDirection: "column", ...props });
1725
- var SaveChangesDialogActions = ({ actions }) => {
1726
- const [isConfirming, setIsConfirming] = useState5(false);
1727
- const { cancel, confirm, discard } = actions;
1728
- const onConfirm = async () => {
1729
- setIsConfirming(true);
1730
- await confirm.action();
1731
- setIsConfirming(false);
1732
- };
1733
- return /* @__PURE__ */ React16.createElement(DialogActions2, null, cancel && /* @__PURE__ */ React16.createElement(Button2, { variant: "text", color: "secondary", onClick: cancel.action }, cancel.label), discard && /* @__PURE__ */ React16.createElement(Button2, { variant: "text", color: "secondary", onClick: discard.action }, discard.label), /* @__PURE__ */ React16.createElement(Button2, { variant: "contained", color: "secondary", onClick: onConfirm, loading: isConfirming }, confirm.label));
1734
- };
1735
- SaveChangesDialog.Title = SaveChangesDialogTitle;
1736
- SaveChangesDialog.Content = SaveChangesDialogContent;
1737
- SaveChangesDialog.ContentText = SaveChangesDialogContentText;
1738
- SaveChangesDialog.Actions = SaveChangesDialogActions;
1739
- var useDialog = () => {
1740
- const [isOpen, setIsOpen] = useState5(false);
1741
- const open = () => setIsOpen(true);
1742
- const close = () => setIsOpen(false);
1743
- return { isOpen, open, close };
1744
- };
1745
-
1746
2073
  // src/components/class-manager/class-manager-panel.tsx
1747
2074
  var id = "global-classes-manager";
1748
2075
  var { panel, usePanelActions } = createPanel({
@@ -1756,7 +2083,8 @@ var { panel, usePanelActions } = createPanel({
1756
2083
  onClose: () => {
1757
2084
  changeEditMode("edit");
1758
2085
  unblockPanelInteractions();
1759
- }
2086
+ },
2087
+ isOpenPreviousElement: true
1760
2088
  });
1761
2089
  function ClassManagerPanel() {
1762
2090
  const isDirty2 = useDirtyState();
@@ -1768,7 +2096,7 @@ function ClassManagerPanel() {
1768
2096
  closeSaveChangesDialog();
1769
2097
  };
1770
2098
  usePreventUnload();
1771
- return /* @__PURE__ */ React17.createElement(ThemeProvider, null, /* @__PURE__ */ React17.createElement(ErrorBoundary, { fallback: /* @__PURE__ */ React17.createElement(ErrorBoundaryFallback, null) }, /* @__PURE__ */ React17.createElement(Panel, null, /* @__PURE__ */ React17.createElement(SearchAndFilterProvider, null, /* @__PURE__ */ React17.createElement(PanelHeader, null, /* @__PURE__ */ React17.createElement(Stack8, { p: 1, pl: 2, width: "100%", direction: "row", alignItems: "center" }, /* @__PURE__ */ React17.createElement(Stack8, { width: "100%", direction: "row", gap: 1 }, /* @__PURE__ */ React17.createElement(PanelHeaderTitle, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ React17.createElement(FlippedColorSwatchIcon, { fontSize: "inherit" }), __13("Class Manager", "elementor")), /* @__PURE__ */ React17.createElement(TotalCssClassCounter, null)), /* @__PURE__ */ React17.createElement(
2099
+ return /* @__PURE__ */ React18.createElement(ThemeProvider, null, /* @__PURE__ */ React18.createElement(ErrorBoundary, { fallback: /* @__PURE__ */ React18.createElement(ErrorBoundaryFallback, null) }, /* @__PURE__ */ React18.createElement(Panel, null, /* @__PURE__ */ React18.createElement(SearchAndFilterProvider, null, /* @__PURE__ */ React18.createElement(PanelHeader, null, /* @__PURE__ */ React18.createElement(Stack9, { p: 1, pl: 2, width: "100%", direction: "row", alignItems: "center" }, /* @__PURE__ */ React18.createElement(Stack9, { width: "100%", direction: "row", gap: 1 }, /* @__PURE__ */ React18.createElement(PanelHeaderTitle, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ React18.createElement(FlippedColorSwatchIcon, { fontSize: "inherit" }), __14("Class Manager", "elementor")), /* @__PURE__ */ React18.createElement(TotalCssClassCounter, null)), /* @__PURE__ */ React18.createElement(
1772
2100
  CloseButton,
1773
2101
  {
1774
2102
  sx: { marginLeft: "auto" },
@@ -1781,7 +2109,7 @@ function ClassManagerPanel() {
1781
2109
  closePanel();
1782
2110
  }
1783
2111
  }
1784
- ))), /* @__PURE__ */ React17.createElement(
2112
+ ))), /* @__PURE__ */ React18.createElement(
1785
2113
  PanelBody,
1786
2114
  {
1787
2115
  sx: {
@@ -1790,10 +2118,10 @@ function ClassManagerPanel() {
1790
2118
  height: "100%"
1791
2119
  }
1792
2120
  },
1793
- /* @__PURE__ */ React17.createElement(Box9, { px: 2, pb: 1 }, /* @__PURE__ */ React17.createElement(Stack8, { direction: "row", justifyContent: "spaceBetween", gap: 0.5, sx: { pb: 0.5 } }, /* @__PURE__ */ React17.createElement(Box9, { sx: { flexGrow: 1 } }, /* @__PURE__ */ React17.createElement(ClassManagerSearch, null)), /* @__PURE__ */ React17.createElement(CssClassFilter, null)), /* @__PURE__ */ React17.createElement(ActiveFilters, null)),
1794
- /* @__PURE__ */ React17.createElement(Divider3, null),
1795
- /* @__PURE__ */ React17.createElement(
1796
- Box9,
2121
+ /* @__PURE__ */ React18.createElement(Box10, { px: 2, pb: 1 }, /* @__PURE__ */ React18.createElement(Stack9, { direction: "row", justifyContent: "spaceBetween", gap: 0.5, sx: { pb: 0.5 } }, /* @__PURE__ */ React18.createElement(Box10, { sx: { flexGrow: 1 } }, /* @__PURE__ */ React18.createElement(ClassManagerSearch, null)), /* @__PURE__ */ React18.createElement(CssClassFilter, null)), /* @__PURE__ */ React18.createElement(ActiveFilters, null)),
2122
+ /* @__PURE__ */ React18.createElement(Divider4, null),
2123
+ /* @__PURE__ */ React18.createElement(
2124
+ Box10,
1797
2125
  {
1798
2126
  px: 2,
1799
2127
  sx: {
@@ -1801,9 +2129,9 @@ function ClassManagerPanel() {
1801
2129
  overflowY: "auto"
1802
2130
  }
1803
2131
  },
1804
- /* @__PURE__ */ React17.createElement(GlobalClassesList, { disabled: isPublishing })
2132
+ /* @__PURE__ */ React18.createElement(GlobalClassesList, { disabled: isPublishing })
1805
2133
  )
1806
- ), /* @__PURE__ */ React17.createElement(PanelFooter, null, /* @__PURE__ */ React17.createElement(
2134
+ ), /* @__PURE__ */ React18.createElement(PanelFooter, null, /* @__PURE__ */ React18.createElement(
1807
2135
  Button3,
1808
2136
  {
1809
2137
  fullWidth: true,
@@ -1814,19 +2142,19 @@ function ClassManagerPanel() {
1814
2142
  disabled: !isDirty2,
1815
2143
  loading: isPublishing
1816
2144
  },
1817
- __13("Save changes", "elementor")
1818
- ))))), /* @__PURE__ */ React17.createElement(ClassManagerIntroduction, null), isSaveChangesDialogOpen && /* @__PURE__ */ React17.createElement(SaveChangesDialog, null, /* @__PURE__ */ React17.createElement(DialogHeader, { onClose: closeSaveChangesDialog, logo: false }, /* @__PURE__ */ React17.createElement(SaveChangesDialog.Title, null, __13("You have unsaved changes", "elementor"))), /* @__PURE__ */ React17.createElement(SaveChangesDialog.Content, null, /* @__PURE__ */ React17.createElement(SaveChangesDialog.ContentText, null, __13("You have unsaved changes in the Class Manager.", "elementor")), /* @__PURE__ */ React17.createElement(SaveChangesDialog.ContentText, null, __13("To avoid losing your updates, save your changes before leaving.", "elementor"))), /* @__PURE__ */ React17.createElement(
2145
+ __14("Save changes", "elementor")
2146
+ ))))), /* @__PURE__ */ React18.createElement(ClassManagerIntroduction, null), isSaveChangesDialogOpen && /* @__PURE__ */ React18.createElement(SaveChangesDialog, null, /* @__PURE__ */ React18.createElement(DialogHeader2, { onClose: closeSaveChangesDialog, logo: false }, /* @__PURE__ */ React18.createElement(SaveChangesDialog.Title, null, __14("You have unsaved changes", "elementor"))), /* @__PURE__ */ React18.createElement(SaveChangesDialog.Content, null, /* @__PURE__ */ React18.createElement(SaveChangesDialog.ContentText, null, __14("You have unsaved changes in the Class Manager.", "elementor")), /* @__PURE__ */ React18.createElement(SaveChangesDialog.ContentText, null, __14("To avoid losing your updates, save your changes before leaving.", "elementor"))), /* @__PURE__ */ React18.createElement(
1819
2147
  SaveChangesDialog.Actions,
1820
2148
  {
1821
2149
  actions: {
1822
2150
  discard: {
1823
- label: __13("Discard", "elementor"),
2151
+ label: __14("Discard", "elementor"),
1824
2152
  action: () => {
1825
2153
  resetAndClosePanel();
1826
2154
  }
1827
2155
  },
1828
2156
  confirm: {
1829
- label: __13("Save & Continue", "elementor"),
2157
+ label: __14("Save & Continue", "elementor"),
1830
2158
  action: async () => {
1831
2159
  await publish();
1832
2160
  closeSaveChangesDialog();
@@ -1837,11 +2165,11 @@ function ClassManagerPanel() {
1837
2165
  }
1838
2166
  )));
1839
2167
  }
1840
- var CloseButton = ({ onClose, ...props }) => /* @__PURE__ */ React17.createElement(IconButton4, { size: "small", color: "secondary", onClick: onClose, "aria-label": "Close", ...props }, /* @__PURE__ */ React17.createElement(XIcon, { fontSize: "small" }));
1841
- var ErrorBoundaryFallback = () => /* @__PURE__ */ React17.createElement(Box9, { role: "alert", sx: { minHeight: "100%", p: 2 } }, /* @__PURE__ */ React17.createElement(Alert, { severity: "error", sx: { mb: 2, maxWidth: 400, textAlign: "center" } }, /* @__PURE__ */ React17.createElement("strong", null, __13("Something went wrong", "elementor"))));
2168
+ var CloseButton = ({ onClose, ...props }) => /* @__PURE__ */ React18.createElement(IconButton4, { size: "small", color: "secondary", onClick: onClose, "aria-label": "Close", ...props }, /* @__PURE__ */ React18.createElement(XIcon, { fontSize: "small" }));
2169
+ var ErrorBoundaryFallback = () => /* @__PURE__ */ React18.createElement(Box10, { role: "alert", sx: { minHeight: "100%", p: 2 } }, /* @__PURE__ */ React18.createElement(Alert2, { severity: "error", sx: { mb: 2, maxWidth: 400, textAlign: "center" } }, /* @__PURE__ */ React18.createElement("strong", null, __14("Something went wrong", "elementor"))));
1842
2170
  var usePreventUnload = () => {
1843
2171
  const isDirty2 = useDirtyState();
1844
- useEffect2(() => {
2172
+ useEffect3(() => {
1845
2173
  const handleBeforeUnload = (event) => {
1846
2174
  if (isDirty2) {
1847
2175
  event.preventDefault();
@@ -1867,7 +2195,7 @@ var usePublish = () => {
1867
2195
  var TotalCssClassCounter = () => {
1868
2196
  const filters = useFilters();
1869
2197
  const cssClasses = useClassesOrder();
1870
- return /* @__PURE__ */ React17.createElement(
2198
+ return /* @__PURE__ */ React18.createElement(
1871
2199
  Chip4,
1872
2200
  {
1873
2201
  size: "small",
@@ -1877,11 +2205,17 @@ var TotalCssClassCounter = () => {
1877
2205
  };
1878
2206
 
1879
2207
  // src/components/class-manager/class-manager-button.tsx
2208
+ var trackGlobalClassesButton = () => {
2209
+ trackGlobalClasses({
2210
+ event: "classManagerOpened",
2211
+ source: "style-panel"
2212
+ });
2213
+ };
1880
2214
  var ClassManagerButton = () => {
1881
2215
  const document = useActiveDocument2();
1882
2216
  const { open: openPanel } = usePanelActions();
1883
2217
  const { save: saveDocument } = useActiveDocumentActions();
1884
- const { open: openSaveChangesDialog, close: closeSaveChangesDialog, isOpen: isSaveChangesDialogOpen } = useDialog();
2218
+ const { open: openSaveChangesDialog, close: closeSaveChangesDialog, isOpen: isSaveChangesDialogOpen } = useDialog2();
1885
2219
  const { prefetchClassesUsage } = usePrefetchCssClassUsage();
1886
2220
  const { userCan } = useUserStylesCapability();
1887
2221
  const isUserAllowedToUpdateClass = userCan(globalClassesStylesProvider.getKey()).update;
@@ -1894,25 +2228,31 @@ var ClassManagerButton = () => {
1894
2228
  return;
1895
2229
  }
1896
2230
  openPanel();
2231
+ trackGlobalClassesButton();
2232
+ trackGlobalClasses({
2233
+ event: "classManagerOpened",
2234
+ source: "style-panel"
2235
+ });
1897
2236
  prefetchClassesUsage();
1898
2237
  };
1899
- return /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement(Tooltip6, { title: __14("Class Manager", "elementor"), placement: "top" }, /* @__PURE__ */ React18.createElement(IconButton5, { size: "tiny", onClick: handleOpenPanel, sx: { marginInlineEnd: -0.75 } }, /* @__PURE__ */ React18.createElement(FlippedColorSwatchIcon, { fontSize: "tiny" }))), isSaveChangesDialogOpen && /* @__PURE__ */ React18.createElement(SaveChangesDialog, null, /* @__PURE__ */ React18.createElement(SaveChangesDialog.Title, null, __14("You have unsaved changes", "elementor")), /* @__PURE__ */ React18.createElement(SaveChangesDialog.Content, null, /* @__PURE__ */ React18.createElement(SaveChangesDialog.ContentText, { sx: { mb: 2 } }, __14(
2238
+ return /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement(Tooltip6, { title: __15("Class Manager", "elementor"), placement: "top" }, /* @__PURE__ */ React19.createElement(IconButton5, { size: "tiny", onClick: handleOpenPanel, sx: { marginInlineEnd: -0.75 } }, /* @__PURE__ */ React19.createElement(FlippedColorSwatchIcon, { fontSize: "tiny" }))), isSaveChangesDialogOpen && /* @__PURE__ */ React19.createElement(SaveChangesDialog2, null, /* @__PURE__ */ React19.createElement(SaveChangesDialog2.Title, null, __15("You have unsaved changes", "elementor")), /* @__PURE__ */ React19.createElement(SaveChangesDialog2.Content, null, /* @__PURE__ */ React19.createElement(SaveChangesDialog2.ContentText, { sx: { mb: 2 } }, __15(
1900
2239
  "To open the Class Manager, save your page first. You can't continue without saving.",
1901
2240
  "elementor"
1902
- ))), /* @__PURE__ */ React18.createElement(
1903
- SaveChangesDialog.Actions,
2241
+ ))), /* @__PURE__ */ React19.createElement(
2242
+ SaveChangesDialog2.Actions,
1904
2243
  {
1905
2244
  actions: {
1906
2245
  cancel: {
1907
- label: __14("Stay here", "elementor"),
2246
+ label: __15("Stay here", "elementor"),
1908
2247
  action: closeSaveChangesDialog
1909
2248
  },
1910
2249
  confirm: {
1911
- label: __14("Save & Continue", "elementor"),
2250
+ label: __15("Save & Continue", "elementor"),
1912
2251
  action: async () => {
1913
2252
  await saveDocument();
1914
2253
  closeSaveChangesDialog();
1915
2254
  openPanel();
2255
+ trackGlobalClassesButton();
1916
2256
  prefetchClassesUsage();
1917
2257
  }
1918
2258
  }
@@ -1922,11 +2262,11 @@ var ClassManagerButton = () => {
1922
2262
  };
1923
2263
 
1924
2264
  // src/components/convert-local-class-to-global-class.tsx
1925
- import * as React19 from "react";
2265
+ import * as React20 from "react";
1926
2266
  import { validateStyleLabel as validateStyleLabel2 } from "@elementor/editor-styles-repository";
1927
2267
  import { MenuListItem as MenuListItem2 } from "@elementor/editor-ui";
1928
- import { Divider as Divider4 } from "@elementor/ui";
1929
- import { __ as __15 } from "@wordpress/i18n";
2268
+ import { Divider as Divider5 } from "@elementor/ui";
2269
+ import { __ as __16 } from "@wordpress/i18n";
1930
2270
  var ConvertLocalClassToGlobalClass = (props) => {
1931
2271
  const localStyleData = props.styleDef;
1932
2272
  const handleConversion = () => {
@@ -1937,9 +2277,15 @@ var ConvertLocalClassToGlobalClass = (props) => {
1937
2277
  const newId = globalClassesStylesProvider.actions.create?.(newClassName, localStyleData.variants);
1938
2278
  if (newId) {
1939
2279
  props.successCallback(newId);
2280
+ trackGlobalClasses({
2281
+ classId: newId,
2282
+ event: "classCreated",
2283
+ source: "converted",
2284
+ classTitle: newClassName
2285
+ });
1940
2286
  }
1941
2287
  };
1942
- return /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement(
2288
+ return /* @__PURE__ */ React20.createElement(React20.Fragment, null, /* @__PURE__ */ React20.createElement(
1943
2289
  MenuListItem2,
1944
2290
  {
1945
2291
  disabled: !props.canConvert,
@@ -1953,8 +2299,8 @@ var ConvertLocalClassToGlobalClass = (props) => {
1953
2299
  }
1954
2300
  }
1955
2301
  },
1956
- __15("Convert to global class", "elementor")
1957
- ), /* @__PURE__ */ React19.createElement(Divider4, null));
2302
+ __16("Convert to global class", "elementor")
2303
+ ), /* @__PURE__ */ React20.createElement(Divider5, null));
1958
2304
  };
1959
2305
  function createClassName(prefix) {
1960
2306
  let i = 1;
@@ -1966,11 +2312,11 @@ function createClassName(prefix) {
1966
2312
  }
1967
2313
 
1968
2314
  // src/components/populate-store.tsx
1969
- import { useEffect as useEffect3 } from "react";
2315
+ import { useEffect as useEffect4 } from "react";
1970
2316
  import { __useDispatch as useDispatch2 } from "@elementor/store";
1971
2317
  function PopulateStore() {
1972
2318
  const dispatch5 = useDispatch2();
1973
- useEffect3(() => {
2319
+ useEffect4(() => {
1974
2320
  Promise.all([apiClient.all("preview"), apiClient.all("frontend")]).then(
1975
2321
  ([previewRes, frontendRes]) => {
1976
2322
  const { data: previewData } = previewRes;
@@ -1993,14 +2339,223 @@ function PopulateStore() {
1993
2339
  return null;
1994
2340
  }
1995
2341
 
2342
+ // src/mcp-integration/index.ts
2343
+ import { getMCPByDomain as getMCPByDomain2 } from "@elementor/editor-mcp";
2344
+
2345
+ // src/mcp-integration/classes-resource.ts
2346
+ import { getMCPByDomain } from "@elementor/editor-mcp";
2347
+ var GLOBAL_CLASSES_URI = "elementor://classes";
2348
+ var initClassesResource = () => {
2349
+ const { mcpServer } = getMCPByDomain("classes");
2350
+ mcpServer.resource(
2351
+ "global-classes",
2352
+ GLOBAL_CLASSES_URI,
2353
+ {
2354
+ description: "Global classes list."
2355
+ },
2356
+ async () => {
2357
+ return {
2358
+ contents: [{ uri: GLOBAL_CLASSES_URI, text: localStorage["elementor-global-classes"] ?? {} }]
2359
+ };
2360
+ }
2361
+ );
2362
+ };
2363
+
2364
+ // src/mcp-integration/mcp-apply-unapply-global-classes.ts
2365
+ import { doApplyClasses, doGetAppliedClasses, doUnapplyClass } from "@elementor/editor-editing-panel";
2366
+ import { stylesRepository } from "@elementor/editor-styles-repository";
2367
+ import { z } from "@elementor/schema";
2368
+ function initMcpApplyUnapplyGlobalClasses(server) {
2369
+ server.addTool({
2370
+ name: "list-all-global-classes",
2371
+ description: `List all classes applied to a specific element
2372
+
2373
+ ## When to use this tool:
2374
+ - When a user requests to see which classes or global classes exists.
2375
+ - When you need the list of global classes to allow the user to select from.
2376
+ - At least once before applying or unapplying a class, to ensure the class ID is correct.
2377
+
2378
+ `,
2379
+ outputSchema: {
2380
+ appliedClasses: z.array(
2381
+ z.object({
2382
+ id: z.string().describe("The ID of the class"),
2383
+ label: z.string().describe("The label of the class"),
2384
+ variants: z.array(
2385
+ z.object({
2386
+ meta: z.object({
2387
+ breakpoint: z.string().optional(),
2388
+ state: z.string().optional()
2389
+ }),
2390
+ props: z.record(z.any())
2391
+ })
2392
+ )
2393
+ })
2394
+ )
2395
+ },
2396
+ handler: async () => {
2397
+ const globalClassesProvider = stylesRepository.getProviderByKey("global-classes");
2398
+ if (!globalClassesProvider) {
2399
+ throw new Error("Global classes provider not found");
2400
+ }
2401
+ const result = [];
2402
+ globalClassesProvider.actions.all().forEach((style) => {
2403
+ const { id: id2, label, variants } = style;
2404
+ result.push({
2405
+ id: id2,
2406
+ label,
2407
+ variants: variants.map((variant) => ({
2408
+ meta: {
2409
+ breakpoint: variant.meta.breakpoint,
2410
+ state: variant.meta.state
2411
+ },
2412
+ props: variant.props
2413
+ }))
2414
+ });
2415
+ });
2416
+ return { appliedClasses: result };
2417
+ }
2418
+ });
2419
+ server.addTool({
2420
+ schema: {
2421
+ classId: z.string().describe("The ID of the class to apply"),
2422
+ elementId: z.string().describe("The ID of the element to which the class will be applied")
2423
+ },
2424
+ name: "apply-global-class",
2425
+ description: `Apply a global class to the current element
2426
+
2427
+ ## When to use this tool:
2428
+ - When a user requests to apply a global class or a class to an element in the Elementor editor.
2429
+ - When you need to add a specific class to an element's applied classes.
2430
+
2431
+ ## Prerequisites:
2432
+ - Ensure you have the most up-to-date list of classes applied to the element to avoid duplicates. You can use the "list-applied-classes" tool to fetch the current classes.
2433
+ - Make sure you have the correct class ID that you want to apply.`,
2434
+ handler: async (params) => {
2435
+ const { classId, elementId } = params;
2436
+ const appliedClasses = doGetAppliedClasses(elementId);
2437
+ doApplyClasses(elementId, [...appliedClasses, classId]);
2438
+ return `Class ${classId} applied to element ${elementId} successfully.`;
2439
+ }
2440
+ });
2441
+ server.addTool({
2442
+ name: "unapply-global-class",
2443
+ schema: {
2444
+ classId: z.string().describe("The ID of the class to unapply"),
2445
+ elementId: z.string().describe("The ID of the element from which the class will be unapplied")
2446
+ },
2447
+ description: `Unapply a (global) class from the current element
2448
+
2449
+ ## When to use this tool:
2450
+ - When a user requests to unapply a global class or a class from an element in the Elementor editor.
2451
+ - When you need to remove a specific class from an element's applied classes.
2452
+
2453
+ ## Prerequisites:
2454
+ - Ensure you have the most up-to-date list of classes applied to the element to avoid errors. You can use the "list-global-classes" tool to fetch the all classes applied to all elements.
2455
+ - Make sure you have the correct class ID that you want to unapply.
2456
+
2457
+ <note>
2458
+ If the user want to unapply a class by it's name and not ID, please use the "list-global-classes" tool to get the class ID from the name first.
2459
+ </note>
2460
+ `,
2461
+ handler: async (params) => {
2462
+ const { classId, elementId } = params;
2463
+ const ok = doUnapplyClass(elementId, classId);
2464
+ if (!ok) {
2465
+ throw new Error(`Class ${classId} is not applied to element ${elementId}, cannot unapply it.`);
2466
+ }
2467
+ return `Class ${classId} unapplied from element ${elementId} successfully.`;
2468
+ }
2469
+ });
2470
+ }
2471
+
2472
+ // src/mcp-integration/mcp-get-global-class-usages.ts
2473
+ import { z as z2 } from "@elementor/schema";
2474
+ function initMcpApplyGetGlobalClassUsages(reg) {
2475
+ const { addTool } = reg;
2476
+ const globalClassesUsageSchema = {
2477
+ usages: z2.array(
2478
+ z2.object({
2479
+ classId: z2.string().describe(
2480
+ 'The ID of the class, not visible to the user. To retreive the name of the class, use the "list-global-classes" tool'
2481
+ ),
2482
+ usages: z2.array(
2483
+ z2.object({
2484
+ pageId: z2.string().describe("The ID of the page where the class is used"),
2485
+ title: z2.string().describe("The title of the page where the class is used"),
2486
+ total: z2.number().describe("The number of times the class is used on this page"),
2487
+ elements: z2.array(z2.string()).describe("List of element IDs using this class on the page")
2488
+ })
2489
+ )
2490
+ })
2491
+ )
2492
+ };
2493
+ addTool({
2494
+ name: "get-global-class-usages",
2495
+ description: `Retreive the usage details of global classes within the Elementor editor, accross all pages.
2496
+
2497
+ ## Prequisites:
2498
+ - Use "list-global-classes" tool to be able to match class IDs to class names/labels.
2499
+
2500
+ ## When to use this tool:
2501
+ - When a user requests to see where a specific global class is being used accross the site.
2502
+ - When you need to manage or clean up unused global classes.
2503
+ - Before deleting a global class, to ensure it is not in use in any other pages.
2504
+ `,
2505
+ outputSchema: globalClassesUsageSchema,
2506
+ handler: async () => {
2507
+ const data = await fetchCssClassUsage();
2508
+ const result = {
2509
+ usages: []
2510
+ };
2511
+ Object.entries(data).forEach(
2512
+ ([classId, usageDetails]) => {
2513
+ const newEntry = {
2514
+ classId,
2515
+ usages: []
2516
+ };
2517
+ if (typeof usageDetails !== "number") {
2518
+ const { content } = usageDetails;
2519
+ content.forEach((detail) => {
2520
+ newEntry.usages.push({
2521
+ pageId: String(detail.pageId),
2522
+ title: detail.title,
2523
+ total: detail.total,
2524
+ elements: detail.elements
2525
+ });
2526
+ });
2527
+ result.usages.push(newEntry);
2528
+ }
2529
+ }
2530
+ );
2531
+ return result;
2532
+ }
2533
+ });
2534
+ }
2535
+
2536
+ // src/mcp-integration/index.ts
2537
+ var initMcpIntegration = () => {
2538
+ const reg = getMCPByDomain2("classes");
2539
+ reg.setMCPDescription(
2540
+ "Tools for managing and applying Global CSS classes to elements within the Elementor editor."
2541
+ );
2542
+ initMcpApplyUnapplyGlobalClasses(reg);
2543
+ initMcpApplyGetGlobalClassUsages(reg);
2544
+ initClassesResource();
2545
+ };
2546
+
2547
+ // src/sync-with-document.tsx
2548
+ import { useEffect as useEffect5 } from "react";
2549
+ import { __privateListenTo as listenTo, v1ReadyEvent } from "@elementor/editor-v1-adapters";
2550
+
1996
2551
  // src/sync-with-document-save.ts
1997
2552
  import { getCurrentUser } from "@elementor/editor-current-user";
1998
2553
  import { setDocumentModifiedStatus as setDocumentModifiedStatus2 } from "@elementor/editor-documents";
1999
2554
  import { registerDataHook } from "@elementor/editor-v1-adapters";
2000
- import { __getState as getState3, __subscribeWithSelector as subscribeWithSelector2 } from "@elementor/store";
2001
- function syncWithDocumentSave() {
2555
+ import { __getState as getState4, __subscribeWithSelector as subscribeWithSelector2 } from "@elementor/store";
2556
+ function syncWithDocumentSave(panelActions) {
2002
2557
  const unsubscribe = syncDirtyState();
2003
- bindSaveAction();
2558
+ bindSaveAction(panelActions);
2004
2559
  return unsubscribe;
2005
2560
  }
2006
2561
  function syncDirtyState() {
@@ -2011,31 +2566,52 @@ function syncDirtyState() {
2011
2566
  setDocumentModifiedStatus2(true);
2012
2567
  });
2013
2568
  }
2014
- function bindSaveAction() {
2015
- registerDataHook("after", "document/save/save", (args) => {
2569
+ function bindSaveAction(panelActions) {
2570
+ registerDataHook("dependency", "document/save/save", (args) => {
2016
2571
  const user = getCurrentUser();
2017
2572
  const canEdit = user?.capabilities.includes(UPDATE_CLASS_CAPABILITY_KEY);
2018
2573
  if (!canEdit) {
2019
- return;
2574
+ return true;
2020
2575
  }
2021
- return saveGlobalClasses({
2022
- context: args.status === "publish" ? "frontend" : "preview"
2576
+ saveGlobalClasses({
2577
+ context: args.status === "publish" ? "frontend" : "preview",
2578
+ onApprove: panelActions?.open
2023
2579
  });
2580
+ return true;
2024
2581
  });
2025
2582
  }
2026
2583
  function isDirty() {
2027
- return selectIsDirty(getState3());
2584
+ return selectIsDirty(getState4());
2585
+ }
2586
+
2587
+ // src/sync-with-document.tsx
2588
+ function SyncWithDocumentSave() {
2589
+ const panelActions = usePanelActions();
2590
+ useEffect5(() => {
2591
+ listenTo(v1ReadyEvent(), () => {
2592
+ syncWithDocumentSave(panelActions);
2593
+ });
2594
+ }, []);
2595
+ return null;
2028
2596
  }
2029
2597
 
2030
2598
  // src/init.ts
2031
2599
  function init() {
2032
2600
  registerSlice(slice);
2033
2601
  registerPanel(panel);
2034
- stylesRepository.register(globalClassesStylesProvider);
2602
+ stylesRepository2.register(globalClassesStylesProvider);
2035
2603
  injectIntoLogic({
2036
2604
  id: "global-classes-populate-store",
2037
2605
  component: PopulateStore
2038
2606
  });
2607
+ injectIntoLogic({
2608
+ id: "global-classes-sync-with-document",
2609
+ component: SyncWithDocumentSave
2610
+ });
2611
+ injectIntoLogic({
2612
+ id: "global-classes-prefetch-css-class-usage",
2613
+ component: PrefetchCssClassUsage
2614
+ });
2039
2615
  injectIntoCssClassConvert({
2040
2616
  id: "global-classes-convert-from-local-class",
2041
2617
  component: ConvertLocalClassToGlobalClass
@@ -2048,9 +2624,7 @@ function init() {
2048
2624
  name: "global",
2049
2625
  getThemeColor: (theme) => theme.palette.global.dark
2050
2626
  });
2051
- listenTo(v1ReadyEvent(), () => {
2052
- syncWithDocumentSave();
2053
- });
2627
+ initMcpIntegration();
2054
2628
  }
2055
2629
  export {
2056
2630
  init