@elementor/editor-global-classes 0.22.2 → 3.32.0-21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +0 -21
- package/dist/index.js +1069 -327
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1049 -279
- package/dist/index.mjs.map +1 -1
- package/package.json +18 -18
- package/src/api.ts +14 -2
- package/src/components/class-manager/class-item.tsx +40 -65
- package/src/components/class-manager/class-manager-button.tsx +4 -0
- package/src/components/class-manager/class-manager-panel.tsx +82 -74
- package/src/components/class-manager/delete-confirmation-dialog.tsx +26 -6
- package/src/components/class-manager/global-classes-list.tsx +76 -57
- package/src/components/class-manager/not-found.tsx +138 -0
- package/src/components/convert-local-class-to-global-class.tsx +62 -0
- package/src/components/css-class-usage/components/css-class-usage-popover.tsx +169 -0
- package/src/components/css-class-usage/components/css-class-usage-trigger.tsx +116 -0
- package/src/components/css-class-usage/components/index.ts +2 -0
- package/src/components/css-class-usage/types.ts +19 -0
- package/src/components/css-class-usage/utils.ts +10 -0
- package/src/components/search-and-filter/components/filter/active-filters.tsx +54 -0
- package/src/components/search-and-filter/components/filter/clear-icon-button.tsx +31 -0
- package/src/components/search-and-filter/components/filter/css-class-filter.tsx +74 -0
- package/src/components/search-and-filter/components/filter/filter-list.tsx +77 -0
- package/src/components/{class-manager → search-and-filter/components/search}/class-manager-search.tsx +12 -11
- package/src/components/search-and-filter/context.tsx +78 -0
- package/src/global-classes-styles-provider.ts +13 -8
- package/src/hooks/use-css-class-usage-by-id.ts +15 -0
- package/src/hooks/use-css-class-usage.ts +13 -0
- package/src/hooks/use-empty-css-class.ts +12 -0
- package/src/hooks/use-filtered-css-class-usage.tsx +67 -0
- package/src/hooks/use-filters.ts +30 -0
- package/src/hooks/use-prefetch-css-class-usage.ts +16 -0
- package/src/init.ts +11 -1
- package/src/store.ts +23 -6
- package/src/components/class-manager/class-manager-class-not-found.tsx +0 -56
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/editor-global-classes",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.32.0-21",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Elementor Team",
|
|
6
6
|
"homepage": "https://elementor.com/",
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
},
|
|
19
19
|
"repository": {
|
|
20
20
|
"type": "git",
|
|
21
|
-
"url": "git+https://github.com/elementor/elementor
|
|
21
|
+
"url": "git+https://github.com/elementor/elementor.git",
|
|
22
22
|
"directory": "packages/core/editor-global-classes"
|
|
23
23
|
},
|
|
24
24
|
"bugs": {
|
|
25
|
-
"url": "https://github.com/elementor/elementor
|
|
25
|
+
"url": "https://github.com/elementor/elementor/issues"
|
|
26
26
|
},
|
|
27
27
|
"publishConfig": {
|
|
28
28
|
"access": "public"
|
|
@@ -39,22 +39,22 @@
|
|
|
39
39
|
"dev": "tsup --config=../../tsup.dev.ts"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@elementor/editor": "0
|
|
43
|
-
"@elementor/editor-current-user": "
|
|
44
|
-
"@elementor/editor-documents": "
|
|
45
|
-
"@elementor/editor-editing-panel": "
|
|
46
|
-
"@elementor/editor-panels": "
|
|
47
|
-
"@elementor/editor-props": "
|
|
48
|
-
"@elementor/editor-styles": "
|
|
49
|
-
"@elementor/editor-styles-repository": "
|
|
50
|
-
"@elementor/editor-ui": "
|
|
51
|
-
"@elementor/editor-v1-adapters": "
|
|
52
|
-
"@elementor/http-client": "
|
|
42
|
+
"@elementor/editor": "3.32.0-21",
|
|
43
|
+
"@elementor/editor-current-user": "3.32.0-21",
|
|
44
|
+
"@elementor/editor-documents": "3.32.0-21",
|
|
45
|
+
"@elementor/editor-editing-panel": "3.32.0-21",
|
|
46
|
+
"@elementor/editor-panels": "3.32.0-21",
|
|
47
|
+
"@elementor/editor-props": "3.32.0-21",
|
|
48
|
+
"@elementor/editor-styles": "3.32.0-21",
|
|
49
|
+
"@elementor/editor-styles-repository": "3.32.0-21",
|
|
50
|
+
"@elementor/editor-ui": "3.32.0-21",
|
|
51
|
+
"@elementor/editor-v1-adapters": "3.32.0-21",
|
|
52
|
+
"@elementor/http-client": "3.32.0-21",
|
|
53
53
|
"@elementor/icons": "1.46.0",
|
|
54
|
-
"@elementor/query": "
|
|
55
|
-
"@elementor/store": "
|
|
56
|
-
"@elementor/ui": "1.36.
|
|
57
|
-
"@elementor/utils": "
|
|
54
|
+
"@elementor/query": "3.32.0-21",
|
|
55
|
+
"@elementor/store": "3.32.0-21",
|
|
56
|
+
"@elementor/ui": "1.36.2",
|
|
57
|
+
"@elementor/utils": "3.32.0-21",
|
|
58
58
|
"@wordpress/i18n": "^5.13.0"
|
|
59
59
|
},
|
|
60
60
|
"peerDependencies": {
|
package/src/api.ts
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import { type StyleDefinition, type StyleDefinitionID, type StyleDefinitionsMap } from '@elementor/editor-styles';
|
|
2
2
|
import { type HttpResponse, httpService } from '@elementor/http-client';
|
|
3
3
|
|
|
4
|
+
import { type CssClassUsage } from './components/css-class-usage/types';
|
|
4
5
|
import { type GlobalClasses } from './store';
|
|
5
6
|
|
|
6
7
|
const RESOURCE_URL = '/global-classes';
|
|
8
|
+
const BASE_URL = 'elementor/v1';
|
|
9
|
+
const RESOURCE_USAGE_URL = `${ RESOURCE_URL }/usage`;
|
|
7
10
|
|
|
8
|
-
|
|
11
|
+
type GlobalClassesUsageResponse = HttpResponse< CssClassUsage >;
|
|
12
|
+
|
|
13
|
+
export type GlobalClassesGetAllResponse = HttpResponse<
|
|
14
|
+
StyleDefinitionsMap,
|
|
15
|
+
{
|
|
16
|
+
order: StyleDefinition[ 'id' ][];
|
|
17
|
+
}
|
|
18
|
+
>;
|
|
9
19
|
|
|
10
20
|
type UpdatePayload = GlobalClasses & {
|
|
11
21
|
changes: {
|
|
@@ -18,8 +28,10 @@ type UpdatePayload = GlobalClasses & {
|
|
|
18
28
|
export type ApiContext = 'preview' | 'frontend';
|
|
19
29
|
|
|
20
30
|
export const apiClient = {
|
|
31
|
+
usage: () => httpService().get< GlobalClassesUsageResponse >( `${ BASE_URL }${ RESOURCE_USAGE_URL }` ),
|
|
32
|
+
|
|
21
33
|
all: ( context: ApiContext = 'preview' ) =>
|
|
22
|
-
httpService().get< GlobalClassesGetAllResponse >(
|
|
34
|
+
httpService().get< GlobalClassesGetAllResponse >( `${ BASE_URL }${ RESOURCE_URL }`, {
|
|
23
35
|
params: { context },
|
|
24
36
|
} ),
|
|
25
37
|
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { useRef } from 'react';
|
|
3
|
-
import { EXPERIMENTAL_FEATURES } from '@elementor/editor-editing-panel';
|
|
2
|
+
import { useRef, useState } from 'react';
|
|
4
3
|
import { validateStyleLabel } from '@elementor/editor-styles-repository';
|
|
5
4
|
import { EditableField, EllipsisWithTooltip, MenuListItem, useEditable, WarningInfotip } from '@elementor/editor-ui';
|
|
6
|
-
import { isExperimentActive } from '@elementor/editor-v1-adapters';
|
|
7
5
|
import { DotsVerticalIcon } from '@elementor/icons';
|
|
8
6
|
import {
|
|
9
7
|
bindMenu,
|
|
@@ -22,11 +20,11 @@ import {
|
|
|
22
20
|
} from '@elementor/ui';
|
|
23
21
|
import { __ } from '@wordpress/i18n';
|
|
24
22
|
|
|
23
|
+
import { CssClassUsageTrigger } from '../css-class-usage/components';
|
|
24
|
+
import { useSearchAndFilters } from '../search-and-filter/context';
|
|
25
25
|
import { useDeleteConfirmation } from './delete-confirmation-dialog';
|
|
26
26
|
import { SortableTrigger, type SortableTriggerProps } from './sortable';
|
|
27
27
|
|
|
28
|
-
const isVersion311IsActive = isExperimentActive( EXPERIMENTAL_FEATURES.V_3_31 );
|
|
29
|
-
|
|
30
28
|
type ClassItemProps = React.PropsWithChildren< {
|
|
31
29
|
id: string;
|
|
32
30
|
label: string;
|
|
@@ -34,20 +32,13 @@ type ClassItemProps = React.PropsWithChildren< {
|
|
|
34
32
|
selected?: boolean;
|
|
35
33
|
disabled?: boolean;
|
|
36
34
|
sortableTriggerProps: SortableTriggerProps;
|
|
37
|
-
isSearchActive: boolean;
|
|
38
35
|
} >;
|
|
39
36
|
|
|
40
|
-
export const ClassItem = ( {
|
|
41
|
-
id,
|
|
42
|
-
label,
|
|
43
|
-
renameClass,
|
|
44
|
-
selected,
|
|
45
|
-
disabled,
|
|
46
|
-
sortableTriggerProps,
|
|
47
|
-
isSearchActive,
|
|
48
|
-
}: ClassItemProps ) => {
|
|
37
|
+
export const ClassItem = ( { id, label, renameClass, selected, disabled, sortableTriggerProps }: ClassItemProps ) => {
|
|
49
38
|
const itemRef = useRef< HTMLElement >( null );
|
|
50
|
-
|
|
39
|
+
const {
|
|
40
|
+
search: { inputValue },
|
|
41
|
+
} = useSearchAndFilters();
|
|
51
42
|
const {
|
|
52
43
|
ref: editableRef,
|
|
53
44
|
openEditMode,
|
|
@@ -59,7 +50,7 @@ export const ClassItem = ( {
|
|
|
59
50
|
onSubmit: renameClass,
|
|
60
51
|
validation: validateLabel,
|
|
61
52
|
} );
|
|
62
|
-
|
|
53
|
+
const [ selectedCssUsage, setSelectedCssUsage ] = useState( '' );
|
|
63
54
|
const { openDialog } = useDeleteConfirmation();
|
|
64
55
|
|
|
65
56
|
const popupState = usePopupState( {
|
|
@@ -67,7 +58,8 @@ export const ClassItem = ( {
|
|
|
67
58
|
disableAutoFocus: true,
|
|
68
59
|
} );
|
|
69
60
|
|
|
70
|
-
const isSelected = ( selected || popupState.isOpen ) && ! disabled;
|
|
61
|
+
const isSelected = ( selectedCssUsage === id || selected || popupState.isOpen ) && ! disabled;
|
|
62
|
+
|
|
71
63
|
return (
|
|
72
64
|
<>
|
|
73
65
|
<Stack p={ 0 }>
|
|
@@ -82,7 +74,7 @@ export const ClassItem = ( {
|
|
|
82
74
|
ref={ itemRef }
|
|
83
75
|
dense
|
|
84
76
|
disableGutters
|
|
85
|
-
showSortIndicator={
|
|
77
|
+
showSortIndicator={ inputValue.length >= 2 }
|
|
86
78
|
showActions={ isSelected || isEditing }
|
|
87
79
|
shape="rounded"
|
|
88
80
|
onDoubleClick={ openEditMode }
|
|
@@ -103,6 +95,9 @@ export const ClassItem = ( {
|
|
|
103
95
|
<EllipsisWithTooltip title={ label } as={ Typography } variant="caption" />
|
|
104
96
|
) }
|
|
105
97
|
</Indicator>
|
|
98
|
+
<Box className={ 'class-item-locator' }>
|
|
99
|
+
<CssClassUsageTrigger id={ id } onClick={ setSelectedCssUsage } />
|
|
100
|
+
</Box>
|
|
106
101
|
<Tooltip
|
|
107
102
|
placement="top"
|
|
108
103
|
className={ 'class-item-more-actions' }
|
|
@@ -152,55 +147,35 @@ export const ClassItem = ( {
|
|
|
152
147
|
);
|
|
153
148
|
};
|
|
154
149
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
// Experimental start
|
|
158
|
-
|
|
159
|
-
const StyledListItemButtonV2 = styled( ListItemButton, {
|
|
160
|
-
shouldForwardProp: ( prop: string ) => ! [ 'showActions', 'showSortIndicator' ].includes( prop ),
|
|
161
|
-
} )< ListItemButtonProps & { showActions: boolean; showSortIndicator: boolean } >(
|
|
162
|
-
( { showActions, showSortIndicator } ) =>
|
|
163
|
-
`
|
|
164
|
-
min-height: 36px;
|
|
165
|
-
|
|
166
|
-
&.visible-class-item {
|
|
167
|
-
box-shadow: none !important;
|
|
168
|
-
}
|
|
169
|
-
.class-item-sortable-trigger {
|
|
170
|
-
visibility: ${ showSortIndicator && showActions ? 'visible' : 'hidden' };
|
|
171
|
-
}
|
|
172
|
-
&:hover&:not(:disabled) {
|
|
173
|
-
.class-item-sortable-trigger {
|
|
174
|
-
visibility: ${ showSortIndicator ? 'visible' : 'hidden' };
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
`
|
|
178
|
-
);
|
|
179
|
-
|
|
180
|
-
const StyledListItemButtonV1 = styled( ListItemButton, {
|
|
150
|
+
const StyledListItemButton = styled( ListItemButton, {
|
|
181
151
|
shouldForwardProp: ( prop: string ) => ! [ 'showActions', 'showSortIndicator' ].includes( prop ),
|
|
182
152
|
} )< ListItemButtonProps & { showActions: boolean; showSortIndicator: boolean } >(
|
|
183
|
-
( { showActions } ) => `
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
153
|
+
( { showActions, showSortIndicator } ) => `
|
|
154
|
+
min-height: 36px;
|
|
155
|
+
|
|
156
|
+
&.visible-class-item {
|
|
157
|
+
box-shadow: none !important;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.class-item-locator {
|
|
161
|
+
visibility: hidden;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.class-item-sortable-trigger {
|
|
165
|
+
visibility: ${ showSortIndicator && showActions ? 'visible' : 'hidden' };
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
&:hover:not(:disabled) {
|
|
169
|
+
.class-item-locator {
|
|
170
|
+
visibility: visible;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.class-item-sortable-trigger {
|
|
174
|
+
visibility: ${ showSortIndicator ? 'visible' : 'hidden' };
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
`
|
|
200
178
|
);
|
|
201
|
-
// Experimental start
|
|
202
|
-
|
|
203
|
-
const StyledListItemButton = isVersion311IsActive ? StyledListItemButtonV2 : StyledListItemButtonV1;
|
|
204
179
|
|
|
205
180
|
const Indicator = styled( Box, {
|
|
206
181
|
shouldForwardProp: ( prop: string ) => ! [ 'isActive', 'isError' ].includes( prop ),
|
|
@@ -8,6 +8,7 @@ import { IconButton, Tooltip } from '@elementor/ui';
|
|
|
8
8
|
import { __ } from '@wordpress/i18n';
|
|
9
9
|
|
|
10
10
|
import { globalClassesStylesProvider } from '../../global-classes-styles-provider';
|
|
11
|
+
import { usePrefetchCssClassUsage } from '../../hooks/use-prefetch-css-class-usage';
|
|
11
12
|
import { usePanelActions } from './class-manager-panel';
|
|
12
13
|
import { FlippedColorSwatchIcon } from './flipped-color-swatch-icon';
|
|
13
14
|
import { SaveChangesDialog, useDialog } from './save-changes-dialog';
|
|
@@ -17,6 +18,7 @@ export const ClassManagerButton = () => {
|
|
|
17
18
|
const { open: openPanel } = usePanelActions();
|
|
18
19
|
const { save: saveDocument } = useActiveDocumentActions();
|
|
19
20
|
const { open: openSaveChangesDialog, close: closeSaveChangesDialog, isOpen: isSaveChangesDialogOpen } = useDialog();
|
|
21
|
+
const { prefetchClassesUsage } = usePrefetchCssClassUsage();
|
|
20
22
|
|
|
21
23
|
const { userCan } = useUserStylesCapability();
|
|
22
24
|
|
|
@@ -33,6 +35,7 @@ export const ClassManagerButton = () => {
|
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
openPanel();
|
|
38
|
+
prefetchClassesUsage();
|
|
36
39
|
};
|
|
37
40
|
|
|
38
41
|
return (
|
|
@@ -65,6 +68,7 @@ export const ClassManagerButton = () => {
|
|
|
65
68
|
await saveDocument();
|
|
66
69
|
closeSaveChangesDialog();
|
|
67
70
|
openPanel();
|
|
71
|
+
prefetchClassesUsage();
|
|
68
72
|
},
|
|
69
73
|
},
|
|
70
74
|
} }
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { useEffect } from 'react';
|
|
2
1
|
import * as React from 'react';
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
3
|
import { setDocumentModifiedStatus } from '@elementor/editor-documents';
|
|
4
|
-
import { EXPERIMENTAL_FEATURES } from '@elementor/editor-editing-panel';
|
|
5
4
|
import {
|
|
6
5
|
__createPanel as createPanel,
|
|
7
6
|
Panel,
|
|
@@ -11,7 +10,7 @@ import {
|
|
|
11
10
|
PanelHeaderTitle,
|
|
12
11
|
} from '@elementor/editor-panels';
|
|
13
12
|
import { ThemeProvider } from '@elementor/editor-ui';
|
|
14
|
-
import { changeEditMode
|
|
13
|
+
import { changeEditMode } from '@elementor/editor-v1-adapters';
|
|
15
14
|
import { XIcon } from '@elementor/icons';
|
|
16
15
|
import { useMutation } from '@elementor/query';
|
|
17
16
|
import { __dispatch as dispatch } from '@elementor/store';
|
|
@@ -19,6 +18,7 @@ import {
|
|
|
19
18
|
Alert,
|
|
20
19
|
Box,
|
|
21
20
|
Button,
|
|
21
|
+
Chip,
|
|
22
22
|
DialogHeader,
|
|
23
23
|
Divider,
|
|
24
24
|
ErrorBoundary,
|
|
@@ -26,22 +26,24 @@ import {
|
|
|
26
26
|
type IconButtonProps,
|
|
27
27
|
Stack,
|
|
28
28
|
} from '@elementor/ui';
|
|
29
|
-
import { useDebounceState } from '@elementor/utils';
|
|
30
29
|
import { __ } from '@wordpress/i18n';
|
|
31
30
|
|
|
31
|
+
import { useClassesOrder } from '../../hooks/use-classes-order';
|
|
32
32
|
import { useDirtyState } from '../../hooks/use-dirty-state';
|
|
33
|
+
import { useFilters } from '../../hooks/use-filters';
|
|
33
34
|
import { saveGlobalClasses } from '../../save-global-classes';
|
|
34
35
|
import { slice } from '../../store';
|
|
36
|
+
import { ActiveFilters } from '../search-and-filter/components/filter/active-filters';
|
|
37
|
+
import { CssClassFilter } from '../search-and-filter/components/filter/css-class-filter';
|
|
38
|
+
import { ClassManagerSearch } from '../search-and-filter/components/search/class-manager-search';
|
|
39
|
+
import { SearchAndFilterProvider } from '../search-and-filter/context';
|
|
35
40
|
import { ClassManagerIntroduction } from './class-manager-introduction';
|
|
36
|
-
import { ClassManagerSearch } from './class-manager-search';
|
|
37
41
|
import { hasDeletedItems, onDelete } from './delete-class';
|
|
38
42
|
import { FlippedColorSwatchIcon } from './flipped-color-swatch-icon';
|
|
39
43
|
import { GlobalClassesList } from './global-classes-list';
|
|
40
44
|
import { blockPanelInteractions, unblockPanelInteractions } from './panel-interactions';
|
|
41
45
|
import { SaveChangesDialog, useDialog } from './save-changes-dialog';
|
|
42
46
|
|
|
43
|
-
const isVersion311IsActive = isExperimentActive( EXPERIMENTAL_FEATURES.V_3_31 );
|
|
44
|
-
|
|
45
47
|
const id = 'global-classes-manager';
|
|
46
48
|
|
|
47
49
|
// We need to disable the app-bar buttons, and the elements overlays when opening the classes manager panel.
|
|
@@ -65,13 +67,7 @@ export const { panel, usePanelActions } = createPanel( {
|
|
|
65
67
|
} );
|
|
66
68
|
|
|
67
69
|
export function ClassManagerPanel() {
|
|
68
|
-
const { debouncedValue, inputValue, handleChange } = useDebounceState( {
|
|
69
|
-
delay: 300,
|
|
70
|
-
initialValue: '',
|
|
71
|
-
} );
|
|
72
|
-
|
|
73
70
|
const isDirty = useDirtyState();
|
|
74
|
-
|
|
75
71
|
const { close: closePanel } = usePanelActions();
|
|
76
72
|
const { open: openSaveChangesDialog, close: closeSaveChangesDialog, isOpen: isSaveChangesDialogOpen } = useDialog();
|
|
77
73
|
|
|
@@ -88,72 +84,72 @@ export function ClassManagerPanel() {
|
|
|
88
84
|
<ThemeProvider>
|
|
89
85
|
<ErrorBoundary fallback={ <ErrorBoundaryFallback /> }>
|
|
90
86
|
<Panel>
|
|
91
|
-
<
|
|
92
|
-
<
|
|
93
|
-
<
|
|
94
|
-
<
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
<PanelBody
|
|
112
|
-
sx={ {
|
|
113
|
-
display: 'flex',
|
|
114
|
-
flexDirection: 'column',
|
|
115
|
-
height: '100%',
|
|
116
|
-
} }
|
|
117
|
-
>
|
|
118
|
-
{ isVersion311IsActive && (
|
|
119
|
-
<>
|
|
120
|
-
<ClassManagerSearch searchValue={ inputValue } onChange={ handleChange } />
|
|
121
|
-
<Divider
|
|
122
|
-
sx={ {
|
|
123
|
-
borderWidth: '1px 0 0 0',
|
|
87
|
+
<SearchAndFilterProvider>
|
|
88
|
+
<PanelHeader>
|
|
89
|
+
<Stack p={ 1 } pl={ 2 } width="100%" direction="row" alignItems="center">
|
|
90
|
+
<Stack width="100%" direction="row" gap={ 1 }>
|
|
91
|
+
<PanelHeaderTitle sx={ { display: 'flex', alignItems: 'center', gap: 0.5 } }>
|
|
92
|
+
<FlippedColorSwatchIcon fontSize="inherit" />
|
|
93
|
+
{ __( 'Class Manager', 'elementor' ) }
|
|
94
|
+
</PanelHeaderTitle>
|
|
95
|
+
<TotalCssClassCounter />
|
|
96
|
+
</Stack>
|
|
97
|
+
<CloseButton
|
|
98
|
+
sx={ { marginLeft: 'auto' } }
|
|
99
|
+
disabled={ isPublishing }
|
|
100
|
+
onClose={ () => {
|
|
101
|
+
if ( isDirty ) {
|
|
102
|
+
openSaveChangesDialog();
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
closePanel();
|
|
124
107
|
} }
|
|
125
108
|
/>
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
<Box
|
|
130
|
-
px={ 2 }
|
|
109
|
+
</Stack>
|
|
110
|
+
</PanelHeader>
|
|
111
|
+
<PanelBody
|
|
131
112
|
sx={ {
|
|
132
|
-
|
|
133
|
-
|
|
113
|
+
display: 'flex',
|
|
114
|
+
flexDirection: 'column',
|
|
115
|
+
height: '100%',
|
|
134
116
|
} }
|
|
135
117
|
>
|
|
136
|
-
<
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
</
|
|
156
|
-
|
|
118
|
+
<Box px={ 2 } pb={ 1 }>
|
|
119
|
+
<Stack direction="row" justifyContent="spaceBetween" gap={ 0.5 } sx={ { pb: 0.5 } }>
|
|
120
|
+
<Box sx={ { flexGrow: 1 } }>
|
|
121
|
+
<ClassManagerSearch />
|
|
122
|
+
</Box>
|
|
123
|
+
<CssClassFilter />
|
|
124
|
+
</Stack>
|
|
125
|
+
<ActiveFilters />
|
|
126
|
+
</Box>
|
|
127
|
+
<Divider />
|
|
128
|
+
<Box
|
|
129
|
+
px={ 2 }
|
|
130
|
+
sx={ {
|
|
131
|
+
flexGrow: 1,
|
|
132
|
+
overflowY: 'auto',
|
|
133
|
+
} }
|
|
134
|
+
>
|
|
135
|
+
<GlobalClassesList disabled={ isPublishing } />
|
|
136
|
+
</Box>
|
|
137
|
+
</PanelBody>
|
|
138
|
+
|
|
139
|
+
<PanelFooter>
|
|
140
|
+
<Button
|
|
141
|
+
fullWidth
|
|
142
|
+
size="small"
|
|
143
|
+
color="global"
|
|
144
|
+
variant="contained"
|
|
145
|
+
onClick={ publish }
|
|
146
|
+
disabled={ ! isDirty }
|
|
147
|
+
loading={ isPublishing }
|
|
148
|
+
>
|
|
149
|
+
{ __( 'Save changes', 'elementor' ) }
|
|
150
|
+
</Button>
|
|
151
|
+
</PanelFooter>
|
|
152
|
+
</SearchAndFilterProvider>
|
|
157
153
|
</Panel>
|
|
158
154
|
</ErrorBoundary>
|
|
159
155
|
<ClassManagerIntroduction />
|
|
@@ -240,3 +236,15 @@ const usePublish = () => {
|
|
|
240
236
|
},
|
|
241
237
|
} );
|
|
242
238
|
};
|
|
239
|
+
|
|
240
|
+
const TotalCssClassCounter = () => {
|
|
241
|
+
const filters = useFilters();
|
|
242
|
+
const cssClasses = useClassesOrder();
|
|
243
|
+
|
|
244
|
+
return (
|
|
245
|
+
<Chip
|
|
246
|
+
size={ 'small' }
|
|
247
|
+
label={ filters ? `${ filters.length } / ${ cssClasses?.length }` : cssClasses?.length }
|
|
248
|
+
/>
|
|
249
|
+
);
|
|
250
|
+
};
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
} from '@elementor/ui';
|
|
14
14
|
import { __ } from '@wordpress/i18n';
|
|
15
15
|
|
|
16
|
+
import { useCssClassUsageByID } from '../../hooks/use-css-class-usage-by-id';
|
|
16
17
|
import { deleteClass } from './delete-class';
|
|
17
18
|
|
|
18
19
|
type DeleteConfirmationDialogProps = Pick< StyleDefinition, 'id' | 'label' >;
|
|
@@ -48,12 +49,27 @@ const TITLE_ID = 'delete-class-dialog';
|
|
|
48
49
|
|
|
49
50
|
const DeleteConfirmationDialog = ( { label, id }: DeleteConfirmationDialogProps ) => {
|
|
50
51
|
const { closeDialog } = useDeleteConfirmation();
|
|
51
|
-
|
|
52
|
+
const {
|
|
53
|
+
data: { total, content },
|
|
54
|
+
} = useCssClassUsageByID( id );
|
|
52
55
|
const onConfirm = () => {
|
|
53
56
|
deleteClass( id );
|
|
54
57
|
|
|
55
58
|
closeDialog();
|
|
56
59
|
};
|
|
60
|
+
// translators: %1: total usage count, %2: number of pages
|
|
61
|
+
const text =
|
|
62
|
+
total && content.length
|
|
63
|
+
? __(
|
|
64
|
+
'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.',
|
|
65
|
+
'elementor'
|
|
66
|
+
)
|
|
67
|
+
.replace( '%1', total.toString() )
|
|
68
|
+
.replace( '%2', content.length.toString() )
|
|
69
|
+
: __(
|
|
70
|
+
'Will permanently remove it from your project and may affect the design across all elements using it. This action cannot be undone.',
|
|
71
|
+
'elementor'
|
|
72
|
+
);
|
|
57
73
|
|
|
58
74
|
return (
|
|
59
75
|
<Dialog open onClose={ closeDialog } aria-labelledby={ TITLE_ID } maxWidth="xs">
|
|
@@ -67,17 +83,21 @@ const DeleteConfirmationDialog = ( { label, id }: DeleteConfirmationDialogProps
|
|
|
67
83
|
<Typography variant="subtitle2" component="span">
|
|
68
84
|
{ label }
|
|
69
85
|
</Typography>
|
|
70
|
-
{
|
|
71
|
-
'will permanently remove it from your project and may affect the design across all elements using it. This action cannot be undone.',
|
|
72
|
-
'elementor'
|
|
73
|
-
) }
|
|
86
|
+
{ text }
|
|
74
87
|
</DialogContentText>
|
|
75
88
|
</DialogContent>
|
|
76
89
|
<DialogActions>
|
|
77
90
|
<Button color="secondary" onClick={ closeDialog }>
|
|
78
91
|
{ __( 'Not now', 'elementor' ) }
|
|
79
92
|
</Button>
|
|
80
|
-
|
|
93
|
+
|
|
94
|
+
<Button
|
|
95
|
+
// eslint-disable-next-line jsx-a11y/no-autofocus
|
|
96
|
+
autoFocus
|
|
97
|
+
variant="contained"
|
|
98
|
+
color="error"
|
|
99
|
+
onClick={ onConfirm }
|
|
100
|
+
>
|
|
81
101
|
{ __( 'Delete', 'elementor' ) }
|
|
82
102
|
</Button>
|
|
83
103
|
</DialogActions>
|