@elementor/editor-editing-panel 1.40.0 → 1.41.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 +32 -0
- package/dist/index.d.mts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +1177 -732
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1070 -614
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -6
- package/src/action.tsx +26 -0
- package/src/components/add-or-remove-content.tsx +11 -3
- package/src/components/css-classes/css-class-item.tsx +3 -2
- package/src/components/css-classes/css-class-menu.tsx +15 -5
- package/src/components/css-classes/css-class-selector.tsx +1 -0
- package/src/components/css-classes/use-apply-and-unapply-class.ts +8 -4
- package/src/components/section-content.tsx +16 -6
- package/src/components/style-sections/background-section/background-section.tsx +6 -3
- package/src/components/style-sections/border-section/border-field.tsx +3 -0
- package/src/components/style-sections/layout-section/display-field.tsx +2 -1
- package/src/components/style-sections/layout-section/flex-order-field.tsx +5 -2
- package/src/components/style-sections/layout-section/flex-size-field.tsx +16 -12
- package/src/components/style-sections/typography-section/text-stroke-field.tsx +3 -0
- package/src/components/style-tab.tsx +1 -1
- package/src/contexts/style-context.tsx +11 -2
- package/src/contexts/styles-inheritance-context.tsx +9 -7
- package/src/controls-actions.ts +2 -0
- package/src/controls-registry/styles-field.tsx +3 -0
- package/src/init.ts +11 -1
- package/src/reset-style-props.tsx +31 -0
- package/src/styles-inheritance/components/action-icons.tsx +8 -0
- package/src/styles-inheritance/components/breakpoint-icon.tsx +47 -0
- package/src/styles-inheritance/components/index.ts +4 -0
- package/src/styles-inheritance/components/label-chip.tsx +43 -0
- package/src/styles-inheritance/components/value-component.tsx +25 -0
- package/src/styles-inheritance/consts.ts +17 -0
- package/src/styles-inheritance/create-styles-inheritance.ts +50 -12
- package/src/{hooks → styles-inheritance/hooks}/use-normalized-inheritance-chain-items.tsx +41 -11
- package/src/styles-inheritance/init-styles-inheritance-transformers.ts +38 -0
- package/src/styles-inheritance/init.ts +8 -0
- package/src/styles-inheritance/styles-inheritance-indicator.tsx +35 -32
- package/src/styles-inheritance/styles-inheritance-infotip.tsx +113 -19
- package/src/styles-inheritance/styles-inheritance-transformers-registry.tsx +3 -0
- package/src/styles-inheritance/transformers/background-color-overlay-transformer.tsx +27 -0
- package/src/styles-inheritance/transformers/background-gradient-overlay-transformer.tsx +50 -0
- package/src/styles-inheritance/transformers/background-image-overlay-transformer.tsx +79 -0
- package/src/styles-inheritance/transformers/background-overlay-transformer.tsx +20 -0
- package/src/styles-inheritance/types.ts +6 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/editor-editing-panel",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.41.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Elementor Team",
|
|
6
6
|
"homepage": "https://elementor.com/",
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@elementor/editor": "0.19.4",
|
|
43
|
-
"@elementor/editor-canvas": "0.22.
|
|
44
|
-
"@elementor/editor-controls": "0.
|
|
43
|
+
"@elementor/editor-canvas": "0.22.2",
|
|
44
|
+
"@elementor/editor-controls": "0.34.0",
|
|
45
45
|
"@elementor/editor-current-user": "0.5.0",
|
|
46
46
|
"@elementor/editor-documents": "0.13.6",
|
|
47
47
|
"@elementor/editor-elements": "0.8.4",
|
|
@@ -49,16 +49,17 @@
|
|
|
49
49
|
"@elementor/editor-props": "0.12.1",
|
|
50
50
|
"@elementor/editor-responsive": "0.13.5",
|
|
51
51
|
"@elementor/editor-styles": "0.6.8",
|
|
52
|
-
"@elementor/editor-styles-repository": "0.10.
|
|
53
|
-
"@elementor/editor-ui": "0.
|
|
52
|
+
"@elementor/editor-styles-repository": "0.10.1",
|
|
53
|
+
"@elementor/editor-ui": "0.10.0",
|
|
54
54
|
"@elementor/editor-v1-adapters": "0.12.0",
|
|
55
|
-
"@elementor/icons": "1.
|
|
55
|
+
"@elementor/icons": "1.44.0",
|
|
56
56
|
"@elementor/locations": "0.8.0",
|
|
57
57
|
"@elementor/menus": "0.1.5",
|
|
58
58
|
"@elementor/schema": "0.1.2",
|
|
59
59
|
"@elementor/session": "0.1.0",
|
|
60
60
|
"@elementor/ui": "1.34.5",
|
|
61
61
|
"@elementor/utils": "0.4.0",
|
|
62
|
+
"@elementor/wp-media": "0.6.0",
|
|
62
63
|
"@wordpress/i18n": "^5.13.0"
|
|
63
64
|
},
|
|
64
65
|
"peerDependencies": {
|
package/src/action.tsx
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type ElementType as ReactElementType } from 'react';
|
|
3
|
+
import { IconButton, Tooltip } from '@elementor/ui';
|
|
4
|
+
|
|
5
|
+
const SIZE = 'tiny';
|
|
6
|
+
|
|
7
|
+
type ActionProps = {
|
|
8
|
+
title: string;
|
|
9
|
+
visible?: boolean;
|
|
10
|
+
icon: ReactElementType;
|
|
11
|
+
onClick: () => void;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default function Action( { title, visible = true, icon: Icon, onClick }: ActionProps ) {
|
|
15
|
+
if ( ! visible ) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<Tooltip placement="bottom" title={ title } arrow={ true }>
|
|
21
|
+
<IconButton aria-label={ title } size={ SIZE } onClick={ onClick }>
|
|
22
|
+
<Icon fontSize={ SIZE } />
|
|
23
|
+
</IconButton>
|
|
24
|
+
</Tooltip>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
@@ -13,9 +13,17 @@ type Props = {
|
|
|
13
13
|
isAdded: boolean;
|
|
14
14
|
onAdd: () => void;
|
|
15
15
|
onRemove: () => void;
|
|
16
|
+
disabled?: boolean;
|
|
16
17
|
};
|
|
17
18
|
|
|
18
|
-
export const AddOrRemoveContent = ( {
|
|
19
|
+
export const AddOrRemoveContent = ( {
|
|
20
|
+
isAdded,
|
|
21
|
+
label,
|
|
22
|
+
onAdd,
|
|
23
|
+
onRemove,
|
|
24
|
+
children,
|
|
25
|
+
disabled,
|
|
26
|
+
}: PropsWithChildren< Props > ) => {
|
|
19
27
|
return (
|
|
20
28
|
<SectionContent>
|
|
21
29
|
<Stack
|
|
@@ -28,11 +36,11 @@ export const AddOrRemoveContent = ( { isAdded, label, onAdd, onRemove, children
|
|
|
28
36
|
>
|
|
29
37
|
<ControlLabel>{ label }</ControlLabel>
|
|
30
38
|
{ isAdded ? (
|
|
31
|
-
<IconButton size={ SIZE } onClick={ onRemove } aria-label="Remove">
|
|
39
|
+
<IconButton size={ SIZE } onClick={ onRemove } aria-label="Remove" disabled={ disabled }>
|
|
32
40
|
<MinusIcon fontSize={ SIZE } />
|
|
33
41
|
</IconButton>
|
|
34
42
|
) : (
|
|
35
|
-
<IconButton size={ SIZE } onClick={ onAdd } aria-label="Add">
|
|
43
|
+
<IconButton size={ SIZE } onClick={ onAdd } aria-label="Add" disabled={ disabled }>
|
|
36
44
|
<PlusIcon fontSize={ SIZE } />
|
|
37
45
|
</IconButton>
|
|
38
46
|
) }
|
|
@@ -24,6 +24,7 @@ type CssClassItemProps = {
|
|
|
24
24
|
id: string | null;
|
|
25
25
|
provider: string | null;
|
|
26
26
|
label: string;
|
|
27
|
+
fixed?: boolean;
|
|
27
28
|
isActive: boolean;
|
|
28
29
|
color: ChipOwnProps[ 'color' ];
|
|
29
30
|
icon: ReactElement | null;
|
|
@@ -37,7 +38,7 @@ type CssClassItemProps = {
|
|
|
37
38
|
const CHIP_SIZE = 'tiny';
|
|
38
39
|
|
|
39
40
|
export function CssClassItem( props: CssClassItemProps ) {
|
|
40
|
-
const { chipProps, icon, color: colorProp, ...classProps } = props;
|
|
41
|
+
const { chipProps, icon, color: colorProp, fixed, ...classProps } = props;
|
|
41
42
|
const { id, provider, label, isActive, onClickActive, renameLabel, setError } = classProps;
|
|
42
43
|
|
|
43
44
|
const { meta, setMetaState } = useStyle();
|
|
@@ -139,7 +140,7 @@ export function CssClassItem( props: CssClassItemProps ) {
|
|
|
139
140
|
) }
|
|
140
141
|
</UnstableChipGroup>
|
|
141
142
|
<CssClassProvider { ...classProps } handleRename={ openEditMode }>
|
|
142
|
-
<CssClassMenu popupState={ popupState } anchorEl={ chipRef } />
|
|
143
|
+
<CssClassMenu popupState={ popupState } anchorEl={ chipRef } fixed={ fixed } />
|
|
143
144
|
</CssClassProvider>
|
|
144
145
|
</>
|
|
145
146
|
);
|
|
@@ -30,9 +30,10 @@ const STATES: State[] = [
|
|
|
30
30
|
type CssClassMenuProps = {
|
|
31
31
|
popupState: PopupState;
|
|
32
32
|
anchorEl: HTMLElement | null;
|
|
33
|
+
fixed?: boolean;
|
|
33
34
|
};
|
|
34
35
|
|
|
35
|
-
export function CssClassMenu( { popupState, anchorEl }: CssClassMenuProps ) {
|
|
36
|
+
export function CssClassMenu( { popupState, anchorEl, fixed }: CssClassMenuProps ) {
|
|
36
37
|
const { provider } = useCssClass();
|
|
37
38
|
|
|
38
39
|
const handleKeyDown = ( e: React.KeyboardEvent< HTMLElement > ) => {
|
|
@@ -57,7 +58,7 @@ export function CssClassMenu( { popupState, anchorEl }: CssClassMenuProps ) {
|
|
|
57
58
|
disableAutoFocusItem
|
|
58
59
|
>
|
|
59
60
|
{ /* 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 */ }
|
|
60
|
-
{ getMenuItemsByProvider( { provider, closeMenu: popupState.close } ) }
|
|
61
|
+
{ getMenuItemsByProvider( { provider, closeMenu: popupState.close, fixed } ) }
|
|
61
62
|
<MenuSubheader sx={ { typography: 'caption', color: 'text.secondary', pb: 0.5, pt: 1 } }>
|
|
62
63
|
{ __( 'States', 'elementor' ) }
|
|
63
64
|
</MenuSubheader>
|
|
@@ -80,7 +81,15 @@ function useModifiedStates( styleId: string | null ): Partial< Record< StyleDefi
|
|
|
80
81
|
);
|
|
81
82
|
}
|
|
82
83
|
|
|
83
|
-
function getMenuItemsByProvider( {
|
|
84
|
+
function getMenuItemsByProvider( {
|
|
85
|
+
provider,
|
|
86
|
+
closeMenu,
|
|
87
|
+
fixed,
|
|
88
|
+
}: {
|
|
89
|
+
provider: string | null;
|
|
90
|
+
closeMenu: () => void;
|
|
91
|
+
fixed?: boolean;
|
|
92
|
+
} ) {
|
|
84
93
|
if ( ! provider ) {
|
|
85
94
|
return [];
|
|
86
95
|
}
|
|
@@ -88,11 +97,12 @@ function getMenuItemsByProvider( { provider, closeMenu }: { provider: string | n
|
|
|
88
97
|
const providerInstance = stylesRepository.getProviderByKey( provider );
|
|
89
98
|
const providerActions = providerInstance?.actions;
|
|
90
99
|
|
|
91
|
-
const
|
|
100
|
+
const canUpdate = providerActions?.update;
|
|
101
|
+
const canUnapply = ! fixed;
|
|
92
102
|
|
|
93
103
|
const actions = [
|
|
94
104
|
canUpdate && <RenameClassMenuItem key="rename-class" closeMenu={ closeMenu } />,
|
|
95
|
-
|
|
105
|
+
canUnapply && <UnapplyClassMenuItem key="unapply-class" closeMenu={ closeMenu } />,
|
|
96
106
|
].filter( Boolean );
|
|
97
107
|
|
|
98
108
|
if ( actions.length ) {
|
|
@@ -31,7 +31,6 @@ export function useApplyClass() {
|
|
|
31
31
|
const prevActiveId = activeId;
|
|
32
32
|
|
|
33
33
|
applyClass( classId );
|
|
34
|
-
setDocumentModifiedStatus( true );
|
|
35
34
|
|
|
36
35
|
return prevActiveId;
|
|
37
36
|
},
|
|
@@ -76,7 +75,6 @@ export function useUnapplyClass() {
|
|
|
76
75
|
const prevActiveId = activeId;
|
|
77
76
|
|
|
78
77
|
unapplyClass( classId );
|
|
79
|
-
setDocumentModifiedStatus( true );
|
|
80
78
|
|
|
81
79
|
return prevActiveId;
|
|
82
80
|
},
|
|
@@ -158,13 +156,19 @@ function useSetClasses() {
|
|
|
158
156
|
const { element } = useElement();
|
|
159
157
|
const currentClassesProp = useClassesProp();
|
|
160
158
|
|
|
159
|
+
const isVersion330Active = isExperimentActive( 'e_v_3_30' );
|
|
160
|
+
|
|
161
161
|
return useMemo( () => {
|
|
162
162
|
const setClasses = ( ids: StyleDefinitionID[] ) => {
|
|
163
163
|
updateElementSettings( {
|
|
164
164
|
id: element.id,
|
|
165
165
|
props: { [ currentClassesProp ]: classesPropTypeUtil.create( ids ) },
|
|
166
|
-
withHistory: false,
|
|
166
|
+
withHistory: isVersion330Active ? false : true,
|
|
167
167
|
} );
|
|
168
|
+
|
|
169
|
+
if ( isVersion330Active ) {
|
|
170
|
+
setDocumentModifiedStatus( true );
|
|
171
|
+
}
|
|
168
172
|
};
|
|
169
173
|
|
|
170
174
|
const getAppliedClasses = () =>
|
|
@@ -174,5 +178,5 @@ function useSetClasses() {
|
|
|
174
178
|
setClasses,
|
|
175
179
|
getAppliedClasses,
|
|
176
180
|
};
|
|
177
|
-
}, [ currentClassesProp, element.id ] );
|
|
181
|
+
}, [ currentClassesProp, element.id, isVersion330Active ] );
|
|
178
182
|
}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import { type FC, type PropsWithChildren } from 'react';
|
|
1
|
+
import { createContext, type FC, type PropsWithChildren, useContext, useRef } from 'react';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { Stack } from '@elementor/ui';
|
|
4
4
|
|
|
5
|
+
const SectionContentRefContext = createContext< React.RefObject< HTMLElement > | null >( null );
|
|
6
|
+
|
|
7
|
+
export const useSectionContentRef = () => useContext( SectionContentRefContext );
|
|
8
|
+
|
|
5
9
|
type SectionContentProps = PropsWithChildren< {
|
|
6
10
|
gap?: number;
|
|
7
11
|
sx?: {
|
|
@@ -9,8 +13,14 @@ type SectionContentProps = PropsWithChildren< {
|
|
|
9
13
|
};
|
|
10
14
|
} >;
|
|
11
15
|
|
|
12
|
-
export const SectionContent: FC< SectionContentProps > = ( { gap = 2, sx, children } ) =>
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
export const SectionContent: FC< SectionContentProps > = ( { gap = 2, sx, children } ) => {
|
|
17
|
+
const ref = useRef< HTMLElement >( null );
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<SectionContentRefContext.Provider value={ ref }>
|
|
21
|
+
<Stack gap={ gap } sx={ { ...sx } } ref={ ref }>
|
|
22
|
+
{ children }
|
|
23
|
+
</Stack>
|
|
24
|
+
</SectionContentRefContext.Provider>
|
|
25
|
+
);
|
|
26
|
+
};
|
|
@@ -2,11 +2,14 @@ import * as React from 'react';
|
|
|
2
2
|
import { BackgroundControl } from '@elementor/editor-controls';
|
|
3
3
|
|
|
4
4
|
import { StylesField } from '../../../controls-registry/styles-field';
|
|
5
|
+
import { SectionContent } from '../../section-content';
|
|
5
6
|
|
|
6
7
|
export const BackgroundSection = () => {
|
|
7
8
|
return (
|
|
8
|
-
<
|
|
9
|
-
<
|
|
10
|
-
|
|
9
|
+
<SectionContent>
|
|
10
|
+
<StylesField bind="background">
|
|
11
|
+
<BackgroundControl />
|
|
12
|
+
</StylesField>
|
|
13
|
+
</SectionContent>
|
|
11
14
|
);
|
|
12
15
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { __ } from '@wordpress/i18n';
|
|
3
3
|
|
|
4
|
+
import { useStyle } from '../../../contexts/style-context';
|
|
4
5
|
import { useStylesFields } from '../../../hooks/use-styles-fields';
|
|
5
6
|
import { AddOrRemoveContent } from '../../add-or-remove-content';
|
|
6
7
|
import { BorderColorField } from './border-color-field';
|
|
@@ -14,6 +15,7 @@ const initialBorder = {
|
|
|
14
15
|
};
|
|
15
16
|
|
|
16
17
|
export const BorderField = () => {
|
|
18
|
+
const { canEdit } = useStyle();
|
|
17
19
|
const [ border, setBorder ] = useStylesFields( Object.keys( initialBorder ) );
|
|
18
20
|
|
|
19
21
|
const addBorder = () => {
|
|
@@ -36,6 +38,7 @@ export const BorderField = () => {
|
|
|
36
38
|
isAdded={ hasBorder }
|
|
37
39
|
onAdd={ addBorder }
|
|
38
40
|
onRemove={ removeBorder }
|
|
41
|
+
disabled={ ! canEdit }
|
|
39
42
|
>
|
|
40
43
|
<BorderWidthField />
|
|
41
44
|
<BorderColorField />
|
|
@@ -6,6 +6,7 @@ import { __ } from '@wordpress/i18n';
|
|
|
6
6
|
|
|
7
7
|
import { useStylesInheritanceChain } from '../../../contexts/styles-inheritance-context';
|
|
8
8
|
import { StylesField } from '../../../controls-registry/styles-field';
|
|
9
|
+
import { EXPERIMENTAL_FEATURES } from '../../../sync/experiments-flags';
|
|
9
10
|
import { ControlLabel } from '../../control-label';
|
|
10
11
|
|
|
11
12
|
type Displays = 'block' | 'flex' | 'inline-block' | 'inline-flex' | 'none';
|
|
@@ -32,7 +33,7 @@ const displayFieldItems: ToggleButtonGroupItem< Displays >[] = [
|
|
|
32
33
|
];
|
|
33
34
|
|
|
34
35
|
export const DisplayField = () => {
|
|
35
|
-
const isDisplayNoneFeatureActive = isExperimentActive(
|
|
36
|
+
const isDisplayNoneFeatureActive = isExperimentActive( EXPERIMENTAL_FEATURES.V_3_30 );
|
|
36
37
|
const items = [ ...displayFieldItems ];
|
|
37
38
|
|
|
38
39
|
if ( isDisplayNoneFeatureActive ) {
|
|
@@ -6,6 +6,7 @@ import { ArrowDownSmallIcon, ArrowUpSmallIcon, PencilIcon } from '@elementor/ico
|
|
|
6
6
|
import { DirectionProvider, Grid, ThemeProvider } from '@elementor/ui';
|
|
7
7
|
import { __ } from '@wordpress/i18n';
|
|
8
8
|
|
|
9
|
+
import { useStyle } from '../../../contexts/style-context';
|
|
9
10
|
import { StylesField } from '../../../controls-registry/styles-field';
|
|
10
11
|
import { useDirection } from '../../../hooks/use-direction';
|
|
11
12
|
import { useStylesField } from '../../../hooks/use-styles-field';
|
|
@@ -47,8 +48,9 @@ const items: ToggleButtonGroupItem< GroupControlItemOption >[] = [
|
|
|
47
48
|
];
|
|
48
49
|
|
|
49
50
|
export const FlexOrderField = () => {
|
|
50
|
-
const { isSiteRtl } = useDirection()
|
|
51
|
-
|
|
51
|
+
const { isSiteRtl } = useDirection();
|
|
52
|
+
const [ order, setOrder ] = useStylesField< NumberPropValue | null >( 'order' );
|
|
53
|
+
const { canEdit } = useStyle();
|
|
52
54
|
|
|
53
55
|
const [ groupControlValue, setGroupControlValue ] = useState( getGroupControlValue( order?.value || null ) );
|
|
54
56
|
|
|
@@ -79,6 +81,7 @@ export const FlexOrderField = () => {
|
|
|
79
81
|
value={ groupControlValue }
|
|
80
82
|
onChange={ handleToggleButtonChange }
|
|
81
83
|
exclusive={ true }
|
|
84
|
+
disabled={ ! canEdit }
|
|
82
85
|
/>
|
|
83
86
|
</Grid>
|
|
84
87
|
</Grid>
|
|
@@ -11,6 +11,7 @@ import { ExpandIcon, PencilIcon, ShrinkIcon } from '@elementor/icons';
|
|
|
11
11
|
import { DirectionProvider, Grid, ThemeProvider } from '@elementor/ui';
|
|
12
12
|
import { __ } from '@wordpress/i18n';
|
|
13
13
|
|
|
14
|
+
import { useStyle } from '../../../contexts/style-context';
|
|
14
15
|
import { StylesField } from '../../../controls-registry/styles-field';
|
|
15
16
|
import { useDirection } from '../../../hooks/use-direction';
|
|
16
17
|
import { useStylesFields } from '../../../hooks/use-styles-fields';
|
|
@@ -44,6 +45,7 @@ const items: ToggleButtonGroupItem< GroupItem >[] = [
|
|
|
44
45
|
|
|
45
46
|
export const FlexSizeField = () => {
|
|
46
47
|
const { isSiteRtl } = useDirection();
|
|
48
|
+
const { canEdit } = useStyle();
|
|
47
49
|
|
|
48
50
|
const [ fields, setFields ] = useStylesFields< {
|
|
49
51
|
'flex-grow': NumberPropValue | null;
|
|
@@ -93,19 +95,21 @@ export const FlexSizeField = () => {
|
|
|
93
95
|
<ThemeProvider>
|
|
94
96
|
<SectionContent>
|
|
95
97
|
<Grid container gap={ 2 } alignItems="center" flexWrap="nowrap">
|
|
96
|
-
<
|
|
97
|
-
<
|
|
98
|
+
<StylesField bind={ activeGroup ?? '' }>
|
|
99
|
+
<Grid item xs={ 6 }>
|
|
98
100
|
<ControlLabel>{ __( 'Size', 'elementor' ) }</ControlLabel>
|
|
99
|
-
</
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
101
|
+
</Grid>
|
|
102
|
+
|
|
103
|
+
<Grid item xs={ 6 } sx={ { display: 'flex', justifyContent: 'end' } }>
|
|
104
|
+
<ControlToggleButtonGroup
|
|
105
|
+
value={ activeGroup }
|
|
106
|
+
onChange={ onChangeGroup }
|
|
107
|
+
disabled={ ! canEdit }
|
|
108
|
+
items={ items }
|
|
109
|
+
exclusive={ true }
|
|
110
|
+
/>
|
|
111
|
+
</Grid>
|
|
112
|
+
</StylesField>
|
|
109
113
|
</Grid>
|
|
110
114
|
{ 'custom' === activeGroup && <FlexCustomField /> }
|
|
111
115
|
</SectionContent>
|
|
@@ -2,6 +2,7 @@ import * as React from 'react';
|
|
|
2
2
|
import { StrokeControl } from '@elementor/editor-controls';
|
|
3
3
|
import { __ } from '@wordpress/i18n';
|
|
4
4
|
|
|
5
|
+
import { useStyle } from '../../../contexts/style-context';
|
|
5
6
|
import { StylesField } from '../../../controls-registry/styles-field';
|
|
6
7
|
import { useStylesField } from '../../../hooks/use-styles-field';
|
|
7
8
|
import { AddOrRemoveContent } from '../../add-or-remove-content';
|
|
@@ -24,6 +25,7 @@ const initTextStroke = {
|
|
|
24
25
|
};
|
|
25
26
|
|
|
26
27
|
export const TextStrokeField = () => {
|
|
28
|
+
const { canEdit } = useStyle();
|
|
27
29
|
const [ textStroke, setTextStroke ] = useStylesField( 'stroke' );
|
|
28
30
|
|
|
29
31
|
const addTextStroke = () => {
|
|
@@ -43,6 +45,7 @@ export const TextStrokeField = () => {
|
|
|
43
45
|
isAdded={ hasTextStroke }
|
|
44
46
|
onAdd={ addTextStroke }
|
|
45
47
|
onRemove={ removeTextStroke }
|
|
48
|
+
disabled={ ! canEdit }
|
|
46
49
|
>
|
|
47
50
|
<StrokeControl />
|
|
48
51
|
</AddOrRemoveContent>
|
|
@@ -50,7 +50,7 @@ const PanelSection = ( { section }: { section: Section } ) => {
|
|
|
50
50
|
const SectionComponent = component;
|
|
51
51
|
const isExpanded = isExperimentActive( EXPERIMENTAL_FEATURES.V_3_30 )
|
|
52
52
|
? tabDefaults.defaultSectionsExpanded.style?.includes( name )
|
|
53
|
-
:
|
|
53
|
+
: false;
|
|
54
54
|
|
|
55
55
|
return (
|
|
56
56
|
<Section title={ title } defaultExpanded={ isExpanded }>
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
type StyleDefinitionState,
|
|
7
7
|
type StyleDefinitionVariant,
|
|
8
8
|
} from '@elementor/editor-styles';
|
|
9
|
-
import { type StylesProvider, stylesRepository } from '@elementor/editor-styles-repository';
|
|
9
|
+
import { type StylesProvider, stylesRepository, useUserStylesCapability } from '@elementor/editor-styles-repository';
|
|
10
10
|
|
|
11
11
|
import { StylesProviderNotFoundError } from '../errors';
|
|
12
12
|
|
|
@@ -14,6 +14,7 @@ type ContextValue = {
|
|
|
14
14
|
setId: Dispatch< StyleDefinition[ 'id' ] | null >;
|
|
15
15
|
meta: StyleDefinitionVariant[ 'meta' ];
|
|
16
16
|
setMetaState: Dispatch< StyleDefinitionState >;
|
|
17
|
+
canEdit?: boolean;
|
|
17
18
|
} & ( ContextValueWithProvider | ContextValueWithoutProvider );
|
|
18
19
|
|
|
19
20
|
type ContextValueWithProvider = {
|
|
@@ -33,11 +34,15 @@ type Props = PropsWithChildren< Omit< ContextValue, 'provider' > >;
|
|
|
33
34
|
export function StyleProvider( { children, ...props }: Props ) {
|
|
34
35
|
const provider = props.id === null ? null : getProviderByStyleId( props.id );
|
|
35
36
|
|
|
37
|
+
const { userCan } = useUserStylesCapability();
|
|
38
|
+
|
|
36
39
|
if ( props.id && ! provider ) {
|
|
37
40
|
throw new StylesProviderNotFoundError( { context: { styleId: props.id } } );
|
|
38
41
|
}
|
|
39
42
|
|
|
40
|
-
|
|
43
|
+
const canEdit = userCan( provider?.getKey() ?? '' ).updateProps;
|
|
44
|
+
|
|
45
|
+
return <Context.Provider value={ { ...props, provider, canEdit } as ContextValue }>{ children }</Context.Provider>;
|
|
41
46
|
}
|
|
42
47
|
|
|
43
48
|
export function useStyle() {
|
|
@@ -57,3 +62,7 @@ export function getProviderByStyleId( styleId: StyleDefinitionID ) {
|
|
|
57
62
|
|
|
58
63
|
return styleProvider ?? null;
|
|
59
64
|
}
|
|
65
|
+
|
|
66
|
+
export function useIsStyle(): boolean {
|
|
67
|
+
return !! useContext( Context );
|
|
68
|
+
}
|
|
@@ -3,6 +3,7 @@ import { createContext, type PropsWithChildren, useContext } from 'react';
|
|
|
3
3
|
import { getWidgetsCache, useElementSetting } from '@elementor/editor-elements';
|
|
4
4
|
import { classesPropTypeUtil, type ClassesPropValue } from '@elementor/editor-props';
|
|
5
5
|
import { getBreakpointsTree } from '@elementor/editor-responsive';
|
|
6
|
+
import { getStylesSchema } from '@elementor/editor-styles';
|
|
6
7
|
import { stylesRepository } from '@elementor/editor-styles-repository';
|
|
7
8
|
|
|
8
9
|
import { useStylesRerender } from '../hooks/use-styles-rerender';
|
|
@@ -50,13 +51,17 @@ export function useStylesInheritanceChain( path: string[] ): SnapshotPropValue[]
|
|
|
50
51
|
throw new Error( 'useStylesInheritanceChain must be used within a StyleInheritanceProvider' );
|
|
51
52
|
}
|
|
52
53
|
|
|
54
|
+
const schema = getStylesSchema();
|
|
55
|
+
|
|
56
|
+
const topLevelPropType = schema?.[ path[ 0 ] ];
|
|
57
|
+
|
|
53
58
|
const snapshot = useStylesInheritanceSnapshot();
|
|
54
59
|
|
|
55
60
|
if ( ! snapshot ) {
|
|
56
61
|
return [];
|
|
57
62
|
}
|
|
58
63
|
|
|
59
|
-
return context.getInheritanceChain( snapshot, path );
|
|
64
|
+
return context.getInheritanceChain( snapshot, path, topLevelPropType );
|
|
60
65
|
}
|
|
61
66
|
|
|
62
67
|
const useAppliedStyles = () => {
|
|
@@ -68,12 +73,9 @@ const useAppliedStyles = () => {
|
|
|
68
73
|
|
|
69
74
|
const classesProp = useElementSetting< ClassesPropValue >( element.id, currentClassesProp );
|
|
70
75
|
|
|
71
|
-
const appliedStyles = classesPropTypeUtil.extract( classesProp );
|
|
76
|
+
const appliedStyles = classesPropTypeUtil.extract( classesProp ) ?? [];
|
|
72
77
|
|
|
73
|
-
return stylesRepository
|
|
74
|
-
.all()
|
|
75
|
-
.filter( ( style ) => appliedStyles?.includes( style.id ) )
|
|
76
|
-
.concat( baseStyles );
|
|
78
|
+
return stylesRepository.all().filter( ( style ) => [ ...baseStyles, ...appliedStyles ].includes( style.id ) );
|
|
77
79
|
};
|
|
78
80
|
|
|
79
81
|
const useBaseStyles = () => {
|
|
@@ -81,5 +83,5 @@ const useBaseStyles = () => {
|
|
|
81
83
|
const widgetsCache = getWidgetsCache();
|
|
82
84
|
const widgetCache = widgetsCache?.[ elementType.key ];
|
|
83
85
|
|
|
84
|
-
return Object.
|
|
86
|
+
return Object.keys( widgetCache?.base_styles ?? {} );
|
|
85
87
|
};
|
package/src/controls-actions.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { ControlAdornmentsProvider, PropKeyProvider, PropProvider } from '@eleme
|
|
|
3
3
|
import { type PropKey, type PropValue } from '@elementor/editor-props';
|
|
4
4
|
import { getStylesSchema } from '@elementor/editor-styles';
|
|
5
5
|
|
|
6
|
+
import { useStyle } from '../contexts/style-context';
|
|
6
7
|
import { useStylesField } from '../hooks/use-styles-field';
|
|
7
8
|
import { StylesInheritanceIndicator } from '../styles-inheritance/styles-inheritance-indicator';
|
|
8
9
|
import { createTopLevelOjectType } from './create-top-level-object-type';
|
|
@@ -15,6 +16,7 @@ export type StylesFieldProps = {
|
|
|
15
16
|
|
|
16
17
|
export const StylesField = ( { bind, placeholder, children }: StylesFieldProps ) => {
|
|
17
18
|
const [ value, setValue ] = useStylesField( bind );
|
|
19
|
+
const { canEdit } = useStyle();
|
|
18
20
|
|
|
19
21
|
const stylesSchema = getStylesSchema();
|
|
20
22
|
|
|
@@ -41,6 +43,7 @@ export const StylesField = ( { bind, placeholder, children }: StylesFieldProps )
|
|
|
41
43
|
value={ values }
|
|
42
44
|
setValue={ setValues }
|
|
43
45
|
placeholder={ placeholderValues }
|
|
46
|
+
disabled={ ! canEdit }
|
|
44
47
|
>
|
|
45
48
|
<PropKeyProvider bind={ bind }>{ children }</PropKeyProvider>
|
|
46
49
|
</PropProvider>
|
package/src/init.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { injectIntoLogic } from '@elementor/editor';
|
|
2
2
|
import { PrefetchUserData } from '@elementor/editor-current-user';
|
|
3
3
|
import { __registerPanel as registerPanel } from '@elementor/editor-panels';
|
|
4
|
-
import { blockCommand } from '@elementor/editor-v1-adapters';
|
|
4
|
+
import { blockCommand, isExperimentActive } from '@elementor/editor-v1-adapters';
|
|
5
5
|
|
|
6
6
|
import { EditingPanelHooks } from './components/editing-panel-hooks';
|
|
7
7
|
import { init as initDynamics } from './dynamics/init';
|
|
8
8
|
import { panel } from './panel';
|
|
9
|
+
import { initResetStyleProps } from './reset-style-props';
|
|
10
|
+
import { init as initStylesInheritance } from './styles-inheritance/init';
|
|
11
|
+
import { EXPERIMENTAL_FEATURES } from './sync/experiments-flags';
|
|
9
12
|
import { isAtomicWidgetSelected } from './sync/is-atomic-widget-selected';
|
|
10
13
|
|
|
11
14
|
export function init() {
|
|
@@ -24,6 +27,13 @@ export function init() {
|
|
|
24
27
|
|
|
25
28
|
// TODO: Move it from here once we have dynamic package.
|
|
26
29
|
initDynamics();
|
|
30
|
+
|
|
31
|
+
// TODO: Move it from here once we have styles-inheritance package.
|
|
32
|
+
initStylesInheritance();
|
|
33
|
+
|
|
34
|
+
if ( isExperimentActive( EXPERIMENTAL_FEATURES.V_3_30 ) ) {
|
|
35
|
+
initResetStyleProps();
|
|
36
|
+
}
|
|
27
37
|
}
|
|
28
38
|
|
|
29
39
|
const blockV1Panel = () => {
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useBoundProp } from '@elementor/editor-controls';
|
|
2
|
+
import { BrushBigIcon } from '@elementor/icons';
|
|
3
|
+
import { __ } from '@wordpress/i18n';
|
|
4
|
+
|
|
5
|
+
import { useIsStyle } from './contexts/style-context';
|
|
6
|
+
import { controlActionsMenu } from './controls-actions';
|
|
7
|
+
|
|
8
|
+
const { registerAction } = controlActionsMenu;
|
|
9
|
+
|
|
10
|
+
export function initResetStyleProps() {
|
|
11
|
+
registerAction( {
|
|
12
|
+
id: 'reset-style-value',
|
|
13
|
+
useProps: useResetStyleValueProps,
|
|
14
|
+
} );
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Temporary fix for the issue with ControlToggleButtonGroup.
|
|
18
|
+
const EXCLUDED_BINDS = [ 'order', 'flex-grow', 'flex-shrink', 'flex-basis' ];
|
|
19
|
+
|
|
20
|
+
export function useResetStyleValueProps() {
|
|
21
|
+
const isStyle = useIsStyle();
|
|
22
|
+
const { value, setValue, path, bind } = useBoundProp();
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
visible:
|
|
26
|
+
isStyle && value !== null && value !== undefined && path.length <= 2 && ! EXCLUDED_BINDS.includes( bind ),
|
|
27
|
+
title: __( 'Clear', 'elementor' ),
|
|
28
|
+
icon: BrushBigIcon,
|
|
29
|
+
onClick: () => setValue( null ),
|
|
30
|
+
};
|
|
31
|
+
}
|