@elementor/editor-editing-panel 0.16.0 → 0.18.0
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/CHANGELOG.md +44 -0
- package/dist/index.d.mts +26 -9
- package/dist/index.d.ts +26 -9
- package/dist/index.js +910 -360
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +886 -327
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -7
- package/src/components/settings-tab.tsx +5 -2
- package/src/components/style-sections/effects-section/box-shadow-repeater.tsx +224 -0
- package/src/components/style-sections/effects-section/effects-section.tsx +18 -0
- package/src/components/style-sections/position-section/z-index-control.tsx +11 -7
- package/src/components/style-sections/size-section.tsx +23 -20
- package/src/components/style-sections/spacing-section/linked-dimensions-control.tsx +62 -47
- package/src/components/style-sections/typography-section/font-size-control.tsx +10 -6
- package/src/components/style-sections/typography-section/font-weight-control.tsx +16 -12
- package/src/components/style-sections/typography-section/letter-spacing-control.tsx +10 -6
- package/src/components/style-sections/typography-section/text-alignment-control.tsx +47 -0
- package/src/components/style-sections/typography-section/text-color-control.tsx +10 -6
- package/src/components/style-sections/typography-section/text-direction-control.tsx +37 -0
- package/src/components/style-sections/typography-section/text-style-control.tsx +37 -34
- package/src/components/style-sections/typography-section/transform-control.tsx +14 -12
- package/src/components/style-sections/typography-section/typography-section.tsx +4 -0
- package/src/components/style-sections/typography-section/word-spacing-control.tsx +10 -6
- package/src/components/style-tab.tsx +5 -1
- package/src/controls/components/control-type-container.tsx +28 -0
- package/src/controls/components/repeater.tsx +197 -0
- package/src/controls/control-actions/actions/popover-action.tsx +58 -0
- package/src/controls/control-actions/control-actions-menu.ts +8 -0
- package/src/controls/control-actions/control-actions.tsx +43 -0
- package/src/controls/control-replacement.ts +15 -7
- package/src/controls/control-types/color-control.tsx +21 -18
- package/src/controls/control-types/image-control.tsx +56 -59
- package/src/controls/control-types/image-media-control.tsx +73 -0
- package/src/controls/control-types/number-control.tsx +13 -9
- package/src/controls/control-types/select-control.tsx +13 -9
- package/src/controls/control-types/size-control.tsx +17 -13
- package/src/controls/control-types/text-area-control.tsx +15 -11
- package/src/controls/control-types/text-control.tsx +9 -3
- package/src/controls/control-types/toggle-control.tsx +3 -2
- package/src/controls/control.tsx +1 -7
- package/src/controls/controls-registry.tsx +19 -10
- package/src/controls/create-control.tsx +31 -0
- package/src/controls/settings-control.tsx +2 -9
- package/src/dynamics/components/dynamic-selection-control.tsx +4 -3
- package/src/dynamics/components/dynamic-selection.tsx +19 -8
- package/src/dynamics/dynamic-control.tsx +1 -1
- package/src/dynamics/hooks/use-prop-dynamic-action.tsx +23 -0
- package/src/dynamics/hooks/use-prop-dynamic-tags.ts +4 -4
- package/src/dynamics/hooks/use-prop-value-history.ts +26 -0
- package/src/dynamics/init.ts +9 -0
- package/src/dynamics/types.ts +6 -3
- package/src/dynamics/utils.ts +18 -5
- package/src/index.ts +2 -0
- package/src/types.ts +35 -14
- package/src/controls/components/control-container.tsx +0 -18
|
@@ -28,11 +28,13 @@ import {
|
|
|
28
28
|
TabPanel,
|
|
29
29
|
} from '@elementor/ui';
|
|
30
30
|
import { __ } from '@wordpress/i18n';
|
|
31
|
+
import { usePropValueHistory } from '../hooks/use-prop-value-history';
|
|
31
32
|
|
|
32
33
|
const SIZE = 'tiny';
|
|
33
34
|
|
|
34
35
|
export const DynamicSelectionControl = () => {
|
|
35
36
|
const { bind, value, setValue } = useControl< DynamicPropValue | null >();
|
|
37
|
+
const [ propValueFromHistory ] = usePropValueHistory( bind );
|
|
36
38
|
const { name: tagName = '' } = value?.value || {};
|
|
37
39
|
|
|
38
40
|
const selectionPopoverId = useId();
|
|
@@ -41,8 +43,7 @@ export const DynamicSelectionControl = () => {
|
|
|
41
43
|
const dynamicTag = useDynamicTag( bind, tagName );
|
|
42
44
|
|
|
43
45
|
const removeDynamicTag = () => {
|
|
44
|
-
|
|
45
|
-
setValue( null );
|
|
46
|
+
setValue( propValueFromHistory ?? null );
|
|
46
47
|
};
|
|
47
48
|
|
|
48
49
|
if ( ! dynamicTag ) {
|
|
@@ -50,7 +51,7 @@ export const DynamicSelectionControl = () => {
|
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
return (
|
|
53
|
-
<Box
|
|
54
|
+
<Box>
|
|
54
55
|
<Tag
|
|
55
56
|
fullWidth
|
|
56
57
|
showActionsOnHover
|
|
@@ -18,7 +18,9 @@ import {
|
|
|
18
18
|
Typography,
|
|
19
19
|
} from '@elementor/ui';
|
|
20
20
|
import { __ } from '@wordpress/i18n';
|
|
21
|
-
import { PropKey } from '../../types';
|
|
21
|
+
import { PropKey, PropValue } from '../../types';
|
|
22
|
+
import { isDynamicPropValue } from '../utils';
|
|
23
|
+
import { usePropValueHistory } from '../hooks/use-prop-value-history';
|
|
22
24
|
|
|
23
25
|
type Option = {
|
|
24
26
|
label: string;
|
|
@@ -35,9 +37,11 @@ export type DynamicSelectionProps = {
|
|
|
35
37
|
|
|
36
38
|
export const DynamicSelection = ( { onSelect }: DynamicSelectionProps ) => {
|
|
37
39
|
const [ searchValue, setSearchValue ] = useState( '' );
|
|
38
|
-
|
|
39
40
|
const { groups: dynamicGroups } = getAtomicDynamicTags() || {};
|
|
40
|
-
const { bind, value:
|
|
41
|
+
const { bind, value: currentValue, setValue } = useControl< DynamicPropValue | PropValue >();
|
|
42
|
+
const [ , updatePropValueHistory ] = usePropValueHistory( bind );
|
|
43
|
+
|
|
44
|
+
const isCurrentValueDynamic = isDynamicPropValue( currentValue );
|
|
41
45
|
|
|
42
46
|
const options = useFilteredOptions( bind, searchValue );
|
|
43
47
|
|
|
@@ -45,6 +49,16 @@ export const DynamicSelection = ( { onSelect }: DynamicSelectionProps ) => {
|
|
|
45
49
|
setSearchValue( event.target.value );
|
|
46
50
|
};
|
|
47
51
|
|
|
52
|
+
const handleSetDynamicTag = ( value: string ) => {
|
|
53
|
+
if ( ! isCurrentValueDynamic ) {
|
|
54
|
+
updatePropValueHistory( currentValue );
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
setValue( { $$type: 'dynamic', value: { name: value, settings: {} } } );
|
|
58
|
+
|
|
59
|
+
onSelect?.();
|
|
60
|
+
};
|
|
61
|
+
|
|
48
62
|
return (
|
|
49
63
|
<Stack>
|
|
50
64
|
<Box px={ 1.5 } pb={ 1 }>
|
|
@@ -73,7 +87,7 @@ export const DynamicSelection = ( { onSelect }: DynamicSelectionProps ) => {
|
|
|
73
87
|
{ dynamicGroups?.[ category ]?.title || category }
|
|
74
88
|
</ListSubheader>
|
|
75
89
|
{ items.map( ( { value, label: tagLabel } ) => {
|
|
76
|
-
const isSelected = value ===
|
|
90
|
+
const isSelected = isCurrentValueDynamic && value === currentValue?.value?.name;
|
|
77
91
|
|
|
78
92
|
return (
|
|
79
93
|
<MenuItem
|
|
@@ -82,10 +96,7 @@ export const DynamicSelection = ( { onSelect }: DynamicSelectionProps ) => {
|
|
|
82
96
|
// eslint-disable-next-line jsx-a11y/no-autofocus
|
|
83
97
|
autoFocus={ isSelected }
|
|
84
98
|
sx={ { typography: 'caption' } }
|
|
85
|
-
onClick={ () =>
|
|
86
|
-
setValue( { $$type: 'dynamic', value: { name: value } } );
|
|
87
|
-
onSelect?.();
|
|
88
|
-
} }
|
|
99
|
+
onClick={ () => handleSetDynamicTag( value ) }
|
|
89
100
|
>
|
|
90
101
|
{ tagLabel }
|
|
91
102
|
</MenuItem>
|
|
@@ -18,7 +18,7 @@ export const DynamicControl = ( { bind, children }: DynamicControlProps ) => {
|
|
|
18
18
|
throw new Error( `Dynamic tag ${ name } not found` );
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
const defaultValue = dynamicTag.props_schema[ bind ]?.
|
|
21
|
+
const defaultValue = dynamicTag.props_schema[ bind ]?.default;
|
|
22
22
|
const dynamicValue = settings?.[ bind ] ?? defaultValue;
|
|
23
23
|
|
|
24
24
|
const setDynamicValue = ( newValue: PropValue ) => {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useElementContext } from '../../contexts/element-context';
|
|
3
|
+
import { supportsDynamic } from '../utils';
|
|
4
|
+
import { DynamicSelection } from '../components/dynamic-selection';
|
|
5
|
+
import { DatabaseIcon } from '@elementor/icons';
|
|
6
|
+
import { __ } from '@wordpress/i18n';
|
|
7
|
+
import { useControl } from '../../controls/control-context';
|
|
8
|
+
import { PopoverActionProps } from '../../controls/control-actions/actions/popover-action';
|
|
9
|
+
|
|
10
|
+
export const usePropDynamicAction = (): PopoverActionProps => {
|
|
11
|
+
const { bind } = useControl();
|
|
12
|
+
const { elementType } = useElementContext();
|
|
13
|
+
|
|
14
|
+
const propType = elementType.propsSchema[ bind ];
|
|
15
|
+
const visible = !! propType && supportsDynamic( propType );
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
visible,
|
|
19
|
+
icon: DatabaseIcon,
|
|
20
|
+
title: __( 'Dynamic Tags', 'elementor' ),
|
|
21
|
+
popoverContent: ( { closePopover } ) => <DynamicSelection onSelect={ closePopover } />,
|
|
22
|
+
};
|
|
23
|
+
};
|
|
@@ -2,17 +2,17 @@ import { useMemo } from 'react';
|
|
|
2
2
|
import { useElementContext } from '../../contexts/element-context';
|
|
3
3
|
import { getAtomicDynamicTags } from '../sync/get-atomic-dynamic-tags';
|
|
4
4
|
import { PropKey } from '../../types';
|
|
5
|
-
import {
|
|
5
|
+
import { getDynamicPropType } from '../utils';
|
|
6
6
|
|
|
7
7
|
export const usePropDynamicTags = ( propName: PropKey ) => {
|
|
8
8
|
let categories: string[] = [];
|
|
9
9
|
|
|
10
10
|
const { elementType } = useElementContext();
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const propType = elementType.propsSchema?.[ propName ];
|
|
13
13
|
|
|
14
|
-
if (
|
|
15
|
-
const propDynamicType =
|
|
14
|
+
if ( propType ) {
|
|
15
|
+
const propDynamicType = getDynamicPropType( propType );
|
|
16
16
|
|
|
17
17
|
categories = propDynamicType?.settings.categories || [];
|
|
18
18
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useElementContext } from '../../contexts/element-context';
|
|
2
|
+
import { PropValue } from '../../types';
|
|
3
|
+
|
|
4
|
+
export const PROPS_VALUES_HISTORY_KEY = 'elementor/dynamic/non-dynamic-values-history';
|
|
5
|
+
|
|
6
|
+
export const usePropValueHistory = ( path: string ) => {
|
|
7
|
+
const valuesHistory = getValues();
|
|
8
|
+
const { element } = useElementContext();
|
|
9
|
+
const key = `${ element.id }-${ path }`;
|
|
10
|
+
|
|
11
|
+
const value = valuesHistory[ key ] ?? null;
|
|
12
|
+
|
|
13
|
+
const setValue = ( newValue: PropValue ) => {
|
|
14
|
+
setValues( { ...valuesHistory, [ key ]: newValue } );
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
return [ value, setValue ] as const;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const getValues = () => {
|
|
21
|
+
return JSON.parse( sessionStorage.getItem( PROPS_VALUES_HISTORY_KEY ) || '{}' );
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const setValues = ( values: Record< string, PropValue > ) => {
|
|
25
|
+
sessionStorage.setItem( PROPS_VALUES_HISTORY_KEY, JSON.stringify( values ) );
|
|
26
|
+
};
|
package/src/dynamics/init.ts
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import { DynamicSelectionControl } from './components/dynamic-selection-control';
|
|
2
2
|
import { replaceControl } from '../controls/control-replacement';
|
|
3
3
|
import { isDynamicPropValue } from './utils';
|
|
4
|
+
import { usePropDynamicAction } from './hooks/use-prop-dynamic-action';
|
|
5
|
+
import { controlActionsMenu } from '../controls/control-actions/control-actions-menu';
|
|
6
|
+
|
|
7
|
+
const { registerPopoverAction } = controlActionsMenu;
|
|
4
8
|
|
|
5
9
|
export const init = () => {
|
|
6
10
|
replaceControl( {
|
|
7
11
|
component: DynamicSelectionControl,
|
|
8
12
|
condition: ( { value } ) => isDynamicPropValue( value ),
|
|
9
13
|
} );
|
|
14
|
+
|
|
15
|
+
registerPopoverAction( {
|
|
16
|
+
id: 'dynamic-tags',
|
|
17
|
+
useProps: usePropDynamicAction,
|
|
18
|
+
} );
|
|
10
19
|
};
|
package/src/dynamics/types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ControlItem, PropsSchema, TransformablePropValue } from '../types';
|
|
1
|
+
import { ControlItem, PropsSchema, TransformablePropType, TransformablePropValue } from '../types';
|
|
2
2
|
|
|
3
3
|
export type ExtendedWindow = Window & {
|
|
4
4
|
elementor?: {
|
|
@@ -22,11 +22,14 @@ export type DynamicTag = {
|
|
|
22
22
|
props_schema: PropsSchema;
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
export type DynamicPropType = {
|
|
25
|
+
export type DynamicPropType = TransformablePropType & {
|
|
26
26
|
key: 'dynamic';
|
|
27
27
|
settings: {
|
|
28
28
|
categories: string[];
|
|
29
29
|
};
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
-
export type DynamicPropValue = TransformablePropValue<
|
|
32
|
+
export type DynamicPropValue = TransformablePropValue<
|
|
33
|
+
'dynamic',
|
|
34
|
+
{ name: string; settings?: Record< string, unknown > }
|
|
35
|
+
>;
|
package/src/dynamics/utils.ts
CHANGED
|
@@ -1,9 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { DynamicPropType } from './types';
|
|
1
|
+
import { PropType, PropValue, TransformablePropType } from '../types';
|
|
2
|
+
import { DynamicPropType, DynamicPropValue } from './types';
|
|
3
3
|
import { isTransformable } from '../props/is-transformable';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
const DYNAMIC_PROP_TYPE_KEY = 'dynamic';
|
|
6
6
|
|
|
7
|
-
export const
|
|
8
|
-
|
|
7
|
+
export const isDynamicPropType = ( prop: TransformablePropType ): prop is DynamicPropType =>
|
|
8
|
+
prop.key === DYNAMIC_PROP_TYPE_KEY;
|
|
9
|
+
|
|
10
|
+
export const getDynamicPropType = ( propType: PropType ): DynamicPropType | null => {
|
|
11
|
+
const dynamicPropType = propType.kind === 'union' && propType.prop_types[ DYNAMIC_PROP_TYPE_KEY ];
|
|
12
|
+
|
|
13
|
+
return dynamicPropType && isDynamicPropType( dynamicPropType ) ? dynamicPropType : null;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const isDynamicPropValue = ( prop: PropValue ): prop is DynamicPropValue => {
|
|
17
|
+
return isTransformable( prop ) && prop.$$type === DYNAMIC_PROP_TYPE_KEY;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const supportsDynamic = ( propType: PropType ): boolean => {
|
|
21
|
+
return !! getDynamicPropType( propType );
|
|
9
22
|
};
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
export type { PopoverActionProps } from './controls/control-actions/actions/popover-action';
|
|
1
2
|
export { replaceControl } from './controls/control-replacement';
|
|
2
3
|
export { useControl } from './controls/control-context';
|
|
4
|
+
export { controlActionsMenu } from './controls/control-actions/control-actions-menu';
|
|
3
5
|
|
|
4
6
|
import init from './init';
|
|
5
7
|
|
package/src/types.ts
CHANGED
|
@@ -34,32 +34,53 @@ export type Control = {
|
|
|
34
34
|
|
|
35
35
|
export type ControlItem = ControlsSection | Control;
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
type PropTypeKey = string;
|
|
38
|
+
|
|
39
|
+
type BasePropType = {
|
|
40
|
+
default: PropValue;
|
|
39
41
|
settings: Record< string, unknown >;
|
|
42
|
+
meta: Record< string, unknown >;
|
|
40
43
|
};
|
|
41
44
|
|
|
42
|
-
export type
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
default: PropValue;
|
|
46
|
-
settings: Record< string, unknown >;
|
|
47
|
-
};
|
|
48
|
-
additional_types: Array< AdditionalPropType >;
|
|
45
|
+
export type PlainPropType = BasePropType & {
|
|
46
|
+
kind: 'plain';
|
|
47
|
+
key: PropTypeKey;
|
|
49
48
|
};
|
|
50
49
|
|
|
51
|
-
export type
|
|
50
|
+
export type ArrayPropType = BasePropType & {
|
|
51
|
+
kind: 'array';
|
|
52
|
+
key: PropTypeKey;
|
|
53
|
+
item_prop_type: PropType | null;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export type ObjectPropType = BasePropType & {
|
|
57
|
+
kind: 'object';
|
|
58
|
+
key: PropTypeKey;
|
|
59
|
+
shape: Record< string, PropType >;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export type TransformablePropType = PlainPropType | ArrayPropType | ObjectPropType;
|
|
63
|
+
|
|
64
|
+
export type UnionPropType = BasePropType & {
|
|
65
|
+
kind: 'union';
|
|
66
|
+
prop_types: Record< string, TransformablePropType >;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export type PropType = TransformablePropType | UnionPropType;
|
|
70
|
+
|
|
71
|
+
export type PropsSchema = Record< Control[ 'value' ][ 'bind' ], PropType >;
|
|
52
72
|
|
|
53
73
|
type MaybeArray< T > = T | T[];
|
|
54
74
|
|
|
55
|
-
export type TransformablePropValue<
|
|
56
|
-
$$type:
|
|
57
|
-
value:
|
|
75
|
+
export type TransformablePropValue< Type extends string, Value = unknown > = {
|
|
76
|
+
$$type: Type;
|
|
77
|
+
value: Value;
|
|
78
|
+
disabled?: boolean;
|
|
58
79
|
};
|
|
59
80
|
|
|
60
81
|
export type PlainPropValue = MaybeArray< string | number | boolean | object | null | undefined >;
|
|
61
82
|
|
|
62
|
-
export type PropValue = PlainPropValue | TransformablePropValue
|
|
83
|
+
export type PropValue = PlainPropValue | TransformablePropValue< string >;
|
|
63
84
|
|
|
64
85
|
export type PropKey = string;
|
|
65
86
|
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { Stack, StackProps, styled } from '@elementor/ui';
|
|
3
|
-
|
|
4
|
-
const StyledStack = styled( Stack )( ( { theme, gap, direction } ) => ( {
|
|
5
|
-
'> :only-child': {
|
|
6
|
-
width: '100%',
|
|
7
|
-
},
|
|
8
|
-
'&:where( :has( > :nth-child( 2 ):last-child ) ) > :where( * )': {
|
|
9
|
-
width: direction === 'column' ? '100%' : `calc( 50% - ${ theme.spacing( gap / 2 ) })`,
|
|
10
|
-
},
|
|
11
|
-
'&:where( :has( > :nth-child( 3 ):last-child ) ) > :where( * )': {
|
|
12
|
-
width: direction === 'column' ? '100%' : `calc( 33.3333% - ${ theme.spacing( gap * 2 ) } / 3)`,
|
|
13
|
-
},
|
|
14
|
-
} ) );
|
|
15
|
-
|
|
16
|
-
export const ControlContainer = ( props: StackProps ) => (
|
|
17
|
-
<StyledStack gap={ 1 } direction="row" alignItems="center" justifyContent="space-between" { ...props } />
|
|
18
|
-
);
|