@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.
Files changed (72) hide show
  1. package/dist/index.js +191 -3870
  2. package/dist/index.js.map +1 -1
  3. package/dist/index.mjs +184 -3904
  4. package/dist/index.mjs.map +1 -1
  5. package/package.json +23 -23
  6. package/src/init.ts +0 -13
  7. package/src/extended/components/component-introduction.tsx +0 -77
  8. package/src/extended/components/component-panel-header/component-badge.tsx +0 -73
  9. package/src/extended/components/component-panel-header/component-panel-header.tsx +0 -98
  10. package/src/extended/components/component-properties-panel/component-properties-panel-content.tsx +0 -176
  11. package/src/extended/components/component-properties-panel/component-properties-panel.tsx +0 -43
  12. package/src/extended/components/component-properties-panel/properties-empty-state.tsx +0 -51
  13. package/src/extended/components/component-properties-panel/properties-group.tsx +0 -196
  14. package/src/extended/components/component-properties-panel/property-item.tsx +0 -124
  15. package/src/extended/components/component-properties-panel/sortable.tsx +0 -92
  16. package/src/extended/components/component-properties-panel/use-current-editable-item.ts +0 -73
  17. package/src/extended/components/component-properties-panel/utils/generate-unique-label.ts +0 -21
  18. package/src/extended/components/component-properties-panel/utils/validate-group-label.ts +0 -24
  19. package/src/extended/components/components-tab/component-item.tsx +0 -180
  20. package/src/extended/components/components-tab/components.tsx +0 -58
  21. package/src/extended/components/components-tab/delete-confirmation-dialog.tsx +0 -26
  22. package/src/extended/components/create-component-form/create-component-form.tsx +0 -281
  23. package/src/extended/components/create-component-form/hooks/use-form.ts +0 -72
  24. package/src/extended/components/create-component-form/utils/get-component-event-data.ts +0 -54
  25. package/src/extended/components/edit-component/component-modal.tsx +0 -133
  26. package/src/extended/components/edit-component/edit-component.tsx +0 -166
  27. package/src/extended/components/edit-component/use-canvas-document.ts +0 -9
  28. package/src/extended/components/edit-component/use-element-rect.ts +0 -81
  29. package/src/extended/components/instance-editing-panel/instance-editing-panel.tsx +0 -60
  30. package/src/extended/components/overridable-props/indicator.tsx +0 -83
  31. package/src/extended/components/overridable-props/overridable-prop-control.tsx +0 -127
  32. package/src/extended/components/overridable-props/overridable-prop-form.tsx +0 -135
  33. package/src/extended/components/overridable-props/overridable-prop-indicator.tsx +0 -138
  34. package/src/extended/components/overridable-props/utils/validate-prop-label.ts +0 -38
  35. package/src/extended/consts.ts +0 -3
  36. package/src/extended/hooks/use-navigate-back.ts +0 -24
  37. package/src/extended/init.ts +0 -108
  38. package/src/extended/mcp/index.ts +0 -14
  39. package/src/extended/mcp/save-as-component-tool.ts +0 -436
  40. package/src/extended/shortcuts/create-component-shortcut.ts +0 -121
  41. package/src/extended/store/actions/add-overridable-group.ts +0 -53
  42. package/src/extended/store/actions/archive-component.ts +0 -18
  43. package/src/extended/store/actions/create-unpublished-component.ts +0 -99
  44. package/src/extended/store/actions/delete-overridable-group.ts +0 -32
  45. package/src/extended/store/actions/delete-overridable-prop.ts +0 -64
  46. package/src/extended/store/actions/rename-component.ts +0 -48
  47. package/src/extended/store/actions/rename-overridable-group.ts +0 -33
  48. package/src/extended/store/actions/reorder-group-props.ts +0 -37
  49. package/src/extended/store/actions/reorder-overridable-groups.ts +0 -24
  50. package/src/extended/store/actions/reset-sanitized-components.ts +0 -5
  51. package/src/extended/store/actions/set-overridable-prop.ts +0 -109
  52. package/src/extended/store/actions/update-component-sanitized-attribute.ts +0 -7
  53. package/src/extended/store/actions/update-current-component.ts +0 -12
  54. package/src/extended/store/actions/update-overridable-prop-params.ts +0 -52
  55. package/src/extended/store/utils/groups-transformers.ts +0 -187
  56. package/src/extended/sync/before-save.ts +0 -52
  57. package/src/extended/sync/cleanup-overridable-props-on-delete.ts +0 -78
  58. package/src/extended/sync/create-components-before-save.ts +0 -111
  59. package/src/extended/sync/handle-component-edit-mode-container.ts +0 -114
  60. package/src/extended/sync/prevent-non-atomic-nesting.ts +0 -198
  61. package/src/extended/sync/revert-overridables-on-copy-or-duplicate.ts +0 -66
  62. package/src/extended/sync/sanitize-overridable-props.ts +0 -32
  63. package/src/extended/sync/set-component-overridable-props-settings-before-save.ts +0 -22
  64. package/src/extended/sync/update-archived-component-before-save.ts +0 -31
  65. package/src/extended/sync/update-component-title-before-save.ts +0 -18
  66. package/src/extended/utils/component-form-schema.ts +0 -32
  67. package/src/extended/utils/component-name-validation.ts +0 -25
  68. package/src/extended/utils/create-component-model.ts +0 -28
  69. package/src/extended/utils/get-container-for-new-element.ts +0 -49
  70. package/src/extended/utils/is-editing-component.ts +0 -5
  71. package/src/extended/utils/replace-element-with-component.ts +0 -11
  72. package/src/extended/utils/revert-overridable-settings.ts +0 -207
@@ -1,187 +0,0 @@
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 | string[] ): Groups {
9
- const propKeys = Array.isArray( propKey ) ? propKey : [ propKey ];
10
-
11
- return {
12
- ...groups,
13
- items: Object.fromEntries(
14
- Object.entries( groups.items ).map( ( [ groupId, group ] ) => [
15
- groupId,
16
- {
17
- ...group,
18
- props: group.props.filter( ( p ) => ! propKeys.includes( p ) ),
19
- },
20
- ] )
21
- ),
22
- };
23
- }
24
-
25
- export function addPropToGroup( groups: Groups, groupId: string, propKey: string ): Groups {
26
- const group = groups.items[ groupId ];
27
-
28
- if ( ! group ) {
29
- return groups;
30
- }
31
-
32
- if ( group.props.includes( propKey ) ) {
33
- return groups;
34
- }
35
-
36
- return {
37
- ...groups,
38
- items: {
39
- ...groups.items,
40
- [ groupId ]: {
41
- ...group,
42
- props: [ ...group.props, propKey ],
43
- },
44
- },
45
- };
46
- }
47
-
48
- export function movePropBetweenGroups(
49
- groups: Groups,
50
- propKey: string,
51
- fromGroupId: string,
52
- toGroupId: string
53
- ): Groups {
54
- if ( fromGroupId === toGroupId ) {
55
- return groups;
56
- }
57
-
58
- const withoutProp = removePropFromGroup( groups, fromGroupId, propKey );
59
- return addPropToGroup( withoutProp, toGroupId, propKey );
60
- }
61
-
62
- export function removePropFromGroup( groups: Groups, groupId: string, propKey: string ): Groups {
63
- const group = groups.items[ groupId ];
64
-
65
- if ( ! group ) {
66
- return groups;
67
- }
68
-
69
- return {
70
- ...groups,
71
- items: {
72
- ...groups.items,
73
- [ groupId ]: {
74
- ...group,
75
- props: group.props.filter( ( p ) => p !== propKey ),
76
- },
77
- },
78
- };
79
- }
80
-
81
- type ResolvedGroup = {
82
- groups: Groups;
83
- groupId: string;
84
- };
85
-
86
- export function resolveOrCreateGroup( groups: Groups, requestedGroupId?: string ): ResolvedGroup {
87
- if ( requestedGroupId && groups.items[ requestedGroupId ] ) {
88
- return { groups, groupId: requestedGroupId };
89
- }
90
-
91
- if ( ! requestedGroupId && groups.order.length > 0 ) {
92
- return { groups, groupId: groups.order[ 0 ] };
93
- }
94
-
95
- return createGroup( groups, requestedGroupId );
96
- }
97
-
98
- function createGroup( groups: Groups, groupId?: string, label?: string ): ResolvedGroup {
99
- const newGroupId = groupId || generateUniqueId( 'group' );
100
- const newLabel = label || __( 'Default', 'elementor' );
101
-
102
- return {
103
- groups: {
104
- ...groups,
105
- items: {
106
- ...groups.items,
107
- [ newGroupId ]: {
108
- id: newGroupId,
109
- label: newLabel,
110
- props: [],
111
- },
112
- },
113
- order: [ ...groups.order, newGroupId ],
114
- },
115
- groupId: newGroupId,
116
- };
117
- }
118
-
119
- export function removePropsFromState(
120
- overridableProps: OverridableProps,
121
- propsToRemove: OverridableProp[]
122
- ): OverridableProps {
123
- const overrideKeysToRemove = propsToRemove.map( ( prop ) => prop.overrideKey );
124
-
125
- const remainingProps = Object.fromEntries(
126
- Object.entries( overridableProps.props ).filter( ( [ , prop ] ) => ! propsToRemove.includes( prop ) )
127
- );
128
-
129
- const updatedGroupItems = Object.fromEntries(
130
- Object.entries( overridableProps.groups.items ).map(
131
- ( [ groupId, group ]: [ string, OverridablePropsGroup ] ) => [
132
- groupId,
133
- {
134
- ...group,
135
- props: group.props.filter( ( prop ) => ! overrideKeysToRemove.includes( prop ) ),
136
- },
137
- ]
138
- )
139
- );
140
-
141
- return {
142
- props: remainingProps,
143
- groups: {
144
- items: updatedGroupItems,
145
- order: overridableProps.groups.order.filter( ( groupId ) => ! overrideKeysToRemove.includes( groupId ) ),
146
- },
147
- };
148
- }
149
-
150
- export function ensureGroupInOrder( groups: Groups, groupId: string ): Groups {
151
- if ( groups.order.includes( groupId ) ) {
152
- return groups;
153
- }
154
-
155
- return {
156
- ...groups,
157
- order: [ ...groups.order, groupId ],
158
- };
159
- }
160
-
161
- export function deleteGroup( groups: Groups, groupId: string ): Groups {
162
- const { [ groupId ]: removed, ...remainingItems } = groups.items;
163
-
164
- return {
165
- items: remainingItems,
166
- order: groups.order.filter( ( id ) => id !== groupId ),
167
- };
168
- }
169
-
170
- export function renameGroup( groups: Groups, groupId: string, newLabel: string ): Groups {
171
- const group = groups.items[ groupId ];
172
-
173
- if ( ! group ) {
174
- return groups;
175
- }
176
-
177
- return {
178
- ...groups,
179
- items: {
180
- ...groups.items,
181
- [ groupId ]: {
182
- ...group,
183
- label: newLabel,
184
- },
185
- },
186
- };
187
- }
@@ -1,52 +0,0 @@
1
- import { type V1Document } from '@elementor/editor-documents';
2
- import { type V1Element, type V1ElementData } from '@elementor/editor-elements';
3
-
4
- import { publishDraftComponentsInPageBeforeSave } from '../../sync/publish-draft-components-in-page-before-save';
5
- import { type DocumentSaveStatus } from '../../types';
6
- import { setComponentOverridablePropsSettingsBeforeSave } from '../sync/set-component-overridable-props-settings-before-save';
7
- import { updateArchivedComponentBeforeSave } from '../sync/update-archived-component-before-save';
8
- import { updateComponentTitleBeforeSave } from '../sync/update-component-title-before-save';
9
- import { createComponentsBeforeSave } from './create-components-before-save';
10
-
11
- type Options = {
12
- container: V1Element & {
13
- document: V1Document;
14
- model: {
15
- get: ( key: 'elements' ) => {
16
- toJSON: () => V1ElementData[];
17
- };
18
- };
19
- };
20
- status: DocumentSaveStatus;
21
- };
22
-
23
- export const beforeSave = ( { container, status }: Options ) => {
24
- const elements = container?.model.get( 'elements' ).toJSON?.() ?? [];
25
-
26
- return Promise.all( [
27
- syncComponents( { elements, status } ),
28
- setComponentOverridablePropsSettingsBeforeSave( { container } ),
29
- ] );
30
- };
31
-
32
- // These operations run sequentially to prevent race conditions when multiple
33
- // edits occur on the same component simultaneously.
34
- // TODO: Consolidate these into a single PUT /components endpoint.
35
- const syncComponents = async ( { elements, status }: { elements: V1ElementData[]; status: DocumentSaveStatus } ) => {
36
- // This order is important - first update existing components, then create new components,
37
- // Since new component validation depends on the existing components (preventing duplicate names).
38
- await updateExistingComponentsBeforeSave( { elements, status } );
39
- await createComponentsBeforeSave( { elements, status } );
40
- };
41
-
42
- const updateExistingComponentsBeforeSave = async ( {
43
- elements,
44
- status,
45
- }: {
46
- elements: V1ElementData[];
47
- status: DocumentSaveStatus;
48
- } ) => {
49
- await updateComponentTitleBeforeSave( status );
50
- await updateArchivedComponentBeforeSave( status );
51
- await publishDraftComponentsInPageBeforeSave( { elements, status } );
52
- };
@@ -1,78 +0,0 @@
1
- import { getAllDescendants, type V1Element } from '@elementor/editor-elements';
2
- import { type HookOptions, registerDataHook } from '@elementor/editor-v1-adapters';
3
-
4
- import { componentsSelectors } from '../../store/selectors';
5
- import { deleteOverridableProp } from '../store/actions/delete-overridable-prop';
6
-
7
- type DeleteCommandArgs = {
8
- container?: V1Element;
9
- containers?: V1Element[];
10
- };
11
-
12
- export function initCleanupOverridablePropsOnDelete() {
13
- // This hook is not a real dependency - it doesn't block the execution of the command in any case, only perform side effect.
14
- // We use `dependency` and not `after` hook because the `after` hook doesn't include the children of a deleted container
15
- // in the callback parameters (as they already were deleted).
16
- registerDataHook( 'dependency', 'document/elements/delete', ( args: DeleteCommandArgs, options?: HookOptions ) => {
17
- if ( isPartOfMoveCommand( options ) ) {
18
- return true;
19
- }
20
-
21
- const currentComponentId = componentsSelectors.getCurrentComponentId();
22
-
23
- if ( ! currentComponentId ) {
24
- return true;
25
- }
26
-
27
- const overridableProps = componentsSelectors.getOverridableProps( currentComponentId );
28
-
29
- if ( ! overridableProps || Object.keys( overridableProps.props ).length === 0 ) {
30
- return true;
31
- }
32
-
33
- const containers = args.containers ?? ( args.container ? [ args.container ] : [] );
34
-
35
- if ( containers.length === 0 ) {
36
- return true;
37
- }
38
-
39
- const deletedElementIds = collectDeletedElementIds( containers );
40
-
41
- if ( deletedElementIds.length === 0 ) {
42
- return true;
43
- }
44
-
45
- const propKeysToDelete = Object.entries( overridableProps.props )
46
- .filter( ( [ , prop ] ) => deletedElementIds.includes( prop.elementId ) )
47
- .map( ( [ propKey ] ) => propKey );
48
-
49
- if ( propKeysToDelete.length === 0 ) {
50
- return true;
51
- }
52
-
53
- deleteOverridableProp( { componentId: currentComponentId, propKey: propKeysToDelete, source: 'system' } );
54
-
55
- return true;
56
- } );
57
- }
58
-
59
- function collectDeletedElementIds( containers: V1Element[] ): string[] {
60
- const elementIds = containers
61
- .filter( Boolean )
62
- .flatMap( ( container ) => [ container, ...getAllDescendants( container ) ] )
63
- .map( ( element ) => element.model?.get?.( 'id' ) ?? element.id )
64
- .filter( ( id ): id is string => Boolean( id ) );
65
-
66
- return elementIds;
67
- }
68
-
69
- function isPartOfMoveCommand( options?: HookOptions ): boolean {
70
- // Skip cleanup if this delete is part of a move command
71
- // Move = delete + create, and we don't want to delete the overridable prop in this case.
72
- // See assets/dev/js/editor/document/elements/commands/move.js
73
- const isMoveCommandInTrace =
74
- options?.commandsCurrentTrace?.includes( 'document/elements/move' ) ||
75
- options?.commandsCurrentTrace?.includes( 'document/repeater/move' );
76
-
77
- return Boolean( isMoveCommandInTrace );
78
- }
@@ -1,111 +0,0 @@
1
- import { updateElementSettings, type V1ElementData } from '@elementor/editor-elements';
2
-
3
- import { apiClient } from '../../api';
4
- import { type ComponentInstanceProp } from '../../prop-types/component-instance-prop-type';
5
- import { componentsActions } from '../../store/dispatchers';
6
- import { componentsSelectors } from '../../store/selectors';
7
- import { type DocumentSaveStatus, type UnpublishedComponent } from '../../types';
8
-
9
- export async function createComponentsBeforeSave( {
10
- elements,
11
- status,
12
- }: {
13
- elements: V1ElementData[];
14
- status: DocumentSaveStatus;
15
- } ) {
16
- const unpublishedComponents = componentsSelectors.getUnpublishedComponents();
17
-
18
- if ( ! unpublishedComponents.length ) {
19
- return;
20
- }
21
-
22
- try {
23
- const uidToComponentId = await createComponents( unpublishedComponents, status );
24
-
25
- updateComponentInstances( elements, uidToComponentId );
26
-
27
- componentsActions.add(
28
- unpublishedComponents.map( ( component ) => ( {
29
- id: uidToComponentId.get( component.uid ) as number,
30
- name: component.name,
31
- uid: component.uid,
32
- overridableProps: component.overridableProps ? component.overridableProps : undefined,
33
- } ) )
34
- );
35
- componentsActions.resetUnpublished();
36
- } catch ( error ) {
37
- const failedUids = unpublishedComponents.map( ( component ) => component.uid );
38
- componentsActions.removeUnpublished( failedUids );
39
-
40
- throw new Error( `Failed to publish components: ${ error }` );
41
- }
42
- }
43
-
44
- async function createComponents(
45
- components: UnpublishedComponent[],
46
- status: DocumentSaveStatus
47
- ): Promise< Map< string, number > > {
48
- const response = await apiClient.create( {
49
- status,
50
- items: components.map( ( component ) => ( {
51
- uid: component.uid,
52
- title: component.name,
53
- elements: component.elements,
54
- settings: component.overridableProps ? { overridable_props: component.overridableProps } : undefined,
55
- } ) ),
56
- } );
57
-
58
- const map = new Map< string, number >();
59
-
60
- Object.entries( response ).forEach( ( [ key, value ] ) => {
61
- map.set( key, value );
62
- } );
63
-
64
- return map;
65
- }
66
-
67
- function updateComponentInstances( elements: V1ElementData[], uidToComponentId: Map< string, number > ): void {
68
- elements.forEach( ( element ) => {
69
- const { shouldUpdate, newComponentId } = shouldUpdateElement( element, uidToComponentId );
70
- if ( shouldUpdate ) {
71
- updateElementComponentId( element.id, newComponentId );
72
- }
73
-
74
- if ( element.elements ) {
75
- updateComponentInstances( element.elements, uidToComponentId );
76
- }
77
- } );
78
- }
79
-
80
- function shouldUpdateElement(
81
- element: V1ElementData,
82
- uidToComponentId: Map< string, number >
83
- ): { shouldUpdate: true; newComponentId: number } | { shouldUpdate: false; newComponentId: null } {
84
- if ( element.widgetType === 'e-component' ) {
85
- const currentComponentId = ( element.settings?.component_instance as ComponentInstanceProp )?.value
86
- ?.component_id.value;
87
-
88
- if ( currentComponentId && uidToComponentId.has( currentComponentId.toString() ) ) {
89
- return {
90
- shouldUpdate: true,
91
- newComponentId: uidToComponentId.get( currentComponentId.toString() ) as number,
92
- };
93
- }
94
- }
95
- return { shouldUpdate: false, newComponentId: null };
96
- }
97
-
98
- function updateElementComponentId( elementId: string, componentId: number ): void {
99
- updateElementSettings( {
100
- id: elementId,
101
- props: {
102
- component_instance: {
103
- $$type: 'component-instance',
104
- value: {
105
- component_id: { $$type: 'number', value: componentId },
106
- },
107
- },
108
- },
109
- withHistory: false,
110
- } );
111
- }
@@ -1,114 +0,0 @@
1
- import { type V1Document } from '@elementor/editor-documents';
2
- import { createElement, selectElement, type V1Element } from '@elementor/editor-elements';
3
- import { registerDataHook } from '@elementor/editor-v1-adapters';
4
-
5
- import { COMPONENT_DOCUMENT_TYPE } from '../consts';
6
- import { isEditingComponent } from '../utils/is-editing-component';
7
-
8
- const V4_DEFAULT_CONTAINER_TYPE = 'e-flexbox';
9
-
10
- type Container = Omit< V1Element, 'children' | 'parent' > & {
11
- document?: V1Document;
12
- parent?: Container;
13
- children?: Container[];
14
- };
15
-
16
- export function initHandleComponentEditModeContainer() {
17
- initRedirectDropIntoComponent();
18
- initHandleTopLevelElementDelete();
19
- }
20
-
21
- export type DeleteArgs = {
22
- container?: Container;
23
- containers?: Container[];
24
- };
25
-
26
- function initHandleTopLevelElementDelete() {
27
- registerDataHook( 'after', 'document/elements/delete', ( args: DeleteArgs ) => {
28
- if ( ! isEditingComponent() ) {
29
- return;
30
- }
31
-
32
- const containers = args.containers ?? ( args.container ? [ args.container ] : [] );
33
-
34
- for ( const container of containers ) {
35
- if ( ! container.parent || ! isComponent( container.parent ) ) {
36
- continue;
37
- }
38
-
39
- const component = container.parent;
40
- const isComponentEmpty = component.children?.length === 0;
41
-
42
- if ( isComponentEmpty ) {
43
- createEmptyTopLevelContainer( container.parent );
44
- }
45
- }
46
- } );
47
- }
48
-
49
- type DropArgs = {
50
- container?: Container;
51
- containers?: Container[];
52
- model?: unknown;
53
- options?: unknown;
54
- };
55
-
56
- function initRedirectDropIntoComponent() {
57
- registerDataHook( 'dependency', 'preview/drop', ( args: DropArgs ) => {
58
- if ( ! isEditingComponent() ) {
59
- return true;
60
- }
61
-
62
- const containers = args.containers ?? ( args.container ? [ args.container ] : [] );
63
-
64
- for ( const container of containers ) {
65
- if ( ! isComponent( container ) ) {
66
- continue;
67
- }
68
-
69
- const { shouldRedirect, container: redirectedContainer } = getComponentContainer( container );
70
-
71
- if ( ! shouldRedirect ) {
72
- continue;
73
- }
74
-
75
- if ( args.containers ) {
76
- const index = args.containers.indexOf( container );
77
- args.containers[ index ] = redirectedContainer;
78
- } else {
79
- args.container = redirectedContainer;
80
- }
81
- }
82
-
83
- return true;
84
- } );
85
- }
86
-
87
- function createEmptyTopLevelContainer( container: Container ) {
88
- const newContainer = createElement( {
89
- container,
90
- model: { elType: V4_DEFAULT_CONTAINER_TYPE },
91
- } );
92
-
93
- selectElement( newContainer.id );
94
- }
95
-
96
- function getComponentContainer( container: Container ): { shouldRedirect: boolean; container: Container } {
97
- const topLevelElement = container.children?.[ 0 ];
98
-
99
- if ( topLevelElement ) {
100
- return { shouldRedirect: true, container: topLevelElement };
101
- }
102
-
103
- return { shouldRedirect: false, container };
104
- }
105
-
106
- function isComponent( container: Container ): boolean {
107
- const isDocument = container.id === 'document';
108
-
109
- if ( ! isDocument ) {
110
- return false;
111
- }
112
-
113
- return container.document?.config.type === COMPONENT_DOCUMENT_TYPE;
114
- }