@elementor/editor-global-classes 0.22.2 → 3.32.0-20

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 (35) hide show
  1. package/CHANGELOG.md +0 -21
  2. package/dist/index.js +1069 -327
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.mjs +1049 -279
  5. package/dist/index.mjs.map +1 -1
  6. package/package.json +18 -18
  7. package/src/api.ts +14 -2
  8. package/src/components/class-manager/class-item.tsx +40 -65
  9. package/src/components/class-manager/class-manager-button.tsx +4 -0
  10. package/src/components/class-manager/class-manager-panel.tsx +82 -74
  11. package/src/components/class-manager/delete-confirmation-dialog.tsx +26 -6
  12. package/src/components/class-manager/global-classes-list.tsx +76 -57
  13. package/src/components/class-manager/not-found.tsx +138 -0
  14. package/src/components/convert-local-class-to-global-class.tsx +62 -0
  15. package/src/components/css-class-usage/components/css-class-usage-popover.tsx +169 -0
  16. package/src/components/css-class-usage/components/css-class-usage-trigger.tsx +116 -0
  17. package/src/components/css-class-usage/components/index.ts +2 -0
  18. package/src/components/css-class-usage/types.ts +19 -0
  19. package/src/components/css-class-usage/utils.ts +10 -0
  20. package/src/components/search-and-filter/components/filter/active-filters.tsx +54 -0
  21. package/src/components/search-and-filter/components/filter/clear-icon-button.tsx +31 -0
  22. package/src/components/search-and-filter/components/filter/css-class-filter.tsx +74 -0
  23. package/src/components/search-and-filter/components/filter/filter-list.tsx +77 -0
  24. package/src/components/{class-manager → search-and-filter/components/search}/class-manager-search.tsx +12 -11
  25. package/src/components/search-and-filter/context.tsx +78 -0
  26. package/src/global-classes-styles-provider.ts +13 -8
  27. package/src/hooks/use-css-class-usage-by-id.ts +15 -0
  28. package/src/hooks/use-css-class-usage.ts +13 -0
  29. package/src/hooks/use-empty-css-class.ts +12 -0
  30. package/src/hooks/use-filtered-css-class-usage.tsx +67 -0
  31. package/src/hooks/use-filters.ts +30 -0
  32. package/src/hooks/use-prefetch-css-class-usage.ts +16 -0
  33. package/src/init.ts +11 -1
  34. package/src/store.ts +23 -6
  35. package/src/components/class-manager/class-manager-class-not-found.tsx +0 -56
package/dist/index.mjs CHANGED
@@ -1,25 +1,28 @@
1
1
  // src/init.ts
2
2
  import { injectIntoLogic } from "@elementor/editor";
3
- import { injectIntoClassSelectorActions, registerStyleProviderToColors } from "@elementor/editor-editing-panel";
3
+ import {
4
+ injectIntoClassSelectorActions,
5
+ injectIntoCssClassConvert,
6
+ registerStyleProviderToColors
7
+ } from "@elementor/editor-editing-panel";
4
8
  import { __registerPanel as registerPanel } from "@elementor/editor-panels";
5
9
  import { stylesRepository } from "@elementor/editor-styles-repository";
6
10
  import { __privateListenTo as listenTo, v1ReadyEvent } from "@elementor/editor-v1-adapters";
7
11
  import { __registerSlice as registerSlice } from "@elementor/store";
8
12
 
9
13
  // src/components/class-manager/class-manager-button.tsx
10
- import * as React11 from "react";
14
+ import * as React18 from "react";
11
15
  import {
12
- __useActiveDocument as useActiveDocument,
16
+ __useActiveDocument as useActiveDocument2,
13
17
  __useActiveDocumentActions as useActiveDocumentActions
14
18
  } from "@elementor/editor-documents";
15
19
  import { useUserStylesCapability } from "@elementor/editor-styles-repository";
16
- import { IconButton as IconButton3, Tooltip as Tooltip2 } from "@elementor/ui";
17
- import { __ as __9 } from "@wordpress/i18n";
20
+ import { IconButton as IconButton5, Tooltip as Tooltip6 } from "@elementor/ui";
21
+ import { __ as __14 } from "@wordpress/i18n";
18
22
 
19
23
  // src/global-classes-styles-provider.ts
20
24
  import { generateId } from "@elementor/editor-styles";
21
25
  import { createStylesProvider } from "@elementor/editor-styles-repository";
22
- import { isExperimentActive as isExperimentActive2 } from "@elementor/editor-v1-adapters";
23
26
  import {
24
27
  __dispatch as dispatch,
25
28
  __getState as getState,
@@ -185,13 +188,14 @@ var slice = createSlice({
185
188
  }
186
189
  localHistory.next(state.data);
187
190
  const variant = getVariantByMeta(style, payload.meta);
191
+ let customCss = ("custom_css" in payload ? payload.custom_css : variant?.custom_css) ?? null;
192
+ customCss = customCss?.raw ? customCss : null;
188
193
  if (variant) {
189
194
  variant.props = mergeProps(variant.props, payload.props);
190
- if (Object.keys(variant.props).length === 0) {
191
- style.variants = style.variants.filter((v) => v !== variant);
192
- }
195
+ variant.custom_css = customCss;
196
+ style.variants = getNonEmptyVariants(style);
193
197
  } else {
194
- style.variants.push({ meta: payload.meta, props: payload.props });
198
+ style.variants.push({ meta: payload.meta, props: payload.props, custom_css: customCss });
195
199
  }
196
200
  state.isDirty = true;
197
201
  },
@@ -232,6 +236,11 @@ var slice = createSlice({
232
236
  }
233
237
  }
234
238
  });
239
+ var getNonEmptyVariants = (style) => {
240
+ return style.variants.filter(
241
+ ({ props, custom_css: customCss }) => Object.keys(props).length || customCss?.raw
242
+ );
243
+ };
235
244
  var selectData = (state) => state[SLICE_NAME].data;
236
245
  var selectFrontendInitialData = (state) => state[SLICE_NAME].initialData.frontend;
237
246
  var selectPreviewInitialData = (state) => state[SLICE_NAME].initialData.preview;
@@ -244,6 +253,10 @@ var selectOrderedClasses = createSelector(
244
253
  (items, order) => order.map((id2) => items[id2])
245
254
  );
246
255
  var selectClass = (state, id2) => state[SLICE_NAME].data.items[id2] ?? null;
256
+ var selectEmptyCssClass = createSelector(
257
+ selectData,
258
+ ({ items }) => Object.values(items).filter((cssClass) => cssClass.variants.length === 0)
259
+ );
247
260
 
248
261
  // src/global-classes-styles-provider.ts
249
262
  var MAX_CLASSES = 50;
@@ -262,12 +275,9 @@ var globalClassesStylesProvider = createStylesProvider({
262
275
  all: () => selectOrderedClasses(getState()),
263
276
  get: (id2) => selectClass(getState(), id2),
264
277
  resolveCssName: (id2) => {
265
- if (!isExperimentActive2("e_v_3_30")) {
266
- return id2;
267
- }
268
278
  return selectClass(getState(), id2)?.label ?? id2;
269
279
  },
270
- create: (label) => {
280
+ create: (label, variants = []) => {
271
281
  const classes = selectGlobalClasses(getState());
272
282
  const existingLabels = Object.values(classes).map((style) => style.label);
273
283
  if (existingLabels.includes(label)) {
@@ -280,7 +290,7 @@ var globalClassesStylesProvider = createStylesProvider({
280
290
  id: id2,
281
291
  type: "class",
282
292
  label,
283
- variants: []
293
+ variants
284
294
  })
285
295
  );
286
296
  return id2;
@@ -303,15 +313,77 @@ var globalClassesStylesProvider = createStylesProvider({
303
313
  props: args.props
304
314
  })
305
315
  );
316
+ },
317
+ updateCustomCss: (args) => {
318
+ dispatch(
319
+ slice.actions.updateProps({
320
+ id: args.id,
321
+ meta: args.meta,
322
+ custom_css: args.custom_css,
323
+ props: {}
324
+ })
325
+ );
306
326
  }
307
327
  }
308
328
  });
309
329
 
330
+ // src/hooks/use-prefetch-css-class-usage.ts
331
+ import { useQueryClient } from "@elementor/query";
332
+
333
+ // src/api.ts
334
+ import { httpService } from "@elementor/http-client";
335
+ var RESOURCE_URL = "/global-classes";
336
+ var BASE_URL = "elementor/v1";
337
+ var RESOURCE_USAGE_URL = `${RESOURCE_URL}/usage`;
338
+ var apiClient = {
339
+ usage: () => httpService().get(`${BASE_URL}${RESOURCE_USAGE_URL}`),
340
+ all: (context2 = "preview") => httpService().get(`${BASE_URL}${RESOURCE_URL}`, {
341
+ params: { context: context2 }
342
+ }),
343
+ publish: (payload) => httpService().put("elementor/v1" + RESOURCE_URL, payload, {
344
+ params: {
345
+ context: "frontend"
346
+ }
347
+ }),
348
+ saveDraft: (payload) => httpService().put("elementor/v1" + RESOURCE_URL, payload, {
349
+ params: {
350
+ context: "preview"
351
+ }
352
+ })
353
+ };
354
+
355
+ // src/components/css-class-usage/utils.ts
356
+ var transformData = (data) => Object.entries(data).reduce((acc, [key, value]) => {
357
+ acc[key] = {
358
+ content: value || [],
359
+ total: value.reduce((total, val) => total + (val?.total || 0), 0)
360
+ };
361
+ return acc;
362
+ }, {});
363
+
364
+ // service/css-class-usage-service.ts
365
+ var fetchCssClassUsage = async () => {
366
+ const response = await apiClient.usage();
367
+ return transformData(response.data.data);
368
+ };
369
+
370
+ // src/components/css-class-usage/types.ts
371
+ var QUERY_KEY = "css-classes-usage";
372
+
373
+ // src/hooks/use-prefetch-css-class-usage.ts
374
+ function usePrefetchCssClassUsage() {
375
+ const queryClient = useQueryClient();
376
+ const prefetchClassesUsage = () => queryClient.prefetchQuery({
377
+ queryKey: [QUERY_KEY],
378
+ queryFn: fetchCssClassUsage
379
+ });
380
+ return { prefetchClassesUsage };
381
+ }
382
+
310
383
  // src/components/class-manager/class-manager-panel.tsx
384
+ import * as React17 from "react";
311
385
  import { useEffect as useEffect2 } from "react";
312
- import * as React10 from "react";
313
386
  import { setDocumentModifiedStatus } from "@elementor/editor-documents";
314
- import { EXPERIMENTAL_FEATURES as EXPERIMENTAL_FEATURES2 } from "@elementor/editor-editing-panel";
315
387
  import {
316
388
  __createPanel as createPanel,
317
389
  Panel,
@@ -321,52 +393,185 @@ import {
321
393
  PanelHeaderTitle
322
394
  } from "@elementor/editor-panels";
323
395
  import { ThemeProvider } from "@elementor/editor-ui";
324
- import { changeEditMode, isExperimentActive as isExperimentActive4 } from "@elementor/editor-v1-adapters";
396
+ import { changeEditMode } from "@elementor/editor-v1-adapters";
325
397
  import { XIcon } from "@elementor/icons";
326
398
  import { useMutation } from "@elementor/query";
327
399
  import { __dispatch as dispatch4 } from "@elementor/store";
328
400
  import {
329
401
  Alert,
330
- Box as Box6,
402
+ Box as Box9,
331
403
  Button as Button3,
404
+ Chip as Chip4,
332
405
  DialogHeader,
333
- Divider,
406
+ Divider as Divider3,
334
407
  ErrorBoundary,
335
- IconButton as IconButton2,
336
- Stack as Stack5
408
+ IconButton as IconButton4,
409
+ Stack as Stack8
337
410
  } from "@elementor/ui";
338
- import { useDebounceState } from "@elementor/utils";
339
- import { __ as __8 } from "@wordpress/i18n";
411
+ import { __ as __13 } from "@wordpress/i18n";
340
412
 
341
- // src/hooks/use-dirty-state.ts
413
+ // src/hooks/use-classes-order.ts
342
414
  import { __useSelector as useSelector } from "@elementor/store";
415
+ var useClassesOrder = () => {
416
+ return useSelector(selectOrder);
417
+ };
418
+
419
+ // src/hooks/use-dirty-state.ts
420
+ import { __useSelector as useSelector2 } from "@elementor/store";
343
421
  var useDirtyState = () => {
344
- return useSelector(selectIsDirty);
422
+ return useSelector2(selectIsDirty);
345
423
  };
346
424
 
347
- // src/save-global-classes.ts
348
- import { __dispatch as dispatch2, __getState as getState2 } from "@elementor/store";
425
+ // src/hooks/use-filters.ts
426
+ import { useMemo as useMemo2 } from "react";
349
427
 
350
- // src/api.ts
351
- import { httpService } from "@elementor/http-client";
352
- var RESOURCE_URL = "/global-classes";
353
- var apiClient = {
354
- all: (context2 = "preview") => httpService().get("elementor/v1" + RESOURCE_URL, {
355
- params: { context: context2 }
356
- }),
357
- publish: (payload) => httpService().put("elementor/v1" + RESOURCE_URL, payload, {
358
- params: {
359
- context: "frontend"
428
+ // src/components/search-and-filter/context.tsx
429
+ import * as React from "react";
430
+ import { createContext, useContext } from "react";
431
+ import { useDebounceState } from "@elementor/utils";
432
+ var SearchAndFilterContext = createContext(void 0);
433
+ var INIT_CHECKED_FILTERS = {
434
+ empty: false,
435
+ onThisPage: false,
436
+ unused: false
437
+ };
438
+ var SearchAndFilterProvider = ({ children }) => {
439
+ const [filters, setFilters] = React.useState(INIT_CHECKED_FILTERS);
440
+ const { debouncedValue, inputValue, handleChange } = useDebounceState({
441
+ delay: 300,
442
+ initialValue: ""
443
+ });
444
+ const onClearSearch = () => {
445
+ handleChange("");
446
+ };
447
+ const onClearFilter = () => {
448
+ setFilters(INIT_CHECKED_FILTERS);
449
+ };
450
+ return /* @__PURE__ */ React.createElement(
451
+ SearchAndFilterContext.Provider,
452
+ {
453
+ value: {
454
+ search: {
455
+ debouncedValue,
456
+ inputValue,
457
+ handleChange,
458
+ onClearSearch
459
+ },
460
+ filters: {
461
+ filters,
462
+ setFilters,
463
+ onClearFilter
464
+ }
465
+ }
466
+ },
467
+ children
468
+ );
469
+ };
470
+ var useSearchAndFilters = () => {
471
+ const context2 = useContext(SearchAndFilterContext);
472
+ if (!context2) {
473
+ throw new Error("useSearchContext must be used within a SearchContextProvider");
474
+ }
475
+ return context2;
476
+ };
477
+
478
+ // src/hooks/use-filtered-css-class-usage.tsx
479
+ import { useMemo } from "react";
480
+ import { __useActiveDocument as useActiveDocument } from "@elementor/editor-documents";
481
+
482
+ // src/hooks/use-css-class-usage.ts
483
+ import { useQuery } from "@elementor/query";
484
+ var useCssClassUsage = () => {
485
+ return useQuery({
486
+ queryKey: [QUERY_KEY],
487
+ queryFn: fetchCssClassUsage,
488
+ refetchOnMount: false,
489
+ refetchOnWindowFocus: true
490
+ });
491
+ };
492
+
493
+ // src/hooks/use-empty-css-class.ts
494
+ import { __useSelector } from "@elementor/store";
495
+ var useEmptyCssClass = () => {
496
+ return __useSelector(selectEmptyCssClass);
497
+ };
498
+ var useAllCssClassesIDs = () => {
499
+ const cssClasses = __useSelector(selectGlobalClasses);
500
+ return Object.keys(cssClasses);
501
+ };
502
+
503
+ // src/hooks/use-filtered-css-class-usage.tsx
504
+ var findCssClassKeysByPageID = (data, pageId) => {
505
+ const result = [];
506
+ for (const key in data) {
507
+ data[key].content.forEach((content) => {
508
+ if (+content.pageId === pageId) {
509
+ result.push(key);
510
+ }
511
+ });
512
+ }
513
+ return result;
514
+ };
515
+ var getUnusedClasses = (usedCssClass, potentialUnused) => {
516
+ const set = new Set(usedCssClass);
517
+ return potentialUnused.filter((cssClass) => !set.has(cssClass));
518
+ };
519
+ var EMPTY_FILTERED_CSS_CLASS_RESPONSE = {
520
+ empty: [],
521
+ onThisPage: [],
522
+ unused: []
523
+ };
524
+ var useFilteredCssClassUsage = () => {
525
+ const document = useActiveDocument();
526
+ const emptyCssClasses = useEmptyCssClass();
527
+ const { data, isLoading } = useCssClassUsage();
528
+ const listOfCssClasses = useAllCssClassesIDs();
529
+ const emptyCssClassesIDs = useMemo(() => emptyCssClasses.map(({ id: id2 }) => id2), [emptyCssClasses]);
530
+ const onThisPage = useMemo(() => {
531
+ if (!data || !document) {
532
+ return [];
360
533
  }
361
- }),
362
- saveDraft: (payload) => httpService().put("elementor/v1" + RESOURCE_URL, payload, {
363
- params: {
364
- context: "preview"
534
+ return findCssClassKeysByPageID(data, document.id);
535
+ }, [data, document]);
536
+ const unused = useMemo(() => {
537
+ if (!data) {
538
+ return [];
365
539
  }
366
- })
540
+ return getUnusedClasses(Object.keys(data), listOfCssClasses);
541
+ }, [data, listOfCssClasses]);
542
+ if (isLoading || !data || !document) {
543
+ return EMPTY_FILTERED_CSS_CLASS_RESPONSE;
544
+ }
545
+ return {
546
+ onThisPage,
547
+ unused,
548
+ empty: emptyCssClassesIDs
549
+ };
550
+ };
551
+
552
+ // src/hooks/use-filters.ts
553
+ var useFilters = () => {
554
+ const {
555
+ filters: { filters }
556
+ } = useSearchAndFilters();
557
+ const allFilters = useFilteredCssClassUsage();
558
+ return useMemo2(() => {
559
+ const activeEntries = Object.entries(filters).filter(([, isActive]) => isActive);
560
+ if (activeEntries.length === 0) {
561
+ return null;
562
+ }
563
+ return activeEntries.reduce((acc, [key], index) => {
564
+ const current = allFilters[key] || [];
565
+ if (index === 0) {
566
+ return current;
567
+ }
568
+ return acc.filter((val) => current.includes(val));
569
+ }, []);
570
+ }, [filters, allFilters]);
367
571
  };
368
572
 
369
573
  // src/save-global-classes.ts
574
+ import { __dispatch as dispatch2, __getState as getState2 } from "@elementor/store";
370
575
  async function saveGlobalClasses({ context: context2 }) {
371
576
  const state = selectData(getState2());
372
577
  if (context2 === "preview") {
@@ -408,22 +613,232 @@ function isPlainObject(value) {
408
613
  return !!value && typeof value === "object" && !Array.isArray(value);
409
614
  }
410
615
 
616
+ // src/components/search-and-filter/components/filter/active-filters.tsx
617
+ import * as React4 from "react";
618
+ import { Chip as Chip2, Stack as Stack2 } from "@elementor/ui";
619
+ import { __ as __3 } from "@wordpress/i18n";
620
+
621
+ // src/components/search-and-filter/components/filter/clear-icon-button.tsx
622
+ import * as React2 from "react";
623
+ import { BrushBigIcon } from "@elementor/icons";
624
+ import { Box, IconButton, styled, Tooltip } from "@elementor/ui";
625
+ var ClearIconButton = ({ tooltipText, sx }) => {
626
+ const {
627
+ filters: { onClearFilter }
628
+ } = useSearchAndFilters();
629
+ 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" }))));
630
+ };
631
+ var CustomIconButton = styled(IconButton)(({ theme }) => ({
632
+ "&.Mui-disabled": {
633
+ pointerEvents: "auto",
634
+ "&:hover": {
635
+ color: theme.palette.action.disabled
636
+ }
637
+ }
638
+ }));
639
+
640
+ // src/components/search-and-filter/components/filter/filter-list.tsx
641
+ import * as React3 from "react";
642
+ import { Checkbox, Chip, MenuItem, MenuList, Stack, Typography } from "@elementor/ui";
643
+ import { __ as __2 } from "@wordpress/i18n";
644
+ var filterConfig = {
645
+ unused: __2("Unused", "elementor"),
646
+ empty: __2("Empty", "elementor"),
647
+ onThisPage: __2("On this page", "elementor")
648
+ };
649
+ var FilterList = () => {
650
+ const {
651
+ filters: { filters, setFilters }
652
+ } = useSearchAndFilters();
653
+ const filteredCssClass = useFilteredCssClassUsage();
654
+ const handleOnClick = (value) => {
655
+ setFilters((prev) => ({ ...prev, [value]: !prev[value] }));
656
+ };
657
+ return /* @__PURE__ */ React3.createElement(MenuList, null, /* @__PURE__ */ React3.createElement(MenuItem, { onClick: () => handleOnClick("unused") }, /* @__PURE__ */ React3.createElement(
658
+ LabeledCheckbox,
659
+ {
660
+ label: filterConfig.unused,
661
+ checked: filters.unused,
662
+ suffix: /* @__PURE__ */ React3.createElement(Chip, { size: "tiny", sx: { ml: "auto" }, label: filteredCssClass.unused.length })
663
+ }
664
+ )), /* @__PURE__ */ React3.createElement(MenuItem, { onClick: () => handleOnClick("empty") }, /* @__PURE__ */ React3.createElement(
665
+ LabeledCheckbox,
666
+ {
667
+ label: filterConfig.empty,
668
+ checked: filters.empty,
669
+ suffix: /* @__PURE__ */ React3.createElement(Chip, { size: "tiny", sx: { ml: "auto" }, label: filteredCssClass.empty.length })
670
+ }
671
+ )), /* @__PURE__ */ React3.createElement(MenuItem, { onClick: () => handleOnClick("onThisPage") }, /* @__PURE__ */ React3.createElement(
672
+ LabeledCheckbox,
673
+ {
674
+ label: filterConfig.onThisPage,
675
+ checked: filters.onThisPage,
676
+ suffix: /* @__PURE__ */ React3.createElement(Chip, { size: "tiny", sx: { ml: "auto" }, label: filteredCssClass.onThisPage.length })
677
+ }
678
+ )));
679
+ };
680
+ var LabeledCheckbox = ({ label, suffix, checked }) => /* @__PURE__ */ React3.createElement(Stack, { direction: "row", alignItems: "center", gap: 0.5, flex: 1 }, /* @__PURE__ */ React3.createElement(
681
+ Checkbox,
682
+ {
683
+ size: "small",
684
+ checked,
685
+ sx: {
686
+ padding: 0,
687
+ color: "text.tertiary",
688
+ "&.Mui-checked": {
689
+ color: "text.tertiary"
690
+ }
691
+ }
692
+ }
693
+ ), /* @__PURE__ */ React3.createElement(Typography, { variant: "caption", sx: { color: "text.secondary" } }, label), suffix);
694
+
695
+ // src/components/search-and-filter/components/filter/active-filters.tsx
696
+ var ActiveFilters = () => {
697
+ const {
698
+ filters: { filters, setFilters }
699
+ } = useSearchAndFilters();
700
+ const handleRemove = (key) => {
701
+ setFilters((prev) => ({ ...prev, [key]: false }));
702
+ };
703
+ const activeKeys = Object.keys(filters).filter((key) => filters[key]);
704
+ const showClearIcon = activeKeys.length > 0;
705
+ 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(
706
+ Chip2,
707
+ {
708
+ key,
709
+ label: filterConfig[key],
710
+ onDelete: () => handleRemove(key),
711
+ sx: chipSx,
712
+ size: "tiny"
713
+ }
714
+ ))), showClearIcon && /* @__PURE__ */ React4.createElement(
715
+ ClearIconButton,
716
+ {
717
+ tooltipText: __3("Clear Filters", "elementor"),
718
+ sx: { margin: "0 0 auto auto" }
719
+ }
720
+ ));
721
+ };
722
+ var chipSx = {
723
+ "& .MuiChip-deleteIcon": {
724
+ display: "none",
725
+ transition: "opacity 0.2s"
726
+ },
727
+ "&:hover .MuiChip-deleteIcon": {
728
+ display: "block"
729
+ }
730
+ };
731
+
732
+ // src/components/search-and-filter/components/filter/css-class-filter.tsx
733
+ import * as React5 from "react";
734
+ import { PopoverBody, PopoverHeader } from "@elementor/editor-ui";
735
+ import { FilterIcon } from "@elementor/icons";
736
+ import { bindPopover, bindToggle, Divider, Popover, ToggleButton, Tooltip as Tooltip2, usePopupState } from "@elementor/ui";
737
+ import { __ as __4 } from "@wordpress/i18n";
738
+ var CssClassFilter = () => {
739
+ const {
740
+ filters: { filters }
741
+ } = useSearchAndFilters();
742
+ const popupState = usePopupState({
743
+ variant: "popover",
744
+ disableAutoFocus: true
745
+ });
746
+ const showCleanIcon = Object.values(filters).some((value) => value);
747
+ return /* @__PURE__ */ React5.createElement(React5.Fragment, null, /* @__PURE__ */ React5.createElement(Tooltip2, { title: __4("Filters", "elementor"), placement: "top" }, /* @__PURE__ */ React5.createElement(
748
+ ToggleButton,
749
+ {
750
+ value: "filter",
751
+ size: "tiny",
752
+ selected: popupState.isOpen,
753
+ ...bindToggle(popupState)
754
+ },
755
+ /* @__PURE__ */ React5.createElement(FilterIcon, { fontSize: "tiny" })
756
+ )), /* @__PURE__ */ React5.createElement(
757
+ Popover,
758
+ {
759
+ sx: {
760
+ maxWidth: "344px"
761
+ },
762
+ anchorOrigin: {
763
+ vertical: "top",
764
+ horizontal: "right"
765
+ },
766
+ transformOrigin: {
767
+ vertical: "top",
768
+ horizontal: -21
769
+ },
770
+ ...bindPopover(popupState)
771
+ },
772
+ /* @__PURE__ */ React5.createElement(
773
+ PopoverHeader,
774
+ {
775
+ actions: showCleanIcon ? [
776
+ /* @__PURE__ */ React5.createElement(
777
+ ClearIconButton,
778
+ {
779
+ key: "clear-all-button",
780
+ tooltipText: __4("Clear all", "elementor")
781
+ }
782
+ )
783
+ ] : [],
784
+ onClose: popupState.close,
785
+ title: __4("Filters", "elementor"),
786
+ icon: /* @__PURE__ */ React5.createElement(FilterIcon, { fontSize: "tiny" })
787
+ }
788
+ ),
789
+ /* @__PURE__ */ React5.createElement(
790
+ Divider,
791
+ {
792
+ sx: {
793
+ borderWidth: "1px 0 0 0"
794
+ }
795
+ }
796
+ ),
797
+ /* @__PURE__ */ React5.createElement(PopoverBody, { width: 344, height: 125 }, /* @__PURE__ */ React5.createElement(FilterList, null))
798
+ ));
799
+ };
800
+
801
+ // src/components/search-and-filter/components/search/class-manager-search.tsx
802
+ import * as React6 from "react";
803
+ import { SearchIcon } from "@elementor/icons";
804
+ import { Box as Box2, InputAdornment, Stack as Stack3, TextField } from "@elementor/ui";
805
+ import { __ as __5 } from "@wordpress/i18n";
806
+ var ClassManagerSearch = () => {
807
+ const {
808
+ search: { inputValue, handleChange }
809
+ } = useSearchAndFilters();
810
+ return /* @__PURE__ */ React6.createElement(Stack3, { direction: "row", gap: 0.5, sx: { width: "100%" } }, /* @__PURE__ */ React6.createElement(Box2, { sx: { flexGrow: 1 } }, /* @__PURE__ */ React6.createElement(
811
+ TextField,
812
+ {
813
+ role: "search",
814
+ fullWidth: true,
815
+ size: "tiny",
816
+ value: inputValue,
817
+ placeholder: __5("Search", "elementor"),
818
+ onChange: (e) => handleChange(e.target.value),
819
+ InputProps: {
820
+ startAdornment: /* @__PURE__ */ React6.createElement(InputAdornment, { position: "start" }, /* @__PURE__ */ React6.createElement(SearchIcon, { fontSize: "tiny" }))
821
+ }
822
+ }
823
+ )));
824
+ };
825
+
411
826
  // src/components/class-manager/class-manager-introduction.tsx
412
- import * as React from "react";
413
- import { useState } from "react";
827
+ import * as React7 from "react";
828
+ import { useState as useState2 } from "react";
414
829
  import { useSuppressedMessage } from "@elementor/editor-current-user";
415
830
  import { IntroductionModal } from "@elementor/editor-ui";
416
- import { Box, Image, Typography } from "@elementor/ui";
417
- import { __ as __2 } from "@wordpress/i18n";
831
+ import { Box as Box3, Image, Typography as Typography2 } from "@elementor/ui";
832
+ import { __ as __6 } from "@wordpress/i18n";
418
833
  var MESSAGE_KEY = "global-class-manager";
419
834
  var ClassManagerIntroduction = () => {
420
835
  const [isMessageSuppressed, suppressMessage] = useSuppressedMessage(MESSAGE_KEY);
421
- const [shouldShowIntroduction, setShouldShowIntroduction] = useState(!isMessageSuppressed);
422
- return /* @__PURE__ */ React.createElement(
836
+ const [shouldShowIntroduction, setShouldShowIntroduction] = useState2(!isMessageSuppressed);
837
+ return /* @__PURE__ */ React7.createElement(
423
838
  IntroductionModal,
424
839
  {
425
840
  open: shouldShowIntroduction,
426
- title: __2("Class Manager", "elementor"),
841
+ title: __6("Class Manager", "elementor"),
427
842
  handleClose: (shouldShowAgain) => {
428
843
  if (!shouldShowAgain) {
429
844
  suppressMessage();
@@ -431,7 +846,7 @@ var ClassManagerIntroduction = () => {
431
846
  setShouldShowIntroduction(false);
432
847
  }
433
848
  },
434
- /* @__PURE__ */ React.createElement(
849
+ /* @__PURE__ */ React7.createElement(
435
850
  Image,
436
851
  {
437
852
  sx: { width: "100%", aspectRatio: "16 / 9" },
@@ -439,39 +854,19 @@ var ClassManagerIntroduction = () => {
439
854
  alt: ""
440
855
  }
441
856
  ),
442
- /* @__PURE__ */ React.createElement(IntroductionContent, null)
857
+ /* @__PURE__ */ React7.createElement(IntroductionContent, null)
443
858
  );
444
859
  };
445
860
  var IntroductionContent = () => {
446
- return /* @__PURE__ */ React.createElement(Box, { p: 3 }, /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, __2(
861
+ return /* @__PURE__ */ React7.createElement(Box3, { p: 3 }, /* @__PURE__ */ React7.createElement(Typography2, { variant: "body2" }, __6(
447
862
  "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.",
448
863
  "elementor"
449
- )), /* @__PURE__ */ React.createElement("br", null), /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, __2(
864
+ )), /* @__PURE__ */ React7.createElement("br", null), /* @__PURE__ */ React7.createElement(Typography2, { variant: "body2" }, __6(
450
865
  "Remember, when editing an item within a specific class, any changes you make will apply across all elements in that class.",
451
866
  "elementor"
452
867
  )));
453
868
  };
454
869
 
455
- // src/components/class-manager/class-manager-search.tsx
456
- import * as React2 from "react";
457
- import { SearchIcon } from "@elementor/icons";
458
- import { Box as Box2, Grid, InputAdornment, Stack, TextField } from "@elementor/ui";
459
- import { __ as __3 } from "@wordpress/i18n";
460
- var ClassManagerSearch = ({ searchValue, onChange }) => /* @__PURE__ */ React2.createElement(Grid, { item: true, xs: 6, px: 2, pb: 1 }, /* @__PURE__ */ React2.createElement(Stack, { direction: "row", gap: 0.5, sx: { width: "100%" } }, /* @__PURE__ */ React2.createElement(Box2, { sx: { flexGrow: 1 } }, /* @__PURE__ */ React2.createElement(
461
- TextField,
462
- {
463
- role: "search",
464
- fullWidth: true,
465
- size: "tiny",
466
- value: searchValue,
467
- placeholder: __3("Search", "elementor"),
468
- onChange: (e) => onChange(e.target.value),
469
- InputProps: {
470
- startAdornment: /* @__PURE__ */ React2.createElement(InputAdornment, { position: "start" }, /* @__PURE__ */ React2.createElement(SearchIcon, { fontSize: "tiny" }))
471
- }
472
- }
473
- ))));
474
-
475
870
  // src/components/class-manager/delete-class.ts
476
871
  import { getCurrentDocument, getV1DocumentsManager } from "@elementor/editor-documents";
477
872
  import { __privateRunCommand as runCommand } from "@elementor/editor-v1-adapters";
@@ -498,22 +893,16 @@ var reloadDocument = () => {
498
893
  };
499
894
 
500
895
  // src/components/class-manager/flipped-color-swatch-icon.tsx
501
- import * as React3 from "react";
896
+ import * as React8 from "react";
502
897
  import { ColorSwatchIcon } from "@elementor/icons";
503
- var FlippedColorSwatchIcon = ({ sx, ...props }) => /* @__PURE__ */ React3.createElement(ColorSwatchIcon, { sx: { transform: "rotate(90deg)", ...sx }, ...props });
898
+ var FlippedColorSwatchIcon = ({ sx, ...props }) => /* @__PURE__ */ React8.createElement(ColorSwatchIcon, { sx: { transform: "rotate(90deg)", ...sx }, ...props });
504
899
 
505
900
  // src/components/class-manager/global-classes-list.tsx
506
- import * as React8 from "react";
507
- import { useEffect, useMemo } from "react";
901
+ import * as React15 from "react";
902
+ import { useEffect, useMemo as useMemo3 } from "react";
508
903
  import { __useDispatch as useDispatch } from "@elementor/store";
509
- import { List, Stack as Stack4, styled as styled3, Typography as Typography5 } from "@elementor/ui";
510
- import { __ as __7 } from "@wordpress/i18n";
511
-
512
- // src/hooks/use-classes-order.ts
513
- import { __useSelector as useSelector2 } from "@elementor/store";
514
- var useClassesOrder = () => {
515
- return useSelector2(selectOrder);
516
- };
904
+ import { List, Stack as Stack7, styled as styled6, Typography as Typography7 } from "@elementor/ui";
905
+ import { __ as __12 } from "@wordpress/i18n";
517
906
 
518
907
  // src/hooks/use-ordered-classes.ts
519
908
  import { __useSelector as useSelector3 } from "@elementor/store";
@@ -522,31 +911,281 @@ var useOrderedClasses = () => {
522
911
  };
523
912
 
524
913
  // src/components/class-manager/class-item.tsx
525
- import * as React6 from "react";
526
- import { useRef } from "react";
527
- import { EXPERIMENTAL_FEATURES } from "@elementor/editor-editing-panel";
914
+ import * as React13 from "react";
915
+ import { useRef, useState as useState4 } from "react";
528
916
  import { validateStyleLabel } from "@elementor/editor-styles-repository";
529
- import { EditableField, EllipsisWithTooltip, MenuListItem, useEditable, WarningInfotip } from "@elementor/editor-ui";
530
- import { isExperimentActive as isExperimentActive3 } from "@elementor/editor-v1-adapters";
917
+ import { EditableField, EllipsisWithTooltip as EllipsisWithTooltip2, MenuListItem, useEditable, WarningInfotip } from "@elementor/editor-ui";
531
918
  import { DotsVerticalIcon } from "@elementor/icons";
532
919
  import {
533
920
  bindMenu,
534
- bindTrigger,
535
- Box as Box4,
536
- IconButton,
921
+ bindTrigger as bindTrigger2,
922
+ Box as Box7,
923
+ IconButton as IconButton3,
537
924
  ListItemButton,
538
925
  Menu,
539
- Stack as Stack2,
540
- styled as styled2,
541
- Tooltip,
542
- Typography as Typography3,
543
- usePopupState
926
+ Stack as Stack5,
927
+ styled as styled5,
928
+ Tooltip as Tooltip5,
929
+ Typography as Typography5,
930
+ usePopupState as usePopupState3
544
931
  } from "@elementor/ui";
545
- import { __ as __5 } from "@wordpress/i18n";
932
+ import { __ as __10 } from "@wordpress/i18n";
933
+
934
+ // src/components/css-class-usage/components/css-class-usage-popover.tsx
935
+ import * as React9 from "react";
936
+ import { __useOpenDocumentInNewTab as useOpenDocumentInNewTab } from "@elementor/editor-documents";
937
+ import {
938
+ EllipsisWithTooltip,
939
+ PopoverBody as PopoverBody2,
940
+ PopoverHeader as PopoverHeader2,
941
+ PopoverMenuList
942
+ } from "@elementor/editor-ui";
943
+ import {
944
+ CurrentLocationIcon,
945
+ ExternalLinkIcon,
946
+ FooterTemplateIcon,
947
+ HeaderTemplateIcon,
948
+ PagesIcon,
949
+ PopupTemplateIcon,
950
+ PostTypeIcon
951
+ } from "@elementor/icons";
952
+ 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";
953
+ import { __ as __7 } from "@wordpress/i18n";
954
+
955
+ // src/hooks/use-css-class-usage-by-id.ts
956
+ var EMPTY_CLASS_USAGE = {
957
+ total: 0,
958
+ content: []
959
+ };
960
+ var useCssClassUsageByID = (id2) => {
961
+ const { data, ...rest } = useCssClassUsage();
962
+ const classData = data?.[id2] ?? EMPTY_CLASS_USAGE;
963
+ return { ...rest, data: classData };
964
+ };
965
+
966
+ // src/components/css-class-usage/components/css-class-usage-popover.tsx
967
+ var iconMapper = {
968
+ "wp-post": {
969
+ label: __7("Post", "elementor"),
970
+ icon: /* @__PURE__ */ React9.createElement(PostTypeIcon, { fontSize: "inherit" })
971
+ },
972
+ "wp-page": {
973
+ label: __7("Page", "elementor"),
974
+ icon: /* @__PURE__ */ React9.createElement(PagesIcon, { fontSize: "inherit" })
975
+ },
976
+ popup: {
977
+ label: __7("Popup", "elementor"),
978
+ icon: /* @__PURE__ */ React9.createElement(PopupTemplateIcon, { fontSize: "inherit" })
979
+ },
980
+ header: {
981
+ label: __7("Header", "elementor"),
982
+ icon: /* @__PURE__ */ React9.createElement(HeaderTemplateIcon, { fontSize: "inherit" })
983
+ },
984
+ footer: {
985
+ label: __7("Footer", "elementor"),
986
+ icon: /* @__PURE__ */ React9.createElement(FooterTemplateIcon, { fontSize: "inherit" })
987
+ }
988
+ };
989
+ var CssClassUsagePopover = ({
990
+ cssClassID,
991
+ onClose
992
+ }) => {
993
+ const { data: classUsage } = useCssClassUsageByID(cssClassID);
994
+ const onNavigate = useOpenDocumentInNewTab();
995
+ const cssClassUsageRecords = classUsage?.content.map(
996
+ ({ title, elements, pageId, type }) => ({
997
+ type: "item",
998
+ value: pageId,
999
+ label: title,
1000
+ secondaryText: elements.length.toString(),
1001
+ docType: type
1002
+ })
1003
+ ) ?? [];
1004
+ return /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(
1005
+ PopoverHeader2,
1006
+ {
1007
+ icon: /* @__PURE__ */ React9.createElement(CurrentLocationIcon, { fontSize: "tiny" }),
1008
+ 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 }))),
1009
+ onClose
1010
+ }
1011
+ ), /* @__PURE__ */ React9.createElement(Divider2, null), /* @__PURE__ */ React9.createElement(PopoverBody2, { width: 300 }, /* @__PURE__ */ React9.createElement(
1012
+ PopoverMenuList,
1013
+ {
1014
+ onSelect: (value) => onNavigate(+value),
1015
+ items: cssClassUsageRecords,
1016
+ onClose: () => {
1017
+ },
1018
+ menuListTemplate: StyledCssClassUsageItem,
1019
+ menuItemContentTemplate: (cssClassUsageRecord) => /* @__PURE__ */ React9.createElement(Stack4, { flexDirection: "row", flex: 1, alignItems: "center" }, /* @__PURE__ */ React9.createElement(Box4, { display: "flex", sx: { pr: 1 } }, /* @__PURE__ */ React9.createElement(
1020
+ Tooltip3,
1021
+ {
1022
+ disableInteractive: true,
1023
+ title: iconMapper?.[cssClassUsageRecord.docType]?.label ?? cssClassUsageRecord.docType,
1024
+ placement: "top"
1025
+ },
1026
+ /* @__PURE__ */ React9.createElement(Icon, { fontSize: "small" }, iconMapper?.[cssClassUsageRecord.docType]?.icon || /* @__PURE__ */ React9.createElement(PagesIcon, { fontSize: "inherit" }))
1027
+ )), /* @__PURE__ */ React9.createElement(Box4, { sx: { pr: 0.5, maxWidth: "173px" }, display: "flex" }, /* @__PURE__ */ React9.createElement(
1028
+ EllipsisWithTooltip,
1029
+ {
1030
+ title: cssClassUsageRecord.label,
1031
+ as: Typography3,
1032
+ variant: "caption",
1033
+ maxWidth: "173px",
1034
+ sx: {
1035
+ lineHeight: 1
1036
+ }
1037
+ }
1038
+ )), /* @__PURE__ */ React9.createElement(ExternalLinkIcon, { className: "hover-only-icon", fontSize: "tiny" }), /* @__PURE__ */ React9.createElement(
1039
+ Chip3,
1040
+ {
1041
+ sx: {
1042
+ ml: "auto"
1043
+ },
1044
+ size: "tiny",
1045
+ label: cssClassUsageRecord.secondaryText
1046
+ }
1047
+ ))
1048
+ }
1049
+ )));
1050
+ };
1051
+ var StyledCssClassUsageItem = styled2(MenuList2)(({ theme }) => ({
1052
+ "& > li": {
1053
+ display: "flex",
1054
+ cursor: "pointer",
1055
+ height: 32,
1056
+ width: "100%"
1057
+ },
1058
+ '& > [role="option"]': {
1059
+ ...theme.typography.caption,
1060
+ lineHeight: "inherit",
1061
+ padding: theme.spacing(0.5, 1, 0.5, 2),
1062
+ textOverflow: "ellipsis",
1063
+ position: "absolute",
1064
+ top: 0,
1065
+ left: 0,
1066
+ opacity: 1,
1067
+ ".hover-only-icon": {
1068
+ color: theme.palette.text.disabled,
1069
+ opacity: 0
1070
+ },
1071
+ "&:hover": {
1072
+ borderRadius: theme.spacing(0.5),
1073
+ backgroundColor: theme.palette.action.hover,
1074
+ ".hover-only-icon": {
1075
+ color: theme.palette.text.disabled,
1076
+ opacity: 1
1077
+ }
1078
+ }
1079
+ },
1080
+ width: "100%",
1081
+ position: "relative"
1082
+ }));
1083
+
1084
+ // src/components/css-class-usage/components/css-class-usage-trigger.tsx
1085
+ import * as React10 from "react";
1086
+ import { InfoAlert } from "@elementor/editor-ui";
1087
+ import { CurrentLocationIcon as CurrentLocationIcon2 } from "@elementor/icons";
1088
+ import {
1089
+ bindPopover as bindPopover2,
1090
+ bindTrigger,
1091
+ Box as Box5,
1092
+ IconButton as IconButton2,
1093
+ Infotip,
1094
+ Popover as Popover2,
1095
+ styled as styled3,
1096
+ Tooltip as Tooltip4,
1097
+ usePopupState as usePopupState2
1098
+ } from "@elementor/ui";
1099
+ import { __ as __8 } from "@wordpress/i18n";
1100
+ var CssClassUsageTrigger = ({ id: id2, onClick }) => {
1101
+ const {
1102
+ data: { total },
1103
+ isLoading
1104
+ } = useCssClassUsageByID(id2);
1105
+ const cssClassUsagePopover = usePopupState2({ variant: "popover", popupId: "css-class-usage-popover" });
1106
+ if (isLoading) {
1107
+ return null;
1108
+ }
1109
+ const WrapperComponent = total !== 0 ? TooltipWrapper : InfoAlertMessage;
1110
+ return /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(Box5, { position: "relative" }, /* @__PURE__ */ React10.createElement(WrapperComponent, { total }, /* @__PURE__ */ React10.createElement(
1111
+ CustomIconButton2,
1112
+ {
1113
+ disabled: total === 0,
1114
+ size: "tiny",
1115
+ ...bindTrigger(cssClassUsagePopover),
1116
+ onClick: (e) => {
1117
+ if (total !== 0) {
1118
+ bindTrigger(cssClassUsagePopover).onClick(e);
1119
+ onClick(id2);
1120
+ }
1121
+ }
1122
+ },
1123
+ /* @__PURE__ */ React10.createElement(CurrentLocationIcon2, { fontSize: "tiny" })
1124
+ ))), /* @__PURE__ */ React10.createElement(Box5, null, /* @__PURE__ */ React10.createElement(
1125
+ Popover2,
1126
+ {
1127
+ anchorOrigin: {
1128
+ vertical: "center",
1129
+ horizontal: "right"
1130
+ },
1131
+ transformOrigin: {
1132
+ vertical: 15,
1133
+ horizontal: -50
1134
+ },
1135
+ ...bindPopover2(cssClassUsagePopover),
1136
+ onClose: () => {
1137
+ bindPopover2(cssClassUsagePopover).onClose();
1138
+ onClick("");
1139
+ }
1140
+ },
1141
+ /* @__PURE__ */ React10.createElement(
1142
+ CssClassUsagePopover,
1143
+ {
1144
+ onClose: cssClassUsagePopover.close,
1145
+ "aria-label": "css-class-usage-popover",
1146
+ cssClassID: id2
1147
+ }
1148
+ )
1149
+ )));
1150
+ };
1151
+ var CustomIconButton2 = styled3(IconButton2)(({ theme }) => ({
1152
+ "&.Mui-disabled": {
1153
+ pointerEvents: "auto",
1154
+ // Enable hover
1155
+ "&:hover": {
1156
+ color: theme.palette.action.disabled
1157
+ // optional
1158
+ }
1159
+ },
1160
+ height: "22px",
1161
+ width: "22px"
1162
+ }));
1163
+ var TooltipWrapper = ({ children, total }) => /* @__PURE__ */ React10.createElement(
1164
+ Tooltip4,
1165
+ {
1166
+ disableInteractive: true,
1167
+ placement: "top",
1168
+ title: `${__8("Show {{number}} {{locations}}", "elementor").replace("{{number}}", total.toString()).replace(
1169
+ "{{locations}}",
1170
+ total === 1 ? __8("location", "elementor") : __8("locations", "elementor")
1171
+ )}`
1172
+ },
1173
+ /* @__PURE__ */ React10.createElement("span", null, children)
1174
+ );
1175
+ var InfoAlertMessage = ({ children }) => /* @__PURE__ */ React10.createElement(
1176
+ Infotip,
1177
+ {
1178
+ disableInteractive: true,
1179
+ placement: "top",
1180
+ color: "secondary",
1181
+ content: /* @__PURE__ */ React10.createElement(InfoAlert, { sx: { mt: 1 } }, __8("This class isn\u2019t being used yet.", "elementor"))
1182
+ },
1183
+ /* @__PURE__ */ React10.createElement("span", null, children)
1184
+ );
546
1185
 
547
1186
  // src/components/class-manager/delete-confirmation-dialog.tsx
548
- import * as React4 from "react";
549
- import { createContext, useContext, useState as useState2 } from "react";
1187
+ import * as React11 from "react";
1188
+ import { createContext as createContext2, useContext as useContext2, useState as useState3 } from "react";
550
1189
  import { AlertOctagonFilledIcon } from "@elementor/icons";
551
1190
  import {
552
1191
  Button,
@@ -555,34 +1194,50 @@ import {
555
1194
  DialogContent,
556
1195
  DialogContentText,
557
1196
  DialogTitle,
558
- Typography as Typography2
1197
+ Typography as Typography4
559
1198
  } from "@elementor/ui";
560
- import { __ as __4 } from "@wordpress/i18n";
561
- var context = createContext(null);
1199
+ import { __ as __9 } from "@wordpress/i18n";
1200
+ var context = createContext2(null);
562
1201
  var DeleteConfirmationProvider = ({ children }) => {
563
- const [dialogProps, setDialogProps] = useState2(null);
1202
+ const [dialogProps, setDialogProps] = useState3(null);
564
1203
  const openDialog = (props) => {
565
1204
  setDialogProps(props);
566
1205
  };
567
1206
  const closeDialog = () => {
568
1207
  setDialogProps(null);
569
1208
  };
570
- return /* @__PURE__ */ React4.createElement(context.Provider, { value: { openDialog, closeDialog, dialogProps } }, children, !!dialogProps && /* @__PURE__ */ React4.createElement(DeleteConfirmationDialog, { ...dialogProps }));
1209
+ return /* @__PURE__ */ React11.createElement(context.Provider, { value: { openDialog, closeDialog, dialogProps } }, children, !!dialogProps && /* @__PURE__ */ React11.createElement(DeleteConfirmationDialog, { ...dialogProps }));
571
1210
  };
572
1211
  var TITLE_ID = "delete-class-dialog";
573
1212
  var DeleteConfirmationDialog = ({ label, id: id2 }) => {
574
1213
  const { closeDialog } = useDeleteConfirmation();
1214
+ const {
1215
+ data: { total, content }
1216
+ } = useCssClassUsageByID(id2);
575
1217
  const onConfirm = () => {
576
1218
  deleteClass(id2);
577
1219
  closeDialog();
578
1220
  };
579
- return /* @__PURE__ */ React4.createElement(Dialog, { open: true, onClose: closeDialog, "aria-labelledby": TITLE_ID, maxWidth: "xs" }, /* @__PURE__ */ React4.createElement(DialogTitle, { id: TITLE_ID, display: "flex", alignItems: "center", gap: 1, sx: { lineHeight: 1 } }, /* @__PURE__ */ React4.createElement(AlertOctagonFilledIcon, { color: "error" }), __4("Delete this class?", "elementor")), /* @__PURE__ */ React4.createElement(DialogContent, null, /* @__PURE__ */ React4.createElement(DialogContentText, { variant: "body2", color: "textPrimary" }, __4("Deleting", "elementor"), /* @__PURE__ */ React4.createElement(Typography2, { variant: "subtitle2", component: "span" }, "\xA0", label, "\xA0"), __4(
580
- "will permanently remove it from your project and may affect the design across all elements using it. This action cannot be undone.",
1221
+ const text = total && content.length ? __9(
1222
+ "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.",
1223
+ "elementor"
1224
+ ).replace("%1", total.toString()).replace("%2", content.length.toString()) : __9(
1225
+ "Will permanently remove it from your project and may affect the design across all elements using it. This action cannot be undone.",
581
1226
  "elementor"
582
- ))), /* @__PURE__ */ React4.createElement(DialogActions, null, /* @__PURE__ */ React4.createElement(Button, { color: "secondary", onClick: closeDialog }, __4("Not now", "elementor")), /* @__PURE__ */ React4.createElement(Button, { variant: "contained", color: "error", onClick: onConfirm }, __4("Delete", "elementor"))));
1227
+ );
1228
+ 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(
1229
+ Button,
1230
+ {
1231
+ autoFocus: true,
1232
+ variant: "contained",
1233
+ color: "error",
1234
+ onClick: onConfirm
1235
+ },
1236
+ __9("Delete", "elementor")
1237
+ )));
583
1238
  };
584
1239
  var useDeleteConfirmation = () => {
585
- const contextValue = useContext(context);
1240
+ const contextValue = useContext2(context);
586
1241
  if (!contextValue) {
587
1242
  throw new Error("useDeleteConfirmation must be used within a DeleteConfirmationProvider");
588
1243
  }
@@ -590,18 +1245,18 @@ var useDeleteConfirmation = () => {
590
1245
  };
591
1246
 
592
1247
  // src/components/class-manager/sortable.tsx
593
- import * as React5 from "react";
1248
+ import * as React12 from "react";
594
1249
  import { GripVerticalIcon } from "@elementor/icons";
595
1250
  import {
596
- Box as Box3,
597
- styled,
1251
+ Box as Box6,
1252
+ styled as styled4,
598
1253
  UnstableSortableItem,
599
1254
  UnstableSortableProvider
600
1255
  } from "@elementor/ui";
601
- var SortableProvider = (props) => /* @__PURE__ */ React5.createElement(UnstableSortableProvider, { restrictAxis: true, variant: "static", dragPlaceholderStyle: { opacity: "1" }, ...props });
602
- var SortableTrigger = (props) => /* @__PURE__ */ React5.createElement(StyledSortableTrigger, { ...props, role: "button", className: "class-item-sortable-trigger" }, /* @__PURE__ */ React5.createElement(GripVerticalIcon, { fontSize: "tiny" }));
1256
+ var SortableProvider = (props) => /* @__PURE__ */ React12.createElement(UnstableSortableProvider, { restrictAxis: true, variant: "static", dragPlaceholderStyle: { opacity: "1" }, ...props });
1257
+ var SortableTrigger = (props) => /* @__PURE__ */ React12.createElement(StyledSortableTrigger, { ...props, role: "button", className: "class-item-sortable-trigger" }, /* @__PURE__ */ React12.createElement(GripVerticalIcon, { fontSize: "tiny" }));
603
1258
  var SortableItem = ({ children, id: id2, ...props }) => {
604
- return /* @__PURE__ */ React5.createElement(
1259
+ return /* @__PURE__ */ React12.createElement(
605
1260
  UnstableSortableItem,
606
1261
  {
607
1262
  ...props,
@@ -617,8 +1272,8 @@ var SortableItem = ({ children, id: id2, ...props }) => {
617
1272
  isDragOverlay,
618
1273
  isDragPlaceholder
619
1274
  }) => {
620
- return /* @__PURE__ */ React5.createElement(
621
- Box3,
1275
+ return /* @__PURE__ */ React12.createElement(
1276
+ Box6,
622
1277
  {
623
1278
  ...itemProps,
624
1279
  style: itemStyle,
@@ -636,37 +1291,31 @@ var SortableItem = ({ children, id: id2, ...props }) => {
636
1291
  triggerStyle,
637
1292
  isDragPlaceholder
638
1293
  }),
639
- showDropIndication && /* @__PURE__ */ React5.createElement(SortableItemIndicator, { style: dropIndicationStyle })
1294
+ showDropIndication && /* @__PURE__ */ React12.createElement(SortableItemIndicator, { style: dropIndicationStyle })
640
1295
  );
641
1296
  }
642
1297
  }
643
1298
  );
644
1299
  };
645
- var StyledSortableTrigger = styled("div")(({ theme }) => ({
1300
+ var StyledSortableTrigger = styled4("div")(({ theme }) => ({
646
1301
  position: "absolute",
647
1302
  left: 0,
648
1303
  top: "50%",
649
1304
  transform: `translate( -${theme.spacing(1.5)}, -50% )`,
650
1305
  color: theme.palette.action.active
651
1306
  }));
652
- var SortableItemIndicator = styled(Box3)`
1307
+ var SortableItemIndicator = styled4(Box6)`
653
1308
  width: 100%;
654
1309
  height: 1px;
655
1310
  background-color: ${({ theme }) => theme.palette.text.primary};
656
1311
  `;
657
1312
 
658
1313
  // src/components/class-manager/class-item.tsx
659
- var isVersion311IsActive = isExperimentActive3(EXPERIMENTAL_FEATURES.V_3_31);
660
- var ClassItem = ({
661
- id: id2,
662
- label,
663
- renameClass,
664
- selected,
665
- disabled,
666
- sortableTriggerProps,
667
- isSearchActive
668
- }) => {
1314
+ var ClassItem = ({ id: id2, label, renameClass, selected, disabled, sortableTriggerProps }) => {
669
1315
  const itemRef = useRef(null);
1316
+ const {
1317
+ search: { inputValue }
1318
+ } = useSearchAndFilters();
670
1319
  const {
671
1320
  ref: editableRef,
672
1321
  openEditMode,
@@ -678,13 +1327,14 @@ var ClassItem = ({
678
1327
  onSubmit: renameClass,
679
1328
  validation: validateLabel
680
1329
  });
1330
+ const [selectedCssUsage, setSelectedCssUsage] = useState4("");
681
1331
  const { openDialog } = useDeleteConfirmation();
682
- const popupState = usePopupState({
1332
+ const popupState = usePopupState3({
683
1333
  variant: "popover",
684
1334
  disableAutoFocus: true
685
1335
  });
686
- const isSelected = (selected || popupState.isOpen) && !disabled;
687
- return /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Stack2, { p: 0 }, /* @__PURE__ */ React6.createElement(
1336
+ const isSelected = (selectedCssUsage === id2 || selected || popupState.isOpen) && !disabled;
1337
+ return /* @__PURE__ */ React13.createElement(React13.Fragment, null, /* @__PURE__ */ React13.createElement(Stack5, { p: 0 }, /* @__PURE__ */ React13.createElement(
688
1338
  WarningInfotip,
689
1339
  {
690
1340
  open: Boolean(error),
@@ -693,13 +1343,13 @@ var ClassItem = ({
693
1343
  width: itemRef.current?.getBoundingClientRect().width,
694
1344
  offset: [0, -15]
695
1345
  },
696
- /* @__PURE__ */ React6.createElement(
1346
+ /* @__PURE__ */ React13.createElement(
697
1347
  StyledListItemButton,
698
1348
  {
699
1349
  ref: itemRef,
700
1350
  dense: true,
701
1351
  disableGutters: true,
702
- showSortIndicator: isSearchActive,
1352
+ showSortIndicator: inputValue.length >= 2,
703
1353
  showActions: isSelected || isEditing,
704
1354
  shape: "rounded",
705
1355
  onDoubleClick: openEditMode,
@@ -707,27 +1357,28 @@ var ClassItem = ({
707
1357
  disabled,
708
1358
  focusVisibleClassName: "visible-class-item"
709
1359
  },
710
- /* @__PURE__ */ React6.createElement(SortableTrigger, { ...sortableTriggerProps }),
711
- /* @__PURE__ */ React6.createElement(Indicator, { isActive: isEditing, isError: !!error }, isEditing ? /* @__PURE__ */ React6.createElement(
1360
+ /* @__PURE__ */ React13.createElement(SortableTrigger, { ...sortableTriggerProps }),
1361
+ /* @__PURE__ */ React13.createElement(Indicator, { isActive: isEditing, isError: !!error }, isEditing ? /* @__PURE__ */ React13.createElement(
712
1362
  EditableField,
713
1363
  {
714
1364
  ref: editableRef,
715
- as: Typography3,
1365
+ as: Typography5,
716
1366
  variant: "caption",
717
1367
  ...getEditableProps()
718
1368
  }
719
- ) : /* @__PURE__ */ React6.createElement(EllipsisWithTooltip, { title: label, as: Typography3, variant: "caption" })),
720
- /* @__PURE__ */ React6.createElement(
721
- Tooltip,
1369
+ ) : /* @__PURE__ */ React13.createElement(EllipsisWithTooltip2, { title: label, as: Typography5, variant: "caption" })),
1370
+ /* @__PURE__ */ React13.createElement(Box7, { className: "class-item-locator" }, /* @__PURE__ */ React13.createElement(CssClassUsageTrigger, { id: id2, onClick: setSelectedCssUsage })),
1371
+ /* @__PURE__ */ React13.createElement(
1372
+ Tooltip5,
722
1373
  {
723
1374
  placement: "top",
724
1375
  className: "class-item-more-actions",
725
- title: __5("More actions", "elementor")
1376
+ title: __10("More actions", "elementor")
726
1377
  },
727
- /* @__PURE__ */ React6.createElement(IconButton, { size: "tiny", ...bindTrigger(popupState), "aria-label": "More actions" }, /* @__PURE__ */ React6.createElement(DotsVerticalIcon, { fontSize: "tiny" }))
1378
+ /* @__PURE__ */ React13.createElement(IconButton3, { size: "tiny", ...bindTrigger2(popupState), "aria-label": "More actions" }, /* @__PURE__ */ React13.createElement(DotsVerticalIcon, { fontSize: "tiny" }))
728
1379
  )
729
1380
  )
730
- )), /* @__PURE__ */ React6.createElement(
1381
+ )), /* @__PURE__ */ React13.createElement(
731
1382
  Menu,
732
1383
  {
733
1384
  ...bindMenu(popupState),
@@ -740,7 +1391,7 @@ var ClassItem = ({
740
1391
  horizontal: "right"
741
1392
  }
742
1393
  },
743
- /* @__PURE__ */ React6.createElement(
1394
+ /* @__PURE__ */ React13.createElement(
744
1395
  MenuListItem,
745
1396
  {
746
1397
  sx: { minWidth: "160px" },
@@ -749,9 +1400,9 @@ var ClassItem = ({
749
1400
  openEditMode();
750
1401
  }
751
1402
  },
752
- /* @__PURE__ */ React6.createElement(Typography3, { variant: "caption", sx: { color: "text.primary" } }, __5("Rename", "elementor"))
1403
+ /* @__PURE__ */ React13.createElement(Typography5, { variant: "caption", sx: { color: "text.primary" } }, __10("Rename", "elementor"))
753
1404
  ),
754
- /* @__PURE__ */ React6.createElement(
1405
+ /* @__PURE__ */ React13.createElement(
755
1406
  MenuListItem,
756
1407
  {
757
1408
  onClick: () => {
@@ -759,52 +1410,40 @@ var ClassItem = ({
759
1410
  openDialog({ id: id2, label });
760
1411
  }
761
1412
  },
762
- /* @__PURE__ */ React6.createElement(Typography3, { variant: "caption", sx: { color: "error.light" } }, __5("Delete", "elementor"))
1413
+ /* @__PURE__ */ React13.createElement(Typography5, { variant: "caption", sx: { color: "error.light" } }, __10("Delete", "elementor"))
763
1414
  )
764
1415
  ));
765
1416
  };
766
- var StyledListItemButtonV2 = styled2(ListItemButton, {
1417
+ var StyledListItemButton = styled5(ListItemButton, {
767
1418
  shouldForwardProp: (prop) => !["showActions", "showSortIndicator"].includes(prop)
768
1419
  })(
769
1420
  ({ showActions, showSortIndicator }) => `
770
- min-height: 36px;
1421
+ min-height: 36px;
771
1422
 
772
- &.visible-class-item {
773
- box-shadow: none !important;
774
- }
775
- .class-item-sortable-trigger {
776
- visibility: ${showSortIndicator && showActions ? "visible" : "hidden"};
777
- }
778
- &:hover&:not(:disabled) {
779
- .class-item-sortable-trigger {
780
- visibility: ${showSortIndicator ? "visible" : "hidden"};
781
- }
782
- }
783
- `
784
- );
785
- var StyledListItemButtonV1 = styled2(ListItemButton, {
786
- shouldForwardProp: (prop) => !["showActions", "showSortIndicator"].includes(prop)
787
- })(
788
- ({ showActions }) => `
789
- min-height: 36px;
790
- &.visible-class-item {
791
- box-shadow: none !important;
792
- }
793
- .class-item-more-actions, .class-item-sortable-trigger {
794
- visibility: ${showActions ? "visible" : "hidden"};
795
- }
796
- .class-item-sortable-trigger {
797
- visibility: ${showActions ? "visible" : "hidden"};
798
- }
799
- &:hover&:not(:disabled) {
800
- .class-item-more-actions, .class-item-sortable-trigger {
801
- visibility: visible;
802
- }
803
- }
804
- `
1423
+ &.visible-class-item {
1424
+ box-shadow: none !important;
1425
+ }
1426
+
1427
+ .class-item-locator {
1428
+ visibility: hidden;
1429
+ }
1430
+
1431
+ .class-item-sortable-trigger {
1432
+ visibility: ${showSortIndicator && showActions ? "visible" : "hidden"};
1433
+ }
1434
+
1435
+ &:hover:not(:disabled) {
1436
+ .class-item-locator {
1437
+ visibility: visible;
1438
+ }
1439
+
1440
+ .class-item-sortable-trigger {
1441
+ visibility: ${showSortIndicator ? "visible" : "hidden"};
1442
+ }
1443
+ }
1444
+ `
805
1445
  );
806
- var StyledListItemButton = isVersion311IsActive ? StyledListItemButtonV2 : StyledListItemButtonV1;
807
- var Indicator = styled2(Box4, {
1446
+ var Indicator = styled5(Box7, {
808
1447
  shouldForwardProp: (prop) => !["isActive", "isError"].includes(prop)
809
1448
  })(({ theme, isActive, isError }) => ({
810
1449
  display: "flex",
@@ -833,67 +1472,125 @@ var validateLabel = (newLabel) => {
833
1472
  return result.errorMessage;
834
1473
  };
835
1474
 
836
- // src/components/class-manager/class-manager-class-not-found.tsx
837
- import * as React7 from "react";
838
- import { Box as Box5, Link, Stack as Stack3, Typography as Typography4 } from "@elementor/ui";
839
- import { __ as __6 } from "@wordpress/i18n";
840
- var CssClassNotFound = ({ onClear, searchValue }) => /* @__PURE__ */ React7.createElement(
841
- Stack3,
1475
+ // src/components/class-manager/not-found.tsx
1476
+ import * as React14 from "react";
1477
+ import { ColorSwatchIcon as ColorSwatchIcon2, PhotoIcon } from "@elementor/icons";
1478
+ import { Box as Box8, Link, Stack as Stack6, Typography as Typography6 } from "@elementor/ui";
1479
+ import { __ as __11 } from "@wordpress/i18n";
1480
+ var getNotFoundType = (searchValue, filters, filteredClasses) => {
1481
+ const searchNotFound = filteredClasses.length <= 0 && searchValue.length > 1;
1482
+ const filterNotFound = filters && filters.length === 0;
1483
+ const filterAndSearchNotFound = searchNotFound && filterNotFound;
1484
+ if (filterAndSearchNotFound) {
1485
+ return "filterAndSearch";
1486
+ }
1487
+ if (searchNotFound) {
1488
+ return "search";
1489
+ }
1490
+ if (filterNotFound) {
1491
+ return "filter";
1492
+ }
1493
+ return void 0;
1494
+ };
1495
+ var notFound = {
1496
+ filterAndSearch: {
1497
+ mainText: __11("Sorry, nothing matched.", "elementor"),
1498
+ sceneryText: __11("Try something else.", "elementor"),
1499
+ icon: /* @__PURE__ */ React14.createElement(PhotoIcon, { color: "inherit", fontSize: "large" })
1500
+ },
1501
+ search: {
1502
+ mainText: __11("Sorry, nothing matched", "elementor"),
1503
+ sceneryText: __11("Clear your input and try something else.", "elementor"),
1504
+ icon: /* @__PURE__ */ React14.createElement(PhotoIcon, { color: "inherit", fontSize: "large" })
1505
+ },
1506
+ filter: {
1507
+ mainText: __11("Sorry, nothing matched that search.", "elementor"),
1508
+ sceneryText: __11("Clear the filters and try something else.", "elementor"),
1509
+ icon: /* @__PURE__ */ React14.createElement(ColorSwatchIcon2, { color: "inherit", fontSize: "large" })
1510
+ }
1511
+ };
1512
+ var NotFound = ({ notFoundType }) => {
1513
+ const {
1514
+ search: { onClearSearch, inputValue },
1515
+ filters: { onClearFilter }
1516
+ } = useSearchAndFilters();
1517
+ switch (notFoundType) {
1518
+ case "filter":
1519
+ return /* @__PURE__ */ React14.createElement(NotFoundLayout, { ...notFound.filter, onClear: onClearFilter });
1520
+ case "search":
1521
+ return /* @__PURE__ */ React14.createElement(NotFoundLayout, { ...notFound.search, searchValue: inputValue, onClear: onClearSearch });
1522
+ case "filterAndSearch":
1523
+ return /* @__PURE__ */ React14.createElement(
1524
+ NotFoundLayout,
1525
+ {
1526
+ ...notFound.filterAndSearch,
1527
+ onClear: () => {
1528
+ onClearFilter();
1529
+ onClearSearch();
1530
+ }
1531
+ }
1532
+ );
1533
+ }
1534
+ };
1535
+ var NotFoundLayout = ({ onClear, searchValue, mainText, sceneryText, icon }) => /* @__PURE__ */ React14.createElement(
1536
+ Stack6,
842
1537
  {
843
1538
  color: "text.secondary",
844
1539
  pt: 5,
845
1540
  alignItems: "center",
846
1541
  gap: 1,
847
1542
  overflow: "hidden",
848
- maxWidth: "170px",
849
1543
  justifySelf: "center"
850
1544
  },
851
- /* @__PURE__ */ React7.createElement(FlippedColorSwatchIcon, { color: "inherit", fontSize: "large" }),
852
- /* @__PURE__ */ React7.createElement(Box5, null, /* @__PURE__ */ React7.createElement(Typography4, { align: "center", variant: "subtitle2", color: "inherit" }, __6("Sorry, nothing matched", "elementor")), /* @__PURE__ */ React7.createElement(
853
- Typography4,
1545
+ icon,
1546
+ /* @__PURE__ */ React14.createElement(
1547
+ Box8,
854
1548
  {
855
- variant: "subtitle2",
856
- color: "inherit",
857
1549
  sx: {
858
- display: "flex",
859
- width: "100%",
860
- justifyContent: "center"
1550
+ width: "100%"
861
1551
  }
862
1552
  },
863
- /* @__PURE__ */ React7.createElement("span", null, "\u201C"),
864
- /* @__PURE__ */ React7.createElement(
865
- "span",
1553
+ /* @__PURE__ */ React14.createElement(Typography6, { align: "center", variant: "subtitle2", color: "inherit" }, mainText),
1554
+ searchValue && /* @__PURE__ */ React14.createElement(
1555
+ Typography6,
866
1556
  {
867
- style: {
868
- maxWidth: "80%",
869
- overflow: "hidden",
870
- textOverflow: "ellipsis"
1557
+ variant: "subtitle2",
1558
+ color: "inherit",
1559
+ sx: {
1560
+ display: "flex",
1561
+ width: "100%",
1562
+ justifyContent: "center"
871
1563
  }
872
1564
  },
873
- searchValue
874
- ),
875
- /* @__PURE__ */ React7.createElement("span", null, "\u201D.")
876
- )),
877
- /* @__PURE__ */ React7.createElement(Typography4, { align: "center", variant: "caption", color: "inherit" }, __6("Try something else.", "elementor"), /* @__PURE__ */ React7.createElement(Link, { color: "secondary", variant: "caption", component: "button", onClick: onClear }, __6("Clear & try again", "elementor")))
1565
+ /* @__PURE__ */ React14.createElement("span", null, "\u201C"),
1566
+ /* @__PURE__ */ React14.createElement(
1567
+ "span",
1568
+ {
1569
+ style: {
1570
+ maxWidth: "80%",
1571
+ overflow: "hidden",
1572
+ textOverflow: "ellipsis"
1573
+ }
1574
+ },
1575
+ searchValue
1576
+ ),
1577
+ /* @__PURE__ */ React14.createElement("span", null, "\u201D.")
1578
+ )
1579
+ ),
1580
+ /* @__PURE__ */ React14.createElement(Typography6, { align: "center", variant: "caption", color: "inherit" }, sceneryText),
1581
+ /* @__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")))
878
1582
  );
879
1583
 
880
1584
  // src/components/class-manager/global-classes-list.tsx
881
- var GlobalClassesList = ({ disabled, searchValue, onSearch }) => {
1585
+ var GlobalClassesList = ({ disabled }) => {
1586
+ const {
1587
+ search: { debouncedValue: searchValue }
1588
+ } = useSearchAndFilters();
882
1589
  const cssClasses = useOrderedClasses();
883
1590
  const dispatch5 = useDispatch();
1591
+ const filters = useFilters();
884
1592
  const [classesOrder, reorderClasses] = useReorder();
885
- const lowercaseLabels = useMemo(
886
- () => cssClasses.map((cssClass) => ({
887
- ...cssClass,
888
- lowerLabel: cssClass.label.toLowerCase()
889
- })),
890
- [cssClasses]
891
- );
892
- const filteredClasses = useMemo(() => {
893
- return searchValue.length > 1 ? lowercaseLabels.filter(
894
- (cssClass) => cssClass.lowerLabel.toLowerCase().includes(searchValue.toLowerCase())
895
- ) : cssClasses;
896
- }, [searchValue, cssClasses, lowercaseLabels]);
1593
+ const filteredCssClasses = useFilteredCssClasses();
897
1594
  useEffect(() => {
898
1595
  const handler = (event) => {
899
1596
  if (event.key === "z" && (event.ctrlKey || event.metaKey)) {
@@ -912,13 +1609,16 @@ var GlobalClassesList = ({ disabled, searchValue, onSearch }) => {
912
1609
  return () => window.removeEventListener("keydown", handler);
913
1610
  }, [dispatch5]);
914
1611
  if (!cssClasses?.length) {
915
- return /* @__PURE__ */ React8.createElement(EmptyState, null);
1612
+ return /* @__PURE__ */ React15.createElement(EmptyState, null);
916
1613
  }
917
- return /* @__PURE__ */ React8.createElement(DeleteConfirmationProvider, null, filteredClasses.length <= 0 && searchValue.length > 1 ? /* @__PURE__ */ React8.createElement(CssClassNotFound, { onClear: () => onSearch(""), searchValue }) : /* @__PURE__ */ React8.createElement(List, { sx: { display: "flex", flexDirection: "column", gap: 0.5 } }, /* @__PURE__ */ React8.createElement(SortableProvider, { value: classesOrder, onChange: reorderClasses }, filteredClasses?.map(({ id: id2, label }) => {
918
- return /* @__PURE__ */ React8.createElement(SortableItem, { key: id2, id: id2 }, ({ isDragged, isDragPlaceholder, triggerProps, triggerStyle }) => /* @__PURE__ */ React8.createElement(
1614
+ const notFoundType = getNotFoundType(searchValue, filters, filteredCssClasses);
1615
+ if (notFoundType) {
1616
+ return /* @__PURE__ */ React15.createElement(NotFound, { notFoundType });
1617
+ }
1618
+ return /* @__PURE__ */ React15.createElement(DeleteConfirmationProvider, null, /* @__PURE__ */ React15.createElement(List, { sx: { display: "flex", flexDirection: "column", gap: 0.5 } }, /* @__PURE__ */ React15.createElement(SortableProvider, { value: classesOrder, onChange: reorderClasses }, filteredCssClasses?.map(({ id: id2, label }) => {
1619
+ return /* @__PURE__ */ React15.createElement(SortableItem, { key: id2, id: id2 }, ({ isDragged, isDragPlaceholder, triggerProps, triggerStyle }) => /* @__PURE__ */ React15.createElement(
919
1620
  ClassItem,
920
1621
  {
921
- isSearchActive: searchValue.length < 2,
922
1622
  id: id2,
923
1623
  label,
924
1624
  renameClass: (newLabel) => {
@@ -938,11 +1638,11 @@ var GlobalClassesList = ({ disabled, searchValue, onSearch }) => {
938
1638
  ));
939
1639
  }))));
940
1640
  };
941
- var EmptyState = () => /* @__PURE__ */ React8.createElement(Stack4, { alignItems: "center", gap: 1.5, pt: 10, px: 0.5, maxWidth: "260px", margin: "auto" }, /* @__PURE__ */ React8.createElement(FlippedColorSwatchIcon, { fontSize: "large" }), /* @__PURE__ */ React8.createElement(StyledHeader, { variant: "subtitle2", component: "h2", color: "text.secondary" }, __7("There are no global classes yet.", "elementor")), /* @__PURE__ */ React8.createElement(Typography5, { align: "center", variant: "caption", color: "text.secondary" }, __7(
1641
+ 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(
942
1642
  "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.",
943
1643
  "elementor"
944
1644
  )));
945
- var StyledHeader = styled3(Typography5)(({ theme, variant }) => ({
1645
+ var StyledHeader = styled6(Typography7)(({ theme, variant }) => ({
946
1646
  "&.MuiTypography-root": {
947
1647
  ...theme.typography[variant]
948
1648
  }
@@ -955,6 +1655,32 @@ var useReorder = () => {
955
1655
  };
956
1656
  return [order, reorder];
957
1657
  };
1658
+ var useFilteredCssClasses = () => {
1659
+ const cssClasses = useOrderedClasses();
1660
+ const {
1661
+ search: { debouncedValue: searchValue }
1662
+ } = useSearchAndFilters();
1663
+ const filters = useFilters();
1664
+ const lowercaseLabels = useMemo3(
1665
+ () => cssClasses.map((cssClass) => ({
1666
+ ...cssClass,
1667
+ lowerLabel: cssClass.label.toLowerCase()
1668
+ })),
1669
+ [cssClasses]
1670
+ );
1671
+ const filteredClasses = useMemo3(() => {
1672
+ if (searchValue.length > 1) {
1673
+ return lowercaseLabels.filter((cssClass) => cssClass.lowerLabel.includes(searchValue.toLowerCase()));
1674
+ }
1675
+ return cssClasses;
1676
+ }, [searchValue, cssClasses, lowercaseLabels]);
1677
+ return useMemo3(() => {
1678
+ if (filters && filters.length > 0) {
1679
+ return filteredClasses.filter((cssClass) => filters.includes(cssClass.id));
1680
+ }
1681
+ return filteredClasses;
1682
+ }, [filteredClasses, filters]);
1683
+ };
958
1684
 
959
1685
  // src/components/class-manager/panel-interactions.ts
960
1686
  function blockPanelInteractions() {
@@ -967,8 +1693,8 @@ function unblockPanelInteractions() {
967
1693
  }
968
1694
 
969
1695
  // src/components/class-manager/save-changes-dialog.tsx
970
- import * as React9 from "react";
971
- import { useState as useState3 } from "react";
1696
+ import * as React16 from "react";
1697
+ import { useState as useState5 } from "react";
972
1698
  import { AlertTriangleFilledIcon } from "@elementor/icons";
973
1699
  import {
974
1700
  Button as Button2,
@@ -979,33 +1705,32 @@ import {
979
1705
  DialogTitle as DialogTitle2
980
1706
  } from "@elementor/ui";
981
1707
  var TITLE_ID2 = "save-changes-dialog";
982
- var SaveChangesDialog = ({ children, onClose }) => /* @__PURE__ */ React9.createElement(Dialog2, { open: true, onClose, "aria-labelledby": TITLE_ID2, maxWidth: "xs" }, children);
983
- var SaveChangesDialogTitle = ({ children }) => /* @__PURE__ */ React9.createElement(DialogTitle2, { id: TITLE_ID2, display: "flex", alignItems: "center", gap: 1, sx: { lineHeight: 1 } }, /* @__PURE__ */ React9.createElement(AlertTriangleFilledIcon, { color: "secondary" }), children);
984
- var SaveChangesDialogContent = ({ children }) => /* @__PURE__ */ React9.createElement(DialogContent2, null, children);
985
- var SaveChangesDialogContentText = (props) => /* @__PURE__ */ React9.createElement(DialogContentText2, { variant: "body2", color: "textPrimary", display: "flex", flexDirection: "column", ...props });
1708
+ var SaveChangesDialog = ({ children, onClose }) => /* @__PURE__ */ React16.createElement(Dialog2, { open: true, onClose, "aria-labelledby": TITLE_ID2, maxWidth: "xs" }, children);
1709
+ 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);
1710
+ var SaveChangesDialogContent = ({ children }) => /* @__PURE__ */ React16.createElement(DialogContent2, null, children);
1711
+ var SaveChangesDialogContentText = (props) => /* @__PURE__ */ React16.createElement(DialogContentText2, { variant: "body2", color: "textPrimary", display: "flex", flexDirection: "column", ...props });
986
1712
  var SaveChangesDialogActions = ({ actions }) => {
987
- const [isConfirming, setIsConfirming] = useState3(false);
1713
+ const [isConfirming, setIsConfirming] = useState5(false);
988
1714
  const { cancel, confirm, discard } = actions;
989
1715
  const onConfirm = async () => {
990
1716
  setIsConfirming(true);
991
1717
  await confirm.action();
992
1718
  setIsConfirming(false);
993
1719
  };
994
- return /* @__PURE__ */ React9.createElement(DialogActions2, null, cancel && /* @__PURE__ */ React9.createElement(Button2, { variant: "text", color: "secondary", onClick: cancel.action }, cancel.label), discard && /* @__PURE__ */ React9.createElement(Button2, { variant: "text", color: "secondary", onClick: discard.action }, discard.label), /* @__PURE__ */ React9.createElement(Button2, { variant: "contained", color: "secondary", onClick: onConfirm, loading: isConfirming }, confirm.label));
1720
+ 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));
995
1721
  };
996
1722
  SaveChangesDialog.Title = SaveChangesDialogTitle;
997
1723
  SaveChangesDialog.Content = SaveChangesDialogContent;
998
1724
  SaveChangesDialog.ContentText = SaveChangesDialogContentText;
999
1725
  SaveChangesDialog.Actions = SaveChangesDialogActions;
1000
1726
  var useDialog = () => {
1001
- const [isOpen, setIsOpen] = useState3(false);
1727
+ const [isOpen, setIsOpen] = useState5(false);
1002
1728
  const open = () => setIsOpen(true);
1003
1729
  const close = () => setIsOpen(false);
1004
1730
  return { isOpen, open, close };
1005
1731
  };
1006
1732
 
1007
1733
  // src/components/class-manager/class-manager-panel.tsx
1008
- var isVersion311IsActive2 = isExperimentActive4(EXPERIMENTAL_FEATURES2.V_3_31);
1009
1734
  var id = "global-classes-manager";
1010
1735
  var { panel, usePanelActions } = createPanel({
1011
1736
  id,
@@ -1021,10 +1746,6 @@ var { panel, usePanelActions } = createPanel({
1021
1746
  }
1022
1747
  });
1023
1748
  function ClassManagerPanel() {
1024
- const { debouncedValue, inputValue, handleChange } = useDebounceState({
1025
- delay: 300,
1026
- initialValue: ""
1027
- });
1028
1749
  const isDirty2 = useDirtyState();
1029
1750
  const { close: closePanel } = usePanelActions();
1030
1751
  const { open: openSaveChangesDialog, close: closeSaveChangesDialog, isOpen: isSaveChangesDialogOpen } = useDialog();
@@ -1034,7 +1755,7 @@ function ClassManagerPanel() {
1034
1755
  closeSaveChangesDialog();
1035
1756
  };
1036
1757
  usePreventUnload();
1037
- return /* @__PURE__ */ React10.createElement(ThemeProvider, null, /* @__PURE__ */ React10.createElement(ErrorBoundary, { fallback: /* @__PURE__ */ React10.createElement(ErrorBoundaryFallback, null) }, /* @__PURE__ */ React10.createElement(Panel, null, /* @__PURE__ */ React10.createElement(PanelHeader, null, /* @__PURE__ */ React10.createElement(Stack5, { p: 1, pl: 2, width: "100%", direction: "row", alignItems: "center" }, /* @__PURE__ */ React10.createElement(PanelHeaderTitle, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ React10.createElement(FlippedColorSwatchIcon, { fontSize: "inherit" }), __8("Class Manager", "elementor")), /* @__PURE__ */ React10.createElement(
1758
+ 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(
1038
1759
  CloseButton,
1039
1760
  {
1040
1761
  sx: { marginLeft: "auto" },
@@ -1047,7 +1768,7 @@ function ClassManagerPanel() {
1047
1768
  closePanel();
1048
1769
  }
1049
1770
  }
1050
- ))), /* @__PURE__ */ React10.createElement(
1771
+ ))), /* @__PURE__ */ React17.createElement(
1051
1772
  PanelBody,
1052
1773
  {
1053
1774
  sx: {
@@ -1056,16 +1777,10 @@ function ClassManagerPanel() {
1056
1777
  height: "100%"
1057
1778
  }
1058
1779
  },
1059
- isVersion311IsActive2 && /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(ClassManagerSearch, { searchValue: inputValue, onChange: handleChange }), /* @__PURE__ */ React10.createElement(
1060
- Divider,
1061
- {
1062
- sx: {
1063
- borderWidth: "1px 0 0 0"
1064
- }
1065
- }
1066
- )),
1067
- /* @__PURE__ */ React10.createElement(
1068
- Box6,
1780
+ /* @__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)),
1781
+ /* @__PURE__ */ React17.createElement(Divider3, null),
1782
+ /* @__PURE__ */ React17.createElement(
1783
+ Box9,
1069
1784
  {
1070
1785
  px: 2,
1071
1786
  sx: {
@@ -1073,16 +1788,9 @@ function ClassManagerPanel() {
1073
1788
  overflowY: "auto"
1074
1789
  }
1075
1790
  },
1076
- /* @__PURE__ */ React10.createElement(
1077
- GlobalClassesList,
1078
- {
1079
- disabled: isPublishing,
1080
- searchValue: debouncedValue,
1081
- onSearch: handleChange
1082
- }
1083
- )
1791
+ /* @__PURE__ */ React17.createElement(GlobalClassesList, { disabled: isPublishing })
1084
1792
  )
1085
- ), /* @__PURE__ */ React10.createElement(PanelFooter, null, /* @__PURE__ */ React10.createElement(
1793
+ ), /* @__PURE__ */ React17.createElement(PanelFooter, null, /* @__PURE__ */ React17.createElement(
1086
1794
  Button3,
1087
1795
  {
1088
1796
  fullWidth: true,
@@ -1093,19 +1801,19 @@ function ClassManagerPanel() {
1093
1801
  disabled: !isDirty2,
1094
1802
  loading: isPublishing
1095
1803
  },
1096
- __8("Save changes", "elementor")
1097
- )))), /* @__PURE__ */ React10.createElement(ClassManagerIntroduction, null), isSaveChangesDialogOpen && /* @__PURE__ */ React10.createElement(SaveChangesDialog, null, /* @__PURE__ */ React10.createElement(DialogHeader, { onClose: closeSaveChangesDialog, logo: false }, /* @__PURE__ */ React10.createElement(SaveChangesDialog.Title, null, __8("You have unsaved changes", "elementor"))), /* @__PURE__ */ React10.createElement(SaveChangesDialog.Content, null, /* @__PURE__ */ React10.createElement(SaveChangesDialog.ContentText, null, __8("You have unsaved changes in the Class Manager.", "elementor")), /* @__PURE__ */ React10.createElement(SaveChangesDialog.ContentText, null, __8("To avoid losing your updates, save your changes before leaving.", "elementor"))), /* @__PURE__ */ React10.createElement(
1804
+ __13("Save changes", "elementor")
1805
+ ))))), /* @__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(
1098
1806
  SaveChangesDialog.Actions,
1099
1807
  {
1100
1808
  actions: {
1101
1809
  discard: {
1102
- label: __8("Discard", "elementor"),
1810
+ label: __13("Discard", "elementor"),
1103
1811
  action: () => {
1104
1812
  resetAndClosePanel();
1105
1813
  }
1106
1814
  },
1107
1815
  confirm: {
1108
- label: __8("Save & Continue", "elementor"),
1816
+ label: __13("Save & Continue", "elementor"),
1109
1817
  action: async () => {
1110
1818
  await publish();
1111
1819
  closeSaveChangesDialog();
@@ -1116,8 +1824,8 @@ function ClassManagerPanel() {
1116
1824
  }
1117
1825
  )));
1118
1826
  }
1119
- var CloseButton = ({ onClose, ...props }) => /* @__PURE__ */ React10.createElement(IconButton2, { size: "small", color: "secondary", onClick: onClose, "aria-label": "Close", ...props }, /* @__PURE__ */ React10.createElement(XIcon, { fontSize: "small" }));
1120
- var ErrorBoundaryFallback = () => /* @__PURE__ */ React10.createElement(Box6, { role: "alert", sx: { minHeight: "100%", p: 2 } }, /* @__PURE__ */ React10.createElement(Alert, { severity: "error", sx: { mb: 2, maxWidth: 400, textAlign: "center" } }, /* @__PURE__ */ React10.createElement("strong", null, __8("Something went wrong", "elementor"))));
1827
+ var CloseButton = ({ onClose, ...props }) => /* @__PURE__ */ React17.createElement(IconButton4, { size: "small", color: "secondary", onClick: onClose, "aria-label": "Close", ...props }, /* @__PURE__ */ React17.createElement(XIcon, { fontSize: "small" }));
1828
+ 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"))));
1121
1829
  var usePreventUnload = () => {
1122
1830
  const isDirty2 = useDirtyState();
1123
1831
  useEffect2(() => {
@@ -1143,13 +1851,25 @@ var usePublish = () => {
1143
1851
  }
1144
1852
  });
1145
1853
  };
1854
+ var TotalCssClassCounter = () => {
1855
+ const filters = useFilters();
1856
+ const cssClasses = useClassesOrder();
1857
+ return /* @__PURE__ */ React17.createElement(
1858
+ Chip4,
1859
+ {
1860
+ size: "small",
1861
+ label: filters ? `${filters.length} / ${cssClasses?.length}` : cssClasses?.length
1862
+ }
1863
+ );
1864
+ };
1146
1865
 
1147
1866
  // src/components/class-manager/class-manager-button.tsx
1148
1867
  var ClassManagerButton = () => {
1149
- const document = useActiveDocument();
1868
+ const document = useActiveDocument2();
1150
1869
  const { open: openPanel } = usePanelActions();
1151
1870
  const { save: saveDocument } = useActiveDocumentActions();
1152
1871
  const { open: openSaveChangesDialog, close: closeSaveChangesDialog, isOpen: isSaveChangesDialogOpen } = useDialog();
1872
+ const { prefetchClassesUsage } = usePrefetchCssClassUsage();
1153
1873
  const { userCan } = useUserStylesCapability();
1154
1874
  const isUserAllowedToUpdateClass = userCan(globalClassesStylesProvider.getKey()).update;
1155
1875
  if (!isUserAllowedToUpdateClass) {
@@ -1161,24 +1881,26 @@ var ClassManagerButton = () => {
1161
1881
  return;
1162
1882
  }
1163
1883
  openPanel();
1884
+ prefetchClassesUsage();
1164
1885
  };
1165
- return /* @__PURE__ */ React11.createElement(React11.Fragment, null, /* @__PURE__ */ React11.createElement(Tooltip2, { title: __9("Class Manager", "elementor"), placement: "top" }, /* @__PURE__ */ React11.createElement(IconButton3, { size: "tiny", onClick: handleOpenPanel, sx: { marginInlineEnd: -0.75 } }, /* @__PURE__ */ React11.createElement(FlippedColorSwatchIcon, { fontSize: "tiny" }))), isSaveChangesDialogOpen && /* @__PURE__ */ React11.createElement(SaveChangesDialog, null, /* @__PURE__ */ React11.createElement(SaveChangesDialog.Title, null, __9("You have unsaved changes", "elementor")), /* @__PURE__ */ React11.createElement(SaveChangesDialog.Content, null, /* @__PURE__ */ React11.createElement(SaveChangesDialog.ContentText, { sx: { mb: 2 } }, __9(
1886
+ 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(
1166
1887
  "To open the Class Manager, save your page first. You can't continue without saving.",
1167
1888
  "elementor"
1168
- ))), /* @__PURE__ */ React11.createElement(
1889
+ ))), /* @__PURE__ */ React18.createElement(
1169
1890
  SaveChangesDialog.Actions,
1170
1891
  {
1171
1892
  actions: {
1172
1893
  cancel: {
1173
- label: __9("Stay here", "elementor"),
1894
+ label: __14("Stay here", "elementor"),
1174
1895
  action: closeSaveChangesDialog
1175
1896
  },
1176
1897
  confirm: {
1177
- label: __9("Save & Continue", "elementor"),
1898
+ label: __14("Save & Continue", "elementor"),
1178
1899
  action: async () => {
1179
1900
  await saveDocument();
1180
1901
  closeSaveChangesDialog();
1181
1902
  openPanel();
1903
+ prefetchClassesUsage();
1182
1904
  }
1183
1905
  }
1184
1906
  }
@@ -1186,6 +1908,50 @@ var ClassManagerButton = () => {
1186
1908
  )));
1187
1909
  };
1188
1910
 
1911
+ // src/components/convert-local-class-to-global-class.tsx
1912
+ import * as React19 from "react";
1913
+ import { validateStyleLabel as validateStyleLabel2 } from "@elementor/editor-styles-repository";
1914
+ import { MenuListItem as MenuListItem2 } from "@elementor/editor-ui";
1915
+ import { Divider as Divider4 } from "@elementor/ui";
1916
+ import { __ as __15 } from "@wordpress/i18n";
1917
+ var ConvertLocalClassToGlobalClass = (props) => {
1918
+ const localStyleData = props.styleDef;
1919
+ const handleConversion = () => {
1920
+ const newClassName = createClassName(`converted-class-`);
1921
+ if (!localStyleData) {
1922
+ throw new Error("Style definition is required for converting local class to global class.");
1923
+ }
1924
+ const newId = globalClassesStylesProvider.actions.create?.(newClassName, localStyleData.variants);
1925
+ if (newId) {
1926
+ props.successCallback(newId);
1927
+ }
1928
+ };
1929
+ return /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement(
1930
+ MenuListItem2,
1931
+ {
1932
+ disabled: !props.canConvert,
1933
+ onClick: handleConversion,
1934
+ dense: true,
1935
+ sx: {
1936
+ "&.Mui-focusVisible": {
1937
+ border: "none",
1938
+ boxShadow: "none !important",
1939
+ backgroundColor: "transparent"
1940
+ }
1941
+ }
1942
+ },
1943
+ __15("Convert to global class", "elementor")
1944
+ ), /* @__PURE__ */ React19.createElement(Divider4, null));
1945
+ };
1946
+ function createClassName(prefix) {
1947
+ let i = 1;
1948
+ let newClassName = `${prefix}${i}`;
1949
+ while (!validateStyleLabel2(newClassName, "create").isValid) {
1950
+ newClassName = `${prefix}${++i}`;
1951
+ }
1952
+ return newClassName;
1953
+ }
1954
+
1189
1955
  // src/components/populate-store.tsx
1190
1956
  import { useEffect as useEffect3 } from "react";
1191
1957
  import { __useDispatch as useDispatch2 } from "@elementor/store";
@@ -1251,6 +2017,10 @@ function init() {
1251
2017
  id: "global-classes-populate-store",
1252
2018
  component: PopulateStore
1253
2019
  });
2020
+ injectIntoCssClassConvert({
2021
+ id: "global-classes-convert-from-local-class",
2022
+ component: ConvertLocalClassToGlobalClass
2023
+ });
1254
2024
  injectIntoClassSelectorActions({
1255
2025
  id: "global-classes-manager-button",
1256
2026
  component: ClassManagerButton