@elementor/editor-components 3.33.0-99 → 3.34.2

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 (53) hide show
  1. package/dist/index.js +1860 -123
  2. package/dist/index.js.map +1 -1
  3. package/dist/index.mjs +1863 -110
  4. package/dist/index.mjs.map +1 -1
  5. package/package.json +21 -11
  6. package/src/api.ts +57 -11
  7. package/src/component-instance-transformer.ts +24 -0
  8. package/src/component-overridable-transformer.ts +28 -0
  9. package/src/components/components-tab/component-search.tsx +32 -0
  10. package/src/components/components-tab/components-item.tsx +67 -0
  11. package/src/components/components-tab/components-list.tsx +141 -0
  12. package/src/components/components-tab/components.tsx +17 -0
  13. package/src/components/components-tab/loading-components.tsx +43 -0
  14. package/src/components/components-tab/search-provider.tsx +38 -0
  15. package/src/components/consts.ts +1 -0
  16. package/src/components/create-component-form/create-component-form.tsx +109 -100
  17. package/src/components/create-component-form/utils/get-component-event-data.ts +54 -0
  18. package/src/components/create-component-form/utils/replace-element-with-component.ts +28 -10
  19. package/src/components/edit-component/component-modal.tsx +134 -0
  20. package/src/components/edit-component/edit-component.tsx +134 -0
  21. package/src/components/in-edit-mode.tsx +43 -0
  22. package/src/components/overridable-props/indicator.tsx +81 -0
  23. package/src/components/overridable-props/overridable-prop-form.tsx +98 -0
  24. package/src/components/overridable-props/overridable-prop-indicator.tsx +128 -0
  25. package/src/components/overridable-props/utils/get-overridable-prop.ts +20 -0
  26. package/src/create-component-type.ts +194 -0
  27. package/src/hooks/use-canvas-document.ts +6 -0
  28. package/src/hooks/use-components.ts +6 -9
  29. package/src/hooks/use-element-rect.ts +81 -0
  30. package/src/init.ts +82 -3
  31. package/src/mcp/index.ts +14 -0
  32. package/src/mcp/save-as-component-tool.ts +92 -0
  33. package/src/populate-store.ts +12 -0
  34. package/src/prop-types/component-overridable-prop-type.ts +17 -0
  35. package/src/store/actions.ts +21 -0
  36. package/src/store/components-styles-provider.ts +24 -0
  37. package/src/store/create-unpublished-component.ts +40 -0
  38. package/src/store/load-components-assets.ts +26 -0
  39. package/src/store/load-components-styles.ts +44 -0
  40. package/src/store/remove-component-styles.ts +9 -0
  41. package/src/store/set-overridable-prop.ts +161 -0
  42. package/src/store/store.ts +168 -0
  43. package/src/store/thunks.ts +10 -0
  44. package/src/sync/before-save.ts +15 -0
  45. package/src/sync/create-components-before-save.ts +108 -0
  46. package/src/sync/update-components-before-save.ts +36 -0
  47. package/src/types.ts +91 -0
  48. package/src/utils/component-document-data.ts +19 -0
  49. package/src/utils/get-component-ids.ts +36 -0
  50. package/src/utils/get-container-for-new-element.ts +49 -0
  51. package/src/utils/tracking.ts +47 -0
  52. package/src/components/components-tab.tsx +0 -6
  53. package/src/hooks/use-create-component.ts +0 -13
package/src/types.ts CHANGED
@@ -1,3 +1,94 @@
1
+ import { type V1ElementData } from '@elementor/editor-elements';
2
+ import { type PropValue, type TransformablePropValue } from '@elementor/editor-props';
3
+ import type { StyleDefinition } from '@elementor/editor-styles';
4
+
1
5
  export type ComponentFormValues = {
2
6
  componentName: string;
3
7
  };
8
+
9
+ export type ComponentId = number;
10
+
11
+ export type StylesDefinition = Record< ComponentId, StyleDefinition[] >;
12
+
13
+ export type Component = PublishedComponent | UnpublishedComponent;
14
+
15
+ export type PublishedComponent = BaseComponent & {
16
+ id: number;
17
+ };
18
+
19
+ export type UnpublishedComponent = BaseComponent & {
20
+ elements: V1ElementData[];
21
+ };
22
+
23
+ export type OverridableProp = {
24
+ overrideKey: string;
25
+ label: string;
26
+ elementId: string;
27
+ propKey: string;
28
+ elType: string;
29
+ widgetType: string;
30
+ originValue: PropValue;
31
+ groupId: string;
32
+ };
33
+
34
+ export type OverridablePropsGroup = {
35
+ id: string;
36
+ label: string;
37
+ props: string[];
38
+ };
39
+
40
+ export type OverridableProps = {
41
+ props: Record< string, OverridableProp >;
42
+ groups: {
43
+ items: Record< string, OverridablePropsGroup >;
44
+ order: string[];
45
+ };
46
+ };
47
+
48
+ type BaseComponent = {
49
+ uid: string;
50
+ name: string;
51
+ overridableProps?: OverridableProps;
52
+ };
53
+
54
+ export type DocumentStatus = 'publish' | 'draft';
55
+ export type DocumentSaveStatus = DocumentStatus | 'autosave';
56
+
57
+ export type ExtendedWindow = Window & {
58
+ elementorCommon: Record< string, unknown > & {
59
+ eventsManager: {
60
+ config: {
61
+ locations: Record< string, string >;
62
+ secondaryLocations: Record< string, string >;
63
+ triggers: Record< string, string >;
64
+ };
65
+ };
66
+ };
67
+ };
68
+
69
+ export type Container = {
70
+ model: {
71
+ get: ( key: 'elements' ) => {
72
+ toJSON: () => V1ElementData[];
73
+ };
74
+ };
75
+ };
76
+
77
+ export type ComponentInstancePropValue< TComponentId extends number | string = number | string > =
78
+ TransformablePropValue<
79
+ 'component-instance',
80
+ {
81
+ component_id: TComponentId;
82
+ overrides?: ComponentOverride[];
83
+ }
84
+ >;
85
+
86
+ type ComponentOverride = {
87
+ override_key: string;
88
+ value: TransformablePropValue< string >;
89
+ };
90
+
91
+ export type ComponentOverridable = {
92
+ override_key: string;
93
+ origin_value: TransformablePropValue< string >;
94
+ };
@@ -0,0 +1,19 @@
1
+ import { type Document, getV1DocumentsManager } from '@elementor/editor-documents';
2
+
3
+ type ComponentDocumentData = Document;
4
+
5
+ export const getComponentDocumentData = async ( id: number ) => {
6
+ const documentManager = getV1DocumentsManager();
7
+
8
+ try {
9
+ return await documentManager.request< ComponentDocumentData >( id );
10
+ } catch {
11
+ return null;
12
+ }
13
+ };
14
+
15
+ export const invalidateComponentDocumentData = ( id: number ) => {
16
+ const documentManager = getV1DocumentsManager();
17
+
18
+ documentManager.invalidateCache( id );
19
+ };
@@ -0,0 +1,36 @@
1
+ import { type V1ElementData } from '@elementor/editor-elements';
2
+
3
+ import { TYPE } from '../create-component-type';
4
+ import { type ComponentInstancePropValue } from '../types';
5
+ import { getComponentDocumentData } from './component-document-data';
6
+
7
+ export const getComponentIds = async ( elements: V1ElementData[] ) => {
8
+ const components = elements.map( async ( { widgetType, elType, elements: childElements, settings } ) => {
9
+ const ids: number[] = [];
10
+
11
+ const isComponent = [ widgetType, elType ].includes( TYPE );
12
+
13
+ if ( isComponent ) {
14
+ const componentId = ( settings?.component_instance as ComponentInstancePropValue< number > )?.value
15
+ ?.component_id;
16
+
17
+ const document = await getComponentDocumentData( componentId );
18
+
19
+ childElements = document?.elements;
20
+
21
+ if ( Boolean( componentId ) ) {
22
+ ids.push( componentId );
23
+ }
24
+ }
25
+
26
+ if ( !! childElements?.length ) {
27
+ ids.push( ...( await getComponentIds( childElements ) ) );
28
+ }
29
+
30
+ return ids;
31
+ } );
32
+
33
+ const result = ( await Promise.all( components ) ).flat();
34
+
35
+ return Array.from( new Set( result ) );
36
+ };
@@ -0,0 +1,49 @@
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
+ }
@@ -0,0 +1,47 @@
1
+ import { type V1Element } from '@elementor/editor-elements';
2
+ import { getMixpanel } from '@elementor/mixpanel';
3
+ import { __getState as getState } from '@elementor/store';
4
+
5
+ import { selectCreatedThisSession } from '../store/store';
6
+ import { type ExtendedWindow } from '../types';
7
+
8
+ type ComponentEventData = Record< string, unknown > & {
9
+ action: 'createClicked' | 'created' | 'createCancelled' | 'instanceAdded' | 'edited';
10
+ };
11
+
12
+ export const trackComponentEvent = ( { action, ...data }: ComponentEventData ) => {
13
+ const { dispatchEvent, config } = getMixpanel();
14
+ if ( ! config?.names?.components?.[ action ] ) {
15
+ return;
16
+ }
17
+
18
+ const name = config.names.components[ action ];
19
+ dispatchEvent?.( name, data );
20
+ };
21
+
22
+ export const onElementDrop = ( _args: unknown, element: V1Element ) => {
23
+ if ( ! ( element.model.get( 'widgetType' ) === 'e-component' ) ) {
24
+ return;
25
+ }
26
+
27
+ const editorSettings = element.model.get( 'editor_settings' );
28
+ const componentName = editorSettings?.title;
29
+ const componentUID = editorSettings?.component_uid;
30
+ const instanceId = element.id;
31
+
32
+ const createdThisSession = selectCreatedThisSession( getState() );
33
+ const isSameSessionReuse = componentUID && createdThisSession.includes( componentUID );
34
+
35
+ const eventsManagerConfig = ( window as unknown as ExtendedWindow ).elementorCommon.eventsManager.config;
36
+ const { locations, secondaryLocations } = eventsManagerConfig;
37
+
38
+ trackComponentEvent( {
39
+ action: 'instanceAdded',
40
+ instance_id: instanceId,
41
+ component_uid: componentUID,
42
+ component_name: componentName,
43
+ is_same_session_reuse: isSameSessionReuse,
44
+ location: locations.widgetPanel,
45
+ secondary_location: secondaryLocations.componentsTab,
46
+ } );
47
+ };
@@ -1,6 +0,0 @@
1
- import * as React from 'react';
2
- import { Box } from '@elementor/ui';
3
-
4
- export function ComponentsTab() {
5
- return <Box px={ 2 }>This is the Components tab.</Box>;
6
- }
@@ -1,13 +0,0 @@
1
- import { useMutation, useQueryClient } from '@elementor/query';
2
-
3
- import { apiClient } from '../api';
4
- import { COMPONENTS_QUERY_KEY } from './use-components';
5
-
6
- export const useCreateComponentMutation = () => {
7
- const queryClient = useQueryClient();
8
-
9
- return useMutation( {
10
- mutationFn: apiClient.create,
11
- onSuccess: () => queryClient.invalidateQueries( { queryKey: [ COMPONENTS_QUERY_KEY ] } ),
12
- } );
13
- };