@elementor/editor-components 4.0.0-666 → 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,198 +0,0 @@
1
- import { isAtomicWidget } from '@elementor/editor-canvas';
2
- import { getAllDescendants, getElementType, type V1Element } from '@elementor/editor-elements';
3
- import { type NotificationData, notify } from '@elementor/editor-notifications';
4
- import { blockCommand } from '@elementor/editor-v1-adapters';
5
- import { __ } from '@wordpress/i18n';
6
-
7
- import { type ExtendedWindow } from '../../types';
8
- import { isEditingComponent } from '../utils/is-editing-component';
9
-
10
- type CreateArgs = {
11
- container?: V1Element;
12
- model?: {
13
- elType?: string;
14
- widgetType?: string;
15
- };
16
- };
17
-
18
- type MoveArgs = {
19
- containers?: V1Element[];
20
- container?: V1Element;
21
- target?: V1Element;
22
- };
23
-
24
- type PasteArgs = {
25
- containers?: V1Element[];
26
- container?: V1Element;
27
- storageType?: string;
28
- };
29
-
30
- export type ClipboardElement = {
31
- elType?: string;
32
- widgetType?: string;
33
- elements?: ClipboardElement[];
34
- };
35
-
36
- type StorageContent = {
37
- clipboard?: {
38
- elements?: ClipboardElement[];
39
- };
40
- };
41
-
42
- const NON_ATOMIC_ELEMENT_ALERT: NotificationData = {
43
- type: 'default',
44
- message: __( "This widget isn't compatible with components. Use atomic elements instead.", 'elementor' ),
45
- id: 'non-atomic-element-blocked',
46
- };
47
-
48
- export function initNonAtomicNestingPrevention() {
49
- blockCommand( {
50
- command: 'document/elements/create',
51
- condition: blockNonAtomicCreate,
52
- } );
53
-
54
- blockCommand( {
55
- command: 'document/elements/move',
56
- condition: blockNonAtomicMove,
57
- } );
58
-
59
- blockCommand( {
60
- command: 'document/elements/paste',
61
- condition: blockNonAtomicPaste,
62
- } );
63
- }
64
-
65
- export function isElementAtomic( elementType: string ): boolean {
66
- return getElementType( elementType ) !== null;
67
- }
68
-
69
- function blockNonAtomicCreate( args: CreateArgs ): boolean {
70
- if ( ! isEditingComponent() ) {
71
- return false;
72
- }
73
-
74
- const { model } = args;
75
- const elementType = model?.widgetType || model?.elType;
76
-
77
- if ( ! elementType ) {
78
- return false;
79
- }
80
-
81
- if ( isElementAtomic( elementType ) ) {
82
- return false;
83
- }
84
-
85
- notify( NON_ATOMIC_ELEMENT_ALERT );
86
- return true;
87
- }
88
-
89
- function blockNonAtomicMove( args: MoveArgs ): boolean {
90
- if ( ! isEditingComponent() ) {
91
- return false;
92
- }
93
-
94
- const { containers = [ args.container ] } = args;
95
-
96
- const hasNonAtomicElement = containers.some( ( container ) => {
97
- if ( ! container ) {
98
- return false;
99
- }
100
-
101
- const allElements = getAllDescendants( container );
102
-
103
- return allElements.some( ( element ) => ! isAtomicWidget( element ) );
104
- } );
105
-
106
- if ( hasNonAtomicElement ) {
107
- notify( NON_ATOMIC_ELEMENT_ALERT );
108
- }
109
-
110
- return hasNonAtomicElement;
111
- }
112
-
113
- function blockNonAtomicPaste( args: PasteArgs ): boolean {
114
- if ( ! isEditingComponent() ) {
115
- return false;
116
- }
117
-
118
- const { storageType } = args;
119
-
120
- if ( storageType !== 'localstorage' ) {
121
- return false;
122
- }
123
-
124
- const data = (
125
- window as unknown as ExtendedWindow & { elementorCommon?: { storage?: { get: () => StorageContent } } }
126
- )?.elementorCommon?.storage?.get();
127
-
128
- if ( ! data?.clipboard?.elements ) {
129
- return false;
130
- }
131
-
132
- const hasNonAtomicElement = hasNonAtomicElementsInTree( data.clipboard.elements );
133
-
134
- if ( hasNonAtomicElement ) {
135
- notify( NON_ATOMIC_ELEMENT_ALERT );
136
- }
137
-
138
- return hasNonAtomicElement;
139
- }
140
-
141
- export function hasNonAtomicElementsInTree( elements: ClipboardElement[] ): boolean {
142
- for ( const element of elements ) {
143
- const elementType = element.widgetType || element.elType;
144
-
145
- if ( elementType && ! isElementAtomic( elementType ) ) {
146
- return true;
147
- }
148
-
149
- if ( element.elements?.length ) {
150
- if ( hasNonAtomicElementsInTree( element.elements ) ) {
151
- return true;
152
- }
153
- }
154
- }
155
-
156
- return false;
157
- }
158
-
159
- export function findNonAtomicElements( elements: ClipboardElement[] ): string[] {
160
- const nonAtomicElements: string[] = [];
161
-
162
- for ( const element of elements ) {
163
- const elementType = element.widgetType || element.elType;
164
-
165
- if ( elementType && ! isElementAtomic( elementType ) ) {
166
- nonAtomicElements.push( elementType );
167
- }
168
-
169
- if ( element.elements?.length ) {
170
- nonAtomicElements.push( ...findNonAtomicElements( element.elements ) );
171
- }
172
- }
173
-
174
- return [ ...new Set( nonAtomicElements ) ];
175
- }
176
-
177
- type V1ElementLike = {
178
- elType?: string;
179
- widgetType?: string;
180
- elements?: V1ElementLike[];
181
- };
182
-
183
- export function findNonAtomicElementsInElement( element: V1ElementLike ): string[] {
184
- const nonAtomicElements: string[] = [];
185
- const elementType = element.widgetType || element.elType;
186
-
187
- if ( elementType && ! isElementAtomic( elementType ) ) {
188
- nonAtomicElements.push( elementType );
189
- }
190
-
191
- if ( element.elements?.length ) {
192
- for ( const child of element.elements ) {
193
- nonAtomicElements.push( ...findNonAtomicElementsInElement( child ) );
194
- }
195
- }
196
-
197
- return [ ...new Set( nonAtomicElements ) ];
198
- }
@@ -1,66 +0,0 @@
1
- import { type V1Element, type V1ElementData } from '@elementor/editor-elements';
2
- import { registerDataHook } from '@elementor/editor-v1-adapters';
3
-
4
- import { type ExtendedWindow } from '../../types';
5
- import { isEditingComponent } from '../utils/is-editing-component';
6
- import {
7
- revertAllOverridablesInContainer,
8
- revertAllOverridablesInElementData,
9
- } from '../utils/revert-overridable-settings';
10
-
11
- type CopyArgs = {
12
- storageKey?: string;
13
- };
14
-
15
- type ClipboardData = {
16
- type: string;
17
- siteurl: string;
18
- elements: V1ElementData[];
19
- };
20
-
21
- export function initRevertOverridablesOnCopyOrDuplicate() {
22
- registerDataHook( 'after', 'document/elements/duplicate', ( _args, result: V1Element | V1Element[] ) => {
23
- if ( ! isEditingComponent() ) {
24
- return;
25
- }
26
-
27
- revertOverridablesForDuplicatedElements( result );
28
- } );
29
-
30
- registerDataHook( 'after', 'document/elements/copy', ( args: CopyArgs ) => {
31
- if ( ! isEditingComponent() ) {
32
- return;
33
- }
34
-
35
- revertOverridablesInStorage( args.storageKey ?? 'clipboard' );
36
- } );
37
- }
38
-
39
- function revertOverridablesForDuplicatedElements( duplicatedElements: V1Element | V1Element[] ) {
40
- const containers = Array.isArray( duplicatedElements ) ? duplicatedElements : [ duplicatedElements ];
41
-
42
- containers.forEach( ( container ) => {
43
- revertAllOverridablesInContainer( container );
44
- } );
45
- }
46
-
47
- function revertOverridablesInStorage( storageKey: string ) {
48
- const storage = ( window as unknown as ExtendedWindow ).elementorCommon?.storage;
49
-
50
- if ( ! storage ) {
51
- return;
52
- }
53
-
54
- const storageData = storage.get< ClipboardData >( storageKey );
55
-
56
- if ( ! storageData?.elements?.length ) {
57
- return;
58
- }
59
-
60
- const elementsDataWithOverridablesReverted = storageData.elements.map( revertAllOverridablesInElementData );
61
-
62
- storage.set( storageKey, {
63
- ...storageData,
64
- elements: elementsDataWithOverridablesReverted,
65
- } );
66
- }
@@ -1,32 +0,0 @@
1
- import { useEffect } from 'react';
2
-
3
- import { useCurrentComponentId, useIsSanitizedComponent, useOverridableProps } from '../../store/store';
4
- import { filterValidOverridableProps } from '../../utils/filter-valid-overridable-props';
5
- import { deleteOverridableProp } from '../store/actions/delete-overridable-prop';
6
- import { updateComponentSanitizedAttribute } from '../store/actions/update-component-sanitized-attribute';
7
-
8
- export function SanitizeOverridableProps() {
9
- const currentComponentId = useCurrentComponentId();
10
- const overridableProps = useOverridableProps( currentComponentId );
11
- const isSanitized = useIsSanitizedComponent( currentComponentId, 'overridableProps' );
12
-
13
- useEffect( () => {
14
- if ( isSanitized || ! overridableProps || ! currentComponentId ) {
15
- return;
16
- }
17
-
18
- const filtered = filterValidOverridableProps( overridableProps );
19
-
20
- const propsToDelete = Object.keys( overridableProps.props ?? {} ).filter( ( key ) => ! filtered.props[ key ] );
21
-
22
- if ( propsToDelete.length > 0 ) {
23
- propsToDelete.forEach( ( key ) => {
24
- deleteOverridableProp( { componentId: currentComponentId, propKey: key, source: 'system' } );
25
- } );
26
- }
27
-
28
- updateComponentSanitizedAttribute( currentComponentId, 'overridableProps' );
29
- }, [ currentComponentId, isSanitized, overridableProps ] );
30
-
31
- return null;
32
- }
@@ -1,22 +0,0 @@
1
- import { type V1Document } from '@elementor/editor-documents';
2
- import { type V1Element } from '@elementor/editor-elements';
3
-
4
- import { componentsSelectors } from '../../store/selectors';
5
- import { COMPONENT_DOCUMENT_TYPE } from '../consts';
6
-
7
- export const setComponentOverridablePropsSettingsBeforeSave = ( {
8
- container,
9
- }: {
10
- container: V1Element & { document: V1Document };
11
- } ) => {
12
- const currentDocument = container.document;
13
-
14
- if ( ! currentDocument || currentDocument.config.type !== COMPONENT_DOCUMENT_TYPE ) {
15
- return;
16
- }
17
-
18
- const overridableProps = componentsSelectors.getOverridableProps( currentDocument.id );
19
- if ( overridableProps ) {
20
- container.settings.set( 'overridable_props', overridableProps );
21
- }
22
- };
@@ -1,31 +0,0 @@
1
- import { type NotificationData, notify } from '@elementor/editor-notifications';
2
-
3
- import { apiClient } from '../../api';
4
- import { componentsSelectors } from '../../store/selectors';
5
- import { type DocumentSaveStatus } from '../../types';
6
-
7
- const failedNotification = ( message: string ): NotificationData => ( {
8
- type: 'error',
9
- message: `Failed to archive components: ${ message }`,
10
- id: 'failed-archived-components-notification',
11
- } );
12
-
13
- export const updateArchivedComponentBeforeSave = async ( status: DocumentSaveStatus ) => {
14
- try {
15
- const archivedComponents = componentsSelectors.getArchivedThisSession();
16
-
17
- if ( ! archivedComponents.length ) {
18
- return;
19
- }
20
-
21
- const result = await apiClient.updateArchivedComponents( archivedComponents, status );
22
-
23
- const failedIds = result.failedIds.join( ', ' );
24
-
25
- if ( failedIds ) {
26
- notify( failedNotification( failedIds ) );
27
- }
28
- } catch ( error ) {
29
- throw new Error( `Failed to update archived components: ${ error }` );
30
- }
31
- };
@@ -1,18 +0,0 @@
1
- import { apiClient } from '../../api';
2
- import { componentsActions } from '../../store/dispatchers';
3
- import { componentsSelectors } from '../../store/selectors';
4
- import { type DocumentSaveStatus } from '../../types';
5
-
6
- export const updateComponentTitleBeforeSave = async ( status: DocumentSaveStatus ) => {
7
- const updatedComponentNames = componentsSelectors.getUpdatedComponentNames();
8
-
9
- if ( ! updatedComponentNames.length ) {
10
- return;
11
- }
12
-
13
- const result = await apiClient.updateComponentTitle( updatedComponentNames, status );
14
-
15
- if ( result.failedIds.length === 0 ) {
16
- componentsActions.cleanUpdatedComponentNames();
17
- }
18
- };
@@ -1,32 +0,0 @@
1
- import { z } from '@elementor/schema';
2
- import { __ } from '@wordpress/i18n';
3
-
4
- export const MIN_NAME_LENGTH = 2;
5
- const MAX_NAME_LENGTH = 50;
6
-
7
- const baseComponentSchema = z
8
- .string()
9
- .trim()
10
- .max( MAX_NAME_LENGTH, __( 'Component name is too long. Please keep it under 50 characters.', 'elementor' ) );
11
-
12
- export const createBaseComponentSchema = ( existingNames: string[] ) => {
13
- return z.object( {
14
- componentName: baseComponentSchema.refine( ( value ) => ! existingNames.includes( value ), {
15
- message: __( 'Component name already exists', 'elementor' ),
16
- } ),
17
- } );
18
- };
19
-
20
- export const createSubmitComponentSchema = ( existingNames: string[] ) => {
21
- const baseSchema = createBaseComponentSchema( existingNames );
22
-
23
- return baseSchema.extend( {
24
- componentName: baseSchema.shape.componentName
25
- .refine( ( value ) => value.length > 0, {
26
- message: __( 'Component name is required.', 'elementor' ),
27
- } )
28
- .refine( ( value ) => value.length >= MIN_NAME_LENGTH, {
29
- message: __( 'Component name is too short. Please enter at least 2 characters.', 'elementor' ),
30
- } ),
31
- } );
32
- };
@@ -1,25 +0,0 @@
1
- import { componentsSelectors } from '../../store/selectors';
2
- import { createSubmitComponentSchema } from './component-form-schema';
3
-
4
- type ValidationResult = { isValid: true; errorMessage: null } | { isValid: false; errorMessage: string };
5
-
6
- export function validateComponentName( label: string ): ValidationResult {
7
- const existingComponentTitles = componentsSelectors.getComponents()?.map( ( { name } ) => name ) ?? [];
8
- const schema = createSubmitComponentSchema( existingComponentTitles );
9
- const result = schema.safeParse( { componentName: label.toLowerCase() } );
10
-
11
- if ( result.success ) {
12
- return {
13
- isValid: true,
14
- errorMessage: null,
15
- };
16
- }
17
-
18
- const formattedErrors = result.error.format();
19
- const errorMessage = formattedErrors.componentName?._errors[ 0 ] ?? formattedErrors._errors[ 0 ];
20
-
21
- return {
22
- isValid: false,
23
- errorMessage,
24
- };
25
- }
@@ -1,28 +0,0 @@
1
- import { type V1ElementModelProps } from '@elementor/editor-elements';
2
-
3
- export type ComponentInstanceParams = {
4
- id?: number;
5
- name: string;
6
- uid: string;
7
- };
8
-
9
- export const createComponentModel = ( component: ComponentInstanceParams ): Omit< V1ElementModelProps, 'id' > => {
10
- return {
11
- elType: 'widget',
12
- widgetType: 'e-component',
13
- settings: {
14
- component_instance: {
15
- $$type: 'component-instance',
16
- value: {
17
- component_id: {
18
- $$type: 'number',
19
- value: component.id ?? component.uid,
20
- },
21
- },
22
- },
23
- },
24
- editor_settings: {
25
- component_uid: component.uid,
26
- },
27
- };
28
- };
@@ -1,49 +0,0 @@
1
- import {
2
- getContainer,
3
- getCurrentDocumentContainer,
4
- getSelectedElements,
5
- type V1Element,
6
- } from '@elementor/editor-elements';
7
-
8
- export const getContainerForNewElement = (): { container: V1Element | null; options?: { at: number } } => {
9
- const currentDocumentContainer = getCurrentDocumentContainer();
10
- const selectedElement = getSelectedElementContainer();
11
-
12
- let container, options;
13
-
14
- if ( selectedElement ) {
15
- switch ( selectedElement.model.get( 'elType' ) ) {
16
- case 'widget': {
17
- container = selectedElement?.parent;
18
-
19
- const selectedElIndex = selectedElement.view?._index ?? -1;
20
-
21
- if ( selectedElIndex > -1 ) {
22
- options = { at: selectedElIndex + 1 };
23
- }
24
-
25
- break;
26
- }
27
- case 'section': {
28
- container = selectedElement?.children?.[ 0 ];
29
- break;
30
- }
31
- default: {
32
- container = selectedElement;
33
- break;
34
- }
35
- }
36
- }
37
-
38
- return { container: container ?? currentDocumentContainer, options };
39
- };
40
-
41
- function getSelectedElementContainer() {
42
- const selectedElements = getSelectedElements();
43
-
44
- if ( selectedElements.length !== 1 ) {
45
- return undefined;
46
- }
47
-
48
- return getContainer( selectedElements[ 0 ].id );
49
- }
@@ -1,5 +0,0 @@
1
- import { componentsSelectors } from '../../store/selectors';
2
-
3
- export function isEditingComponent(): boolean {
4
- return componentsSelectors.getCurrentComponentId() !== null;
5
- }
@@ -1,11 +0,0 @@
1
- import { replaceElement, type V1ElementData } from '@elementor/editor-elements';
2
-
3
- import { type ComponentInstanceParams, createComponentModel } from './create-component-model';
4
-
5
- export const replaceElementWithComponent = ( element: V1ElementData, component: ComponentInstanceParams ) => {
6
- return replaceElement( {
7
- currentElementId: element.id,
8
- newElement: createComponentModel( component ),
9
- withHistory: false,
10
- } );
11
- };