@elementor/editor-components 3.35.0-463 → 3.35.0-464

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@elementor/editor-components",
3
3
  "description": "Elementor editor components",
4
- "version": "3.35.0-463",
4
+ "version": "3.35.0-464",
5
5
  "private": false,
6
6
  "author": "Elementor Team",
7
7
  "homepage": "https://elementor.com/",
@@ -40,30 +40,30 @@
40
40
  "dev": "tsup --config=../../tsup.dev.ts"
41
41
  },
42
42
  "dependencies": {
43
- "@elementor/editor": "3.35.0-463",
44
- "@elementor/editor-canvas": "3.35.0-463",
45
- "@elementor/editor-controls": "3.35.0-463",
46
- "@elementor/editor-documents": "3.35.0-463",
47
- "@elementor/editor-editing-panel": "3.35.0-463",
48
- "@elementor/editor-elements": "3.35.0-463",
49
- "@elementor/editor-elements-panel": "3.35.0-463",
50
- "@elementor/editor-mcp": "3.35.0-463",
51
- "@elementor/editor-panels": "3.35.0-463",
52
- "@elementor/editor-props": "3.35.0-463",
53
- "@elementor/editor-styles-repository": "3.35.0-463",
54
- "@elementor/editor-ui": "3.35.0-463",
55
- "@elementor/editor-v1-adapters": "3.35.0-463",
56
- "@elementor/http-client": "3.35.0-463",
43
+ "@elementor/editor": "3.35.0-464",
44
+ "@elementor/editor-canvas": "3.35.0-464",
45
+ "@elementor/editor-controls": "3.35.0-464",
46
+ "@elementor/editor-documents": "3.35.0-464",
47
+ "@elementor/editor-editing-panel": "3.35.0-464",
48
+ "@elementor/editor-elements": "3.35.0-464",
49
+ "@elementor/editor-elements-panel": "3.35.0-464",
50
+ "@elementor/editor-mcp": "3.35.0-464",
51
+ "@elementor/editor-panels": "3.35.0-464",
52
+ "@elementor/editor-props": "3.35.0-464",
53
+ "@elementor/editor-styles-repository": "3.35.0-464",
54
+ "@elementor/editor-ui": "3.35.0-464",
55
+ "@elementor/editor-v1-adapters": "3.35.0-464",
56
+ "@elementor/http-client": "3.35.0-464",
57
57
  "@elementor/icons": "^1.63.0",
58
- "@elementor/mixpanel": "3.35.0-463",
59
- "@elementor/query": "3.35.0-463",
60
- "@elementor/schema": "3.35.0-463",
61
- "@elementor/store": "3.35.0-463",
58
+ "@elementor/mixpanel": "3.35.0-464",
59
+ "@elementor/query": "3.35.0-464",
60
+ "@elementor/schema": "3.35.0-464",
61
+ "@elementor/store": "3.35.0-464",
62
62
  "@elementor/ui": "1.36.17",
63
- "@elementor/utils": "3.35.0-463",
63
+ "@elementor/utils": "3.35.0-464",
64
64
  "@wordpress/i18n": "^5.13.0",
65
- "@elementor/editor-notifications": "3.35.0-463",
66
- "@elementor/editor-current-user": "3.35.0-463"
65
+ "@elementor/editor-notifications": "3.35.0-464",
66
+ "@elementor/editor-current-user": "3.35.0-464"
67
67
  },
68
68
  "peerDependencies": {
69
69
  "react": "^18.3.1",
@@ -4,38 +4,39 @@ import { ComponentPropListIcon } from '@elementor/icons';
4
4
  import { Badge, Box, keyframes, styled, ToggleButton } from '@elementor/ui';
5
5
  import { __ } from '@wordpress/i18n';
6
6
 
7
- export const ComponentsBadge = React.forwardRef< HTMLDivElement, { overridesCount: number; onClick: () => void } >(
8
- ( { overridesCount, onClick }, ref ) => {
9
- const prevCount = usePrevious( overridesCount );
7
+ export const ComponentsBadge = React.forwardRef<
8
+ HTMLDivElement,
9
+ { overridablePropsCount: number; onClick: () => void }
10
+ >( ( { overridablePropsCount, onClick }, ref ) => {
11
+ const prevCount = usePrevious( overridablePropsCount );
10
12
 
11
- const isFirstOverride = prevCount === 0 && overridesCount === 1;
13
+ const isFirstExposedProperty = prevCount === 0 && overridablePropsCount === 1;
12
14
 
13
- return (
14
- <StyledBadge
15
- ref={ ref }
16
- color="primary"
17
- key={ overridesCount }
18
- invisible={ overridesCount === 0 }
19
- animate={ isFirstOverride }
20
- anchorOrigin={ { vertical: 'top', horizontal: 'right' } }
21
- badgeContent={
22
- <Box sx={ { animation: ! isFirstOverride ? `${ slideUp } 300ms ease-out` : 'none' } }>
23
- { overridesCount }
24
- </Box>
25
- }
15
+ return (
16
+ <StyledBadge
17
+ ref={ ref }
18
+ color="primary"
19
+ key={ overridablePropsCount }
20
+ invisible={ overridablePropsCount === 0 }
21
+ animate={ isFirstExposedProperty }
22
+ anchorOrigin={ { vertical: 'top', horizontal: 'right' } }
23
+ badgeContent={
24
+ <Box sx={ { animation: ! isFirstExposedProperty ? `${ slideUp } 300ms ease-out` : 'none' } }>
25
+ { overridablePropsCount }
26
+ </Box>
27
+ }
28
+ >
29
+ <ToggleButton
30
+ value="exposed properties"
31
+ size="tiny"
32
+ onClick={ onClick }
33
+ aria-label={ __( 'View exposed properties', 'elementor' ) }
26
34
  >
27
- <ToggleButton
28
- value="overrides"
29
- size="tiny"
30
- onClick={ onClick }
31
- aria-label={ __( 'View overrides', 'elementor' ) }
32
- >
33
- <ComponentPropListIcon fontSize="tiny" />
34
- </ToggleButton>
35
- </StyledBadge>
36
- );
37
- }
38
- );
35
+ <ComponentPropListIcon fontSize="tiny" />
36
+ </ToggleButton>
37
+ </StyledBadge>
38
+ );
39
+ } );
39
40
 
40
41
  const StyledBadge = styled( Badge, { shouldForwardProp: ( prop ) => prop !== 'animate' } )(
41
42
  ( { theme, animate } ) => ( {
@@ -7,7 +7,8 @@ import { Box, Divider, IconButton, Stack, Tooltip, Typography } from '@elementor
7
7
  import { __ } from '@wordpress/i18n';
8
8
 
9
9
  import { useNavigateBack } from '../../hooks/use-navigate-back';
10
- import { type ComponentsSlice, SLICE_NAME, useCurrentComponentId } from '../../store/store';
10
+ import { type ComponentsSlice, SLICE_NAME, useCurrentComponent } from '../../store/store';
11
+ import { trackComponentEvent } from '../../utils/tracking';
11
12
  import { usePanelActions } from '../component-properties-panel/component-properties-panel';
12
13
  import { ComponentIntroduction } from '../components-tab/component-introduction';
13
14
  import { ComponentsBadge } from './component-badge';
@@ -16,7 +17,7 @@ import { useOverridableProps } from './use-overridable-props';
16
17
  const MESSAGE_KEY = 'components-properties-introduction';
17
18
 
18
19
  export const ComponentPanelHeader = () => {
19
- const currentComponentId = useCurrentComponentId();
20
+ const { id: currentComponentId, uid: componentUid } = useCurrentComponent() ?? { id: null, uid: null };
20
21
  const overridableProps = useOverridableProps( currentComponentId );
21
22
  const onBack = useNavigateBack();
22
23
  const componentName = getComponentName();
@@ -25,7 +26,7 @@ export const ComponentPanelHeader = () => {
25
26
 
26
27
  const { open: openPropertiesPanel } = usePanelActions();
27
28
 
28
- const overridesCount = overridableProps ? Object.keys( overridableProps.props ).length : 0;
29
+ const overridablePropsCount = overridableProps ? Object.keys( overridableProps.props ).length : 0;
29
30
  const anchorRef = React.useRef< HTMLDivElement >( null );
30
31
 
31
32
  if ( ! currentComponentId ) {
@@ -37,6 +38,17 @@ export const ComponentPanelHeader = () => {
37
38
  setShouldShowIntroduction( false );
38
39
  };
39
40
 
41
+ const handleOpenPropertiesPanel = () => {
42
+ openPropertiesPanel();
43
+
44
+ trackComponentEvent( {
45
+ action: 'propertiesPanelOpened',
46
+ source: 'user',
47
+ component_uid: componentUid,
48
+ properties_count: overridablePropsCount,
49
+ } );
50
+ };
51
+
40
52
  return (
41
53
  <Box>
42
54
  <Stack
@@ -58,7 +70,11 @@ export const ComponentPanelHeader = () => {
58
70
  </Typography>
59
71
  </Stack>
60
72
  </Stack>
61
- <ComponentsBadge overridesCount={ overridesCount } ref={ anchorRef } onClick={ openPropertiesPanel } />
73
+ <ComponentsBadge
74
+ overridablePropsCount={ overridablePropsCount }
75
+ ref={ anchorRef }
76
+ onClick={ handleOpenPropertiesPanel }
77
+ />
62
78
  </Stack>
63
79
  <Divider />
64
80
  <ComponentIntroduction
@@ -63,7 +63,12 @@ export function ComponentPropertiesPanelContent( { onClose }: Props ) {
63
63
  const newGroupId = generateUniqueId( 'group' );
64
64
  const newLabel = generateUniqueLabel( groups );
65
65
 
66
- addOverridableGroup( { componentId: currentComponentId, groupId: newGroupId, label: newLabel } );
66
+ addOverridableGroup( {
67
+ componentId: currentComponentId,
68
+ groupId: newGroupId,
69
+ label: newLabel,
70
+ source: 'user',
71
+ } );
67
72
  setDocumentModifiedStatus( true );
68
73
  setIsAddingGroup( false );
69
74
 
@@ -81,7 +86,7 @@ export function ComponentPropertiesPanelContent( { onClose }: Props ) {
81
86
  };
82
87
 
83
88
  const handlePropertyDelete = ( propKey: string ) => {
84
- deleteOverridableProp( { componentId: currentComponentId, propKey } );
89
+ deleteOverridableProp( { componentId: currentComponentId, propKey, source: 'user' } );
85
90
  setDocumentModifiedStatus( true );
86
91
  };
87
92
 
@@ -63,6 +63,7 @@ export function CreateComponentForm() {
63
63
  eventData.current = getComponentEventData( event.detail.element, event.detail.options );
64
64
  trackComponentEvent( {
65
65
  action: 'createClicked',
66
+ source: 'user',
66
67
  ...eventData.current,
67
68
  } );
68
69
  };
@@ -80,11 +81,12 @@ export function CreateComponentForm() {
80
81
  throw new Error( `Can't save element as component: element not found` );
81
82
  }
82
83
 
83
- const { uid, instanceId } = await createUnpublishedComponent(
84
- values.componentName,
85
- element.element,
86
- eventData.current
87
- );
84
+ const { uid, instanceId } = await createUnpublishedComponent( {
85
+ name: values.componentName,
86
+ element: element.element,
87
+ eventData: eventData.current,
88
+ source: 'user',
89
+ } );
88
90
 
89
91
  const publishedComponentId = ( selectComponentByUid( getState(), uid ) as PublishedComponent )?.id;
90
92
 
@@ -121,6 +123,7 @@ export function CreateComponentForm() {
121
123
 
122
124
  trackComponentEvent( {
123
125
  action: 'createCancelled',
126
+ source: 'user',
124
127
  ...eventData.current,
125
128
  } );
126
129
  };
@@ -1,12 +1,9 @@
1
1
  import { replaceElement, type V1ElementData, type V1ElementModelProps } from '@elementor/editor-elements';
2
2
 
3
- import { type OverridableProps } from '../../../types';
4
-
5
3
  type ComponentInstanceParams = {
6
4
  id?: number;
7
5
  name: string;
8
6
  uid: string;
9
- overridableProps?: OverridableProps;
10
7
  };
11
8
 
12
9
  export const replaceElementWithComponent = async ( element: V1ElementData, component: ComponentInstanceParams ) => {
@@ -31,7 +28,6 @@ export const createComponentModel = ( component: ComponentInstanceParams ): Omit
31
28
  },
32
29
  },
33
30
  },
34
- overridable_props: component.overridableProps,
35
31
  },
36
32
  editor_settings: {
37
33
  component_uid: component.uid,
@@ -81,6 +81,7 @@ export function Content( { componentId, overridableProps }: Props ) {
81
81
  widgetType: componentInstanceElement?.elementType.key ?? elementType.key,
82
82
  originValue,
83
83
  originPropFields: matchingOverridableProp?.originPropFields,
84
+ source: 'user',
84
85
  } );
85
86
 
86
87
  if ( ! overridableValue && overridablePropConfig ) {
@@ -257,6 +257,7 @@ function createComponentView(
257
257
 
258
258
  trackComponentEvent( {
259
259
  action: 'edited',
260
+ source: 'user',
260
261
  component_uid: editorSettings?.component_uid,
261
262
  component_name: editorSettings?.title,
262
263
  location,
@@ -106,7 +106,14 @@ export const handleSaveAsComponent = async ( params: z.infer< z.ZodObject< typeo
106
106
  throw new Error( 'Unknown error' );
107
107
  }
108
108
 
109
- createUnpublishedComponent( componentName, element, null, overridableProps, uid );
109
+ await createUnpublishedComponent( {
110
+ name: componentName,
111
+ element,
112
+ eventData: null,
113
+ uid,
114
+ overridableProps,
115
+ source: 'mcp_tool',
116
+ } );
110
117
 
111
118
  return {
112
119
  status: 'ok' as const,
@@ -1,19 +1,24 @@
1
1
  import { __dispatch as dispatch, __getState as getState } from '@elementor/store';
2
2
 
3
3
  import { type ComponentId, type OverridablePropsGroup } from '../../types';
4
- import { selectOverridableProps, slice } from '../store';
4
+ import { type Source, trackComponentEvent } from '../../utils/tracking';
5
+ import { selectCurrentComponent, selectOverridableProps, slice } from '../store';
5
6
 
6
7
  type AddGroupParams = {
7
8
  componentId: ComponentId;
8
9
  groupId: string;
9
10
  label: string;
11
+ source: Source;
10
12
  };
11
13
 
12
14
  export function addOverridableGroup( {
13
15
  componentId,
14
16
  groupId,
15
17
  label,
18
+ source,
16
19
  }: AddGroupParams ): OverridablePropsGroup | undefined {
20
+ const currentComponent = selectCurrentComponent( getState() );
21
+
17
22
  const overridableProps = selectOverridableProps( getState(), componentId );
18
23
 
19
24
  if ( ! overridableProps ) {
@@ -43,5 +48,12 @@ export function addOverridableGroup( {
43
48
  } )
44
49
  );
45
50
 
51
+ trackComponentEvent( {
52
+ action: 'propertiesGroupCreated',
53
+ source,
54
+ component_uid: currentComponent?.uid,
55
+ group_name: label,
56
+ } );
57
+
46
58
  return newGroup;
47
59
  }
@@ -6,23 +6,34 @@ import { generateUniqueId } from '@elementor/utils';
6
6
  import { type ComponentEventData } from '../../components/create-component-form/utils/get-component-event-data';
7
7
  import { replaceElementWithComponent } from '../../components/create-component-form/utils/replace-element-with-component';
8
8
  import { type OverridableProps } from '../../types';
9
- import { trackComponentEvent } from '../../utils/tracking';
9
+ import { type Source, trackComponentEvent } from '../../utils/tracking';
10
10
  import { slice } from '../store';
11
11
 
12
- export async function createUnpublishedComponent(
13
- name: string,
14
- element: V1ElementData,
15
- eventData: ComponentEventData | null,
16
- overridableProps?: OverridableProps,
17
- uid?: string | null
18
- ) {
12
+ type CreateUnpublishedComponentParams = {
13
+ name: string;
14
+ element: V1ElementData;
15
+ eventData: ComponentEventData | null;
16
+ uid?: string | null;
17
+ overridableProps?: OverridableProps;
18
+ source: Source;
19
+ };
20
+
21
+ export async function createUnpublishedComponent( {
22
+ name,
23
+ element,
24
+ eventData,
25
+ uid,
26
+ overridableProps,
27
+ source,
28
+ }: CreateUnpublishedComponentParams ): Promise< { uid: string; instanceId: string } > {
19
29
  const generatedUid = uid ?? generateUniqueId( 'component' );
20
- const componentBase = { uid: generatedUid, name, overridableProps };
30
+ const componentBase = { uid: generatedUid, name };
21
31
 
22
32
  dispatch(
23
33
  slice.actions.addUnpublished( {
24
34
  ...componentBase,
25
35
  elements: [ element ],
36
+ overridableProps,
26
37
  } )
27
38
  );
28
39
 
@@ -32,6 +43,7 @@ export async function createUnpublishedComponent(
32
43
 
33
44
  trackComponentEvent( {
34
45
  action: 'created',
46
+ source,
35
47
  component_uid: generatedUid,
36
48
  component_name: name,
37
49
  ...eventData,
@@ -2,15 +2,17 @@ import { getContainer, updateElementSettings } from '@elementor/editor-elements'
2
2
  import { __dispatch as dispatch, __getState as getState } from '@elementor/store';
3
3
 
4
4
  import { type ComponentId } from '../../types';
5
- import { selectOverridableProps, slice } from '../store';
5
+ import { type Source, trackComponentEvent } from '../../utils/tracking';
6
+ import { selectCurrentComponent, selectOverridableProps, slice } from '../store';
6
7
  import { removePropFromAllGroups } from '../utils/groups-transformers';
7
8
 
8
9
  type DeletePropParams = {
9
10
  componentId: ComponentId;
10
11
  propKey: string;
12
+ source: Source;
11
13
  };
12
14
 
13
- export function deleteOverridableProp( { componentId, propKey }: DeletePropParams ): void {
15
+ export function deleteOverridableProp( { componentId, propKey, source }: DeletePropParams ): void {
14
16
  const overridableProps = selectOverridableProps( getState(), componentId );
15
17
 
16
18
  if ( ! overridableProps ) {
@@ -39,6 +41,18 @@ export function deleteOverridableProp( { componentId, propKey }: DeletePropParam
39
41
  },
40
42
  } )
41
43
  );
44
+
45
+ const currentComponent = selectCurrentComponent( getState() );
46
+
47
+ trackComponentEvent( {
48
+ action: 'propertyRemoved',
49
+ source,
50
+ component_uid: currentComponent?.uid,
51
+ property_id: removedProp.overrideKey,
52
+ property_path: removedProp.propKey,
53
+ property_name: removedProp.label,
54
+ element_type: removedProp.widgetType ?? removedProp.elType,
55
+ } );
42
56
  }
43
57
 
44
58
  function revertElementSetting( elementId: string, settingKey: string, originValue: unknown ): void {
@@ -3,7 +3,8 @@ import { __dispatch as dispatch, __getState as getState } from '@elementor/store
3
3
  import { generateUniqueId } from '@elementor/utils';
4
4
 
5
5
  import { type OriginPropFields, type OverridableProp } from '../../types';
6
- import { selectOverridableProps, slice } from '../store';
6
+ import { type Source, trackComponentEvent } from '../../utils/tracking';
7
+ import { selectCurrentComponent, selectOverridableProps, slice } from '../store';
7
8
  import {
8
9
  addPropToGroup,
9
10
  ensureGroupInOrder,
@@ -23,6 +24,7 @@ type Props = {
23
24
  widgetType: string;
24
25
  originValue: PropValue;
25
26
  originPropFields?: OriginPropFields;
27
+ source: Source;
26
28
  };
27
29
 
28
30
  export function setOverridableProp( {
@@ -36,6 +38,7 @@ export function setOverridableProp( {
36
38
  widgetType,
37
39
  originValue,
38
40
  originPropFields,
41
+ source,
39
42
  }: Props ): OverridableProp | undefined {
40
43
  const overridableProps = selectOverridableProps( getState(), componentId );
41
44
 
@@ -94,5 +97,21 @@ export function setOverridableProp( {
94
97
  } )
95
98
  );
96
99
 
100
+ const isNewProperty = ! existingOverridableProp;
101
+
102
+ if ( isNewProperty ) {
103
+ const currentComponent = selectCurrentComponent( getState() );
104
+
105
+ trackComponentEvent( {
106
+ action: 'propertyExposed',
107
+ source,
108
+ component_uid: currentComponent?.uid,
109
+ property_id: overridableProp.overrideKey,
110
+ property_path: propKey,
111
+ property_name: label,
112
+ element_type: widgetType ?? elType,
113
+ } );
114
+ }
115
+
97
116
  return overridableProp;
98
117
  }
@@ -220,9 +220,16 @@ export const selectCurrentComponentId = createSelector(
220
220
  ( currentComponentId ) => currentComponentId
221
221
  );
222
222
 
223
+ export const selectCurrentComponent = createSelector( selectData, getCurrentComponentId, ( data, currentComponentId ) =>
224
+ data.find( ( component ) => component.id === currentComponentId )
225
+ );
226
+
223
227
  export const useCurrentComponentId = () => {
224
228
  return useSelector( selectCurrentComponentId );
225
229
  };
230
+ export const useCurrentComponent = () => {
231
+ return useSelector( selectCurrentComponent );
232
+ };
226
233
 
227
234
  export const selectUpdatedComponentNames = createSelector(
228
235
  ( state: ComponentsSlice ) => state[ SLICE_NAME ].updatedComponentNames,
@@ -5,18 +5,32 @@ import { __getState as getState } from '@elementor/store';
5
5
  import { selectCreatedThisSession } from '../store/store';
6
6
  import { type ExtendedWindow } from '../types';
7
7
 
8
+ export type Source = 'user' | 'mcp_tool';
9
+
8
10
  type ComponentEventData = Record< string, unknown > & {
9
- action: 'createClicked' | 'created' | 'createCancelled' | 'instanceAdded' | 'edited';
11
+ action:
12
+ | 'createClicked'
13
+ | 'created'
14
+ | 'createCancelled'
15
+ | 'instanceAdded'
16
+ | 'edited'
17
+ | 'propertyExposed'
18
+ | 'propertyRemoved'
19
+ | 'propertiesPanelOpened'
20
+ | 'propertiesGroupCreated';
21
+ source: Source;
10
22
  };
11
23
 
12
- export const trackComponentEvent = ( { action, ...data }: ComponentEventData ) => {
24
+ const FEATURE_NAME = 'Components';
25
+
26
+ export const trackComponentEvent = ( { action, source, ...data }: ComponentEventData ) => {
13
27
  const { dispatchEvent, config } = getMixpanel();
14
28
  if ( ! config?.names?.components?.[ action ] ) {
15
29
  return;
16
30
  }
17
31
 
18
32
  const name = config.names.components[ action ];
19
- dispatchEvent?.( name, data );
33
+ dispatchEvent?.( name, { ...data, source, 'Feature name': FEATURE_NAME } );
20
34
  };
21
35
 
22
36
  export const onElementDrop = ( _args: unknown, element: V1Element ) => {
@@ -37,6 +51,7 @@ export const onElementDrop = ( _args: unknown, element: V1Element ) => {
37
51
 
38
52
  trackComponentEvent( {
39
53
  action: 'instanceAdded',
54
+ source: 'user',
40
55
  instance_id: instanceId,
41
56
  component_uid: componentUID,
42
57
  component_name: componentName,