@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.
Files changed (34) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/dist/index.js +837 -334
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.mjs +865 -317
  5. package/dist/index.mjs.map +1 -1
  6. package/package.json +10 -9
  7. package/src/components/color-variable-creation.tsx +28 -7
  8. package/src/components/color-variable-edit.tsx +117 -0
  9. package/src/components/color-variables-selection.tsx +98 -52
  10. package/src/components/font-variable-creation.tsx +18 -6
  11. package/src/components/font-variable-edit.tsx +146 -0
  12. package/src/components/font-variables-selection.tsx +97 -51
  13. package/src/components/ui/menu-item-content.tsx +51 -0
  14. package/src/components/ui/no-search-results.tsx +38 -0
  15. package/src/components/ui/no-variables.tsx +35 -0
  16. package/src/components/ui/styled-menu-list.tsx +31 -0
  17. package/src/components/variable-selection-popover.tsx +133 -0
  18. package/src/components/variables-repeater-item-slot.tsx +29 -0
  19. package/src/controls/color-variable-control.tsx +90 -0
  20. package/src/controls/font-variable-control.tsx +88 -0
  21. package/src/create-style-variables-repository.ts +3 -2
  22. package/src/hooks/use-prop-color-variable-action.tsx +7 -2
  23. package/src/hooks/use-prop-font-variable-action.tsx +7 -2
  24. package/src/hooks/use-prop-variables.ts +31 -4
  25. package/src/init-color-variables.ts +51 -3
  26. package/src/init-font-variables.ts +2 -2
  27. package/src/service.ts +23 -3
  28. package/src/storage.ts +5 -1
  29. package/src/types.ts +12 -8
  30. package/src/components/styled-menu-item.tsx +0 -10
  31. package/src/components/variables-selection-popover.tsx +0 -119
  32. package/src/controls/color-variables-selection-control.tsx +0 -34
  33. package/src/controls/font-variables-selection-control.tsx +0 -29
  34. /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 Variables, type VariableValue } from './types';
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: VariableValue ): boolean => {
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 { ColorVariablesSelection } from '../components/color-variables-selection';
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
- popoverContent: ( { closePopover } ) => <ColorVariablesSelection onSelect={ closePopover } />,
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 { FontVariablesSelection } from '../components/font-variables-selection';
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
- popoverContent: ( { closePopover } ) => <FontVariablesSelection onSelect={ closePopover } />,
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 { ColorVariablesSelectionControl } from './controls/color-variables-selection-control';
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
- export function initColorVariables() {
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: ColorVariablesSelectionControl,
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 { FontVariablesSelectionControl } from './controls/font-variables-selection-control';
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: FontVariablesSelectionControl,
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 TVariable, type TVariablesList } from './storage';
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 }: TVariable ) => {
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 }: TVariable ) => {
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 ) );