@elementor/editor-variables 0.13.0 → 0.14.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 +46 -0
- package/dist/index.js +837 -334
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +865 -317
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -9
- package/src/components/color-variable-creation.tsx +28 -7
- package/src/components/color-variable-edit.tsx +117 -0
- package/src/components/color-variables-selection.tsx +98 -52
- package/src/components/font-variable-creation.tsx +18 -6
- package/src/components/font-variable-edit.tsx +146 -0
- package/src/components/font-variables-selection.tsx +97 -51
- package/src/components/ui/menu-item-content.tsx +51 -0
- package/src/components/ui/no-search-results.tsx +38 -0
- package/src/components/ui/no-variables.tsx +35 -0
- package/src/components/ui/styled-menu-list.tsx +31 -0
- package/src/components/variable-selection-popover.tsx +133 -0
- package/src/components/variables-repeater-item-slot.tsx +29 -0
- package/src/controls/color-variable-control.tsx +90 -0
- package/src/controls/font-variable-control.tsx +88 -0
- package/src/create-style-variables-repository.ts +3 -2
- package/src/hooks/use-prop-color-variable-action.tsx +7 -2
- package/src/hooks/use-prop-font-variable-action.tsx +7 -2
- package/src/hooks/use-prop-variables.ts +31 -4
- package/src/init-color-variables.ts +51 -3
- package/src/init-font-variables.ts +2 -2
- package/src/service.ts +23 -3
- package/src/storage.ts +5 -1
- package/src/types.ts +12 -8
- package/src/components/styled-menu-item.tsx +0 -10
- package/src/components/variables-selection-popover.tsx +0 -119
- package/src/controls/color-variables-selection-control.tsx +0 -34
- package/src/controls/font-variables-selection-control.tsx +0 -29
- /package/src/components/{color-indicator.tsx → ui/color-indicator.tsx} +0 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { MenuList, styled } from '@elementor/ui';
|
|
2
|
+
|
|
3
|
+
export const VariablesStyledMenuList = styled( MenuList )( ( { theme } ) => ( {
|
|
4
|
+
'& > li': {
|
|
5
|
+
height: 32,
|
|
6
|
+
width: '100%',
|
|
7
|
+
display: 'flex',
|
|
8
|
+
alignItems: 'center',
|
|
9
|
+
},
|
|
10
|
+
'& > [role="option"]': {
|
|
11
|
+
...theme.typography.caption,
|
|
12
|
+
lineHeight: 'inherit',
|
|
13
|
+
padding: theme.spacing( 0.5, 1, 0.5, 2 ),
|
|
14
|
+
'&:hover, &:focus': {
|
|
15
|
+
backgroundColor: theme.palette.action.hover,
|
|
16
|
+
},
|
|
17
|
+
'&[aria-selected="true"]': {
|
|
18
|
+
backgroundColor: theme.palette.action.selected,
|
|
19
|
+
},
|
|
20
|
+
cursor: 'pointer',
|
|
21
|
+
textOverflow: 'ellipsis',
|
|
22
|
+
position: 'absolute',
|
|
23
|
+
top: 0,
|
|
24
|
+
left: 0,
|
|
25
|
+
'&:hover .MuiIconButton-root, .MuiIconButton-root:focus': {
|
|
26
|
+
opacity: 1,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
width: '100%',
|
|
30
|
+
position: 'relative',
|
|
31
|
+
} ) );
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useRef, useState } from 'react';
|
|
3
|
+
|
|
4
|
+
import { colorVariablePropTypeUtil } from '../prop-types/color-variable-prop-type';
|
|
5
|
+
import { fontVariablePropTypeUtil } from '../prop-types/font-variable-prop-type';
|
|
6
|
+
import { type Variable } from '../types';
|
|
7
|
+
import { ColorVariableCreation } from './color-variable-creation';
|
|
8
|
+
import { ColorVariableEdit } from './color-variable-edit';
|
|
9
|
+
import { ColorVariablesSelection } from './color-variables-selection';
|
|
10
|
+
import { FontVariableCreation } from './font-variable-creation';
|
|
11
|
+
import { FontVariableEdit } from './font-variable-edit';
|
|
12
|
+
import { FontVariablesSelection } from './font-variables-selection';
|
|
13
|
+
|
|
14
|
+
const VIEW_LIST = 'list';
|
|
15
|
+
const VIEW_ADD = 'add';
|
|
16
|
+
const VIEW_EDIT = 'edit';
|
|
17
|
+
|
|
18
|
+
type View = typeof VIEW_LIST | typeof VIEW_ADD | typeof VIEW_EDIT;
|
|
19
|
+
|
|
20
|
+
type Props = {
|
|
21
|
+
closePopover: () => void;
|
|
22
|
+
propTypeKey: string;
|
|
23
|
+
selectedVariable?: Variable;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const VariableSelectionPopover = ( { closePopover, propTypeKey, selectedVariable }: Props ) => {
|
|
27
|
+
const [ currentView, setCurrentView ] = useState< View >( VIEW_LIST );
|
|
28
|
+
const editIdRef = useRef< string >( '' );
|
|
29
|
+
|
|
30
|
+
return renderStage( {
|
|
31
|
+
propTypeKey,
|
|
32
|
+
currentView,
|
|
33
|
+
selectedVariable,
|
|
34
|
+
editIdRef,
|
|
35
|
+
setCurrentView,
|
|
36
|
+
closePopover,
|
|
37
|
+
} );
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
type StageProps = {
|
|
41
|
+
propTypeKey: string;
|
|
42
|
+
currentView: View;
|
|
43
|
+
selectedVariable?: Variable;
|
|
44
|
+
editIdRef: React.MutableRefObject< string >;
|
|
45
|
+
setCurrentView: ( stage: View ) => void;
|
|
46
|
+
closePopover: () => void;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
function renderStage( props: StageProps ): React.ReactNode {
|
|
50
|
+
const handleSubmitOnEdit = () => {
|
|
51
|
+
if ( props?.selectedVariable?.key === props.editIdRef.current ) {
|
|
52
|
+
props.closePopover();
|
|
53
|
+
} else {
|
|
54
|
+
props.setCurrentView( VIEW_LIST );
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
if ( fontVariablePropTypeUtil.key === props.propTypeKey ) {
|
|
59
|
+
if ( VIEW_LIST === props.currentView ) {
|
|
60
|
+
return (
|
|
61
|
+
<FontVariablesSelection
|
|
62
|
+
closePopover={ props.closePopover }
|
|
63
|
+
onAdd={ () => {
|
|
64
|
+
props.setCurrentView( VIEW_ADD );
|
|
65
|
+
} }
|
|
66
|
+
onEdit={ ( key ) => {
|
|
67
|
+
props.editIdRef.current = key;
|
|
68
|
+
props.setCurrentView( VIEW_EDIT );
|
|
69
|
+
} }
|
|
70
|
+
/>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if ( VIEW_ADD === props.currentView ) {
|
|
75
|
+
return (
|
|
76
|
+
<FontVariableCreation
|
|
77
|
+
onGoBack={ () => props.setCurrentView( VIEW_LIST ) }
|
|
78
|
+
onClose={ props.closePopover }
|
|
79
|
+
/>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if ( VIEW_EDIT === props.currentView ) {
|
|
84
|
+
return (
|
|
85
|
+
<FontVariableEdit
|
|
86
|
+
editId={ props.editIdRef.current ?? '' }
|
|
87
|
+
onGoBack={ () => props.setCurrentView( VIEW_LIST ) }
|
|
88
|
+
onClose={ props.closePopover }
|
|
89
|
+
onSubmit={ handleSubmitOnEdit }
|
|
90
|
+
/>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if ( colorVariablePropTypeUtil.key === props.propTypeKey ) {
|
|
96
|
+
if ( VIEW_LIST === props.currentView ) {
|
|
97
|
+
return (
|
|
98
|
+
<ColorVariablesSelection
|
|
99
|
+
closePopover={ props.closePopover }
|
|
100
|
+
onAdd={ () => {
|
|
101
|
+
props.setCurrentView( VIEW_ADD );
|
|
102
|
+
} }
|
|
103
|
+
onEdit={ ( key ) => {
|
|
104
|
+
props.editIdRef.current = key;
|
|
105
|
+
props.setCurrentView( VIEW_EDIT );
|
|
106
|
+
} }
|
|
107
|
+
/>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if ( VIEW_ADD === props.currentView ) {
|
|
112
|
+
return (
|
|
113
|
+
<ColorVariableCreation
|
|
114
|
+
onGoBack={ () => props.setCurrentView( VIEW_LIST ) }
|
|
115
|
+
onClose={ props.closePopover }
|
|
116
|
+
/>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if ( VIEW_EDIT === props.currentView ) {
|
|
121
|
+
return (
|
|
122
|
+
<ColorVariableEdit
|
|
123
|
+
editId={ props.editIdRef.current ?? '' }
|
|
124
|
+
onGoBack={ () => props.setCurrentView( VIEW_LIST ) }
|
|
125
|
+
onClose={ props.closePopover }
|
|
126
|
+
onSubmit={ handleSubmitOnEdit }
|
|
127
|
+
/>
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type BackgroundColorOverlayPropValue, type BoxShadowPropValue, type PropValue } from '@elementor/editor-props';
|
|
3
|
+
|
|
4
|
+
import { useVariable } from '../hooks/use-prop-variables';
|
|
5
|
+
import { ColorIndicator } from './ui/color-indicator';
|
|
6
|
+
|
|
7
|
+
const useColorVariable = ( value: BackgroundColorOverlayPropValue | BoxShadowPropValue ) => {
|
|
8
|
+
const variableId = value?.value?.color?.value;
|
|
9
|
+
|
|
10
|
+
return useVariable( variableId || '' );
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const BackgroundRepeaterColorIndicator = ( { value }: { value: PropValue } ) => {
|
|
14
|
+
const colorVariable = useColorVariable( value as BackgroundColorOverlayPropValue );
|
|
15
|
+
|
|
16
|
+
return <ColorIndicator component="span" size="inherit" value={ colorVariable?.value } />;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const BackgroundRepeaterLabel = ( { value }: { value: PropValue } ) => {
|
|
20
|
+
const colorVariable = useColorVariable( value as BackgroundColorOverlayPropValue );
|
|
21
|
+
|
|
22
|
+
return <span>{ colorVariable?.label }</span>;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const BoxShadowRepeaterColorIndicator = ( { value }: { value: PropValue } ) => {
|
|
26
|
+
const colorVariable = useColorVariable( value as BoxShadowPropValue );
|
|
27
|
+
|
|
28
|
+
return <ColorIndicator component="span" size="inherit" value={ colorVariable?.value } />;
|
|
29
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useId, useRef } from 'react';
|
|
3
|
+
import { useBoundProp } from '@elementor/editor-controls';
|
|
4
|
+
import { colorPropTypeUtil } from '@elementor/editor-props';
|
|
5
|
+
import { ColorFilterIcon, DetachIcon } from '@elementor/icons';
|
|
6
|
+
import {
|
|
7
|
+
bindPopover,
|
|
8
|
+
bindTrigger,
|
|
9
|
+
Box,
|
|
10
|
+
IconButton,
|
|
11
|
+
Popover,
|
|
12
|
+
Stack,
|
|
13
|
+
Typography,
|
|
14
|
+
UnstableTag as Tag,
|
|
15
|
+
usePopupState,
|
|
16
|
+
} from '@elementor/ui';
|
|
17
|
+
import { __ } from '@wordpress/i18n';
|
|
18
|
+
|
|
19
|
+
import { ColorIndicator } from '../components/ui/color-indicator';
|
|
20
|
+
import { VariableSelectionPopover } from '../components/variable-selection-popover';
|
|
21
|
+
import { useVariable } from '../hooks/use-prop-variables';
|
|
22
|
+
import { colorVariablePropTypeUtil } from '../prop-types/color-variable-prop-type';
|
|
23
|
+
|
|
24
|
+
const SIZE = 'tiny';
|
|
25
|
+
|
|
26
|
+
export const ColorVariableControl = () => {
|
|
27
|
+
const { setValue: setColor } = useBoundProp();
|
|
28
|
+
const { value: variableValue } = useBoundProp( colorVariablePropTypeUtil );
|
|
29
|
+
|
|
30
|
+
const anchorRef = useRef< HTMLDivElement >( null );
|
|
31
|
+
|
|
32
|
+
const popupId = useId();
|
|
33
|
+
const popupState = usePopupState( {
|
|
34
|
+
variant: 'popover',
|
|
35
|
+
popupId: `elementor-variables-list-${ popupId }`,
|
|
36
|
+
} );
|
|
37
|
+
|
|
38
|
+
const selectedVariable = useVariable( variableValue );
|
|
39
|
+
if ( ! selectedVariable ) {
|
|
40
|
+
throw new Error( `Global color variable ${ variableValue } not found` );
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const unlinkVariable = () => {
|
|
44
|
+
setColor( colorPropTypeUtil.create( selectedVariable.value ) );
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<Box ref={ anchorRef }>
|
|
49
|
+
<Tag
|
|
50
|
+
fullWidth
|
|
51
|
+
showActionsOnHover
|
|
52
|
+
startIcon={
|
|
53
|
+
<Stack spacing={ 0.75 } direction="row" alignItems="center">
|
|
54
|
+
<ColorIndicator size="inherit" value={ selectedVariable.value } component="span" />
|
|
55
|
+
<ColorFilterIcon fontSize="inherit" sx={ { mr: 1 } } />
|
|
56
|
+
</Stack>
|
|
57
|
+
}
|
|
58
|
+
label={
|
|
59
|
+
<Box sx={ { display: 'inline-grid', minWidth: 0 } }>
|
|
60
|
+
<Typography
|
|
61
|
+
sx={ { textOverflow: 'ellipsis', overflowX: 'hidden', lineHeight: 1 } }
|
|
62
|
+
variant="caption"
|
|
63
|
+
>
|
|
64
|
+
{ selectedVariable.label }
|
|
65
|
+
</Typography>
|
|
66
|
+
</Box>
|
|
67
|
+
}
|
|
68
|
+
actions={
|
|
69
|
+
<IconButton size={ SIZE } onClick={ unlinkVariable } aria-label={ __( 'Unlink', 'elementor' ) }>
|
|
70
|
+
<DetachIcon fontSize={ SIZE } />
|
|
71
|
+
</IconButton>
|
|
72
|
+
}
|
|
73
|
+
{ ...bindTrigger( popupState ) }
|
|
74
|
+
/>
|
|
75
|
+
<Popover
|
|
76
|
+
disableScrollLock
|
|
77
|
+
anchorEl={ anchorRef.current }
|
|
78
|
+
anchorOrigin={ { vertical: 'bottom', horizontal: 'right' } }
|
|
79
|
+
transformOrigin={ { vertical: 'top', horizontal: 'right' } }
|
|
80
|
+
{ ...bindPopover( popupState ) }
|
|
81
|
+
>
|
|
82
|
+
<VariableSelectionPopover
|
|
83
|
+
selectedVariable={ selectedVariable }
|
|
84
|
+
closePopover={ popupState.close }
|
|
85
|
+
propTypeKey={ colorVariablePropTypeUtil.key }
|
|
86
|
+
/>
|
|
87
|
+
</Popover>
|
|
88
|
+
</Box>
|
|
89
|
+
);
|
|
90
|
+
};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useId, useRef } from 'react';
|
|
3
|
+
import { useBoundProp } from '@elementor/editor-controls';
|
|
4
|
+
import { stringPropTypeUtil } from '@elementor/editor-props';
|
|
5
|
+
import { ColorFilterIcon, DetachIcon } from '@elementor/icons';
|
|
6
|
+
import {
|
|
7
|
+
bindPopover,
|
|
8
|
+
bindTrigger,
|
|
9
|
+
Box,
|
|
10
|
+
IconButton,
|
|
11
|
+
Popover,
|
|
12
|
+
Stack,
|
|
13
|
+
Typography,
|
|
14
|
+
UnstableTag as Tag,
|
|
15
|
+
usePopupState,
|
|
16
|
+
} from '@elementor/ui';
|
|
17
|
+
import { __ } from '@wordpress/i18n';
|
|
18
|
+
|
|
19
|
+
import { VariableSelectionPopover } from '../components/variable-selection-popover';
|
|
20
|
+
import { useVariable } from '../hooks/use-prop-variables';
|
|
21
|
+
import { fontVariablePropTypeUtil } from '../prop-types/font-variable-prop-type';
|
|
22
|
+
|
|
23
|
+
const SIZE = 'tiny';
|
|
24
|
+
|
|
25
|
+
export const FontVariableControl = () => {
|
|
26
|
+
const { setValue: setFontFamily } = useBoundProp();
|
|
27
|
+
const { value: variableValue } = useBoundProp( fontVariablePropTypeUtil );
|
|
28
|
+
|
|
29
|
+
const anchorRef = useRef< HTMLDivElement >( null );
|
|
30
|
+
|
|
31
|
+
const popupId = useId();
|
|
32
|
+
const popupState = usePopupState( {
|
|
33
|
+
variant: 'popover',
|
|
34
|
+
popupId: `elementor-variables-list-${ popupId }`,
|
|
35
|
+
} );
|
|
36
|
+
|
|
37
|
+
const selectedVariable = useVariable( variableValue );
|
|
38
|
+
if ( ! selectedVariable ) {
|
|
39
|
+
throw new Error( `Global font variable ${ variableValue } not found` );
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const unlinkVariable = () => {
|
|
43
|
+
setFontFamily( stringPropTypeUtil.create( selectedVariable.value ) );
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<Box ref={ anchorRef }>
|
|
48
|
+
<Tag
|
|
49
|
+
fullWidth
|
|
50
|
+
showActionsOnHover
|
|
51
|
+
startIcon={
|
|
52
|
+
<Stack spacing={ 0.75 } direction="row" alignItems="center">
|
|
53
|
+
<ColorFilterIcon fontSize={ 'inherit' } sx={ { mr: 1 } } />
|
|
54
|
+
</Stack>
|
|
55
|
+
}
|
|
56
|
+
label={
|
|
57
|
+
<Box sx={ { display: 'inline-grid', minWidth: 0 } }>
|
|
58
|
+
<Typography
|
|
59
|
+
sx={ { textOverflow: 'ellipsis', overflowX: 'hidden', lineHeight: 1 } }
|
|
60
|
+
variant="caption"
|
|
61
|
+
>
|
|
62
|
+
{ selectedVariable.label }
|
|
63
|
+
</Typography>
|
|
64
|
+
</Box>
|
|
65
|
+
}
|
|
66
|
+
actions={
|
|
67
|
+
<IconButton size={ SIZE } onClick={ unlinkVariable } aria-label={ __( 'Unlink', 'elementor' ) }>
|
|
68
|
+
<DetachIcon fontSize={ SIZE } />
|
|
69
|
+
</IconButton>
|
|
70
|
+
}
|
|
71
|
+
{ ...bindTrigger( popupState ) }
|
|
72
|
+
/>
|
|
73
|
+
<Popover
|
|
74
|
+
disableScrollLock
|
|
75
|
+
anchorEl={ anchorRef.current }
|
|
76
|
+
anchorOrigin={ { vertical: 'bottom', horizontal: 'right' } }
|
|
77
|
+
transformOrigin={ { vertical: 'top', horizontal: 'right' } }
|
|
78
|
+
{ ...bindPopover( popupState ) }
|
|
79
|
+
>
|
|
80
|
+
<VariableSelectionPopover
|
|
81
|
+
selectedVariable={ selectedVariable }
|
|
82
|
+
closePopover={ popupState.close }
|
|
83
|
+
propTypeKey={ fontVariablePropTypeUtil.key }
|
|
84
|
+
/>
|
|
85
|
+
</Popover>
|
|
86
|
+
</Box>
|
|
87
|
+
);
|
|
88
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { type StyleVariables, type
|
|
1
|
+
import { type StyleVariables, type Variable } from './types';
|
|
2
2
|
|
|
3
3
|
type VariablesChangeCallback = ( variables: StyleVariables ) => void;
|
|
4
|
+
type Variables = Record< string, Variable >;
|
|
4
5
|
|
|
5
6
|
export const createStyleVariablesRepository = () => {
|
|
6
7
|
const variables: StyleVariables = {};
|
|
@@ -20,7 +21,7 @@ export const createStyleVariablesRepository = () => {
|
|
|
20
21
|
}
|
|
21
22
|
};
|
|
22
23
|
|
|
23
|
-
const shouldUpdate = ( key: string, newValue:
|
|
24
|
+
const shouldUpdate = ( key: string, newValue: string ): boolean => {
|
|
24
25
|
return ! ( key in variables ) || variables[ key ] !== newValue;
|
|
25
26
|
};
|
|
26
27
|
|
|
@@ -3,7 +3,8 @@ import { type PopoverActionProps, useBoundProp } from '@elementor/editor-editing
|
|
|
3
3
|
import { ColorFilterIcon } from '@elementor/icons';
|
|
4
4
|
import { __ } from '@wordpress/i18n';
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { VariableSelectionPopover } from '../components/variable-selection-popover';
|
|
7
|
+
import { colorVariablePropTypeUtil } from '../prop-types/color-variable-prop-type';
|
|
7
8
|
import { supportsColorVariables } from '../utils';
|
|
8
9
|
|
|
9
10
|
export const usePropColorVariableAction = (): PopoverActionProps => {
|
|
@@ -15,6 +16,10 @@ export const usePropColorVariableAction = (): PopoverActionProps => {
|
|
|
15
16
|
visible,
|
|
16
17
|
icon: ColorFilterIcon,
|
|
17
18
|
title: __( 'Variables', 'elementor' ),
|
|
18
|
-
|
|
19
|
+
content: ( { close: closePopover } ) => {
|
|
20
|
+
return (
|
|
21
|
+
<VariableSelectionPopover closePopover={ closePopover } propTypeKey={ colorVariablePropTypeUtil.key } />
|
|
22
|
+
);
|
|
23
|
+
},
|
|
19
24
|
};
|
|
20
25
|
};
|
|
@@ -3,7 +3,8 @@ import { type PopoverActionProps, useBoundProp } from '@elementor/editor-editing
|
|
|
3
3
|
import { ColorFilterIcon } from '@elementor/icons';
|
|
4
4
|
import { __ } from '@wordpress/i18n';
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { VariableSelectionPopover } from '../components/variable-selection-popover';
|
|
7
|
+
import { fontVariablePropTypeUtil } from '../prop-types/font-variable-prop-type';
|
|
7
8
|
import { supportsFontVariables } from '../utils';
|
|
8
9
|
|
|
9
10
|
export const usePropFontVariableAction = (): PopoverActionProps => {
|
|
@@ -15,6 +16,10 @@ export const usePropFontVariableAction = (): PopoverActionProps => {
|
|
|
15
16
|
visible,
|
|
16
17
|
icon: ColorFilterIcon,
|
|
17
18
|
title: __( 'Variables', 'elementor' ),
|
|
18
|
-
|
|
19
|
+
content: ( { close: closePopover } ) => {
|
|
20
|
+
return (
|
|
21
|
+
<VariableSelectionPopover closePopover={ closePopover } propTypeKey={ fontVariablePropTypeUtil.key } />
|
|
22
|
+
);
|
|
23
|
+
},
|
|
19
24
|
};
|
|
20
25
|
};
|
|
@@ -6,10 +6,6 @@ import { type TVariable } from '../storage';
|
|
|
6
6
|
import { styleVariablesRepository } from '../style-variables-repository';
|
|
7
7
|
import { type Variable } from '../types';
|
|
8
8
|
|
|
9
|
-
export const usePropVariables = ( propKey: PropKey ) => {
|
|
10
|
-
return useMemo( () => normalizeVariables( propKey ), [ propKey ] );
|
|
11
|
-
};
|
|
12
|
-
|
|
13
9
|
export const useVariable = ( key: string ) => {
|
|
14
10
|
const variables = service.variables();
|
|
15
11
|
|
|
@@ -23,6 +19,24 @@ export const useVariable = ( key: string ) => {
|
|
|
23
19
|
};
|
|
24
20
|
};
|
|
25
21
|
|
|
22
|
+
export const useFilteredVariables = ( searchValue: string, propTypeKey: string ) => {
|
|
23
|
+
const variables = usePropVariables( propTypeKey );
|
|
24
|
+
|
|
25
|
+
const filteredVariables = variables.filter( ( { label } ) => {
|
|
26
|
+
return label.toLowerCase().includes( searchValue.toLowerCase() );
|
|
27
|
+
} );
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
list: filteredVariables,
|
|
31
|
+
hasMatches: filteredVariables.length > 0,
|
|
32
|
+
isSourceNotEmpty: variables.length > 0,
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const usePropVariables = ( propKey: PropKey ) => {
|
|
37
|
+
return useMemo( () => normalizeVariables( propKey ), [ propKey ] );
|
|
38
|
+
};
|
|
39
|
+
|
|
26
40
|
const normalizeVariables = ( propKey: string ) => {
|
|
27
41
|
const variables = service.variables();
|
|
28
42
|
|
|
@@ -42,6 +56,19 @@ export const createVariable = ( newVariable: Variable ): Promise< string > => {
|
|
|
42
56
|
styleVariablesRepository.update( {
|
|
43
57
|
[ id ]: variable,
|
|
44
58
|
} );
|
|
59
|
+
|
|
45
60
|
return id;
|
|
46
61
|
} );
|
|
47
62
|
};
|
|
63
|
+
|
|
64
|
+
export const updateVariable = ( updateId: string, { value, label }: { value: string; label: string } ) => {
|
|
65
|
+
return service
|
|
66
|
+
.update( updateId, { value, label } )
|
|
67
|
+
.then( ( { id, variable }: { id: string; variable: TVariable } ) => {
|
|
68
|
+
styleVariablesRepository.update( {
|
|
69
|
+
[ id ]: variable,
|
|
70
|
+
} );
|
|
71
|
+
|
|
72
|
+
return id;
|
|
73
|
+
} );
|
|
74
|
+
};
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { styleTransformersRegistry } from '@elementor/editor-canvas';
|
|
2
|
+
import { injectIntoRepeaterItemIcon, injectIntoRepeaterItemLabel } from '@elementor/editor-controls';
|
|
2
3
|
import { controlActionsMenu, registerControlReplacement } from '@elementor/editor-editing-panel';
|
|
4
|
+
import { backgroundColorOverlayPropTypeUtil, type PropValue, shadowPropTypeUtil } from '@elementor/editor-props';
|
|
3
5
|
|
|
4
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
BackgroundRepeaterColorIndicator,
|
|
8
|
+
BackgroundRepeaterLabel,
|
|
9
|
+
BoxShadowRepeaterColorIndicator,
|
|
10
|
+
} from './components/variables-repeater-item-slot';
|
|
11
|
+
import { ColorVariableControl } from './controls/color-variable-control';
|
|
5
12
|
import { usePropColorVariableAction } from './hooks/use-prop-color-variable-action';
|
|
6
13
|
import { colorVariablePropTypeUtil } from './prop-types/color-variable-prop-type';
|
|
7
14
|
import { variableTransformer } from './transformers/variable-transformer';
|
|
@@ -9,9 +16,19 @@ import { hasAssignedColorVariable } from './utils';
|
|
|
9
16
|
|
|
10
17
|
const { registerPopoverAction } = controlActionsMenu;
|
|
11
18
|
|
|
12
|
-
|
|
19
|
+
const conditions = {
|
|
20
|
+
backgroundOverlay: ( { value: prop }: { value: PropValue } ) => {
|
|
21
|
+
return hasAssignedColorVariable( backgroundColorOverlayPropTypeUtil.extract( prop )?.color );
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
boxShadow: ( { value: prop }: { value: PropValue } ) => {
|
|
25
|
+
return hasAssignedColorVariable( shadowPropTypeUtil.extract( prop )?.color );
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
function registerControlsAndActions() {
|
|
13
30
|
registerControlReplacement( {
|
|
14
|
-
component:
|
|
31
|
+
component: ColorVariableControl,
|
|
15
32
|
condition: ( { value } ) => hasAssignedColorVariable( value ),
|
|
16
33
|
} );
|
|
17
34
|
|
|
@@ -19,6 +36,37 @@ export function initColorVariables() {
|
|
|
19
36
|
id: 'color-variables',
|
|
20
37
|
useProps: usePropColorVariableAction,
|
|
21
38
|
} );
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function registerRepeaterItemIcons() {
|
|
42
|
+
injectIntoRepeaterItemIcon( {
|
|
43
|
+
id: 'color-variables-background-icon',
|
|
44
|
+
component: BackgroundRepeaterColorIndicator,
|
|
45
|
+
condition: conditions.backgroundOverlay,
|
|
46
|
+
} );
|
|
22
47
|
|
|
48
|
+
injectIntoRepeaterItemIcon( {
|
|
49
|
+
id: 'color-variables-icon',
|
|
50
|
+
component: BoxShadowRepeaterColorIndicator,
|
|
51
|
+
condition: conditions.boxShadow,
|
|
52
|
+
} );
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function registerRepeaterItemLabels() {
|
|
56
|
+
injectIntoRepeaterItemLabel( {
|
|
57
|
+
id: 'color-variables-label',
|
|
58
|
+
component: BackgroundRepeaterLabel,
|
|
59
|
+
condition: conditions.backgroundOverlay,
|
|
60
|
+
} );
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function registerStyleTransformers() {
|
|
23
64
|
styleTransformersRegistry.register( colorVariablePropTypeUtil.key, variableTransformer );
|
|
24
65
|
}
|
|
66
|
+
|
|
67
|
+
export function initColorVariables() {
|
|
68
|
+
registerControlsAndActions();
|
|
69
|
+
registerRepeaterItemIcons();
|
|
70
|
+
registerRepeaterItemLabels();
|
|
71
|
+
registerStyleTransformers();
|
|
72
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { styleTransformersRegistry } from '@elementor/editor-canvas';
|
|
2
2
|
import { controlActionsMenu, registerControlReplacement } from '@elementor/editor-editing-panel';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { FontVariableControl } from './controls/font-variable-control';
|
|
5
5
|
import { usePropFontVariableAction } from './hooks/use-prop-font-variable-action';
|
|
6
6
|
import { fontVariablePropTypeUtil } from './prop-types/font-variable-prop-type';
|
|
7
7
|
import { variableTransformer } from './transformers/variable-transformer';
|
|
@@ -11,7 +11,7 @@ const { registerPopoverAction } = controlActionsMenu;
|
|
|
11
11
|
|
|
12
12
|
export function initFontVariables() {
|
|
13
13
|
registerControlReplacement( {
|
|
14
|
-
component:
|
|
14
|
+
component: FontVariableControl,
|
|
15
15
|
condition: ( { value } ) => hasAssignedFontVariable( value ),
|
|
16
16
|
} );
|
|
17
17
|
|
package/src/service.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { apiClient } from './api';
|
|
2
|
-
import { OP_RW, Storage, type
|
|
2
|
+
import { OP_RW, Storage, type TVariablesList } from './storage';
|
|
3
|
+
import { styleVariablesRepository } from './style-variables-repository';
|
|
4
|
+
import { type Variable } from './types';
|
|
3
5
|
|
|
4
6
|
const storage = new Storage();
|
|
5
7
|
|
|
@@ -29,11 +31,13 @@ export const service = {
|
|
|
29
31
|
|
|
30
32
|
storage.fill( variables, watermark );
|
|
31
33
|
|
|
34
|
+
styleVariablesRepository.update( variables );
|
|
35
|
+
|
|
32
36
|
return variables;
|
|
33
37
|
} );
|
|
34
38
|
},
|
|
35
39
|
|
|
36
|
-
create: ( { type, label, value }:
|
|
40
|
+
create: ( { type, label, value }: Variable ) => {
|
|
37
41
|
return apiClient
|
|
38
42
|
.create( type, label, value )
|
|
39
43
|
.then( ( response ) => {
|
|
@@ -54,6 +58,10 @@ export const service = {
|
|
|
54
58
|
|
|
55
59
|
storage.add( variableId, createdVariable );
|
|
56
60
|
|
|
61
|
+
styleVariablesRepository.update( {
|
|
62
|
+
[ variableId ]: createdVariable,
|
|
63
|
+
} );
|
|
64
|
+
|
|
57
65
|
return {
|
|
58
66
|
id: variableId,
|
|
59
67
|
variable: createdVariable,
|
|
@@ -61,7 +69,7 @@ export const service = {
|
|
|
61
69
|
} );
|
|
62
70
|
},
|
|
63
71
|
|
|
64
|
-
update: ( id: string, { label, value }:
|
|
72
|
+
update: ( id: string, { label, value }: Omit< Variable, 'type' > ) => {
|
|
65
73
|
return apiClient
|
|
66
74
|
.update( id, label, value )
|
|
67
75
|
.then( ( response ) => {
|
|
@@ -82,6 +90,10 @@ export const service = {
|
|
|
82
90
|
|
|
83
91
|
storage.update( variableId, updatedVariable );
|
|
84
92
|
|
|
93
|
+
styleVariablesRepository.update( {
|
|
94
|
+
[ variableId ]: updatedVariable,
|
|
95
|
+
} );
|
|
96
|
+
|
|
85
97
|
return {
|
|
86
98
|
id: variableId,
|
|
87
99
|
variable: updatedVariable,
|
|
@@ -110,6 +122,10 @@ export const service = {
|
|
|
110
122
|
|
|
111
123
|
storage.update( variableId, deletedVariable );
|
|
112
124
|
|
|
125
|
+
styleVariablesRepository.update( {
|
|
126
|
+
[ variableId ]: deletedVariable,
|
|
127
|
+
} );
|
|
128
|
+
|
|
113
129
|
return {
|
|
114
130
|
id: variableId,
|
|
115
131
|
variable: deletedVariable,
|
|
@@ -138,6 +154,10 @@ export const service = {
|
|
|
138
154
|
|
|
139
155
|
storage.update( variableId, restoredVariable );
|
|
140
156
|
|
|
157
|
+
styleVariablesRepository.update( {
|
|
158
|
+
[ variableId ]: restoredVariable,
|
|
159
|
+
} );
|
|
160
|
+
|
|
141
161
|
return {
|
|
142
162
|
id: variableId,
|
|
143
163
|
variable: restoredVariable,
|
package/src/storage.ts
CHANGED
|
@@ -34,8 +34,12 @@ export class Storage {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
fill( variables: TVariablesList, watermark: number ) {
|
|
37
|
+
this.state.variables = {};
|
|
38
|
+
if ( variables && Object.keys( variables ).length ) {
|
|
39
|
+
this.state.variables = variables;
|
|
40
|
+
}
|
|
41
|
+
|
|
37
42
|
this.state.watermark = watermark;
|
|
38
|
-
this.state.variables = variables;
|
|
39
43
|
|
|
40
44
|
localStorage.setItem( STORAGE_WATERMARK_KEY, this.state.watermark.toString() );
|
|
41
45
|
localStorage.setItem( STORAGE_KEY, JSON.stringify( this.state.variables ) );
|