@elementor/editor-components 3.33.0-170 → 3.33.0-172
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +135 -48
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +139 -49
- package/dist/index.mjs.map +1 -1
- package/package.json +12 -11
- package/src/api.ts +1 -1
- package/src/components/components-tab/components-list.tsx +5 -3
- package/src/components/create-component-form/create-component-form.tsx +33 -39
- package/src/hooks/use-components.ts +6 -9
- package/src/hooks/use-create-component.ts +18 -9
- package/src/init.ts +11 -1
- package/src/populate-store.ts +12 -0
- package/src/store.ts +73 -0
- package/src/thunks.ts +18 -0
|
@@ -6,9 +6,8 @@ import { StarIcon } from '@elementor/icons';
|
|
|
6
6
|
import { Alert, Button, FormLabel, Grid, Popover, Snackbar, Stack, TextField, Typography } from '@elementor/ui';
|
|
7
7
|
import { __ } from '@wordpress/i18n';
|
|
8
8
|
|
|
9
|
-
import { type CreateComponentResponse } from '../../api';
|
|
10
9
|
import { useComponents } from '../../hooks/use-components';
|
|
11
|
-
import {
|
|
10
|
+
import { useCreateComponent } from '../../hooks/use-create-component';
|
|
12
11
|
import { type ComponentFormValues } from '../../types';
|
|
13
12
|
import { useForm } from './hooks/use-form';
|
|
14
13
|
import { createBaseComponentSchema, createSubmitComponentSchema } from './utils/component-form-schema';
|
|
@@ -35,8 +34,7 @@ export function CreateComponentForm() {
|
|
|
35
34
|
|
|
36
35
|
const [ resultNotification, setResultNotification ] = useState< ResultNotification | null >( null );
|
|
37
36
|
|
|
38
|
-
const {
|
|
39
|
-
|
|
37
|
+
const { createComponent, isPending } = useCreateComponent();
|
|
40
38
|
useEffect( () => {
|
|
41
39
|
const OPEN_SAVE_AS_COMPONENT_FORM_EVENT = 'elementor/editor/open-save-as-component-form';
|
|
42
40
|
|
|
@@ -57,43 +55,39 @@ export function CreateComponentForm() {
|
|
|
57
55
|
throw new Error( `Can't save element as component: element not found` );
|
|
58
56
|
}
|
|
59
57
|
|
|
60
|
-
|
|
61
|
-
{
|
|
58
|
+
try {
|
|
59
|
+
const result = await createComponent( {
|
|
62
60
|
name: values.componentName,
|
|
63
61
|
content: [ element.element.model.toJSON( { remove: [ 'default' ] } ) ],
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
throw new Error( `Can't replace element with component: element not found` );
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
replaceElementWithComponent( element.element, {
|
|
72
|
-
id: result.component_id,
|
|
73
|
-
name: values.componentName,
|
|
74
|
-
} );
|
|
75
|
-
|
|
76
|
-
setResultNotification( {
|
|
77
|
-
show: true,
|
|
78
|
-
// Translators: %1$s: Component name, %2$s: Component ID
|
|
79
|
-
message: __( 'Component saved successfully as: %1$s (ID: %2$s)', 'elementor' )
|
|
80
|
-
.replace( '%1$s', values.componentName )
|
|
81
|
-
.replace( '%2$s', result.component_id.toString() ),
|
|
82
|
-
type: 'success',
|
|
83
|
-
} );
|
|
84
|
-
|
|
85
|
-
resetAndClosePopup();
|
|
86
|
-
},
|
|
87
|
-
onError: () => {
|
|
88
|
-
const errorMessage = __( 'Failed to save component. Please try again.', 'elementor' );
|
|
89
|
-
setResultNotification( {
|
|
90
|
-
show: true,
|
|
91
|
-
message: errorMessage,
|
|
92
|
-
type: 'error',
|
|
93
|
-
} );
|
|
94
|
-
},
|
|
62
|
+
} );
|
|
63
|
+
|
|
64
|
+
if ( ! element ) {
|
|
65
|
+
throw new Error( `Can't replace element with component: element not found` );
|
|
95
66
|
}
|
|
96
|
-
|
|
67
|
+
|
|
68
|
+
replaceElementWithComponent( element.element, {
|
|
69
|
+
id: result.component_id,
|
|
70
|
+
name: values.componentName,
|
|
71
|
+
} );
|
|
72
|
+
|
|
73
|
+
setResultNotification( {
|
|
74
|
+
show: true,
|
|
75
|
+
// Translators: %1$s: Component name, %2$s: Component ID
|
|
76
|
+
message: __( 'Component saved successfully as: %1$s (ID: %2$s)', 'elementor' )
|
|
77
|
+
.replace( '%1$s', values.componentName )
|
|
78
|
+
.replace( '%2$s', result.component_id.toString() ),
|
|
79
|
+
type: 'success',
|
|
80
|
+
} );
|
|
81
|
+
|
|
82
|
+
resetAndClosePopup();
|
|
83
|
+
} catch {
|
|
84
|
+
const errorMessage = __( 'Failed to save component. Please try again.', 'elementor' );
|
|
85
|
+
setResultNotification( {
|
|
86
|
+
show: true,
|
|
87
|
+
message: errorMessage,
|
|
88
|
+
type: 'error',
|
|
89
|
+
} );
|
|
90
|
+
}
|
|
97
91
|
};
|
|
98
92
|
|
|
99
93
|
const resetAndClosePopup = () => {
|
|
@@ -146,7 +140,7 @@ const Form = ( {
|
|
|
146
140
|
} ) => {
|
|
147
141
|
const { values, errors, isValid, handleChange, validateForm } = useForm< ComponentFormValues >( initialValues );
|
|
148
142
|
|
|
149
|
-
const {
|
|
143
|
+
const { components } = useComponents();
|
|
150
144
|
|
|
151
145
|
const existingComponentNames = useMemo( () => {
|
|
152
146
|
return components?.map( ( component ) => component.name ) ?? [];
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { __useSelector as useSelector } from '@elementor/store';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
export const COMPONENTS_QUERY_KEY = 'components';
|
|
3
|
+
import { selectComponents, selectLoadIsPending } from '../store';
|
|
6
4
|
|
|
7
5
|
export const useComponents = () => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
} );
|
|
6
|
+
const components = useSelector( selectComponents );
|
|
7
|
+
const isLoading = useSelector( selectLoadIsPending );
|
|
8
|
+
|
|
9
|
+
return { components, isLoading };
|
|
13
10
|
};
|
|
@@ -1,13 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { __useDispatch as useDispatch, __useSelector as useSelector, type AnyAction } from '@elementor/store';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { type CreateComponentPayload } from '../api';
|
|
4
|
+
import { selectCreateIsError, selectCreateIsPending } from '../store';
|
|
5
|
+
import { createComponent } from '../thunks';
|
|
5
6
|
|
|
6
|
-
export const
|
|
7
|
-
const
|
|
7
|
+
export const useCreateComponent = () => {
|
|
8
|
+
const dispatch = useDispatch();
|
|
9
|
+
const isPending = useSelector( selectCreateIsPending );
|
|
10
|
+
const isError = useSelector( selectCreateIsError );
|
|
8
11
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
12
|
+
const createComponentAction = async ( payload: CreateComponentPayload ) => {
|
|
13
|
+
const result = await dispatch( createComponent( payload ) as unknown as AnyAction );
|
|
14
|
+
return result.payload;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
createComponent: createComponentAction,
|
|
19
|
+
isPending,
|
|
20
|
+
isError,
|
|
21
|
+
};
|
|
13
22
|
};
|
package/src/init.ts
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
import { injectIntoTop } from '@elementor/editor';
|
|
1
|
+
import { injectIntoLogic, injectIntoTop } from '@elementor/editor';
|
|
2
2
|
import { injectTab } from '@elementor/editor-elements-panel';
|
|
3
|
+
import { __registerSlice as registerSlice } from '@elementor/store';
|
|
3
4
|
import { __ } from '@wordpress/i18n';
|
|
4
5
|
|
|
5
6
|
import { Components } from './components/components-tab/components';
|
|
6
7
|
import { CreateComponentForm } from './components/create-component-form/create-component-form';
|
|
8
|
+
import { PopulateStore } from './populate-store';
|
|
9
|
+
import { slice } from './store';
|
|
7
10
|
|
|
8
11
|
export function init() {
|
|
12
|
+
registerSlice( slice );
|
|
13
|
+
|
|
9
14
|
injectTab( {
|
|
10
15
|
id: 'components',
|
|
11
16
|
label: __( 'Components', 'elementor' ),
|
|
@@ -16,4 +21,9 @@ export function init() {
|
|
|
16
21
|
id: 'create-component-popup',
|
|
17
22
|
component: CreateComponentForm,
|
|
18
23
|
} );
|
|
24
|
+
|
|
25
|
+
injectIntoLogic( {
|
|
26
|
+
id: 'components-populate-store',
|
|
27
|
+
component: PopulateStore,
|
|
28
|
+
} );
|
|
19
29
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { __dispatch as dispatch } from '@elementor/store';
|
|
3
|
+
|
|
4
|
+
import { loadComponents } from './thunks';
|
|
5
|
+
|
|
6
|
+
export function PopulateStore() {
|
|
7
|
+
useEffect( () => {
|
|
8
|
+
dispatch( loadComponents() );
|
|
9
|
+
}, [] );
|
|
10
|
+
|
|
11
|
+
return null;
|
|
12
|
+
}
|
package/src/store.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__createSelector as createSelector,
|
|
3
|
+
__createSlice as createSlice,
|
|
4
|
+
type PayloadAction,
|
|
5
|
+
type SliceState,
|
|
6
|
+
} from '@elementor/store';
|
|
7
|
+
|
|
8
|
+
import { createComponent, loadComponents } from './thunks';
|
|
9
|
+
import { type Component } from './types';
|
|
10
|
+
|
|
11
|
+
type GetComponentResponse = Component[];
|
|
12
|
+
|
|
13
|
+
type Status = 'idle' | 'pending' | 'error';
|
|
14
|
+
export type ComponentsState = {
|
|
15
|
+
data: Component[];
|
|
16
|
+
loadStatus: Status;
|
|
17
|
+
createStatus: Status;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const initialState: ComponentsState = {
|
|
21
|
+
data: [],
|
|
22
|
+
loadStatus: 'idle',
|
|
23
|
+
createStatus: 'idle',
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const SLICE_NAME = 'components';
|
|
27
|
+
export const slice = createSlice( {
|
|
28
|
+
name: SLICE_NAME,
|
|
29
|
+
initialState,
|
|
30
|
+
reducers: {
|
|
31
|
+
add: ( state, { payload } ) => {
|
|
32
|
+
state.data.push( payload );
|
|
33
|
+
},
|
|
34
|
+
load: ( state, { payload } ) => {
|
|
35
|
+
state.data = payload;
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
extraReducers: ( builder ) => {
|
|
39
|
+
builder.addCase( loadComponents.fulfilled, ( state, { payload }: PayloadAction< GetComponentResponse > ) => {
|
|
40
|
+
state.data = payload;
|
|
41
|
+
state.loadStatus = 'idle';
|
|
42
|
+
} );
|
|
43
|
+
builder.addCase( loadComponents.pending, ( state ) => {
|
|
44
|
+
state.loadStatus = 'pending';
|
|
45
|
+
} );
|
|
46
|
+
builder.addCase( loadComponents.rejected, ( state ) => {
|
|
47
|
+
state.loadStatus = 'error';
|
|
48
|
+
} );
|
|
49
|
+
builder.addCase( createComponent.fulfilled, ( state, { payload, meta } ) => {
|
|
50
|
+
state.createStatus = 'idle';
|
|
51
|
+
state.data.push( {
|
|
52
|
+
id: payload.component_id,
|
|
53
|
+
name: meta.arg.name,
|
|
54
|
+
} );
|
|
55
|
+
} );
|
|
56
|
+
builder.addCase( createComponent.pending, ( state ) => {
|
|
57
|
+
state.createStatus = 'pending';
|
|
58
|
+
} );
|
|
59
|
+
builder.addCase( createComponent.rejected, ( state ) => {
|
|
60
|
+
state.createStatus = 'error';
|
|
61
|
+
} );
|
|
62
|
+
},
|
|
63
|
+
} );
|
|
64
|
+
|
|
65
|
+
const selectData = ( state: SliceState< typeof slice > ) => state[ SLICE_NAME ].data;
|
|
66
|
+
const selectLoadStatus = ( state: SliceState< typeof slice > ) => state[ SLICE_NAME ].loadStatus;
|
|
67
|
+
const selectCreateStatus = ( state: SliceState< typeof slice > ) => state[ SLICE_NAME ].createStatus;
|
|
68
|
+
|
|
69
|
+
export const selectComponents = createSelector( selectData, ( data: Component[] ) => data );
|
|
70
|
+
export const selectLoadIsPending = createSelector( selectLoadStatus, ( status ) => status === 'pending' );
|
|
71
|
+
export const selectLoadIsError = createSelector( selectLoadStatus, ( status ) => status === 'error' );
|
|
72
|
+
export const selectCreateIsPending = createSelector( selectCreateStatus, ( status ) => status === 'pending' );
|
|
73
|
+
export const selectCreateIsError = createSelector( selectCreateStatus, ( status ) => status === 'error' );
|
package/src/thunks.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { __createAsyncThunk as createAsyncThunk } from '@elementor/store';
|
|
2
|
+
|
|
3
|
+
import { apiClient, type CreateComponentPayload, type CreateComponentResponse } from './api';
|
|
4
|
+
|
|
5
|
+
const createComponent = createAsyncThunk< CreateComponentResponse, CreateComponentPayload >(
|
|
6
|
+
'components/create',
|
|
7
|
+
async ( payload: CreateComponentPayload ) => {
|
|
8
|
+
const response = await apiClient.create( payload );
|
|
9
|
+
return { ...response, name: payload.name };
|
|
10
|
+
}
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
const loadComponents = createAsyncThunk( 'components/load', async () => {
|
|
14
|
+
const response = await apiClient.get();
|
|
15
|
+
return response;
|
|
16
|
+
} );
|
|
17
|
+
|
|
18
|
+
export { createComponent, loadComponents };
|