@elementor/editor-components 4.0.0-665 → 4.0.0-667
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 +191 -3870
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +184 -3904
- package/dist/index.mjs.map +1 -1
- package/package.json +23 -23
- package/src/init.ts +0 -13
- package/src/extended/components/component-introduction.tsx +0 -77
- package/src/extended/components/component-panel-header/component-badge.tsx +0 -73
- package/src/extended/components/component-panel-header/component-panel-header.tsx +0 -98
- package/src/extended/components/component-properties-panel/component-properties-panel-content.tsx +0 -176
- package/src/extended/components/component-properties-panel/component-properties-panel.tsx +0 -43
- package/src/extended/components/component-properties-panel/properties-empty-state.tsx +0 -51
- package/src/extended/components/component-properties-panel/properties-group.tsx +0 -196
- package/src/extended/components/component-properties-panel/property-item.tsx +0 -124
- package/src/extended/components/component-properties-panel/sortable.tsx +0 -92
- package/src/extended/components/component-properties-panel/use-current-editable-item.ts +0 -73
- package/src/extended/components/component-properties-panel/utils/generate-unique-label.ts +0 -21
- package/src/extended/components/component-properties-panel/utils/validate-group-label.ts +0 -24
- package/src/extended/components/components-tab/component-item.tsx +0 -180
- package/src/extended/components/components-tab/components.tsx +0 -58
- package/src/extended/components/components-tab/delete-confirmation-dialog.tsx +0 -26
- package/src/extended/components/create-component-form/create-component-form.tsx +0 -281
- package/src/extended/components/create-component-form/hooks/use-form.ts +0 -72
- package/src/extended/components/create-component-form/utils/get-component-event-data.ts +0 -54
- package/src/extended/components/edit-component/component-modal.tsx +0 -133
- package/src/extended/components/edit-component/edit-component.tsx +0 -166
- package/src/extended/components/edit-component/use-canvas-document.ts +0 -9
- package/src/extended/components/edit-component/use-element-rect.ts +0 -81
- package/src/extended/components/instance-editing-panel/instance-editing-panel.tsx +0 -60
- package/src/extended/components/overridable-props/indicator.tsx +0 -83
- package/src/extended/components/overridable-props/overridable-prop-control.tsx +0 -127
- package/src/extended/components/overridable-props/overridable-prop-form.tsx +0 -135
- package/src/extended/components/overridable-props/overridable-prop-indicator.tsx +0 -138
- package/src/extended/components/overridable-props/utils/validate-prop-label.ts +0 -38
- package/src/extended/consts.ts +0 -3
- package/src/extended/hooks/use-navigate-back.ts +0 -24
- package/src/extended/init.ts +0 -108
- package/src/extended/mcp/index.ts +0 -14
- package/src/extended/mcp/save-as-component-tool.ts +0 -436
- package/src/extended/shortcuts/create-component-shortcut.ts +0 -121
- package/src/extended/store/actions/add-overridable-group.ts +0 -53
- package/src/extended/store/actions/archive-component.ts +0 -18
- package/src/extended/store/actions/create-unpublished-component.ts +0 -99
- package/src/extended/store/actions/delete-overridable-group.ts +0 -32
- package/src/extended/store/actions/delete-overridable-prop.ts +0 -64
- package/src/extended/store/actions/rename-component.ts +0 -48
- package/src/extended/store/actions/rename-overridable-group.ts +0 -33
- package/src/extended/store/actions/reorder-group-props.ts +0 -37
- package/src/extended/store/actions/reorder-overridable-groups.ts +0 -24
- package/src/extended/store/actions/reset-sanitized-components.ts +0 -5
- package/src/extended/store/actions/set-overridable-prop.ts +0 -109
- package/src/extended/store/actions/update-component-sanitized-attribute.ts +0 -7
- package/src/extended/store/actions/update-current-component.ts +0 -12
- package/src/extended/store/actions/update-overridable-prop-params.ts +0 -52
- package/src/extended/store/utils/groups-transformers.ts +0 -187
- package/src/extended/sync/before-save.ts +0 -52
- package/src/extended/sync/cleanup-overridable-props-on-delete.ts +0 -78
- package/src/extended/sync/create-components-before-save.ts +0 -111
- package/src/extended/sync/handle-component-edit-mode-container.ts +0 -114
- package/src/extended/sync/prevent-non-atomic-nesting.ts +0 -198
- package/src/extended/sync/revert-overridables-on-copy-or-duplicate.ts +0 -66
- package/src/extended/sync/sanitize-overridable-props.ts +0 -32
- package/src/extended/sync/set-component-overridable-props-settings-before-save.ts +0 -22
- package/src/extended/sync/update-archived-component-before-save.ts +0 -31
- package/src/extended/sync/update-component-title-before-save.ts +0 -18
- package/src/extended/utils/component-form-schema.ts +0 -32
- package/src/extended/utils/component-name-validation.ts +0 -25
- package/src/extended/utils/create-component-model.ts +0 -28
- package/src/extended/utils/get-container-for-new-element.ts +0 -49
- package/src/extended/utils/is-editing-component.ts +0 -5
- package/src/extended/utils/replace-element-with-component.ts +0 -11
- package/src/extended/utils/revert-overridable-settings.ts +0 -207
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { EditableField, EllipsisWithTooltip, MenuListItem } from '@elementor/editor-ui';
|
|
3
|
-
import { DotsVerticalIcon } from '@elementor/icons';
|
|
4
|
-
import {
|
|
5
|
-
bindMenu,
|
|
6
|
-
bindTrigger,
|
|
7
|
-
Box,
|
|
8
|
-
IconButton,
|
|
9
|
-
List,
|
|
10
|
-
Menu,
|
|
11
|
-
Stack,
|
|
12
|
-
Tooltip,
|
|
13
|
-
Typography,
|
|
14
|
-
usePopupState,
|
|
15
|
-
} from '@elementor/ui';
|
|
16
|
-
import { __ } from '@wordpress/i18n';
|
|
17
|
-
|
|
18
|
-
import { type OverridableProp, type OverridablePropsGroup } from '../../../types';
|
|
19
|
-
import { PropertyItem } from './property-item';
|
|
20
|
-
import { SortableItem, SortableProvider, SortableTrigger, type SortableTriggerProps } from './sortable';
|
|
21
|
-
import { type GroupLabelEditableState } from './use-current-editable-item';
|
|
22
|
-
|
|
23
|
-
type Props = {
|
|
24
|
-
group: OverridablePropsGroup;
|
|
25
|
-
props: Record< string, OverridableProp >;
|
|
26
|
-
allGroups: { value: string; label: string }[];
|
|
27
|
-
allGroupsRecord: Record< string, OverridablePropsGroup >;
|
|
28
|
-
sortableTriggerProps: SortableTriggerProps;
|
|
29
|
-
isDragPlaceholder?: boolean;
|
|
30
|
-
setIsAddingGroup: ( isAddingGroup: boolean ) => void;
|
|
31
|
-
onPropsReorder: ( newOrder: string[] ) => void;
|
|
32
|
-
onPropertyDelete: ( propKey: string ) => void;
|
|
33
|
-
onPropertyUpdate: ( propKey: string, data: { label: string; group: string | null } ) => void;
|
|
34
|
-
onGroupDelete: ( groupId: string ) => void;
|
|
35
|
-
editableLabelProps: GroupLabelEditableState;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
export function PropertiesGroup( {
|
|
39
|
-
group,
|
|
40
|
-
props,
|
|
41
|
-
allGroups,
|
|
42
|
-
sortableTriggerProps,
|
|
43
|
-
isDragPlaceholder,
|
|
44
|
-
onPropsReorder,
|
|
45
|
-
onPropertyDelete,
|
|
46
|
-
onPropertyUpdate,
|
|
47
|
-
onGroupDelete,
|
|
48
|
-
editableLabelProps,
|
|
49
|
-
}: Props ) {
|
|
50
|
-
const groupProps = group.props
|
|
51
|
-
.map( ( propId ) => props[ propId ] )
|
|
52
|
-
.filter( ( prop ): prop is OverridableProp => Boolean( prop ) );
|
|
53
|
-
|
|
54
|
-
const popupState = usePopupState( {
|
|
55
|
-
variant: 'popover',
|
|
56
|
-
disableAutoFocus: true,
|
|
57
|
-
} );
|
|
58
|
-
|
|
59
|
-
const { editableRef, isEditing, error, getEditableProps, setEditingGroupId, editingGroupId } = editableLabelProps;
|
|
60
|
-
|
|
61
|
-
const hasProperties = group.props.length > 0;
|
|
62
|
-
const isThisGroupEditing = isEditing && editingGroupId === group.id;
|
|
63
|
-
|
|
64
|
-
const handleRenameClick = () => {
|
|
65
|
-
popupState.close();
|
|
66
|
-
setEditingGroupId( group.id );
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
const handleDeleteClick = () => {
|
|
70
|
-
popupState.close();
|
|
71
|
-
onGroupDelete( group.id );
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
return (
|
|
75
|
-
<Box
|
|
76
|
-
sx={ {
|
|
77
|
-
opacity: isDragPlaceholder ? 0.5 : 1,
|
|
78
|
-
} }
|
|
79
|
-
>
|
|
80
|
-
<Stack gap={ 1 }>
|
|
81
|
-
<Box
|
|
82
|
-
className="group-header"
|
|
83
|
-
sx={ {
|
|
84
|
-
position: 'relative',
|
|
85
|
-
'&:hover .group-sortable-trigger': {
|
|
86
|
-
visibility: 'visible',
|
|
87
|
-
},
|
|
88
|
-
'& .group-sortable-trigger': {
|
|
89
|
-
visibility: 'hidden',
|
|
90
|
-
},
|
|
91
|
-
'&:hover .group-menu': {
|
|
92
|
-
visibility: 'visible',
|
|
93
|
-
},
|
|
94
|
-
'& .group-menu': {
|
|
95
|
-
visibility: 'hidden',
|
|
96
|
-
},
|
|
97
|
-
} }
|
|
98
|
-
>
|
|
99
|
-
<SortableTrigger triggerClassName="group-sortable-trigger" { ...sortableTriggerProps } />
|
|
100
|
-
<Stack direction="row" alignItems="center" justifyContent="space-between" gap={ 2 }>
|
|
101
|
-
{ isThisGroupEditing ? (
|
|
102
|
-
<Box
|
|
103
|
-
sx={ {
|
|
104
|
-
height: 28,
|
|
105
|
-
display: 'flex',
|
|
106
|
-
alignItems: 'center',
|
|
107
|
-
border: 2,
|
|
108
|
-
borderColor: 'text.secondary',
|
|
109
|
-
borderRadius: 1,
|
|
110
|
-
pl: 0.5,
|
|
111
|
-
flexGrow: 1,
|
|
112
|
-
overflow: 'hidden',
|
|
113
|
-
textOverflow: 'ellipsis',
|
|
114
|
-
whiteSpace: 'nowrap',
|
|
115
|
-
width: '100%',
|
|
116
|
-
} }
|
|
117
|
-
>
|
|
118
|
-
<EditableField
|
|
119
|
-
ref={ editableRef }
|
|
120
|
-
as={ Typography }
|
|
121
|
-
variant="caption"
|
|
122
|
-
error={ error ?? undefined }
|
|
123
|
-
sx={ { color: 'text.primary', fontWeight: 400, lineHeight: 1.66 } }
|
|
124
|
-
{ ...getEditableProps() }
|
|
125
|
-
/>
|
|
126
|
-
</Box>
|
|
127
|
-
) : (
|
|
128
|
-
<EllipsisWithTooltip
|
|
129
|
-
title={ group.label }
|
|
130
|
-
as={ Typography }
|
|
131
|
-
variant="caption"
|
|
132
|
-
sx={ { color: 'text.primary', fontWeight: 400, lineHeight: 1.66 } }
|
|
133
|
-
/>
|
|
134
|
-
) }
|
|
135
|
-
<IconButton
|
|
136
|
-
className="group-menu"
|
|
137
|
-
size="tiny"
|
|
138
|
-
sx={ { p: 0.25, visibility: isThisGroupEditing ? 'visible' : undefined } }
|
|
139
|
-
aria-label={ __( 'Group actions', 'elementor' ) }
|
|
140
|
-
{ ...bindTrigger( popupState ) }
|
|
141
|
-
>
|
|
142
|
-
<DotsVerticalIcon fontSize="tiny" />
|
|
143
|
-
</IconButton>
|
|
144
|
-
</Stack>
|
|
145
|
-
</Box>
|
|
146
|
-
<List sx={ { p: 0, display: 'flex', flexDirection: 'column', gap: 1 } }>
|
|
147
|
-
<SortableProvider value={ group.props } onChange={ onPropsReorder }>
|
|
148
|
-
{ groupProps.map( ( prop ) => (
|
|
149
|
-
<SortableItem key={ prop.overrideKey } id={ prop.overrideKey }>
|
|
150
|
-
{ ( { triggerProps, triggerStyle, isDragPlaceholder: isItemDragPlaceholder } ) => (
|
|
151
|
-
<PropertyItem
|
|
152
|
-
prop={ prop }
|
|
153
|
-
sortableTriggerProps={ { ...triggerProps, style: triggerStyle } }
|
|
154
|
-
isDragPlaceholder={ isItemDragPlaceholder }
|
|
155
|
-
groups={ allGroups }
|
|
156
|
-
existingLabels={ Object.values( props ).map( ( p ) => p.label ) }
|
|
157
|
-
onDelete={ onPropertyDelete }
|
|
158
|
-
onUpdate={ ( data ) => onPropertyUpdate( prop.overrideKey, data ) }
|
|
159
|
-
/>
|
|
160
|
-
) }
|
|
161
|
-
</SortableItem>
|
|
162
|
-
) ) }
|
|
163
|
-
</SortableProvider>
|
|
164
|
-
</List>
|
|
165
|
-
</Stack>
|
|
166
|
-
<Menu
|
|
167
|
-
{ ...bindMenu( popupState ) }
|
|
168
|
-
anchorOrigin={ { vertical: 'bottom', horizontal: 'right' } }
|
|
169
|
-
transformOrigin={ { vertical: 'top', horizontal: 'right' } }
|
|
170
|
-
>
|
|
171
|
-
<MenuListItem sx={ { minWidth: '160px' } } onClick={ handleRenameClick }>
|
|
172
|
-
<Typography variant="caption" sx={ { color: 'text.primary' } }>
|
|
173
|
-
{ __( 'Rename', 'elementor' ) }
|
|
174
|
-
</Typography>
|
|
175
|
-
</MenuListItem>
|
|
176
|
-
<Tooltip
|
|
177
|
-
title={
|
|
178
|
-
hasProperties ? __( 'To delete the group, first remove all the properties', 'elementor' ) : ''
|
|
179
|
-
}
|
|
180
|
-
placement="right"
|
|
181
|
-
>
|
|
182
|
-
<span>
|
|
183
|
-
<MenuListItem onClick={ handleDeleteClick } disabled={ hasProperties }>
|
|
184
|
-
<Typography
|
|
185
|
-
variant="caption"
|
|
186
|
-
sx={ { color: hasProperties ? 'text.disabled' : 'error.light' } }
|
|
187
|
-
>
|
|
188
|
-
{ __( 'Delete', 'elementor' ) }
|
|
189
|
-
</Typography>
|
|
190
|
-
</MenuListItem>
|
|
191
|
-
</span>
|
|
192
|
-
</Tooltip>
|
|
193
|
-
</Menu>
|
|
194
|
-
</Box>
|
|
195
|
-
);
|
|
196
|
-
}
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { getWidgetsCache } from '@elementor/editor-elements';
|
|
3
|
-
import { XIcon } from '@elementor/icons';
|
|
4
|
-
import { bindPopover, bindTrigger, Box, IconButton, Popover, Typography, usePopupState } from '@elementor/ui';
|
|
5
|
-
|
|
6
|
-
import { type OverridableProp } from '../../../types';
|
|
7
|
-
import { OverridablePropForm } from '../overridable-props/overridable-prop-form';
|
|
8
|
-
import { SortableTrigger, type SortableTriggerProps } from './sortable';
|
|
9
|
-
|
|
10
|
-
type PropertyItemProps = {
|
|
11
|
-
prop: OverridableProp;
|
|
12
|
-
sortableTriggerProps: SortableTriggerProps;
|
|
13
|
-
isDragPlaceholder?: boolean;
|
|
14
|
-
groups: { value: string; label: string }[];
|
|
15
|
-
existingLabels: string[];
|
|
16
|
-
onDelete: ( propKey: string ) => void;
|
|
17
|
-
onUpdate: ( data: { label: string; group: string | null } ) => void;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export function PropertyItem( {
|
|
21
|
-
prop,
|
|
22
|
-
sortableTriggerProps,
|
|
23
|
-
isDragPlaceholder,
|
|
24
|
-
groups,
|
|
25
|
-
existingLabels,
|
|
26
|
-
onDelete,
|
|
27
|
-
onUpdate,
|
|
28
|
-
}: PropertyItemProps ) {
|
|
29
|
-
const popoverState = usePopupState( {
|
|
30
|
-
variant: 'popover',
|
|
31
|
-
} );
|
|
32
|
-
const icon = getElementIcon( prop );
|
|
33
|
-
const popoverProps = bindPopover( popoverState );
|
|
34
|
-
|
|
35
|
-
const handleSubmit = ( data: { label: string; group: string | null } ) => {
|
|
36
|
-
onUpdate( data );
|
|
37
|
-
popoverState.close();
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const handleDelete = ( event: React.MouseEvent ) => {
|
|
41
|
-
event.stopPropagation();
|
|
42
|
-
onDelete( prop.overrideKey );
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
return (
|
|
46
|
-
<>
|
|
47
|
-
<Box
|
|
48
|
-
{ ...bindTrigger( popoverState ) }
|
|
49
|
-
sx={ {
|
|
50
|
-
position: 'relative',
|
|
51
|
-
pl: 0.5,
|
|
52
|
-
pr: 1,
|
|
53
|
-
py: 0.25,
|
|
54
|
-
minHeight: 28,
|
|
55
|
-
borderRadius: 1,
|
|
56
|
-
border: '1px solid',
|
|
57
|
-
borderColor: 'divider',
|
|
58
|
-
display: 'flex',
|
|
59
|
-
alignItems: 'center',
|
|
60
|
-
gap: 0.5,
|
|
61
|
-
opacity: isDragPlaceholder ? 0.5 : 1,
|
|
62
|
-
cursor: 'pointer',
|
|
63
|
-
'&:hover': {
|
|
64
|
-
backgroundColor: 'action.hover',
|
|
65
|
-
},
|
|
66
|
-
'&:hover .sortable-trigger': {
|
|
67
|
-
visibility: 'visible',
|
|
68
|
-
},
|
|
69
|
-
'& .sortable-trigger': {
|
|
70
|
-
visibility: 'hidden',
|
|
71
|
-
},
|
|
72
|
-
'&:hover .delete-button': {
|
|
73
|
-
visibility: 'visible',
|
|
74
|
-
},
|
|
75
|
-
'& .delete-button': {
|
|
76
|
-
visibility: 'hidden',
|
|
77
|
-
},
|
|
78
|
-
} }
|
|
79
|
-
>
|
|
80
|
-
<SortableTrigger { ...sortableTriggerProps } />
|
|
81
|
-
<Box
|
|
82
|
-
sx={ { display: 'flex', alignItems: 'center', color: 'text.primary', fontSize: 12, padding: 0.25 } }
|
|
83
|
-
>
|
|
84
|
-
<i className={ icon } />
|
|
85
|
-
</Box>
|
|
86
|
-
<Typography variant="caption" sx={ { color: 'text.primary', flexGrow: 1, fontSize: 10 } }>
|
|
87
|
-
{ prop.label }
|
|
88
|
-
</Typography>
|
|
89
|
-
<IconButton size="tiny" onClick={ handleDelete } aria-label="Delete property" sx={ { p: 0.25 } }>
|
|
90
|
-
<XIcon fontSize="tiny" />
|
|
91
|
-
</IconButton>
|
|
92
|
-
</Box>
|
|
93
|
-
|
|
94
|
-
<Popover
|
|
95
|
-
{ ...popoverProps }
|
|
96
|
-
anchorOrigin={ { vertical: 'bottom', horizontal: 'left' } }
|
|
97
|
-
transformOrigin={ { vertical: 'top', horizontal: 'left' } }
|
|
98
|
-
PaperProps={ { sx: { width: popoverState.anchorEl?.getBoundingClientRect().width } } }
|
|
99
|
-
>
|
|
100
|
-
<OverridablePropForm
|
|
101
|
-
onSubmit={ handleSubmit }
|
|
102
|
-
currentValue={ prop }
|
|
103
|
-
groups={ groups }
|
|
104
|
-
existingLabels={ existingLabels }
|
|
105
|
-
sx={ { width: '100%' } }
|
|
106
|
-
/>
|
|
107
|
-
</Popover>
|
|
108
|
-
</>
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function getElementIcon( prop: OverridableProp ): string {
|
|
113
|
-
const elType = prop.elType === 'widget' ? prop.widgetType : prop.elType;
|
|
114
|
-
|
|
115
|
-
const widgetsCache = getWidgetsCache();
|
|
116
|
-
|
|
117
|
-
if ( ! widgetsCache ) {
|
|
118
|
-
return 'eicon-apps';
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const widgetConfig = widgetsCache[ elType ];
|
|
122
|
-
|
|
123
|
-
return widgetConfig?.icon || 'eicon-apps';
|
|
124
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { GripVerticalIcon } from '@elementor/icons';
|
|
3
|
-
import {
|
|
4
|
-
Box,
|
|
5
|
-
styled,
|
|
6
|
-
UnstableSortableItem,
|
|
7
|
-
type UnstableSortableItemProps,
|
|
8
|
-
type UnstableSortableItemRenderProps,
|
|
9
|
-
UnstableSortableProvider,
|
|
10
|
-
type UnstableSortableProviderProps,
|
|
11
|
-
} from '@elementor/ui';
|
|
12
|
-
|
|
13
|
-
export const SortableProvider = < T extends string >( props: UnstableSortableProviderProps< T > ) => (
|
|
14
|
-
<UnstableSortableProvider restrictAxis variant="static" dragPlaceholderStyle={ { opacity: '1' } } { ...props } />
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
export type SortableTriggerProps = React.HTMLAttributes< HTMLDivElement > & {
|
|
18
|
-
triggerClassName?: string;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export const SortableTrigger = ( { triggerClassName, ...props }: SortableTriggerProps ) => (
|
|
22
|
-
<StyledSortableTrigger
|
|
23
|
-
{ ...props }
|
|
24
|
-
role="button"
|
|
25
|
-
className={ `sortable-trigger ${ triggerClassName ?? '' }`.trim() }
|
|
26
|
-
aria-label="sort"
|
|
27
|
-
>
|
|
28
|
-
<GripVerticalIcon fontSize="tiny" />
|
|
29
|
-
</StyledSortableTrigger>
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
type SortableItemProps = {
|
|
33
|
-
id: UnstableSortableItemProps[ 'id' ];
|
|
34
|
-
children: ( props: SortableItemRenderData ) => React.ReactNode;
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export type SortableItemRenderData = {
|
|
38
|
-
isDragged: boolean;
|
|
39
|
-
isDragPlaceholder: boolean;
|
|
40
|
-
triggerProps: React.HTMLAttributes< HTMLElement >;
|
|
41
|
-
triggerStyle: React.CSSProperties;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
export const SortableItem = ( { children, id }: SortableItemProps ) => (
|
|
45
|
-
<UnstableSortableItem
|
|
46
|
-
id={ id }
|
|
47
|
-
render={ ( {
|
|
48
|
-
itemProps,
|
|
49
|
-
isDragged,
|
|
50
|
-
triggerProps,
|
|
51
|
-
itemStyle,
|
|
52
|
-
triggerStyle,
|
|
53
|
-
dropIndicationStyle,
|
|
54
|
-
showDropIndication,
|
|
55
|
-
isDragOverlay,
|
|
56
|
-
isDragPlaceholder,
|
|
57
|
-
}: UnstableSortableItemRenderProps ) => (
|
|
58
|
-
<Box
|
|
59
|
-
{ ...itemProps }
|
|
60
|
-
style={ itemStyle }
|
|
61
|
-
component="div"
|
|
62
|
-
role="listitem"
|
|
63
|
-
sx={ {
|
|
64
|
-
backgroundColor: isDragOverlay ? 'background.paper' : undefined,
|
|
65
|
-
} }
|
|
66
|
-
>
|
|
67
|
-
{ children( {
|
|
68
|
-
isDragged,
|
|
69
|
-
isDragPlaceholder,
|
|
70
|
-
triggerProps,
|
|
71
|
-
triggerStyle,
|
|
72
|
-
} ) }
|
|
73
|
-
{ showDropIndication && <SortableItemIndicator style={ dropIndicationStyle } /> }
|
|
74
|
-
</Box>
|
|
75
|
-
) }
|
|
76
|
-
/>
|
|
77
|
-
);
|
|
78
|
-
|
|
79
|
-
const StyledSortableTrigger = styled( 'div' )( ( { theme } ) => ( {
|
|
80
|
-
position: 'absolute',
|
|
81
|
-
left: '-2px',
|
|
82
|
-
top: '50%',
|
|
83
|
-
transform: `translate( -${ theme.spacing( 1.5 ) }, -50% )`,
|
|
84
|
-
color: theme.palette.action.active,
|
|
85
|
-
cursor: 'grab',
|
|
86
|
-
} ) );
|
|
87
|
-
|
|
88
|
-
const SortableItemIndicator = styled( Box )`
|
|
89
|
-
width: 100%;
|
|
90
|
-
height: 1px;
|
|
91
|
-
background-color: ${ ( { theme } ) => theme.palette.text.primary };
|
|
92
|
-
`;
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { useState } from 'react';
|
|
2
|
-
import type * as React from 'react';
|
|
3
|
-
import { setDocumentModifiedStatus } from '@elementor/editor-documents';
|
|
4
|
-
import { useEditable } from '@elementor/editor-ui';
|
|
5
|
-
import { __ } from '@wordpress/i18n';
|
|
6
|
-
|
|
7
|
-
import { useCurrentComponentId, useOverridableProps } from '../../../store/store';
|
|
8
|
-
import { renameOverridableGroup } from '../../store/actions/rename-overridable-group';
|
|
9
|
-
import { validateGroupLabel } from './utils/validate-group-label';
|
|
10
|
-
|
|
11
|
-
export type GroupLabelEditableState = {
|
|
12
|
-
editableRef: React.RefObject< HTMLElement | null >;
|
|
13
|
-
isEditing: boolean;
|
|
14
|
-
error: string | null;
|
|
15
|
-
getEditableProps: () => { value: string };
|
|
16
|
-
setEditingGroupId: ( groupId: string ) => void;
|
|
17
|
-
editingGroupId: string | null;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export function useCurrentEditableItem(): GroupLabelEditableState {
|
|
21
|
-
const [ editingGroupId, setEditingGroupId ] = useState< string | null >( null );
|
|
22
|
-
const currentComponentId = useCurrentComponentId();
|
|
23
|
-
const overridableProps = useOverridableProps( currentComponentId );
|
|
24
|
-
|
|
25
|
-
const allGroupsRecord = overridableProps?.groups?.items ?? {};
|
|
26
|
-
const currentGroup = editingGroupId ? allGroupsRecord[ editingGroupId ] : null;
|
|
27
|
-
|
|
28
|
-
const validateLabel = ( newLabel: string ): string | null => {
|
|
29
|
-
const otherGroups = Object.fromEntries(
|
|
30
|
-
Object.entries( allGroupsRecord ).filter( ( [ id ] ) => id !== editingGroupId )
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
return validateGroupLabel( newLabel, otherGroups ) || null;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const handleSubmit = ( newLabel: string ) => {
|
|
37
|
-
if ( ! editingGroupId || ! currentComponentId ) {
|
|
38
|
-
throw new Error( __( 'Group ID or component ID is missing', 'elementor' ) );
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
renameOverridableGroup( {
|
|
42
|
-
componentId: currentComponentId,
|
|
43
|
-
groupId: editingGroupId,
|
|
44
|
-
label: newLabel,
|
|
45
|
-
} );
|
|
46
|
-
|
|
47
|
-
setDocumentModifiedStatus( true );
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const {
|
|
51
|
-
ref: editableRef,
|
|
52
|
-
openEditMode,
|
|
53
|
-
isEditing,
|
|
54
|
-
error,
|
|
55
|
-
getProps: getEditableProps,
|
|
56
|
-
} = useEditable( {
|
|
57
|
-
value: currentGroup?.label ?? '',
|
|
58
|
-
onSubmit: handleSubmit,
|
|
59
|
-
validation: validateLabel,
|
|
60
|
-
} );
|
|
61
|
-
|
|
62
|
-
return {
|
|
63
|
-
editableRef,
|
|
64
|
-
isEditing,
|
|
65
|
-
error,
|
|
66
|
-
getEditableProps,
|
|
67
|
-
setEditingGroupId: ( groupId ) => {
|
|
68
|
-
setEditingGroupId( groupId );
|
|
69
|
-
openEditMode();
|
|
70
|
-
},
|
|
71
|
-
editingGroupId,
|
|
72
|
-
};
|
|
73
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { type OverridablePropsGroup } from '../../../../types';
|
|
2
|
-
|
|
3
|
-
const DEFAULT_NEW_GROUP_LABEL = 'New group';
|
|
4
|
-
|
|
5
|
-
export function generateUniqueLabel( groups: OverridablePropsGroup[] ): string {
|
|
6
|
-
const existingLabels = new Set( groups.map( ( group ) => group.label ) );
|
|
7
|
-
|
|
8
|
-
if ( ! existingLabels.has( DEFAULT_NEW_GROUP_LABEL ) ) {
|
|
9
|
-
return DEFAULT_NEW_GROUP_LABEL;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
let index = 1;
|
|
13
|
-
let newLabel = `${ DEFAULT_NEW_GROUP_LABEL }-${ index }`;
|
|
14
|
-
|
|
15
|
-
while ( existingLabels.has( newLabel ) ) {
|
|
16
|
-
index++;
|
|
17
|
-
newLabel = `${ DEFAULT_NEW_GROUP_LABEL }-${ index }`;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return newLabel;
|
|
21
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { __ } from '@wordpress/i18n';
|
|
2
|
-
|
|
3
|
-
import { type OverridablePropsGroup } from '../../../../types';
|
|
4
|
-
|
|
5
|
-
export const ERROR_MESSAGES = {
|
|
6
|
-
EMPTY_NAME: __( 'Group name is required', 'elementor' ),
|
|
7
|
-
DUPLICATE_NAME: __( 'Group name already exists', 'elementor' ),
|
|
8
|
-
} as const;
|
|
9
|
-
|
|
10
|
-
export function validateGroupLabel( label: string, existingGroups: Record< string, OverridablePropsGroup > ): string {
|
|
11
|
-
const trimmedLabel = label.trim();
|
|
12
|
-
|
|
13
|
-
if ( ! trimmedLabel ) {
|
|
14
|
-
return ERROR_MESSAGES.EMPTY_NAME;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const isDuplicate = Object.values( existingGroups ).some( ( group ) => group.label === trimmedLabel );
|
|
18
|
-
|
|
19
|
-
if ( isDuplicate ) {
|
|
20
|
-
return ERROR_MESSAGES.DUPLICATE_NAME;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return '';
|
|
24
|
-
}
|