@elementor/editor-components 4.0.0-543 → 4.0.0-545
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 +739 -590
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +676 -527
- package/dist/index.mjs.map +1 -1
- package/package.json +22 -22
- package/src/components/component-panel-header/component-panel-header.tsx +2 -2
- package/src/components/component-properties-panel/component-properties-panel-content.tsx +2 -2
- package/src/components/component-properties-panel/use-current-editable-item.ts +1 -2
- package/src/components/edit-component/edit-component.tsx +3 -0
- package/src/components/instance-editing-panel/instance-editing-panel.tsx +11 -9
- package/src/components/instance-editing-panel/override-prop-control.tsx +60 -44
- package/src/components/instance-editing-panel/override-props-group.tsx +3 -10
- package/src/components/instance-editing-panel/use-resolved-origin-value.tsx +6 -19
- package/src/components/overridable-props/overridable-prop-indicator.tsx +3 -2
- package/src/hooks/use-sanitize-overridable-props.ts +31 -0
- package/src/provider/component-instance-context.tsx +21 -0
- package/src/store/actions/create-unpublished-component.ts +12 -2
- package/src/store/actions/reset-sanitized-components.ts +7 -0
- package/src/store/actions/update-component-sanitized-attribute.ts +8 -0
- package/src/store/store.ts +35 -0
- package/src/sync/handle-component-edit-mode-container.ts +1 -1
- package/src/utils/filter-valid-overridable-props.ts +84 -0
- package/src/utils/overridable-props-utils.ts +58 -0
- package/src/utils/tracking.ts +5 -1
- package/src/components/component-panel-header/use-overridable-props.ts +0 -14
package/src/store/store.ts
CHANGED
|
@@ -21,6 +21,8 @@ type GetComponentResponse = PublishedComponent[];
|
|
|
21
21
|
|
|
22
22
|
type Status = 'idle' | 'pending' | 'error';
|
|
23
23
|
|
|
24
|
+
export type SanitizeAttributes = 'overridableProps';
|
|
25
|
+
|
|
24
26
|
type ComponentsState = {
|
|
25
27
|
data: PublishedComponent[];
|
|
26
28
|
unpublishedData: UnpublishedComponent[];
|
|
@@ -31,6 +33,10 @@ type ComponentsState = {
|
|
|
31
33
|
path: ComponentsPathItem[];
|
|
32
34
|
currentComponentId: V1Document[ 'id' ] | null;
|
|
33
35
|
updatedComponentNames: Record< number, string >;
|
|
36
|
+
|
|
37
|
+
// We use this map to flag any sanitized attribute of a given component
|
|
38
|
+
// This map currently resets in response to the `editor/documents/open` command
|
|
39
|
+
sanitized: Record< ComponentId, Partial< Record< SanitizeAttributes, boolean > > >;
|
|
34
40
|
};
|
|
35
41
|
|
|
36
42
|
export type ComponentsSlice = SliceState< typeof slice >;
|
|
@@ -51,6 +57,7 @@ export const initialState: ComponentsState = {
|
|
|
51
57
|
path: [],
|
|
52
58
|
currentComponentId: null,
|
|
53
59
|
updatedComponentNames: {},
|
|
60
|
+
sanitized: {},
|
|
54
61
|
};
|
|
55
62
|
|
|
56
63
|
export const SLICE_NAME = 'components';
|
|
@@ -135,6 +142,21 @@ export const slice = createSlice( {
|
|
|
135
142
|
cleanUpdatedComponentNames: ( state ) => {
|
|
136
143
|
state.updatedComponentNames = {};
|
|
137
144
|
},
|
|
145
|
+
updateComponentSanitizedAttribute: (
|
|
146
|
+
state,
|
|
147
|
+
{
|
|
148
|
+
payload: { componentId, attribute },
|
|
149
|
+
}: PayloadAction< { componentId: ComponentId; attribute: SanitizeAttributes } >
|
|
150
|
+
) => {
|
|
151
|
+
if ( ! state.sanitized[ componentId ] ) {
|
|
152
|
+
state.sanitized[ componentId ] = {};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
state.sanitized[ componentId ][ attribute ] = true;
|
|
156
|
+
},
|
|
157
|
+
resetSanitizedComponents: ( state ) => {
|
|
158
|
+
state.sanitized = {};
|
|
159
|
+
},
|
|
138
160
|
},
|
|
139
161
|
extraReducers: ( builder ) => {
|
|
140
162
|
builder.addCase( loadComponents.fulfilled, ( state, { payload }: PayloadAction< GetComponentResponse > ) => {
|
|
@@ -248,3 +270,16 @@ export const selectUpdatedComponentNames = createSelector(
|
|
|
248
270
|
title,
|
|
249
271
|
} ) )
|
|
250
272
|
);
|
|
273
|
+
|
|
274
|
+
const useSanitizedComponents = () => {
|
|
275
|
+
return useSelector( ( state: ComponentsSlice ) => state[ SLICE_NAME ].sanitized );
|
|
276
|
+
};
|
|
277
|
+
export const useIsSanitizedComponent = ( componentId: ComponentId | null, key: SanitizeAttributes ) => {
|
|
278
|
+
const sanitizedComponents = useSanitizedComponents();
|
|
279
|
+
|
|
280
|
+
if ( ! componentId ) {
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
return !! sanitizedComponents[ componentId ]?.[ key ];
|
|
285
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { getElementSetting } from '@elementor/editor-elements';
|
|
2
|
+
|
|
3
|
+
import { getOverridableProp } from '../components/overridable-props/utils/get-overridable-prop';
|
|
4
|
+
import { type ComponentInstanceOverride } from '../prop-types/component-instance-overrides-prop-type';
|
|
5
|
+
import { componentInstanceOverridesPropTypeUtil } from '../prop-types/component-instance-overrides-prop-type';
|
|
6
|
+
import { componentInstancePropTypeUtil } from '../prop-types/component-instance-prop-type';
|
|
7
|
+
import { componentOverridablePropTypeUtil } from '../prop-types/component-overridable-prop-type';
|
|
8
|
+
import { type OverridableProp, type OverridableProps } from '../types';
|
|
9
|
+
import { extractInnerOverrideInfo } from './overridable-props-utils';
|
|
10
|
+
|
|
11
|
+
export function filterValidOverridableProps( overridableProps: OverridableProps ): OverridableProps {
|
|
12
|
+
const validProps: Record< string, OverridableProp > = {};
|
|
13
|
+
|
|
14
|
+
for ( const [ key, prop ] of Object.entries( overridableProps.props ) ) {
|
|
15
|
+
if ( isExposedPropValid( prop ) ) {
|
|
16
|
+
validProps[ key ] = prop;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const validPropKeys = new Set( Object.keys( validProps ) );
|
|
21
|
+
const filteredGroups = {
|
|
22
|
+
items: Object.fromEntries(
|
|
23
|
+
Object.entries( overridableProps.groups.items ).map( ( [ groupId, group ] ) => [
|
|
24
|
+
groupId,
|
|
25
|
+
{ ...group, props: group.props.filter( ( propKey ) => validPropKeys.has( propKey ) ) },
|
|
26
|
+
] )
|
|
27
|
+
),
|
|
28
|
+
order: overridableProps.groups.order,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
return { props: validProps, groups: filteredGroups };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function isExposedPropValid( prop: OverridableProp ): boolean {
|
|
35
|
+
if ( ! prop.originPropFields ) {
|
|
36
|
+
// if no originPropFields - the prop is on the widget level itself, therefore no need to lookup for a corresponding component's overridables
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const setting = getElementSetting( prop.elementId, 'component_instance' );
|
|
41
|
+
const componentInstance = componentInstancePropTypeUtil.extract( setting );
|
|
42
|
+
|
|
43
|
+
if ( ! componentInstance?.component_id?.value ) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const overrides = componentInstanceOverridesPropTypeUtil.extract( componentInstance.overrides ) ?? undefined;
|
|
48
|
+
const matchingOverride = findOverrideByOuterKey( overrides, prop.overrideKey );
|
|
49
|
+
const innerOverrideInfo = extractInnerOverrideInfo( matchingOverride );
|
|
50
|
+
|
|
51
|
+
if ( ! innerOverrideInfo ) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const { componentId, innerOverrideKey } = innerOverrideInfo;
|
|
56
|
+
const innerOverridableProp = getOverridableProp( { componentId, overrideKey: innerOverrideKey } );
|
|
57
|
+
|
|
58
|
+
if ( ! innerOverridableProp ) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return isExposedPropValid( innerOverridableProp );
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function findOverrideByOuterKey(
|
|
66
|
+
overrides: ComponentInstanceOverride[] | undefined,
|
|
67
|
+
outerKey: string
|
|
68
|
+
): ComponentInstanceOverride | null {
|
|
69
|
+
if ( ! overrides ) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
overrides.find( ( override ) => {
|
|
75
|
+
const overridableValue = componentOverridablePropTypeUtil.extract( override );
|
|
76
|
+
|
|
77
|
+
if ( overridableValue ) {
|
|
78
|
+
return overridableValue.override_key === outerKey;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return override.value.override_key === outerKey;
|
|
82
|
+
} ) ?? null
|
|
83
|
+
);
|
|
84
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { componentInstanceOverridePropTypeUtil } from '../prop-types/component-instance-override-prop-type';
|
|
2
|
+
import {
|
|
3
|
+
type ComponentInstanceOverride,
|
|
4
|
+
type ComponentInstanceOverridesPropValue,
|
|
5
|
+
} from '../prop-types/component-instance-overrides-prop-type';
|
|
6
|
+
import { componentOverridablePropTypeUtil } from '../prop-types/component-overridable-prop-type';
|
|
7
|
+
|
|
8
|
+
export type InnerOverrideInfo = {
|
|
9
|
+
componentId: number;
|
|
10
|
+
innerOverrideKey: string;
|
|
11
|
+
overrideValue: unknown;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export function getMatchingOverride(
|
|
15
|
+
overrides: ComponentInstanceOverridesPropValue,
|
|
16
|
+
overrideKey: string
|
|
17
|
+
): ComponentInstanceOverride | null {
|
|
18
|
+
return (
|
|
19
|
+
overrides?.find( ( override ) => {
|
|
20
|
+
const overridableValue = componentOverridablePropTypeUtil.extract( override );
|
|
21
|
+
|
|
22
|
+
if ( overridableValue ) {
|
|
23
|
+
const overrideValue = componentInstanceOverridePropTypeUtil.extract( overridableValue.origin_value );
|
|
24
|
+
return overrideValue?.override_key === overrideKey;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return override.value.override_key === overrideKey;
|
|
28
|
+
} ) ?? null
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function extractInnerOverrideInfo( override: ComponentInstanceOverride | null ): InnerOverrideInfo | null {
|
|
33
|
+
if ( ! override ) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const overridableValue = componentOverridablePropTypeUtil.extract( override );
|
|
38
|
+
const innerOverride = overridableValue
|
|
39
|
+
? componentInstanceOverridePropTypeUtil.extract( overridableValue.origin_value )
|
|
40
|
+
: componentInstanceOverridePropTypeUtil.extract( override );
|
|
41
|
+
|
|
42
|
+
if ( ! innerOverride ) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const {
|
|
47
|
+
schema_source: schemaSource,
|
|
48
|
+
override_key: innerOverrideKey,
|
|
49
|
+
override_value: overrideValue,
|
|
50
|
+
} = innerOverride;
|
|
51
|
+
const componentId = schemaSource?.id;
|
|
52
|
+
|
|
53
|
+
if ( ! componentId || ! innerOverrideKey ) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return { componentId, innerOverrideKey, overrideValue };
|
|
58
|
+
}
|
package/src/utils/tracking.ts
CHANGED
|
@@ -5,7 +5,7 @@ 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';
|
|
8
|
+
export type Source = 'user' | 'mcp_tool' | 'system';
|
|
9
9
|
|
|
10
10
|
type ComponentEventData = Record< string, unknown > & {
|
|
11
11
|
action:
|
|
@@ -24,6 +24,10 @@ type ComponentEventData = Record< string, unknown > & {
|
|
|
24
24
|
const FEATURE_NAME = 'Components';
|
|
25
25
|
|
|
26
26
|
export const trackComponentEvent = ( { action, source, ...data }: ComponentEventData ) => {
|
|
27
|
+
if ( source === 'system' ) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
27
31
|
const { dispatchEvent, config } = getMixpanel();
|
|
28
32
|
if ( ! config?.names?.components?.[ action ] ) {
|
|
29
33
|
return;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { __useSelector as useSelector } from '@elementor/store';
|
|
2
|
-
|
|
3
|
-
import { type ComponentsSlice, selectOverridableProps } from '../../store/store';
|
|
4
|
-
import { type ComponentId, type OverridableProps } from '../../types';
|
|
5
|
-
|
|
6
|
-
export function useOverridableProps( componentId: ComponentId | null ): OverridableProps | undefined {
|
|
7
|
-
return useSelector( ( state: ComponentsSlice ) => {
|
|
8
|
-
if ( ! componentId ) {
|
|
9
|
-
return undefined;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
return selectOverridableProps( state, componentId );
|
|
13
|
-
} );
|
|
14
|
-
}
|