@elementor/editor-variables 0.15.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/CHANGELOG.md +88 -0
  2. package/dist/index.js +894 -486
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.mjs +892 -511
  5. package/dist/index.mjs.map +1 -1
  6. package/package.json +9 -9
  7. package/src/components/color-variable-creation.tsx +37 -58
  8. package/src/components/color-variable-edit.tsx +110 -86
  9. package/src/components/color-variables-selection.tsx +32 -34
  10. package/src/components/fields/color-field.tsx +54 -0
  11. package/src/components/fields/font-field.tsx +85 -0
  12. package/src/components/fields/label-field.tsx +54 -0
  13. package/src/components/font-variable-creation.tsx +39 -78
  14. package/src/components/font-variable-edit.tsx +108 -114
  15. package/src/components/font-variables-selection.tsx +32 -34
  16. package/src/components/ui/delete-confirmation-dialog.tsx +52 -0
  17. package/src/components/ui/deleted-variable-alert.tsx +47 -0
  18. package/src/components/ui/menu-item-content.tsx +2 -5
  19. package/src/components/ui/tags/assigned-tag.tsx +45 -0
  20. package/src/components/ui/tags/deleted-tag.tsx +37 -0
  21. package/src/components/ui/variable/assigned-variable.tsx +70 -0
  22. package/src/components/ui/variable/deleted-variable.tsx +76 -0
  23. package/src/controls/color-variable-control.tsx +21 -48
  24. package/src/controls/font-variable-control.tsx +20 -43
  25. package/src/create-style-variables-repository.ts +44 -5
  26. package/src/hooks/use-prop-variables.ts +6 -0
  27. package/src/init-color-variables.ts +3 -48
  28. package/src/renderers/style-variables-renderer.tsx +10 -4
  29. package/src/repeater-injections.ts +35 -0
  30. package/src/service.ts +23 -2
  31. package/src/sync/enqueue-font.ts +7 -0
  32. package/src/sync/types.ts +5 -0
  33. package/src/transformers/variable-transformer.ts +21 -3
  34. package/src/types.ts +1 -1
  35. package/src/utils/validations.ts +42 -0
  36. package/src/components/ui/variable-tag.tsx +0 -43
@@ -1,14 +1,11 @@
1
1
  import * as React from 'react';
2
2
  import { EllipsisWithTooltip, type VirtualizedItem } from '@elementor/editor-ui';
3
- import { isExperimentActive } from '@elementor/editor-v1-adapters';
4
3
  import { EditIcon } from '@elementor/icons';
5
4
  import { Box, IconButton, ListItemIcon, Typography } from '@elementor/ui';
6
5
  import { __ } from '@wordpress/i18n';
7
6
 
8
7
  const SIZE = 'tiny';
9
8
 
10
- const isVersion330Active = isExperimentActive( 'e_v_3_30' );
11
-
12
9
  export const MenuItemContent = < T, V extends string >( { item }: { item: VirtualizedItem< T, V > } ) => {
13
10
  const onEdit = item.onEdit as ( ( value: V ) => void ) | undefined;
14
11
 
@@ -27,8 +24,8 @@ export const MenuItemContent = < T, V extends string >( { item }: { item: Virtua
27
24
  <EllipsisWithTooltip
28
25
  title={ item.label || item.value }
29
26
  as={ Typography }
30
- variant={ isVersion330Active ? 'caption' : 'body2' }
31
- color={ isVersion330Active ? 'text.primary' : 'text.secondary' }
27
+ variant="caption"
28
+ color="text.primary"
32
29
  sx={ { marginTop: '1px', lineHeight: '2' } }
33
30
  maxWidth="50%"
34
31
  />
@@ -0,0 +1,45 @@
1
+ import * as React from 'react';
2
+ import { DetachIcon } from '@elementor/icons';
3
+ import { Box, IconButton, Stack, Tooltip, Typography, UnstableTag as Tag, type UnstableTagProps } from '@elementor/ui';
4
+ import { __ } from '@wordpress/i18n';
5
+
6
+ export const SIZE = 'tiny';
7
+
8
+ interface VariableTagProps extends UnstableTagProps {
9
+ onUnlink?: () => void;
10
+ }
11
+
12
+ export const AssignedTag = ( { startIcon, label, onUnlink, ...props }: VariableTagProps ) => {
13
+ const actions = [];
14
+
15
+ if ( onUnlink ) {
16
+ actions.push(
17
+ <IconButton key="unlink" size={ SIZE } onClick={ onUnlink } aria-label={ __( 'Unlink', 'elementor' ) }>
18
+ <DetachIcon fontSize={ SIZE } />
19
+ </IconButton>
20
+ );
21
+ }
22
+
23
+ return (
24
+ <Tooltip title={ label } placement="top">
25
+ <Tag
26
+ fullWidth
27
+ showActionsOnHover
28
+ startIcon={
29
+ <Stack gap={ 0.5 } direction="row" alignItems="center">
30
+ { startIcon }
31
+ </Stack>
32
+ }
33
+ label={
34
+ <Box sx={ { display: 'inline-grid', minWidth: 0 } }>
35
+ <Typography sx={ { lineHeight: 1.34 } } variant="caption" noWrap>
36
+ { label }
37
+ </Typography>
38
+ </Box>
39
+ }
40
+ actions={ actions }
41
+ { ...props }
42
+ />
43
+ </Tooltip>
44
+ );
45
+ };
@@ -0,0 +1,37 @@
1
+ import * as React from 'react';
2
+ import { AlertTriangleFilledIcon } from '@elementor/icons';
3
+ import { Box, Chip, type ChipProps, type Theme, Tooltip, Typography } from '@elementor/ui';
4
+ import { __ } from '@wordpress/i18n';
5
+
6
+ export const DeletedTag = React.forwardRef< HTMLDivElement, ChipProps >( ( { label, onClick, ...props }, ref ) => {
7
+ return (
8
+ <Chip
9
+ ref={ ref }
10
+ size="tiny"
11
+ color="warning"
12
+ shape="rounded"
13
+ variant="standard"
14
+ onClick={ onClick }
15
+ icon={ <AlertTriangleFilledIcon /> }
16
+ label={
17
+ <Tooltip title={ label } placement="top">
18
+ <Box sx={ { display: 'flex', gap: 0.5, alignItems: 'center' } }>
19
+ <Typography variant="caption" noWrap>
20
+ { label }
21
+ </Typography>
22
+ <Typography variant="caption" noWrap sx={ { textOverflow: 'initial', overflow: 'visible' } }>
23
+ ({ __( 'deleted', 'elementor' ) })
24
+ </Typography>
25
+ </Box>
26
+ </Tooltip>
27
+ }
28
+ sx={ {
29
+ height: ( theme: Theme ) => theme.spacing( 3.5 ),
30
+ borderRadius: ( theme: Theme ) => theme.spacing( 1 ),
31
+ justifyContent: 'flex-start',
32
+ width: '100%',
33
+ } }
34
+ { ...props }
35
+ />
36
+ );
37
+ } );
@@ -0,0 +1,70 @@
1
+ import { useId, useRef } from 'react';
2
+ import * as React from 'react';
3
+ import { useBoundProp } from '@elementor/editor-controls';
4
+ import { type PropTypeUtil } from '@elementor/editor-props';
5
+ import { ColorFilterIcon } from '@elementor/icons';
6
+ import { bindPopover, bindTrigger, Box, Popover, usePopupState } from '@elementor/ui';
7
+
8
+ import { type Variable } from '../../../types';
9
+ import { VariableSelectionPopover } from '../../variable-selection-popover';
10
+ import { AssignedTag, SIZE } from '../tags/assigned-tag';
11
+
12
+ type Props = {
13
+ variablePropTypeUtil: PropTypeUtil< string, string >;
14
+ fallbackPropTypeUtil: PropTypeUtil< string, string | null > | PropTypeUtil< string, string >;
15
+ additionalStartIcon?: React.ReactNode;
16
+ variable: Variable;
17
+ };
18
+
19
+ export const AssignedVariable = ( {
20
+ variable,
21
+ variablePropTypeUtil,
22
+ fallbackPropTypeUtil,
23
+ additionalStartIcon,
24
+ }: Props ) => {
25
+ const { setValue } = useBoundProp();
26
+ const anchorRef = useRef< HTMLDivElement >( null );
27
+
28
+ const popupId = useId();
29
+ const popupState = usePopupState( {
30
+ variant: 'popover',
31
+ popupId: `elementor-variables-list-${ popupId }`,
32
+ } );
33
+
34
+ const unlinkVariable = () => {
35
+ setValue( fallbackPropTypeUtil.create( variable.value ) );
36
+ };
37
+
38
+ return (
39
+ <Box ref={ anchorRef }>
40
+ <AssignedTag
41
+ label={ variable.label }
42
+ startIcon={
43
+ <>
44
+ <ColorFilterIcon fontSize={ SIZE } />
45
+
46
+ { additionalStartIcon }
47
+ </>
48
+ }
49
+ onUnlink={ unlinkVariable }
50
+ { ...bindTrigger( popupState ) }
51
+ />
52
+ <Popover
53
+ disableScrollLock
54
+ anchorEl={ anchorRef.current }
55
+ anchorOrigin={ { vertical: 'bottom', horizontal: 'right' } }
56
+ transformOrigin={ { vertical: 'top', horizontal: 'right' } }
57
+ PaperProps={ {
58
+ sx: { my: 1 },
59
+ } }
60
+ { ...bindPopover( popupState ) }
61
+ >
62
+ <VariableSelectionPopover
63
+ selectedVariable={ variable }
64
+ closePopover={ popupState.close }
65
+ propTypeKey={ variablePropTypeUtil.key }
66
+ />
67
+ </Popover>
68
+ </Box>
69
+ );
70
+ };
@@ -0,0 +1,76 @@
1
+ import * as React from 'react';
2
+ import { useState } from 'react';
3
+ import { useBoundProp } from '@elementor/editor-controls';
4
+ import { type PropTypeUtil } from '@elementor/editor-props';
5
+ import { isExperimentActive } from '@elementor/editor-v1-adapters';
6
+ import { Backdrop, Infotip } from '@elementor/ui';
7
+
8
+ import { restoreVariable } from '../../../hooks/use-prop-variables';
9
+ import { type Variable } from '../../../types';
10
+ import { DeletedVariableAlert } from '../deleted-variable-alert';
11
+ import { DeletedTag } from '../tags/deleted-tag';
12
+
13
+ const isV331Active = isExperimentActive( 'e_v_3_31' );
14
+
15
+ type Props = {
16
+ variable: Variable;
17
+ variablePropTypeUtil: PropTypeUtil< string, string >;
18
+ fallbackPropTypeUtil: PropTypeUtil< string, string | null > | PropTypeUtil< string, string >;
19
+ };
20
+
21
+ export const DeletedVariable = ( { variable, variablePropTypeUtil, fallbackPropTypeUtil }: Props ) => {
22
+ const { setValue } = useBoundProp();
23
+ const [ showInfotip, setShowInfotip ] = useState< boolean >( false );
24
+
25
+ const toggleInfotip = () => setShowInfotip( ( prev ) => ! prev );
26
+
27
+ const closeInfotip = () => setShowInfotip( false );
28
+
29
+ const unlinkVariable = () => {
30
+ setValue( fallbackPropTypeUtil.create( variable.value ) );
31
+ };
32
+
33
+ const handleRestore = () => {
34
+ if ( ! variable.key ) {
35
+ return;
36
+ }
37
+
38
+ restoreVariable( variable.key ).then( ( key ) => {
39
+ setValue( variablePropTypeUtil.create( key ) );
40
+ closeInfotip();
41
+ } );
42
+ };
43
+
44
+ return (
45
+ <>
46
+ { showInfotip && <Backdrop open onClick={ closeInfotip } invisible /> }
47
+ <Infotip
48
+ color="warning"
49
+ placement="right-start"
50
+ open={ showInfotip }
51
+ disableHoverListener
52
+ onClose={ closeInfotip }
53
+ content={
54
+ <DeletedVariableAlert
55
+ onClose={ closeInfotip }
56
+ onUnlink={ unlinkVariable }
57
+ onRestore={ isV331Active ? handleRestore : undefined }
58
+ label={ variable.label }
59
+ />
60
+ }
61
+ slotProps={ {
62
+ popper: {
63
+ modifiers: [
64
+ {
65
+ name: 'offset',
66
+ options: { offset: [ 0, 24 ] },
67
+ },
68
+ ],
69
+ },
70
+ } }
71
+ >
72
+ <DeletedTag label={ variable.label } onClick={ toggleInfotip } />
73
+ </Infotip>
74
+ </>
75
+ );
76
+ };
@@ -1,66 +1,39 @@
1
1
  import * as React from 'react';
2
- import { useId, useRef } from 'react';
3
2
  import { useBoundProp } from '@elementor/editor-controls';
4
3
  import { colorPropTypeUtil } from '@elementor/editor-props';
5
- import { ColorFilterIcon } from '@elementor/icons';
6
- import { bindPopover, bindTrigger, Box, Popover, usePopupState } from '@elementor/ui';
7
4
 
8
5
  import { ColorIndicator } from '../components/ui/color-indicator';
9
- import { SIZE, VariableTag } from '../components/ui/variable-tag';
10
- import { VariableSelectionPopover } from '../components/variable-selection-popover';
6
+ import { AssignedVariable } from '../components/ui/variable/assigned-variable';
7
+ import { DeletedVariable } from '../components/ui/variable/deleted-variable';
11
8
  import { useVariable } from '../hooks/use-prop-variables';
12
9
  import { colorVariablePropTypeUtil } from '../prop-types/color-variable-prop-type';
13
10
 
14
11
  export const ColorVariableControl = () => {
15
- const { setValue: setColor } = useBoundProp();
16
12
  const { value: variableValue } = useBoundProp( colorVariablePropTypeUtil );
13
+ const assignedVariable = useVariable( variableValue );
17
14
 
18
- const anchorRef = useRef< HTMLDivElement >( null );
19
-
20
- const popupId = useId();
21
- const popupState = usePopupState( {
22
- variant: 'popover',
23
- popupId: `elementor-variables-list-${ popupId }`,
24
- } );
25
-
26
- const selectedVariable = useVariable( variableValue );
27
- if ( ! selectedVariable ) {
15
+ if ( ! assignedVariable ) {
28
16
  throw new Error( `Global color variable ${ variableValue } not found` );
29
17
  }
30
18
 
31
- const unlinkVariable = () => {
32
- setColor( colorPropTypeUtil.create( selectedVariable.value ) );
33
- };
19
+ const isVariableDeleted = assignedVariable?.deleted;
34
20
 
35
- return (
36
- <Box ref={ anchorRef }>
37
- <VariableTag
38
- label={ selectedVariable.label }
39
- startIcon={
40
- <>
41
- <ColorFilterIcon fontSize={ SIZE } />
42
- <ColorIndicator size="inherit" value={ selectedVariable.value } component="span" />
43
- </>
44
- }
45
- onUnlink={ unlinkVariable }
46
- { ...bindTrigger( popupState ) }
21
+ if ( isVariableDeleted ) {
22
+ return (
23
+ <DeletedVariable
24
+ variable={ assignedVariable }
25
+ variablePropTypeUtil={ colorVariablePropTypeUtil }
26
+ fallbackPropTypeUtil={ colorPropTypeUtil }
47
27
  />
48
- <Popover
49
- disableScrollLock
50
- anchorEl={ anchorRef.current }
51
- anchorOrigin={ { vertical: 'bottom', horizontal: 'right' } }
52
- transformOrigin={ { vertical: 'top', horizontal: 'right' } }
53
- PaperProps={ {
54
- sx: { my: 1 },
55
- } }
56
- { ...bindPopover( popupState ) }
57
- >
58
- <VariableSelectionPopover
59
- selectedVariable={ selectedVariable }
60
- closePopover={ popupState.close }
61
- propTypeKey={ colorVariablePropTypeUtil.key }
62
- />
63
- </Popover>
64
- </Box>
28
+ );
29
+ }
30
+
31
+ return (
32
+ <AssignedVariable
33
+ variable={ assignedVariable }
34
+ variablePropTypeUtil={ colorVariablePropTypeUtil }
35
+ fallbackPropTypeUtil={ colorPropTypeUtil }
36
+ additionalStartIcon={ <ColorIndicator size="inherit" value={ assignedVariable.value } component="span" /> }
37
+ />
65
38
  );
66
39
  };
@@ -1,60 +1,37 @@
1
1
  import * as React from 'react';
2
- import { useId, useRef } from 'react';
3
2
  import { useBoundProp } from '@elementor/editor-controls';
4
3
  import { stringPropTypeUtil } from '@elementor/editor-props';
5
- import { ColorFilterIcon } from '@elementor/icons';
6
- import { bindPopover, bindTrigger, Box, Popover, usePopupState } from '@elementor/ui';
7
4
 
8
- import { SIZE, VariableTag } from '../components/ui/variable-tag';
9
- import { VariableSelectionPopover } from '../components/variable-selection-popover';
5
+ import { AssignedVariable } from '../components/ui/variable/assigned-variable';
6
+ import { DeletedVariable } from '../components/ui/variable/deleted-variable';
10
7
  import { useVariable } from '../hooks/use-prop-variables';
11
8
  import { fontVariablePropTypeUtil } from '../prop-types/font-variable-prop-type';
12
9
 
13
10
  export const FontVariableControl = () => {
14
- const { setValue: setFontFamily } = useBoundProp();
15
11
  const { value: variableValue } = useBoundProp( fontVariablePropTypeUtil );
12
+ const assignedVariable = useVariable( variableValue );
16
13
 
17
- const anchorRef = useRef< HTMLDivElement >( null );
18
-
19
- const popupId = useId();
20
- const popupState = usePopupState( {
21
- variant: 'popover',
22
- popupId: `elementor-variables-list-${ popupId }`,
23
- } );
24
-
25
- const selectedVariable = useVariable( variableValue );
26
- if ( ! selectedVariable ) {
14
+ if ( ! assignedVariable ) {
27
15
  throw new Error( `Global font variable ${ variableValue } not found` );
28
16
  }
29
17
 
30
- const unlinkVariable = () => {
31
- setFontFamily( stringPropTypeUtil.create( selectedVariable.value ) );
32
- };
18
+ const isVariableDeleted = assignedVariable?.deleted;
33
19
 
34
- return (
35
- <Box ref={ anchorRef }>
36
- <VariableTag
37
- label={ selectedVariable.label }
38
- startIcon={ <ColorFilterIcon fontSize={ SIZE } /> }
39
- onUnlink={ unlinkVariable }
40
- { ...bindTrigger( popupState ) }
20
+ if ( isVariableDeleted ) {
21
+ return (
22
+ <DeletedVariable
23
+ variable={ assignedVariable }
24
+ variablePropTypeUtil={ fontVariablePropTypeUtil }
25
+ fallbackPropTypeUtil={ stringPropTypeUtil }
41
26
  />
42
- <Popover
43
- disableScrollLock
44
- anchorEl={ anchorRef.current }
45
- anchorOrigin={ { vertical: 'bottom', horizontal: 'right' } }
46
- transformOrigin={ { vertical: 'top', horizontal: 'right' } }
47
- PaperProps={ {
48
- sx: { my: 1 },
49
- } }
50
- { ...bindPopover( popupState ) }
51
- >
52
- <VariableSelectionPopover
53
- selectedVariable={ selectedVariable }
54
- closePopover={ popupState.close }
55
- propTypeKey={ fontVariablePropTypeUtil.key }
56
- />
57
- </Popover>
58
- </Box>
27
+ );
28
+ }
29
+
30
+ return (
31
+ <AssignedVariable
32
+ variable={ assignedVariable }
33
+ variablePropTypeUtil={ fontVariablePropTypeUtil }
34
+ fallbackPropTypeUtil={ stringPropTypeUtil }
35
+ />
59
36
  );
60
37
  };
@@ -1,3 +1,5 @@
1
+ import { fontVariablePropTypeUtil } from './prop-types/font-variable-prop-type';
2
+ import { enqueueFont } from './sync/enqueue-font';
1
3
  import { type StyleVariables, type Variable } from './types';
2
4
 
3
5
  type VariablesChangeCallback = ( variables: StyleVariables ) => void;
@@ -21,16 +23,41 @@ export const createStyleVariablesRepository = () => {
21
23
  }
22
24
  };
23
25
 
24
- const shouldUpdate = ( key: string, newValue: string ): boolean => {
25
- return ! ( key in variables ) || variables[ key ] !== newValue;
26
+ const shouldUpdate = ( key: string, maybeUpdated: Variable ): boolean => {
27
+ if ( ! ( key in variables ) ) {
28
+ return true;
29
+ }
30
+
31
+ if ( variables[ key ].label !== maybeUpdated.label ) {
32
+ return true;
33
+ }
34
+
35
+ if ( variables[ key ].value !== maybeUpdated.value ) {
36
+ return true;
37
+ }
38
+
39
+ if ( ! variables[ key ]?.deleted && maybeUpdated?.deleted ) {
40
+ return true;
41
+ }
42
+
43
+ if ( variables[ key ]?.deleted && ! maybeUpdated?.deleted ) {
44
+ return true;
45
+ }
46
+
47
+ return false;
26
48
  };
27
49
 
28
50
  const applyUpdates = ( updatedVars: Variables ): boolean => {
29
51
  let hasChanges = false;
30
52
 
31
- for ( const [ key, { value } ] of Object.entries( updatedVars ) ) {
32
- if ( shouldUpdate( key, value ) ) {
33
- variables[ key ] = value;
53
+ for ( const [ key, variable ] of Object.entries( updatedVars ) ) {
54
+ if ( shouldUpdate( key, variable ) ) {
55
+ variables[ key ] = variable;
56
+
57
+ if ( variable.type === fontVariablePropTypeUtil.key ) {
58
+ fontEnqueue( variable.value );
59
+ }
60
+
34
61
  hasChanges = true;
35
62
  }
36
63
  }
@@ -38,6 +65,18 @@ export const createStyleVariablesRepository = () => {
38
65
  return hasChanges;
39
66
  };
40
67
 
68
+ const fontEnqueue = ( value: string ): void => {
69
+ if ( ! value ) {
70
+ return;
71
+ }
72
+
73
+ try {
74
+ enqueueFont( value );
75
+ } catch {
76
+ // This prevents font enqueueing failures from breaking variable updates
77
+ }
78
+ };
79
+
41
80
  const update = ( updatedVars: Variables ) => {
42
81
  if ( applyUpdates( updatedVars ) ) {
43
82
  notify();
@@ -66,3 +66,9 @@ export const deleteVariable = ( deleteId: string ) => {
66
66
  return id;
67
67
  } );
68
68
  };
69
+
70
+ export const restoreVariable = ( restoreId: string ) => {
71
+ return service.restore( restoreId ).then( ( { id }: { id: string } ) => {
72
+ return id;
73
+ } );
74
+ };
@@ -1,32 +1,16 @@
1
1
  import { styleTransformersRegistry } from '@elementor/editor-canvas';
2
- import { injectIntoRepeaterItemIcon, injectIntoRepeaterItemLabel } from '@elementor/editor-controls';
3
2
  import { controlActionsMenu, registerControlReplacement } from '@elementor/editor-editing-panel';
4
- import { backgroundColorOverlayPropTypeUtil, type PropValue, shadowPropTypeUtil } from '@elementor/editor-props';
5
3
 
6
- import {
7
- BackgroundRepeaterColorIndicator,
8
- BackgroundRepeaterLabel,
9
- BoxShadowRepeaterColorIndicator,
10
- } from './components/variables-repeater-item-slot';
11
4
  import { ColorVariableControl } from './controls/color-variable-control';
12
5
  import { usePropColorVariableAction } from './hooks/use-prop-color-variable-action';
13
6
  import { colorVariablePropTypeUtil } from './prop-types/color-variable-prop-type';
7
+ import { registerRepeaterInjections } from './repeater-injections';
14
8
  import { variableTransformer } from './transformers/variable-transformer';
15
9
  import { hasAssignedColorVariable } from './utils';
16
10
 
17
11
  const { registerPopoverAction } = controlActionsMenu;
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
+ export function initColorVariables() {
30
14
  registerControlReplacement( {
31
15
  component: ColorVariableControl,
32
16
  condition: ( { value } ) => hasAssignedColorVariable( value ),
@@ -36,37 +20,8 @@ function registerControlsAndActions() {
36
20
  id: 'color-variables',
37
21
  useProps: usePropColorVariableAction,
38
22
  } );
39
- }
40
-
41
- function registerRepeaterItemIcons() {
42
- injectIntoRepeaterItemIcon( {
43
- id: 'color-variables-background-icon',
44
- component: BackgroundRepeaterColorIndicator,
45
- condition: conditions.backgroundOverlay,
46
- } );
47
-
48
- injectIntoRepeaterItemIcon( {
49
- id: 'color-variables-icon',
50
- component: BoxShadowRepeaterColorIndicator,
51
- condition: conditions.boxShadow,
52
- } );
53
- }
54
23
 
55
- function registerRepeaterItemLabels() {
56
- injectIntoRepeaterItemLabel( {
57
- id: 'color-variables-label',
58
- component: BackgroundRepeaterLabel,
59
- condition: conditions.backgroundOverlay,
60
- } );
61
- }
62
-
63
- function registerStyleTransformers() {
64
24
  styleTransformersRegistry.register( colorVariablePropTypeUtil.key, variableTransformer );
65
- }
66
25
 
67
- export function initColorVariables() {
68
- registerControlsAndActions();
69
- registerRepeaterItemIcons();
70
- registerRepeaterItemLabels();
71
- registerStyleTransformers();
26
+ registerRepeaterInjections();
72
27
  }
@@ -5,7 +5,7 @@ import { Portal } from '@elementor/ui';
5
5
 
6
6
  import { styleVariablesRepository } from '../style-variables-repository';
7
7
  import { getCanvasIframeDocument } from '../sync/get-canvas-iframe-document';
8
- import { type StyleVariables } from '../types';
8
+ import { type StyleVariables, type Variable } from '../types';
9
9
 
10
10
  const VARIABLES_WRAPPER = 'body';
11
11
 
@@ -49,8 +49,14 @@ function useStyleVariables() {
49
49
  return variables;
50
50
  }
51
51
 
52
+ function cssVariableDeclaration( key: string, variable: Variable ) {
53
+ const variableName = variable?.deleted ? key : variable.label;
54
+ const value = variable.value;
55
+
56
+ return `--${ variableName }:${ value };`;
57
+ }
58
+
52
59
  function convertToCssVariables( variables: StyleVariables ): string {
53
- return Object.entries( variables )
54
- .map( ( [ key, value ] ) => `--${ key }:${ value };` )
55
- .join( '' );
60
+ const listOfVariables = Object.entries( variables );
61
+ return listOfVariables.map( ( [ key, variable ] ) => cssVariableDeclaration( key, variable ) ).join( '' );
56
62
  }
@@ -0,0 +1,35 @@
1
+ import { injectIntoRepeaterItemIcon, injectIntoRepeaterItemLabel } from '@elementor/editor-controls';
2
+ import { backgroundColorOverlayPropTypeUtil, type PropValue, shadowPropTypeUtil } from '@elementor/editor-props';
3
+
4
+ import {
5
+ BackgroundRepeaterColorIndicator,
6
+ BackgroundRepeaterLabel,
7
+ BoxShadowRepeaterColorIndicator,
8
+ } from './components/variables-repeater-item-slot';
9
+ import { hasAssignedColorVariable } from './utils';
10
+
11
+ export function registerRepeaterInjections() {
12
+ injectIntoRepeaterItemIcon( {
13
+ id: 'color-variables-background-icon',
14
+ component: BackgroundRepeaterColorIndicator,
15
+ condition: ( { value: prop }: { value: PropValue } ) => {
16
+ return hasAssignedColorVariable( backgroundColorOverlayPropTypeUtil.extract( prop )?.color );
17
+ },
18
+ } );
19
+
20
+ injectIntoRepeaterItemIcon( {
21
+ id: 'color-variables-icon',
22
+ component: BoxShadowRepeaterColorIndicator,
23
+ condition: ( { value: prop }: { value: PropValue } ) => {
24
+ return hasAssignedColorVariable( shadowPropTypeUtil.extract( prop )?.color );
25
+ },
26
+ } );
27
+
28
+ injectIntoRepeaterItemLabel( {
29
+ id: 'color-variables-label',
30
+ component: BackgroundRepeaterLabel,
31
+ condition: ( { value: prop }: { value: PropValue } ) => {
32
+ return hasAssignedColorVariable( backgroundColorOverlayPropTypeUtil.extract( prop )?.color );
33
+ },
34
+ } );
35
+ }