@elementor/editor-components 3.35.0-378 → 3.35.0-380

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 (29) hide show
  1. package/dist/index.js +1482 -562
  2. package/dist/index.js.map +1 -1
  3. package/dist/index.mjs +1421 -485
  4. package/dist/index.mjs.map +1 -1
  5. package/package.json +22 -21
  6. package/src/components/component-panel-header/component-badge.tsx +30 -22
  7. package/src/components/component-panel-header/component-panel-header.tsx +21 -1
  8. package/src/components/component-properties-panel/component-properties-panel-content.tsx +165 -0
  9. package/src/components/component-properties-panel/component-properties-panel.tsx +51 -0
  10. package/src/components/component-properties-panel/properties-empty-state.tsx +44 -0
  11. package/src/components/component-properties-panel/properties-group.tsx +191 -0
  12. package/src/components/component-properties-panel/property-item.tsx +121 -0
  13. package/src/components/component-properties-panel/sortable.tsx +92 -0
  14. package/src/components/component-properties-panel/use-current-editable-item.ts +74 -0
  15. package/src/components/component-properties-panel/utils/generate-unique-label.ts +21 -0
  16. package/src/components/component-properties-panel/utils/validate-group-label.ts +24 -0
  17. package/src/components/components-tab/component-introduction.tsx +68 -0
  18. package/src/components/instance-editing-panel/instance-editing-panel.tsx +1 -1
  19. package/src/components/overridable-props/overridable-prop-form.tsx +7 -4
  20. package/src/init.ts +3 -0
  21. package/src/store/actions/add-overridable-group.ts +47 -0
  22. package/src/store/actions/delete-overridable-group.ts +38 -0
  23. package/src/store/actions/delete-overridable-prop.ts +56 -0
  24. package/src/store/actions/rename-overridable-group.ts +39 -0
  25. package/src/store/actions/reorder-group-props.ts +43 -0
  26. package/src/store/actions/reorder-overridable-groups.ts +30 -0
  27. package/src/store/actions/set-overridable-prop.ts +21 -126
  28. package/src/store/actions/update-overridable-prop.ts +58 -0
  29. package/src/store/utils/groups-transformers.ts +185 -0
@@ -0,0 +1,43 @@
1
+ import { __dispatch as dispatch, __getState as getState } from '@elementor/store';
2
+
3
+ import { type ComponentId } from '../../types';
4
+ import { selectOverridableProps, slice } from '../store';
5
+
6
+ type ReorderGroupPropsParams = {
7
+ componentId: ComponentId;
8
+ groupId: string;
9
+ newPropsOrder: string[];
10
+ };
11
+
12
+ export function reorderGroupProps( { componentId, groupId, newPropsOrder }: ReorderGroupPropsParams ): void {
13
+ const overridableProps = selectOverridableProps( getState(), componentId );
14
+
15
+ if ( ! overridableProps ) {
16
+ return;
17
+ }
18
+
19
+ const group = overridableProps.groups.items[ groupId ];
20
+
21
+ if ( ! group ) {
22
+ return;
23
+ }
24
+
25
+ dispatch(
26
+ slice.actions.setOverridableProps( {
27
+ componentId,
28
+ overridableProps: {
29
+ ...overridableProps,
30
+ groups: {
31
+ ...overridableProps.groups,
32
+ items: {
33
+ ...overridableProps.groups.items,
34
+ [ groupId ]: {
35
+ ...group,
36
+ props: newPropsOrder,
37
+ },
38
+ },
39
+ },
40
+ },
41
+ } )
42
+ );
43
+ }
@@ -0,0 +1,30 @@
1
+ import { __dispatch as dispatch, __getState as getState } from '@elementor/store';
2
+
3
+ import { type ComponentId } from '../../types';
4
+ import { selectOverridableProps, slice } from '../store';
5
+
6
+ type ReorderGroupsParams = {
7
+ componentId: ComponentId;
8
+ newOrder: string[];
9
+ };
10
+
11
+ export function reorderOverridableGroups( { componentId, newOrder }: ReorderGroupsParams ): void {
12
+ const overridableProps = selectOverridableProps( getState(), componentId );
13
+
14
+ if ( ! overridableProps ) {
15
+ return;
16
+ }
17
+
18
+ dispatch(
19
+ slice.actions.setOverridableProps( {
20
+ componentId,
21
+ overridableProps: {
22
+ ...overridableProps,
23
+ groups: {
24
+ ...overridableProps.groups,
25
+ order: newOrder,
26
+ },
27
+ },
28
+ } )
29
+ );
30
+ }
@@ -1,10 +1,16 @@
1
1
  import { type PropValue } from '@elementor/editor-props';
2
2
  import { __dispatch as dispatch, __getState as getState } from '@elementor/store';
3
3
  import { generateUniqueId } from '@elementor/utils';
4
- import { __ } from '@wordpress/i18n';
5
4
 
6
- import { type OverridableProp, type OverridableProps, type OverridablePropsGroup } from '../../types';
5
+ import { type OverridableProp } from '../../types';
7
6
  import { selectOverridableProps, slice } from '../store';
7
+ import {
8
+ addPropToGroup,
9
+ ensureGroupInOrder,
10
+ removePropFromGroup,
11
+ removePropsFromState,
12
+ resolveOrCreateGroup,
13
+ } from '../utils/groups-transformers';
8
14
 
9
15
  type Props = {
10
16
  componentId: number;
@@ -17,6 +23,7 @@ type Props = {
17
23
  widgetType: string;
18
24
  originValue: PropValue;
19
25
  };
26
+
20
27
  export function setOverridableProp( {
21
28
  componentId,
22
29
  overrideKey,
@@ -39,14 +46,12 @@ export function setOverridableProp( {
39
46
  ( prop ) => prop.elementId === elementId && prop.propKey === propKey && prop !== existingOverridableProp
40
47
  );
41
48
 
42
- const { props: prevProps, groups: prevGroups } = { ...overridableProps };
43
-
44
- const { groups: updatedGroups, currentGroupId } = getUpdatedGroups(
45
- prevGroups,
46
- groupId || existingOverridableProp?.groupId
49
+ const { groups: groupsAfterResolve, groupId: currentGroupId } = resolveOrCreateGroup(
50
+ overridableProps.groups,
51
+ groupId || existingOverridableProp?.groupId || undefined
47
52
  );
48
53
 
49
- const overridableProp = {
54
+ const overridableProp: OverridableProp = {
50
55
  overrideKey: existingOverridableProp?.overrideKey || generateUniqueId( 'prop' ),
51
56
  label,
52
57
  elementId,
@@ -57,35 +62,23 @@ export function setOverridableProp( {
57
62
  groupId: currentGroupId,
58
63
  };
59
64
 
60
- const { props: propsWithoutDuplicates, groups: groupsWithoutDuplicates } = removeProps( {
61
- props: prevProps,
62
- groups: updatedGroups,
63
- propsToRemove: duplicatedTargetProps,
64
- } );
65
+ const stateAfterRemovingDuplicates = removePropsFromState(
66
+ { ...overridableProps, groups: groupsAfterResolve },
67
+ duplicatedTargetProps
68
+ );
65
69
 
66
70
  const props = {
67
- ...propsWithoutDuplicates,
71
+ ...stateAfterRemovingDuplicates.props,
68
72
  [ overridableProp.overrideKey ]: overridableProp,
69
73
  };
70
74
 
71
- const groups = {
72
- items: {
73
- ...groupsWithoutDuplicates.items,
74
- [ currentGroupId ]: getGroupWithProp( groupsWithoutDuplicates, currentGroupId, overridableProp ),
75
- },
76
- order: groupsWithoutDuplicates.order.includes( currentGroupId )
77
- ? groupsWithoutDuplicates.order
78
- : [ ...groupsWithoutDuplicates.order, currentGroupId ],
79
- };
75
+ let groups = addPropToGroup( stateAfterRemovingDuplicates.groups, currentGroupId, overridableProp.overrideKey );
76
+ groups = ensureGroupInOrder( groups, currentGroupId );
80
77
 
81
78
  const isChangingGroups = existingOverridableProp && existingOverridableProp.groupId !== currentGroupId;
82
79
 
83
80
  if ( isChangingGroups ) {
84
- groups.items[ existingOverridableProp.groupId ] = getGroupWithoutProp(
85
- groupsWithoutDuplicates,
86
- existingOverridableProp.groupId,
87
- overridableProp
88
- );
81
+ groups = removePropFromGroup( groups, existingOverridableProp.groupId, overridableProp.overrideKey );
89
82
  }
90
83
 
91
84
  dispatch(
@@ -100,101 +93,3 @@ export function setOverridableProp( {
100
93
 
101
94
  return overridableProp;
102
95
  }
103
-
104
- type UpdatedGroups = { groups: OverridableProps[ 'groups' ]; currentGroupId: string };
105
-
106
- function getUpdatedGroups( groups: OverridableProps[ 'groups' ], groupId: string | undefined ): UpdatedGroups {
107
- if ( ! groupId ) {
108
- // use first existing group
109
- if ( groups.order.length > 0 ) {
110
- return { groups, currentGroupId: groups.order[ 0 ] };
111
- }
112
-
113
- // create the first group (default)
114
- return addNewGroup( groups );
115
- }
116
-
117
- if ( ! groups.items[ groupId ] ) {
118
- // fallback - if for any reason there's no such group - create it
119
- return addNewGroup( groups, groupId );
120
- }
121
-
122
- // use the existing group
123
- return { groups, currentGroupId: groupId };
124
- }
125
-
126
- function addNewGroup( groups: OverridableProps[ 'groups' ], groupId?: string | undefined ): UpdatedGroups {
127
- const currentGroupId = groupId || generateUniqueId( 'group' );
128
- const updatedGroups = {
129
- ...groups,
130
- items: {
131
- ...groups.items,
132
- [ currentGroupId ]: {
133
- id: currentGroupId,
134
- label: __( 'Default', 'elementor' ),
135
- props: [],
136
- },
137
- },
138
- order: [ ...groups.order, currentGroupId ],
139
- };
140
-
141
- return { groups: updatedGroups, currentGroupId };
142
- }
143
-
144
- function getGroupWithProp(
145
- groups: OverridableProps[ 'groups' ],
146
- groupId: string,
147
- overridableProp: OverridableProp
148
- ): OverridablePropsGroup {
149
- const group: OverridablePropsGroup = { ...groups.items[ groupId ] };
150
-
151
- if ( ! group.props.includes( overridableProp.overrideKey ) ) {
152
- group.props = [ ...group.props, overridableProp.overrideKey ];
153
- }
154
-
155
- return group;
156
- }
157
-
158
- function getGroupWithoutProp(
159
- groups: OverridableProps[ 'groups' ],
160
- groupId: string,
161
- overridableProp: OverridableProp
162
- ): OverridablePropsGroup {
163
- const group = { ...groups.items[ groupId ] };
164
-
165
- if ( group ) {
166
- group.props = group.props.filter( ( key ) => key !== overridableProp.overrideKey );
167
- }
168
-
169
- return group;
170
- }
171
-
172
- function removeProps( {
173
- props,
174
- groups,
175
- propsToRemove,
176
- }: OverridableProps & { propsToRemove: OverridableProp[] } ): OverridableProps {
177
- const allProps = Object.fromEntries(
178
- Object.entries( props ).filter( ( [ , prop ] ) => ! propsToRemove.includes( prop ) )
179
- );
180
-
181
- const overrideKeysToRemove = propsToRemove.map( ( prop ) => prop.overrideKey );
182
-
183
- const allGroupItems = Object.fromEntries(
184
- Object.entries( groups.items ).map( ( [ groupId, group ]: [ string, OverridablePropsGroup ] ) => [
185
- groupId,
186
- {
187
- ...group,
188
- props: group.props.filter( ( prop ) => ! overrideKeysToRemove.includes( prop ) ),
189
- },
190
- ] )
191
- );
192
-
193
- return {
194
- props: allProps,
195
- groups: {
196
- items: allGroupItems,
197
- order: groups.order.filter( ( groupId ) => ! overrideKeysToRemove.includes( groupId ) ),
198
- },
199
- };
200
- }
@@ -0,0 +1,58 @@
1
+ import { __dispatch as dispatch, __getState as getState } from '@elementor/store';
2
+
3
+ import { type ComponentId, type OverridableProp } from '../../types';
4
+ import { selectOverridableProps, slice } from '../store';
5
+ import { movePropBetweenGroups } from '../utils/groups-transformers';
6
+
7
+ type UpdatePropParams = {
8
+ componentId: ComponentId;
9
+ propKey: string;
10
+ label: string;
11
+ groupId: string | null;
12
+ };
13
+
14
+ export function updateOverridableProp( {
15
+ componentId,
16
+ propKey,
17
+ label,
18
+ groupId,
19
+ }: UpdatePropParams ): OverridableProp | undefined {
20
+ const overridableProps = selectOverridableProps( getState(), componentId );
21
+
22
+ if ( ! overridableProps ) {
23
+ return;
24
+ }
25
+
26
+ const prop = overridableProps.props[ propKey ];
27
+
28
+ if ( ! prop ) {
29
+ return;
30
+ }
31
+
32
+ const oldGroupId = prop.groupId;
33
+ const newGroupId = groupId ?? oldGroupId;
34
+
35
+ const updatedProp: OverridableProp = {
36
+ ...prop,
37
+ label,
38
+ groupId: newGroupId,
39
+ };
40
+
41
+ const updatedGroups = movePropBetweenGroups( overridableProps.groups, propKey, oldGroupId, newGroupId );
42
+
43
+ dispatch(
44
+ slice.actions.setOverridableProps( {
45
+ componentId,
46
+ overridableProps: {
47
+ ...overridableProps,
48
+ props: {
49
+ ...overridableProps.props,
50
+ [ propKey ]: updatedProp,
51
+ },
52
+ groups: updatedGroups,
53
+ },
54
+ } )
55
+ );
56
+
57
+ return updatedProp;
58
+ }
@@ -0,0 +1,185 @@
1
+ import { generateUniqueId } from '@elementor/utils';
2
+ import { __ } from '@wordpress/i18n';
3
+
4
+ import { type OverridableProp, type OverridableProps, type OverridablePropsGroup } from '../../types';
5
+
6
+ type Groups = OverridableProps[ 'groups' ];
7
+
8
+ export function removePropFromAllGroups( groups: Groups, propKey: string ): Groups {
9
+ return {
10
+ ...groups,
11
+ items: Object.fromEntries(
12
+ Object.entries( groups.items ).map( ( [ groupId, group ] ) => [
13
+ groupId,
14
+ {
15
+ ...group,
16
+ props: group.props.filter( ( p ) => p !== propKey ),
17
+ },
18
+ ] )
19
+ ),
20
+ };
21
+ }
22
+
23
+ export function addPropToGroup( groups: Groups, groupId: string, propKey: string ): Groups {
24
+ const group = groups.items[ groupId ];
25
+
26
+ if ( ! group ) {
27
+ return groups;
28
+ }
29
+
30
+ if ( group.props.includes( propKey ) ) {
31
+ return groups;
32
+ }
33
+
34
+ return {
35
+ ...groups,
36
+ items: {
37
+ ...groups.items,
38
+ [ groupId ]: {
39
+ ...group,
40
+ props: [ ...group.props, propKey ],
41
+ },
42
+ },
43
+ };
44
+ }
45
+
46
+ export function movePropBetweenGroups(
47
+ groups: Groups,
48
+ propKey: string,
49
+ fromGroupId: string,
50
+ toGroupId: string
51
+ ): Groups {
52
+ if ( fromGroupId === toGroupId ) {
53
+ return groups;
54
+ }
55
+
56
+ const withoutProp = removePropFromGroup( groups, fromGroupId, propKey );
57
+ return addPropToGroup( withoutProp, toGroupId, propKey );
58
+ }
59
+
60
+ export function removePropFromGroup( groups: Groups, groupId: string, propKey: string ): Groups {
61
+ const group = groups.items[ groupId ];
62
+
63
+ if ( ! group ) {
64
+ return groups;
65
+ }
66
+
67
+ return {
68
+ ...groups,
69
+ items: {
70
+ ...groups.items,
71
+ [ groupId ]: {
72
+ ...group,
73
+ props: group.props.filter( ( p ) => p !== propKey ),
74
+ },
75
+ },
76
+ };
77
+ }
78
+
79
+ type ResolvedGroup = {
80
+ groups: Groups;
81
+ groupId: string;
82
+ };
83
+
84
+ export function resolveOrCreateGroup( groups: Groups, requestedGroupId?: string ): ResolvedGroup {
85
+ if ( requestedGroupId && groups.items[ requestedGroupId ] ) {
86
+ return { groups, groupId: requestedGroupId };
87
+ }
88
+
89
+ if ( ! requestedGroupId && groups.order.length > 0 ) {
90
+ return { groups, groupId: groups.order[ 0 ] };
91
+ }
92
+
93
+ return createGroup( groups, requestedGroupId );
94
+ }
95
+
96
+ export function createGroup( groups: Groups, groupId?: string, label?: string ): ResolvedGroup {
97
+ const newGroupId = groupId || generateUniqueId( 'group' );
98
+ const newLabel = label || __( 'Default', 'elementor' );
99
+
100
+ return {
101
+ groups: {
102
+ ...groups,
103
+ items: {
104
+ ...groups.items,
105
+ [ newGroupId ]: {
106
+ id: newGroupId,
107
+ label: newLabel,
108
+ props: [],
109
+ },
110
+ },
111
+ order: [ ...groups.order, newGroupId ],
112
+ },
113
+ groupId: newGroupId,
114
+ };
115
+ }
116
+
117
+ export function removePropsFromState(
118
+ overridableProps: OverridableProps,
119
+ propsToRemove: OverridableProp[]
120
+ ): OverridableProps {
121
+ const overrideKeysToRemove = propsToRemove.map( ( prop ) => prop.overrideKey );
122
+
123
+ const remainingProps = Object.fromEntries(
124
+ Object.entries( overridableProps.props ).filter( ( [ , prop ] ) => ! propsToRemove.includes( prop ) )
125
+ );
126
+
127
+ const updatedGroupItems = Object.fromEntries(
128
+ Object.entries( overridableProps.groups.items ).map(
129
+ ( [ groupId, group ]: [ string, OverridablePropsGroup ] ) => [
130
+ groupId,
131
+ {
132
+ ...group,
133
+ props: group.props.filter( ( prop ) => ! overrideKeysToRemove.includes( prop ) ),
134
+ },
135
+ ]
136
+ )
137
+ );
138
+
139
+ return {
140
+ props: remainingProps,
141
+ groups: {
142
+ items: updatedGroupItems,
143
+ order: overridableProps.groups.order.filter( ( groupId ) => ! overrideKeysToRemove.includes( groupId ) ),
144
+ },
145
+ };
146
+ }
147
+
148
+ export function ensureGroupInOrder( groups: Groups, groupId: string ): Groups {
149
+ if ( groups.order.includes( groupId ) ) {
150
+ return groups;
151
+ }
152
+
153
+ return {
154
+ ...groups,
155
+ order: [ ...groups.order, groupId ],
156
+ };
157
+ }
158
+
159
+ export function deleteGroup( groups: Groups, groupId: string ): Groups {
160
+ const { [ groupId ]: removed, ...remainingItems } = groups.items;
161
+
162
+ return {
163
+ items: remainingItems,
164
+ order: groups.order.filter( ( id ) => id !== groupId ),
165
+ };
166
+ }
167
+
168
+ export function renameGroup( groups: Groups, groupId: string, newLabel: string ): Groups {
169
+ const group = groups.items[ groupId ];
170
+
171
+ if ( ! group ) {
172
+ return groups;
173
+ }
174
+
175
+ return {
176
+ ...groups,
177
+ items: {
178
+ ...groups.items,
179
+ [ groupId ]: {
180
+ ...group,
181
+ label: newLabel,
182
+ },
183
+ },
184
+ };
185
+ }