@elementor/editor-editing-panel 1.10.0 → 1.11.1
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 +89 -0
- package/dist/index.js +809 -804
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +712 -711
- package/dist/index.mjs.map +1 -1
- package/package.json +18 -15
- package/src/components/css-classes/css-class-item.tsx +130 -0
- package/src/components/css-classes/css-class-menu.tsx +151 -0
- package/src/components/{css-class-selector.tsx → css-classes/css-class-selector.tsx} +23 -154
- package/src/components/style-sections/border-section/border-radius-field.tsx +33 -14
- package/src/components/style-sections/layout-section/display-field.tsx +9 -1
- package/src/components/style-sections/layout-section/flex-order-field.tsx +5 -5
- package/src/components/style-sections/layout-section/flex-size-field.tsx +1 -1
- package/src/components/style-sections/layout-section/gap-control-field.tsx +0 -2
- package/src/components/style-sections/position-section/dimensions-field.tsx +1 -1
- package/src/components/style-sections/position-section/position-section.tsx +1 -1
- package/src/components/style-sections/typography-section/font-weight-field.tsx +9 -5
- package/src/components/style-sections/typography-section/text-alignment-field.tsx +16 -8
- package/src/components/style-sections/typography-section/text-stroke-field.tsx +2 -2
- package/src/components/style-sections/typography-section/transform-field.tsx +12 -3
- package/src/components/style-tab.tsx +1 -1
- package/src/controls-registry/controls-registry.tsx +3 -1
- package/src/controls-registry/settings-field.tsx +8 -1
- package/src/dynamics/components/dynamic-selection.tsx +1 -1
- package/src/dynamics/dynamic-control.tsx +1 -1
- package/src/dynamics/types.ts +2 -2
- package/src/dynamics/utils.ts +2 -2
- package/src/hooks/use-persist-dynamic-value.ts +1 -1
- package/src/hooks/use-styles-fields.ts +113 -9
- package/src/index.ts +1 -1
- package/src/init.ts +2 -2
- package/src/sync/types.ts +4 -3
- package/src/components/collapsible-field.tsx +0 -36
- package/src/components/css-class-menu.tsx +0 -101
- package/src/components/editable-field.tsx +0 -166
- package/src/hooks/use-session-storage.ts +0 -46
- package/src/sync/enqueue-font.ts +0 -7
|
@@ -6,7 +6,7 @@ import { __ } from '@wordpress/i18n';
|
|
|
6
6
|
|
|
7
7
|
import { StylesField } from '../../../controls-registry/styles-field';
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
type Side = 'left' | 'right' | 'top' | 'bottom';
|
|
10
10
|
|
|
11
11
|
const sideIcons = {
|
|
12
12
|
left: <SideLeftIcon fontSize={ 'tiny' } />,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { type StringPropValue } from '@elementor/editor-props';
|
|
3
|
+
import { useSessionStorage } from '@elementor/session';
|
|
3
4
|
import { Stack } from '@elementor/ui';
|
|
4
5
|
|
|
5
6
|
import { useStyle } from '../../../contexts/style-context';
|
|
6
|
-
import { useSessionStorage } from '../../../hooks/use-session-storage';
|
|
7
7
|
import { useStylesField } from '../../../hooks/use-styles-field';
|
|
8
8
|
import { useStylesFields } from '../../../hooks/use-styles-fields';
|
|
9
9
|
import { DimensionsField } from './dimensions-field';
|
|
@@ -6,11 +6,15 @@ import { __ } from '@wordpress/i18n';
|
|
|
6
6
|
import { StylesField } from '../../../controls-registry/styles-field';
|
|
7
7
|
|
|
8
8
|
const fontWeightOptions = [
|
|
9
|
-
{ label: __( '
|
|
10
|
-
{ label: __( '
|
|
11
|
-
{ label: __( '
|
|
12
|
-
{ label: __( '
|
|
13
|
-
{ label: __( '
|
|
9
|
+
{ value: '100', label: __( '100 - Thin', 'elementor' ) },
|
|
10
|
+
{ value: '200', label: __( '200 - Extra Light', 'elementor' ) },
|
|
11
|
+
{ value: '300', label: __( '300 - Light', 'elementor' ) },
|
|
12
|
+
{ value: '400', label: __( '400 - Normal', 'elementor' ) },
|
|
13
|
+
{ value: '500', label: __( '500 - Medium', 'elementor' ) },
|
|
14
|
+
{ value: '600', label: __( '600 - Semi Bold', 'elementor' ) },
|
|
15
|
+
{ value: '700', label: __( '700 - Bold', 'elementor' ) },
|
|
16
|
+
{ value: '800', label: __( '800 - Extra Bold', 'elementor' ) },
|
|
17
|
+
{ value: '900', label: __( '900 - Black', 'elementor' ) },
|
|
14
18
|
];
|
|
15
19
|
|
|
16
20
|
export const FontWeightField = () => {
|
|
@@ -1,33 +1,41 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { ControlLabel, type ToggleButtonGroupItem, ToggleControl } from '@elementor/editor-controls';
|
|
3
3
|
import { AlignCenterIcon, AlignJustifiedIcon, AlignLeftIcon, AlignRightIcon } from '@elementor/icons';
|
|
4
|
-
import { Grid } from '@elementor/ui';
|
|
4
|
+
import { Grid, withDirection } from '@elementor/ui';
|
|
5
5
|
import { __ } from '@wordpress/i18n';
|
|
6
6
|
|
|
7
7
|
import { StylesField } from '../../../controls-registry/styles-field';
|
|
8
|
+
import { RotatedIcon } from '../layout-section/utils/rotated-icon';
|
|
8
9
|
|
|
9
|
-
type Alignments = '
|
|
10
|
+
type Alignments = 'start' | 'center' | 'end' | 'justify';
|
|
11
|
+
|
|
12
|
+
const StartIcon = withDirection( AlignLeftIcon );
|
|
13
|
+
const EndIcon = withDirection( AlignRightIcon );
|
|
10
14
|
|
|
11
15
|
const options: ToggleButtonGroupItem< Alignments >[] = [
|
|
12
16
|
{
|
|
13
|
-
value: '
|
|
14
|
-
label: __( '
|
|
15
|
-
renderContent: (
|
|
17
|
+
value: 'start',
|
|
18
|
+
label: __( 'Start', 'elementor' ),
|
|
19
|
+
renderContent: () => <RotatedIcon icon={ StartIcon } size="tiny" />,
|
|
20
|
+
showTooltip: true,
|
|
16
21
|
},
|
|
17
22
|
{
|
|
18
23
|
value: 'center',
|
|
19
24
|
label: __( 'Center', 'elementor' ),
|
|
20
25
|
renderContent: ( { size } ) => <AlignCenterIcon fontSize={ size } />,
|
|
26
|
+
showTooltip: true,
|
|
21
27
|
},
|
|
22
28
|
{
|
|
23
|
-
value: '
|
|
24
|
-
label: __( '
|
|
25
|
-
renderContent: (
|
|
29
|
+
value: 'end',
|
|
30
|
+
label: __( 'End', 'elementor' ),
|
|
31
|
+
renderContent: () => <RotatedIcon icon={ EndIcon } size="tiny" />,
|
|
32
|
+
showTooltip: true,
|
|
26
33
|
},
|
|
27
34
|
{
|
|
28
35
|
value: 'justify',
|
|
29
36
|
label: __( 'Justify', 'elementor' ),
|
|
30
37
|
renderContent: ( { size } ) => <AlignJustifiedIcon fontSize={ size } />,
|
|
38
|
+
showTooltip: true,
|
|
31
39
|
},
|
|
32
40
|
];
|
|
33
41
|
|
|
@@ -24,7 +24,7 @@ const initTextStroke = {
|
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
export const TextStrokeField = () => {
|
|
27
|
-
const [ textStroke, setTextStroke ] = useStylesField( '
|
|
27
|
+
const [ textStroke, setTextStroke ] = useStylesField( 'stroke' );
|
|
28
28
|
|
|
29
29
|
const addTextStroke = () => {
|
|
30
30
|
setTextStroke( initTextStroke );
|
|
@@ -43,7 +43,7 @@ export const TextStrokeField = () => {
|
|
|
43
43
|
onAdd={ addTextStroke }
|
|
44
44
|
onRemove={ removeTextStroke }
|
|
45
45
|
>
|
|
46
|
-
<StylesField bind={ '
|
|
46
|
+
<StylesField bind={ 'stroke' }>
|
|
47
47
|
<StrokeControl />
|
|
48
48
|
</StylesField>
|
|
49
49
|
</AddOrRemoveContent>
|
|
@@ -1,28 +1,37 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { ControlLabel, type ToggleButtonGroupItem, ToggleControl } from '@elementor/editor-controls';
|
|
3
|
-
import { LetterCaseIcon, LetterCaseLowerIcon, LetterCaseUpperIcon } from '@elementor/icons';
|
|
3
|
+
import { LetterCaseIcon, LetterCaseLowerIcon, LetterCaseUpperIcon, MinusIcon } from '@elementor/icons';
|
|
4
4
|
import { Grid } from '@elementor/ui';
|
|
5
5
|
import { __ } from '@wordpress/i18n';
|
|
6
6
|
|
|
7
7
|
import { StylesField } from '../../../controls-registry/styles-field';
|
|
8
8
|
|
|
9
|
-
type Transforms = 'capitalize' | 'uppercase' | 'lowercase';
|
|
9
|
+
type Transforms = 'none' | 'capitalize' | 'uppercase' | 'lowercase';
|
|
10
10
|
|
|
11
11
|
const options: ToggleButtonGroupItem< Transforms >[] = [
|
|
12
|
+
{
|
|
13
|
+
value: 'none',
|
|
14
|
+
label: __( 'None', 'elementor' ),
|
|
15
|
+
renderContent: ( { size } ) => <MinusIcon fontSize={ size } />,
|
|
16
|
+
showTooltip: true,
|
|
17
|
+
},
|
|
12
18
|
{
|
|
13
19
|
value: 'capitalize',
|
|
14
20
|
label: __( 'Capitalize', 'elementor' ),
|
|
15
21
|
renderContent: ( { size } ) => <LetterCaseIcon fontSize={ size } />,
|
|
22
|
+
showTooltip: true,
|
|
16
23
|
},
|
|
17
24
|
{
|
|
18
25
|
value: 'uppercase',
|
|
19
26
|
label: __( 'Uppercase', 'elementor' ),
|
|
20
27
|
renderContent: ( { size } ) => <LetterCaseUpperIcon fontSize={ size } />,
|
|
28
|
+
showTooltip: true,
|
|
21
29
|
},
|
|
22
30
|
{
|
|
23
31
|
value: 'lowercase',
|
|
24
32
|
label: __( 'Lowercase', 'elementor' ),
|
|
25
33
|
renderContent: ( { size } ) => <LetterCaseLowerIcon fontSize={ size } />,
|
|
34
|
+
showTooltip: true,
|
|
26
35
|
},
|
|
27
36
|
];
|
|
28
37
|
|
|
@@ -30,7 +39,7 @@ export const TransformField = () => (
|
|
|
30
39
|
<StylesField bind={ 'text-transform' }>
|
|
31
40
|
<Grid container gap={ 2 } alignItems="center" flexWrap="nowrap">
|
|
32
41
|
<Grid item xs={ 6 }>
|
|
33
|
-
<ControlLabel>{ __( 'Transform', 'elementor' ) }</ControlLabel>
|
|
42
|
+
<ControlLabel>{ __( 'Text Transform', 'elementor' ) }</ControlLabel>
|
|
34
43
|
</Grid>
|
|
35
44
|
<Grid item xs={ 6 } display="flex" justifyContent="end">
|
|
36
45
|
<ToggleControl options={ options } />
|
|
@@ -11,7 +11,7 @@ import { __ } from '@wordpress/i18n';
|
|
|
11
11
|
import { ClassesPropProvider } from '../contexts/classes-prop-context';
|
|
12
12
|
import { useElement } from '../contexts/element-context';
|
|
13
13
|
import { StyleProvider } from '../contexts/style-context';
|
|
14
|
-
import { CssClassSelector } from './css-class-selector';
|
|
14
|
+
import { CssClassSelector } from './css-classes/css-class-selector';
|
|
15
15
|
import { Section } from './section';
|
|
16
16
|
import { SectionsList } from './sections-list';
|
|
17
17
|
import { BackgroundSection } from './style-sections/background-section/background-section';
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
LinkControl,
|
|
5
5
|
SelectControl,
|
|
6
6
|
SizeControl,
|
|
7
|
+
SvgMediaControl,
|
|
7
8
|
TextAreaControl,
|
|
8
9
|
TextControl,
|
|
9
10
|
UrlControl,
|
|
@@ -15,7 +16,8 @@ type ControlRegistry = Record< string, { component: ControlComponent; layout: Co
|
|
|
15
16
|
|
|
16
17
|
const controlTypes = {
|
|
17
18
|
image: { component: ImageControl, layout: 'full' },
|
|
18
|
-
|
|
19
|
+
'svg-media': { component: SvgMediaControl, layout: 'full' },
|
|
20
|
+
text: { component: TextControl, layout: 'full' },
|
|
19
21
|
textarea: { component: TextAreaControl, layout: 'full' },
|
|
20
22
|
size: { component: SizeControl, layout: 'two-columns' },
|
|
21
23
|
select: { component: SelectControl, layout: 'two-columns' },
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { PropKeyProvider, PropProvider } from '@elementor/editor-controls';
|
|
3
3
|
import { updateElementSettings, useElementSetting } from '@elementor/editor-elements';
|
|
4
|
-
import { type PropKey, type PropValue } from '@elementor/editor-props';
|
|
4
|
+
import { type LinkPropValue, type PropKey, type PropValue } from '@elementor/editor-props';
|
|
5
5
|
|
|
6
6
|
import { useElement } from '../contexts/element-context';
|
|
7
7
|
import { createTopLevelOjectType } from './create-top-level-object-type';
|
|
@@ -15,10 +15,17 @@ export const SettingsField = ( { bind, children }: Props ) => {
|
|
|
15
15
|
const { element, elementType } = useElement();
|
|
16
16
|
|
|
17
17
|
const settingsValue = useElementSetting< PropValue >( element.id, bind );
|
|
18
|
+
|
|
19
|
+
const linkValue = useElementSetting< PropValue >( element.id, 'link' ) as LinkPropValue;
|
|
20
|
+
|
|
18
21
|
const value = { [ bind ]: settingsValue };
|
|
19
22
|
|
|
20
23
|
const propType = createTopLevelOjectType( { schema: elementType.propsSchema } );
|
|
21
24
|
|
|
25
|
+
if ( bind === 'tag' && linkValue?.value && 'div-block' === elementType.key ) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
22
29
|
const setValue = ( newValue: Record< string, PropValue > ) => {
|
|
23
30
|
updateElementSettings( {
|
|
24
31
|
id: element.id,
|
|
@@ -6,7 +6,7 @@ import { createTopLevelOjectType } from '../controls-registry/create-top-level-o
|
|
|
6
6
|
import { useDynamicTag } from './hooks/use-dynamic-tag';
|
|
7
7
|
import { dynamicPropTypeUtil, type DynamicPropValue } from './utils';
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
type DynamicControlProps = React.PropsWithChildren< {
|
|
10
10
|
bind: PropKey;
|
|
11
11
|
} >;
|
|
12
12
|
|
package/src/dynamics/types.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type ControlItem
|
|
2
|
-
import { type TransformablePropType, type TransformablePropValue } from '@elementor/editor-props';
|
|
1
|
+
import { type ControlItem } from '@elementor/editor-elements';
|
|
2
|
+
import { type PropsSchema, type TransformablePropType, type TransformablePropValue } from '@elementor/editor-props';
|
|
3
3
|
|
|
4
4
|
export type ExtendedWindow = Window & {
|
|
5
5
|
elementor?: {
|
package/src/dynamics/utils.ts
CHANGED
|
@@ -9,9 +9,9 @@ import { z } from '@elementor/schema';
|
|
|
9
9
|
|
|
10
10
|
import { type DynamicPropType } from './types';
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
const DYNAMIC_PROP_TYPE_KEY = 'dynamic';
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
const isDynamicPropType = ( prop: TransformablePropType ): prop is DynamicPropType =>
|
|
15
15
|
prop.key === DYNAMIC_PROP_TYPE_KEY;
|
|
16
16
|
|
|
17
17
|
export const getDynamicPropType = ( propType: PropType ): DynamicPropType | null => {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { type PropValue } from '@elementor/editor-props';
|
|
2
|
+
import { useSessionStorage } from '@elementor/session';
|
|
2
3
|
|
|
3
4
|
import { useElement } from '../contexts/element-context';
|
|
4
5
|
import { type DynamicPropValue } from '../dynamics/types';
|
|
5
|
-
import { useSessionStorage } from './use-session-storage';
|
|
6
6
|
|
|
7
7
|
export const usePersistDynamicValue = < T extends DynamicPropValue | PropValue >( propKey: string ) => {
|
|
8
8
|
const { element } = useElement();
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
import { useEffect, useReducer } from 'react';
|
|
2
|
-
import {
|
|
1
|
+
import { useEffect, useMemo, useReducer } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
createElementStyle,
|
|
4
|
+
type CreateElementStyleArgs,
|
|
5
|
+
deleteElementStyle,
|
|
6
|
+
type ElementID,
|
|
7
|
+
getElementLabel,
|
|
8
|
+
} from '@elementor/editor-elements';
|
|
3
9
|
import type { Props } from '@elementor/editor-props';
|
|
4
10
|
import { getVariantByMeta, type StyleDefinition, type StyleDefinitionVariant } from '@elementor/editor-styles';
|
|
5
11
|
import { type StylesProvider } from '@elementor/editor-styles-repository';
|
|
12
|
+
import { LOCAL_STYLES_RESERVED_LABEL } from '@elementor/editor-styles-repository';
|
|
13
|
+
import { undoable } from '@elementor/editor-v1-adapters';
|
|
6
14
|
import { __ } from '@wordpress/i18n';
|
|
7
15
|
|
|
8
16
|
import { useClassesProp } from '../contexts/classes-prop-context';
|
|
@@ -15,6 +23,9 @@ export function useStylesFields< T extends Props >( propNames: ( keyof T & strin
|
|
|
15
23
|
const { id, meta, provider } = useStyle();
|
|
16
24
|
const classesProp = useClassesProp();
|
|
17
25
|
|
|
26
|
+
const undoableUpdateStyle = useUndoableUpdateStyle();
|
|
27
|
+
const undoableCreateElementStyle = useUndoableCreateElementStyle();
|
|
28
|
+
|
|
18
29
|
const [ , reRender ] = useReducer( ( p ) => ! p, false );
|
|
19
30
|
|
|
20
31
|
useEffect( () => provider?.subscribe( reRender ), [ provider ] );
|
|
@@ -29,22 +40,23 @@ export function useStylesFields< T extends Props >( propNames: ( keyof T & strin
|
|
|
29
40
|
|
|
30
41
|
const setValue = ( props: T ) => {
|
|
31
42
|
if ( id === null ) {
|
|
32
|
-
|
|
43
|
+
undoableCreateElementStyle( {
|
|
33
44
|
elementId: element.id,
|
|
34
45
|
classesProp,
|
|
35
46
|
meta,
|
|
36
47
|
props,
|
|
37
|
-
label: __( 'local', 'elementor' ),
|
|
38
48
|
} );
|
|
39
49
|
|
|
40
50
|
return;
|
|
41
51
|
}
|
|
42
52
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
53
|
+
undoableUpdateStyle( {
|
|
54
|
+
elementId: element.id,
|
|
55
|
+
styleId: id,
|
|
56
|
+
provider,
|
|
57
|
+
meta,
|
|
58
|
+
props,
|
|
59
|
+
} );
|
|
48
60
|
};
|
|
49
61
|
|
|
50
62
|
return [ value, setValue ] as const;
|
|
@@ -79,3 +91,95 @@ function getProps< T extends Props >( { styleId, elementId, provider, meta, prop
|
|
|
79
91
|
propNames.map( ( key ) => [ key, variant?.props[ key ] ?? null ] )
|
|
80
92
|
) as NullableValues< T >;
|
|
81
93
|
}
|
|
94
|
+
|
|
95
|
+
type UndoableCreateElementStyleArgs = Omit< CreateElementStyleArgs, 'label' >;
|
|
96
|
+
|
|
97
|
+
function useUndoableCreateElementStyle() {
|
|
98
|
+
return useMemo( () => {
|
|
99
|
+
return undoable(
|
|
100
|
+
{
|
|
101
|
+
do: ( payload: UndoableCreateElementStyleArgs ) => {
|
|
102
|
+
return createElementStyle( {
|
|
103
|
+
...payload,
|
|
104
|
+
label: LOCAL_STYLES_RESERVED_LABEL,
|
|
105
|
+
} );
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
undo: ( { elementId }, styleId ) => {
|
|
109
|
+
deleteElementStyle( elementId, styleId );
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
redo: ( payload, styleId ) => {
|
|
113
|
+
return createElementStyle( {
|
|
114
|
+
...payload,
|
|
115
|
+
styleId,
|
|
116
|
+
label: LOCAL_STYLES_RESERVED_LABEL,
|
|
117
|
+
} );
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
title: ( { elementId } ) => getElementLabel( elementId ),
|
|
122
|
+
subtitle: __( 'Style edited', 'elementor' ),
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
}, [] );
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
type UndoableUpdateStyleArgs = {
|
|
129
|
+
elementId: ElementID;
|
|
130
|
+
styleId: StyleDefinition[ 'id' ];
|
|
131
|
+
provider: StylesProvider;
|
|
132
|
+
meta: StyleDefinitionVariant[ 'meta' ];
|
|
133
|
+
props: Props;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
function useUndoableUpdateStyle() {
|
|
137
|
+
return useMemo( () => {
|
|
138
|
+
return undoable(
|
|
139
|
+
{
|
|
140
|
+
do: ( { elementId, styleId, provider, meta, props }: UndoableUpdateStyleArgs ) => {
|
|
141
|
+
if ( ! provider.actions.updateProps ) {
|
|
142
|
+
throw new StylesProviderCannotUpdatePropsError( {
|
|
143
|
+
context: { providerKey: provider.key },
|
|
144
|
+
} );
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const style = provider.actions.getById( styleId, { elementId } );
|
|
148
|
+
|
|
149
|
+
const prevProps = getCurrentProps( style, meta );
|
|
150
|
+
|
|
151
|
+
provider.actions.updateProps(
|
|
152
|
+
{
|
|
153
|
+
id: styleId,
|
|
154
|
+
meta,
|
|
155
|
+
props,
|
|
156
|
+
},
|
|
157
|
+
{ elementId }
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
return prevProps;
|
|
161
|
+
},
|
|
162
|
+
|
|
163
|
+
undo: ( { elementId, styleId, meta, provider }, prevProps ) => {
|
|
164
|
+
provider.actions.updateProps?.( { id: styleId, meta, props: prevProps }, { elementId } );
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
title: ( { elementId } ) => getElementLabel( elementId ),
|
|
169
|
+
subtitle: __( 'Style edited', 'elementor' ),
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
}, [] );
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function getCurrentProps( style: StyleDefinition | null, meta: StyleDefinitionVariant[ 'meta' ] ) {
|
|
176
|
+
if ( ! style ) {
|
|
177
|
+
return {};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const variant = getVariantByMeta( style, meta );
|
|
181
|
+
|
|
182
|
+
const props = variant?.props ?? {};
|
|
183
|
+
|
|
184
|
+
return structuredClone( props );
|
|
185
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { useBoundProp } from '@elementor/editor-controls';
|
|
2
2
|
export type { PopoverActionProps } from './popover-action';
|
|
3
3
|
export { replaceControl } from './control-replacement';
|
|
4
|
-
export { injectIntoClassSelectorActions } from './components/css-class-selector';
|
|
4
|
+
export { injectIntoClassSelectorActions } from './components/css-classes/css-class-selector';
|
|
5
5
|
export { usePanelActions, usePanelStatus } from './panel';
|
|
6
6
|
|
|
7
7
|
import init from './init';
|
package/src/init.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { injectIntoLogic } from '@elementor/editor';
|
|
2
2
|
import { __registerPanel as registerPanel } from '@elementor/editor-panels';
|
|
3
|
-
import {
|
|
3
|
+
import { blockCommand } from '@elementor/editor-v1-adapters';
|
|
4
4
|
|
|
5
5
|
import { EditingPanelHooks } from './components/editing-panel-hooks';
|
|
6
6
|
import { init as initDynamics } from './dynamics/init';
|
|
@@ -21,7 +21,7 @@ export default function init() {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
const blockV1Panel = () => {
|
|
24
|
-
|
|
24
|
+
blockCommand( {
|
|
25
25
|
command: 'panel/editor/open',
|
|
26
26
|
condition: isAtomicWidgetSelected,
|
|
27
27
|
} );
|
package/src/sync/types.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { type ControlItem, type
|
|
1
|
+
import { type ControlItem, type V1Element } from '@elementor/editor-elements';
|
|
2
|
+
import { type PropsSchema } from '@elementor/editor-props';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
type SupportedFonts = 'system' | 'googlefonts' | 'customfonts';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
type EnqueueFont = ( fontFamily: string, context?: 'preview' | 'editor' ) => void;
|
|
6
7
|
|
|
7
8
|
export type ExtendedWindow = Window & {
|
|
8
9
|
elementor?: {
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { useState } from 'react';
|
|
3
|
-
import { MinusIcon, PlusIcon } from '@elementor/icons';
|
|
4
|
-
import { Collapse, IconButton, Stack } from '@elementor/ui';
|
|
5
|
-
import { __ } from '@wordpress/i18n';
|
|
6
|
-
|
|
7
|
-
type CollapsibleFieldProps = React.PropsWithChildren< {
|
|
8
|
-
label: React.ReactNode;
|
|
9
|
-
defaultOpen?: boolean;
|
|
10
|
-
} >;
|
|
11
|
-
|
|
12
|
-
export const CollapsibleField = ( { label, children, defaultOpen = false }: CollapsibleFieldProps ) => {
|
|
13
|
-
const [ open, setOpen ] = useState( defaultOpen );
|
|
14
|
-
|
|
15
|
-
const handleToggle = () => {
|
|
16
|
-
setOpen( ( prevOpen ) => ! prevOpen );
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
return (
|
|
20
|
-
<Stack gap={ 1.5 }>
|
|
21
|
-
<Stack direction="row" justifyContent="space-between" alignItems="center" sx={ { py: 0.5 } }>
|
|
22
|
-
{ label }
|
|
23
|
-
<IconButton
|
|
24
|
-
onClick={ handleToggle }
|
|
25
|
-
size="tiny"
|
|
26
|
-
aria-label={ open ? __( 'Close', 'elementor' ) : __( 'Expand', 'elementor' ) }
|
|
27
|
-
>
|
|
28
|
-
{ open ? <MinusIcon fontSize="tiny" /> : <PlusIcon fontSize="tiny" /> }
|
|
29
|
-
</IconButton>
|
|
30
|
-
</Stack>
|
|
31
|
-
<Collapse in={ open } unmountOnExit>
|
|
32
|
-
{ children }
|
|
33
|
-
</Collapse>
|
|
34
|
-
</Stack>
|
|
35
|
-
);
|
|
36
|
-
};
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { type StyleDefinitionState } from '@elementor/editor-styles';
|
|
3
|
-
import { CheckIcon } from '@elementor/icons';
|
|
4
|
-
import {
|
|
5
|
-
bindMenu,
|
|
6
|
-
Divider,
|
|
7
|
-
ListItemIcon,
|
|
8
|
-
ListItemText,
|
|
9
|
-
ListSubheader,
|
|
10
|
-
Menu,
|
|
11
|
-
MenuItem,
|
|
12
|
-
type PopupState,
|
|
13
|
-
styled,
|
|
14
|
-
} from '@elementor/ui';
|
|
15
|
-
import { __ } from '@wordpress/i18n';
|
|
16
|
-
|
|
17
|
-
import { useStyle } from '../contexts/style-context';
|
|
18
|
-
import { useUnapplyClass } from '../hooks/use-unapply-class';
|
|
19
|
-
|
|
20
|
-
const STATES: NonNullable< StyleDefinitionState >[] = [ 'hover', 'focus', 'active' ];
|
|
21
|
-
|
|
22
|
-
type CssClassMenuProps = { styleId: string; isFixed: boolean; popupState: PopupState };
|
|
23
|
-
|
|
24
|
-
export function CssClassMenu( { styleId, isFixed = false, popupState }: CssClassMenuProps ) {
|
|
25
|
-
const handleKeyDown = ( e: React.KeyboardEvent< HTMLElement > ) => {
|
|
26
|
-
e.stopPropagation();
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<Menu
|
|
31
|
-
MenuListProps={ { dense: true } }
|
|
32
|
-
{ ...bindMenu( popupState ) }
|
|
33
|
-
anchorOrigin={ {
|
|
34
|
-
vertical: 'top',
|
|
35
|
-
horizontal: 'right',
|
|
36
|
-
} }
|
|
37
|
-
onKeyDown={ handleKeyDown }
|
|
38
|
-
>
|
|
39
|
-
{ /* It has to be an array since MUI menu doesn't accept a Fragment as a child, and wrapping the items with an HTML element disrupts keyboard navigation */ }
|
|
40
|
-
{ ! isFixed && [
|
|
41
|
-
<UnapplyClassMenuItem key="unapply-class" styleId={ styleId } />,
|
|
42
|
-
<Divider key="global-class-items-divider" />,
|
|
43
|
-
] }
|
|
44
|
-
<ListSubheader>{ __( 'Add a pseudo selector', 'elementor' ) }</ListSubheader>
|
|
45
|
-
<StateMenuItem key="normal" state={ null } styleId={ styleId } />
|
|
46
|
-
{ STATES.map( ( state ) => {
|
|
47
|
-
return <StateMenuItem key={ state } state={ state } styleId={ styleId } />;
|
|
48
|
-
} ) }
|
|
49
|
-
</Menu>
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
type StateMenuItemProps = {
|
|
54
|
-
state: StyleDefinitionState;
|
|
55
|
-
styleId: string;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
function StateMenuItem( { state, styleId, ...props }: StateMenuItemProps ) {
|
|
59
|
-
const { id: activeId, setId: setActiveId, setMetaState: setActiveMetaState, meta } = useStyle();
|
|
60
|
-
const { state: activeState } = meta;
|
|
61
|
-
|
|
62
|
-
const isActive = styleId === activeId;
|
|
63
|
-
const isSelected = state === activeState && isActive;
|
|
64
|
-
|
|
65
|
-
return (
|
|
66
|
-
<StyledMenuItem
|
|
67
|
-
{ ...props }
|
|
68
|
-
selected={ isSelected }
|
|
69
|
-
onClick={ () => {
|
|
70
|
-
if ( ! isActive ) {
|
|
71
|
-
setActiveId( styleId );
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
setActiveMetaState( state );
|
|
75
|
-
} }
|
|
76
|
-
>
|
|
77
|
-
{ isSelected && (
|
|
78
|
-
<ListItemIcon>
|
|
79
|
-
<CheckIcon />
|
|
80
|
-
</ListItemIcon>
|
|
81
|
-
) }
|
|
82
|
-
<ListItemText primary={ state ? `:${ state }` : 'Normal' } />
|
|
83
|
-
</StyledMenuItem>
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function UnapplyClassMenuItem( { styleId, ...props }: { styleId: string } ) {
|
|
88
|
-
const unapplyClass = useUnapplyClass( styleId );
|
|
89
|
-
|
|
90
|
-
return (
|
|
91
|
-
<StyledMenuItem { ...props } onClick={ unapplyClass }>
|
|
92
|
-
<ListItemText primary="Remove" />
|
|
93
|
-
</StyledMenuItem>
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const StyledMenuItem = styled( MenuItem )( {
|
|
98
|
-
'&:hover': {
|
|
99
|
-
color: 'text.primary', // Overriding global CSS from the editor.
|
|
100
|
-
},
|
|
101
|
-
} );
|