@elementor/editor-global-classes 0.7.0 → 0.8.0
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 +24 -0
- package/dist/index.js +136 -101
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +155 -120
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/components/class-manager/class-manager-panel.tsx +19 -2
- package/src/components/class-manager/global-classes-list.tsx +6 -5
- package/src/global-classes-styles-provider.ts +2 -8
- package/src/hooks/use-classes-order.ts +7 -0
- package/src/hooks/use-dirty-state.ts +7 -0
- package/src/hooks/use-ordered-classes.ts +7 -0
- package/src/publish-global-classes.ts +23 -0
- package/src/store.ts +4 -11
- package/src/sync-with-document-save.ts +4 -17
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/editor-global-classes",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Elementor Team",
|
|
6
6
|
"homepage": "https://elementor.com/",
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@elementor/editor": "0.18.0",
|
|
43
43
|
"@elementor/editor-current-user": "0.2.0",
|
|
44
|
-
"@elementor/editor-editing-panel": "1.
|
|
45
|
-
"@elementor/editor-panels": "0.
|
|
44
|
+
"@elementor/editor-editing-panel": "1.13.1",
|
|
45
|
+
"@elementor/editor-panels": "0.12.0",
|
|
46
46
|
"@elementor/editor-props": "0.9.2",
|
|
47
47
|
"@elementor/editor-styles": "0.5.7",
|
|
48
48
|
"@elementor/editor-styles-repository": "0.7.2",
|
|
@@ -3,13 +3,16 @@ import {
|
|
|
3
3
|
__createPanel as createPanel,
|
|
4
4
|
Panel,
|
|
5
5
|
PanelBody,
|
|
6
|
+
PanelFooter,
|
|
6
7
|
PanelHeader,
|
|
7
8
|
PanelHeaderTitle,
|
|
8
9
|
} from '@elementor/editor-panels';
|
|
9
10
|
import { ColorSwatchIcon, XIcon } from '@elementor/icons';
|
|
10
|
-
import { Alert, Box, ErrorBoundary, IconButton, type IconButtonProps, Stack } from '@elementor/ui';
|
|
11
|
+
import { Alert, Box, Button, ErrorBoundary, IconButton, type IconButtonProps, Stack } from '@elementor/ui';
|
|
11
12
|
import { __ } from '@wordpress/i18n';
|
|
12
13
|
|
|
14
|
+
import { useDirtyState } from '../../hooks/use-dirty-state';
|
|
15
|
+
import { publishGlobalClasses } from '../../publish-global-classes';
|
|
13
16
|
import { ClassManagerIntroduction } from './class-manager-introduction';
|
|
14
17
|
import { GlobalClassesList } from './global-classes-list';
|
|
15
18
|
|
|
@@ -18,7 +21,9 @@ export const { panel, usePanelActions } = createPanel( {
|
|
|
18
21
|
component: ClassManagerPanel,
|
|
19
22
|
} );
|
|
20
23
|
|
|
21
|
-
function ClassManagerPanel() {
|
|
24
|
+
export function ClassManagerPanel() {
|
|
25
|
+
const isDirty = useDirtyState();
|
|
26
|
+
|
|
22
27
|
return (
|
|
23
28
|
<>
|
|
24
29
|
<ErrorBoundary fallback={ <ErrorBoundaryFallback /> }>
|
|
@@ -35,6 +40,18 @@ function ClassManagerPanel() {
|
|
|
35
40
|
<PanelBody px={ 2 }>
|
|
36
41
|
<GlobalClassesList />
|
|
37
42
|
</PanelBody>
|
|
43
|
+
<PanelFooter>
|
|
44
|
+
<Button
|
|
45
|
+
fullWidth
|
|
46
|
+
size="small"
|
|
47
|
+
variant="contained"
|
|
48
|
+
color="global"
|
|
49
|
+
disabled={ ! isDirty }
|
|
50
|
+
onClick={ publishGlobalClasses }
|
|
51
|
+
>
|
|
52
|
+
{ __( 'Save changes', 'elementor' ) }
|
|
53
|
+
</Button>
|
|
54
|
+
</PanelFooter>
|
|
38
55
|
</Panel>
|
|
39
56
|
</ErrorBoundary>
|
|
40
57
|
<ClassManagerIntroduction />
|
|
@@ -25,14 +25,15 @@ import {
|
|
|
25
25
|
import { __ } from '@wordpress/i18n';
|
|
26
26
|
|
|
27
27
|
import { globalClassesStylesProvider } from '../../global-classes-styles-provider';
|
|
28
|
-
import {
|
|
28
|
+
import { useClassesOrder } from '../../hooks/use-classes-order';
|
|
29
|
+
import { useOrderedClasses } from '../../hooks/use-ordered-classes';
|
|
29
30
|
import { DeleteConfirmationProvider, useDeleteConfirmation } from './delete-confirmation-dialog';
|
|
30
31
|
import { SortableItem, SortableItemIndicator, SortableProvider } from './sortable';
|
|
31
32
|
|
|
32
33
|
export const GlobalClassesList = () => {
|
|
33
|
-
const cssClasses =
|
|
34
|
+
const cssClasses = useOrderedClasses();
|
|
34
35
|
|
|
35
|
-
const [ classesOrder, reorderClasses ] =
|
|
36
|
+
const [ classesOrder, reorderClasses ] = useReorder();
|
|
36
37
|
|
|
37
38
|
if ( ! cssClasses?.length ) {
|
|
38
39
|
return <EmptyState />;
|
|
@@ -70,8 +71,8 @@ export const GlobalClassesList = () => {
|
|
|
70
71
|
);
|
|
71
72
|
};
|
|
72
73
|
|
|
73
|
-
const
|
|
74
|
-
const order =
|
|
74
|
+
const useReorder = () => {
|
|
75
|
+
const order = useClassesOrder();
|
|
75
76
|
|
|
76
77
|
const reorder = ( newIds: StyleDefinitionID[] ) => {
|
|
77
78
|
globalClassesStylesProvider.actions.setOrder( newIds );
|
|
@@ -8,19 +8,13 @@ import {
|
|
|
8
8
|
import { __ } from '@wordpress/i18n';
|
|
9
9
|
|
|
10
10
|
import { GlobalClassLabelAlreadyExistsError } from './errors';
|
|
11
|
-
import {
|
|
12
|
-
selectClass,
|
|
13
|
-
selectGlobalClasses,
|
|
14
|
-
selectOrderedGlobalClasses,
|
|
15
|
-
slice,
|
|
16
|
-
type StateWithGlobalClasses,
|
|
17
|
-
} from './store';
|
|
11
|
+
import { selectClass, selectGlobalClasses, selectOrderedClasses, slice, type StateWithGlobalClasses } from './store';
|
|
18
12
|
|
|
19
13
|
export const globalClassesStylesProvider = {
|
|
20
14
|
key: 'global-classes',
|
|
21
15
|
priority: 30,
|
|
22
16
|
actions: {
|
|
23
|
-
get: () =>
|
|
17
|
+
get: () => selectOrderedClasses( getState() ),
|
|
24
18
|
getById: ( id ) => selectClass( getState(), id ),
|
|
25
19
|
create: ( label ) => {
|
|
26
20
|
const classes = selectGlobalClasses( getState() );
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { __dispatch as dispatch, __getState as getState } from '@elementor/store';
|
|
2
|
+
|
|
3
|
+
import { apiClient } from './api';
|
|
4
|
+
import { type GlobalClassesState, selectIsDirty, slice } from './store';
|
|
5
|
+
|
|
6
|
+
export async function publishGlobalClasses() {
|
|
7
|
+
if ( ! isDirty() ) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const state: GlobalClassesState = getState().globalClasses;
|
|
12
|
+
|
|
13
|
+
await apiClient.update( {
|
|
14
|
+
items: state.items,
|
|
15
|
+
order: state.order,
|
|
16
|
+
} );
|
|
17
|
+
|
|
18
|
+
dispatch( slice.actions.setPristine() );
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function isDirty() {
|
|
22
|
+
return selectIsDirty( getState() );
|
|
23
|
+
}
|
package/src/store.ts
CHANGED
|
@@ -9,7 +9,6 @@ import { type UpdateActionPayload } from '@elementor/editor-styles-repository';
|
|
|
9
9
|
import {
|
|
10
10
|
__createSelector as createSelector,
|
|
11
11
|
__createSlice as createSlice,
|
|
12
|
-
__useSelector as useSelector,
|
|
13
12
|
type PayloadAction,
|
|
14
13
|
type SliceState,
|
|
15
14
|
} from '@elementor/store';
|
|
@@ -58,6 +57,8 @@ export const slice = createSlice( {
|
|
|
58
57
|
},
|
|
59
58
|
setOrder( state, { payload }: PayloadAction< StyleDefinitionID[] > ) {
|
|
60
59
|
state.order = payload;
|
|
60
|
+
|
|
61
|
+
state.isDirty = true;
|
|
61
62
|
},
|
|
62
63
|
update( state, { payload }: PayloadAction< { style: UpdateActionPayload } > ) {
|
|
63
64
|
const style = state.items[ payload.style.id ];
|
|
@@ -101,11 +102,11 @@ export const slice = createSlice( {
|
|
|
101
102
|
} );
|
|
102
103
|
|
|
103
104
|
// Selectors
|
|
104
|
-
const selectOrder = ( state: SliceState< typeof slice > ) => state[ SLICE_NAME ].order;
|
|
105
|
+
export const selectOrder = ( state: SliceState< typeof slice > ) => state[ SLICE_NAME ].order;
|
|
105
106
|
|
|
106
107
|
export const selectGlobalClasses = ( state: SliceState< typeof slice > ) => state[ SLICE_NAME ].items;
|
|
107
108
|
|
|
108
|
-
export const
|
|
109
|
+
export const selectOrderedClasses = createSelector( selectGlobalClasses, selectOrder, ( items, order ) =>
|
|
109
110
|
order.map( ( id ) => items[ id ] )
|
|
110
111
|
);
|
|
111
112
|
|
|
@@ -113,11 +114,3 @@ export const selectClass = ( state: SliceState< typeof slice >, id: StyleDefinit
|
|
|
113
114
|
state[ SLICE_NAME ].items[ id ] ?? null;
|
|
114
115
|
|
|
115
116
|
export const selectIsDirty = ( state: SliceState< typeof slice > ) => state.globalClasses.isDirty;
|
|
116
|
-
|
|
117
|
-
export const useOrderedGlobalClasses = () => {
|
|
118
|
-
const items = useSelector( selectOrderedGlobalClasses );
|
|
119
|
-
|
|
120
|
-
return items;
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
export const useGlobalClassesOrder = () => useSelector( selectOrder );
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { __privateRunCommandSync as runCommandSync, registerDataHook } from '@elementor/editor-v1-adapters';
|
|
2
|
-
import {
|
|
2
|
+
import { __getState as getState, __subscribeWithSelector as subscribeWithSelector } from '@elementor/store';
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { publishGlobalClasses } from './publish-global-classes';
|
|
5
|
+
import { selectIsDirty } from './store';
|
|
6
6
|
|
|
7
7
|
export function syncWithDocumentSave() {
|
|
8
8
|
const unsubscribe = syncDirtyState();
|
|
@@ -23,20 +23,7 @@ function syncDirtyState() {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
function bindSaveAction() {
|
|
26
|
-
registerDataHook( 'after', 'document/save/save',
|
|
27
|
-
if ( ! isDirty() ) {
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const state: GlobalClassesState = getState().globalClasses;
|
|
32
|
-
|
|
33
|
-
await apiClient.update( {
|
|
34
|
-
items: state.items,
|
|
35
|
-
order: state.order,
|
|
36
|
-
} );
|
|
37
|
-
|
|
38
|
-
__dispatch( slice.actions.setPristine() );
|
|
39
|
-
} );
|
|
26
|
+
registerDataHook( 'after', 'document/save/save', publishGlobalClasses );
|
|
40
27
|
}
|
|
41
28
|
|
|
42
29
|
function isDirty() {
|