@elementor/editor-editing-panel 1.0.0 → 1.1.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 (117) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/dist/index.d.mts +10 -19
  3. package/dist/index.d.ts +10 -19
  4. package/dist/index.js +1283 -1751
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +1305 -1762
  7. package/dist/index.mjs.map +1 -1
  8. package/package.json +12 -12
  9. package/src/components/add-or-remove-content.tsx +3 -3
  10. package/src/components/collapse-icon.tsx +12 -0
  11. package/src/components/collapsible-content.tsx +5 -14
  12. package/src/components/collapsible-field.tsx +5 -3
  13. package/src/components/css-class-selector-section.tsx +76 -0
  14. package/src/components/editing-panel-hooks.tsx +2 -0
  15. package/src/components/editing-panel-tabs.tsx +23 -13
  16. package/src/components/editing-panel.tsx +9 -6
  17. package/src/components/multi-combobox/index.ts +3 -0
  18. package/src/components/multi-combobox/multi-combobox.tsx +120 -0
  19. package/src/components/multi-combobox/types.ts +26 -0
  20. package/src/components/multi-combobox/use-combobox-actions.ts +62 -0
  21. package/src/components/section.tsx +37 -0
  22. package/src/components/sections-list.tsx +6 -0
  23. package/src/components/settings-tab.tsx +11 -11
  24. package/src/components/style-sections/background-section/background-color-field.tsx +4 -4
  25. package/src/components/style-sections/background-section/background-section.tsx +9 -7
  26. package/src/components/style-sections/border-section/border-color-field.tsx +4 -4
  27. package/src/components/style-sections/border-section/border-field.tsx +4 -3
  28. package/src/components/style-sections/border-section/border-radius-field.tsx +4 -3
  29. package/src/components/style-sections/border-section/border-section.tsx +7 -10
  30. package/src/components/style-sections/border-section/border-style-field.tsx +4 -4
  31. package/src/components/style-sections/border-section/border-width-field.tsx +4 -3
  32. package/src/components/style-sections/effects-section/effects-section.tsx +7 -10
  33. package/src/components/style-sections/layout-section/display-field.tsx +32 -0
  34. package/src/components/style-sections/layout-section/justify-content-field.tsx +82 -0
  35. package/src/components/style-sections/layout-section/layout-section.tsx +17 -0
  36. package/src/components/style-sections/layout-section/utils/rotate-flex-icon.ts +12 -0
  37. package/src/components/style-sections/position-section/dimensions-field.tsx +6 -6
  38. package/src/components/style-sections/position-section/position-field.tsx +4 -4
  39. package/src/components/style-sections/position-section/position-section.tsx +45 -15
  40. package/src/components/style-sections/position-section/z-index-field.tsx +4 -4
  41. package/src/components/style-sections/size-section/overflow-field.tsx +8 -8
  42. package/src/components/style-sections/size-section/size-section.tsx +33 -26
  43. package/src/components/style-sections/spacing-section/spacing-section.tsx +11 -13
  44. package/src/components/style-sections/typography-section/font-family-field.tsx +40 -0
  45. package/src/components/style-sections/typography-section/font-size-field.tsx +4 -4
  46. package/src/components/style-sections/typography-section/font-weight-field.tsx +4 -4
  47. package/src/components/style-sections/typography-section/letter-spacing-field.tsx +4 -4
  48. package/src/components/style-sections/typography-section/text-alignment-field.tsx +9 -9
  49. package/src/components/style-sections/typography-section/text-color-field.tsx +4 -4
  50. package/src/components/style-sections/typography-section/text-direction-field.tsx +7 -7
  51. package/src/components/style-sections/typography-section/text-stroke-field.tsx +3 -3
  52. package/src/components/style-sections/typography-section/text-style-field.tsx +5 -4
  53. package/src/components/style-sections/typography-section/transform-field.tsx +23 -9
  54. package/src/components/style-sections/typography-section/typography-section.tsx +26 -27
  55. package/src/components/style-sections/typography-section/word-spacing-field.tsx +4 -4
  56. package/src/components/style-tab.tsx +67 -31
  57. package/src/contexts/classes-prop-context.tsx +1 -1
  58. package/src/contexts/element-context.tsx +2 -2
  59. package/src/contexts/style-context.tsx +6 -5
  60. package/src/control-replacement.tsx +1 -1
  61. package/src/controls-actions.ts +3 -2
  62. package/src/controls-registry/control-type-container.tsx +3 -2
  63. package/src/controls-registry/control.tsx +2 -1
  64. package/src/controls-registry/controls-registry.tsx +8 -1
  65. package/src/controls-registry/settings-field.tsx +5 -4
  66. package/src/controls-registry/styles-field.tsx +3 -2
  67. package/src/dynamics/components/dynamic-selection-control.tsx +15 -14
  68. package/src/dynamics/components/dynamic-selection.tsx +9 -8
  69. package/src/dynamics/dynamic-control.tsx +4 -4
  70. package/src/dynamics/hooks/use-dynamic-tag.ts +3 -2
  71. package/src/dynamics/hooks/use-prop-dynamic-action.tsx +6 -5
  72. package/src/dynamics/hooks/use-prop-dynamic-tags.ts +3 -2
  73. package/src/dynamics/init.ts +5 -3
  74. package/src/dynamics/sync/get-elementor-config.ts +1 -1
  75. package/src/dynamics/types.ts +2 -2
  76. package/src/dynamics/utils.ts +3 -2
  77. package/src/hooks/use-close-editor-panel.ts +23 -0
  78. package/src/hooks/use-direction.ts +13 -0
  79. package/src/hooks/use-open-editor-panel.ts +4 -3
  80. package/src/hooks/use-prop-value-history.ts +45 -0
  81. package/src/hooks/use-style-prop-history.ts +75 -0
  82. package/src/hooks/use-styles-field.ts +25 -4
  83. package/src/index.ts +1 -1
  84. package/src/init.ts +5 -4
  85. package/src/panel.ts +1 -0
  86. package/src/popover-action.tsx +1 -1
  87. package/src/sync/enqueue-font.ts +7 -0
  88. package/src/sync/get-elementor-config.ts +7 -0
  89. package/src/sync/{should-use-v2-panel.ts → is-atomic-widget-selected.ts} +1 -1
  90. package/src/sync/types.ts +20 -21
  91. package/src/components/accordion-section.tsx +0 -26
  92. package/src/components/control-label.tsx +0 -10
  93. package/src/controls/bound-prop-context.tsx +0 -30
  94. package/src/controls/components/control-toggle-button-group.tsx +0 -68
  95. package/src/controls/components/repeater.tsx +0 -197
  96. package/src/controls/components/text-field-inner-selection.tsx +0 -75
  97. package/src/controls/control-actions/control-actions-context.tsx +0 -27
  98. package/src/controls/control-actions/control-actions-menu.ts +0 -7
  99. package/src/controls/control-actions/control-actions.tsx +0 -31
  100. package/src/controls/controls/box-shadow-repeater-control.tsx +0 -210
  101. package/src/controls/controls/color-control.tsx +0 -25
  102. package/src/controls/controls/equal-unequal-sizes-control.tsx +0 -196
  103. package/src/controls/controls/image-control.tsx +0 -58
  104. package/src/controls/controls/image-media-control.tsx +0 -64
  105. package/src/controls/controls/linked-dimensions-control.tsx +0 -139
  106. package/src/controls/controls/number-control.tsx +0 -29
  107. package/src/controls/controls/select-control.tsx +0 -30
  108. package/src/controls/controls/size-control.tsx +0 -71
  109. package/src/controls/controls/stroke-control.tsx +0 -105
  110. package/src/controls/controls/text-area-control.tsx +0 -31
  111. package/src/controls/controls/text-control.tsx +0 -17
  112. package/src/controls/controls/toggle-control.tsx +0 -26
  113. package/src/controls/create-control-replacement.tsx +0 -53
  114. package/src/controls/create-control.tsx +0 -40
  115. package/src/controls/hooks/use-sync-external-state.tsx +0 -51
  116. package/src/controls/index.ts +0 -24
  117. package/src/dynamics/hooks/use-prop-value-history.ts +0 -26
@@ -1,68 +0,0 @@
1
- import * as React from 'react';
2
- import { JSX } from 'react';
3
- import { StackProps, styled, ToggleButton, ToggleButtonGroup, Tooltip } from '@elementor/ui';
4
-
5
- export type ToggleButtonGroupItem< TValue > = {
6
- value: TValue;
7
- label: string;
8
- icon: JSX.ElementType;
9
- showTooltip?: boolean;
10
- };
11
-
12
- const StyledToggleButtonGroup = styled( ToggleButtonGroup )`
13
- ${ ( { justify } ) => `justify-content: ${ justify };` }
14
- `;
15
-
16
- type ExclusiveValue< TValue > = TValue | null;
17
- type NonExclusiveValue< TValue > = TValue[];
18
-
19
- type Props< TValue > = {
20
- justify?: StackProps[ 'justifyContent' ];
21
- size?: 'tiny' | 'small' | 'medium' | 'large';
22
- items: ToggleButtonGroupItem< TValue >[];
23
- } & (
24
- | {
25
- exclusive?: false;
26
- value: NonExclusiveValue< TValue >;
27
- onChange: ( value: NonExclusiveValue< TValue > ) => void;
28
- }
29
- | {
30
- exclusive: true;
31
- value: ExclusiveValue< TValue >;
32
- onChange: ( value: ExclusiveValue< TValue > ) => void;
33
- }
34
- );
35
-
36
- export const ControlToggleButtonGroup = < TValue, >( {
37
- justify = 'end',
38
- size = 'tiny',
39
- value,
40
- onChange,
41
- items,
42
- exclusive = false,
43
- }: Props< TValue > ) => {
44
- const handleChange = (
45
- _: React.MouseEvent< HTMLElement >,
46
- newValue: typeof exclusive extends true ? ExclusiveValue< TValue > : NonExclusiveValue< TValue >
47
- ) => {
48
- onChange( newValue as never );
49
- };
50
-
51
- return (
52
- <StyledToggleButtonGroup justify={ justify } value={ value } onChange={ handleChange } exclusive={ exclusive }>
53
- { items.map( ( { label: label, value: buttonValue, icon: Icon, showTooltip: showTooltip } ) =>
54
- showTooltip ? (
55
- <Tooltip title={ label } disableFocusListener={ true } placement="top" key={ buttonValue }>
56
- <ToggleButton value={ buttonValue } aria-label={ label } size={ size }>
57
- <Icon fontSize={ size } />
58
- </ToggleButton>
59
- </Tooltip>
60
- ) : (
61
- <ToggleButton key={ buttonValue } value={ buttonValue } aria-label={ label } size={ size }>
62
- <Icon fontSize={ size } />
63
- </ToggleButton>
64
- )
65
- ) }
66
- </StyledToggleButtonGroup>
67
- );
68
- };
@@ -1,197 +0,0 @@
1
- import * as React from 'react';
2
- import { useId, useRef, useState } from 'react';
3
- import { __ } from '@wordpress/i18n';
4
- import { PlusIcon, XIcon, CopyIcon, EyeIcon, EyeOffIcon } from '@elementor/icons';
5
- import {
6
- Box,
7
- Stack,
8
- Popover,
9
- IconButton,
10
- bindTrigger,
11
- bindPopover,
12
- usePopupState,
13
- UnstableTagProps,
14
- UnstableTag,
15
- Typography,
16
- } from '@elementor/ui';
17
-
18
- const SIZE = 'tiny';
19
-
20
- type AnchorEl = HTMLElement | null;
21
-
22
- type Item< T > = {
23
- disabled?: boolean;
24
- } & T;
25
-
26
- export type RepeaterProps< T > = {
27
- label: string;
28
- values?: T[];
29
- setValues: ( newValue: T[] ) => void;
30
- itemSettings: {
31
- initialValues: T;
32
- Label: React.ComponentType< { value: T } >;
33
- Icon: React.ComponentType< { value: T } >;
34
- Content: React.ComponentType< {
35
- value: T;
36
- setValue: ( newValue: T ) => void;
37
- anchorEl: AnchorEl;
38
- } >;
39
- };
40
- };
41
-
42
- export const Repeater = < T, >( {
43
- label,
44
- itemSettings,
45
- values: repeaterValues = [],
46
- setValues: setRepeaterValues,
47
- }: RepeaterProps< Item< T > > ) => {
48
- const addRepeaterItem = () => {
49
- const newItem = structuredClone( itemSettings.initialValues );
50
-
51
- setRepeaterValues( [ ...repeaterValues, newItem ] );
52
- };
53
-
54
- const duplicateRepeaterItem = ( index: number ) => {
55
- setRepeaterValues( [
56
- ...repeaterValues.slice( 0, index ),
57
- structuredClone( repeaterValues[ index ] ),
58
- ...repeaterValues.slice( index ),
59
- ] );
60
- };
61
-
62
- const removeRepeaterItem = ( index: number ) => {
63
- setRepeaterValues( repeaterValues.filter( ( _, i ) => i !== index ) );
64
- };
65
-
66
- const toggleDisableRepeaterItem = ( index: number ) => {
67
- setRepeaterValues(
68
- repeaterValues.map( ( value, i ) => {
69
- if ( i === index ) {
70
- const { disabled, ...rest } = value;
71
-
72
- // If the items should not be disabled, remove the disabled property.
73
- return { ...rest, ...( disabled ? {} : { disabled: true } ) } as Item< T >;
74
- }
75
-
76
- return value;
77
- } )
78
- );
79
- };
80
-
81
- return (
82
- <Stack>
83
- <Stack direction="row" justifyContent="space-between" alignItems="center" sx={ { pb: 1 } }>
84
- <Typography component="label" variant="caption" color="text.secondary">
85
- { label }
86
- </Typography>
87
- <IconButton size={ SIZE } onClick={ addRepeaterItem } aria-label={ __( 'Add item', 'elementor' ) }>
88
- <PlusIcon fontSize={ SIZE } />
89
- </IconButton>
90
- </Stack>
91
- <Stack gap={ 1 }>
92
- { repeaterValues.map( ( value, index ) => (
93
- <RepeaterItem
94
- key={ index }
95
- disabled={ value.disabled }
96
- label={ <itemSettings.Label value={ value } /> }
97
- startIcon={ <itemSettings.Icon value={ value } /> }
98
- removeItem={ () => removeRepeaterItem( index ) }
99
- duplicateItem={ () => duplicateRepeaterItem( index ) }
100
- toggleDisableItem={ () => toggleDisableRepeaterItem( index ) }
101
- >
102
- { ( props ) => (
103
- <itemSettings.Content
104
- { ...props }
105
- value={ value }
106
- setValue={ ( newValue ) =>
107
- setRepeaterValues(
108
- repeaterValues.map( ( item, i ) => ( i === index ? newValue : item ) )
109
- )
110
- }
111
- />
112
- ) }
113
- </RepeaterItem>
114
- ) ) }
115
- </Stack>
116
- </Stack>
117
- );
118
- };
119
-
120
- type RepeaterItemProps = {
121
- label: React.ReactNode;
122
- disabled?: boolean;
123
- startIcon: UnstableTagProps[ 'startIcon' ];
124
- removeItem: () => void;
125
- duplicateItem: () => void;
126
- toggleDisableItem: () => void;
127
- children: ( { anchorEl }: { anchorEl: AnchorEl } ) => React.ReactNode;
128
- };
129
-
130
- const RepeaterItem = ( {
131
- label,
132
- disabled,
133
- startIcon,
134
- children,
135
- removeItem,
136
- duplicateItem,
137
- toggleDisableItem,
138
- }: RepeaterItemProps ) => {
139
- const popupId = useId();
140
- const tagRef = useRef< HTMLElement >( null );
141
- const [ anchorEl, setAnchorEl ] = useState< AnchorEl >( null );
142
-
143
- const popoverState = usePopupState( { popupId, variant: 'popover' } );
144
-
145
- const popoverProps = bindPopover( popoverState );
146
-
147
- return (
148
- <>
149
- <UnstableTag
150
- ref={ tagRef }
151
- label={ label }
152
- showActionsOnHover
153
- variant="outlined"
154
- aria-label={ __( 'Open item', 'elementor' ) }
155
- { ...bindTrigger( popoverState ) }
156
- startIcon={ startIcon }
157
- actions={
158
- <>
159
- <IconButton
160
- size={ SIZE }
161
- onClick={ duplicateItem }
162
- aria-label={ __( 'Duplicate item', 'elementor' ) }
163
- >
164
- <CopyIcon fontSize={ SIZE } />
165
- </IconButton>
166
- <IconButton
167
- size={ SIZE }
168
- onClick={ toggleDisableItem }
169
- aria-label={
170
- disabled ? __( 'Enable item', 'elementor' ) : __( 'Disable item', 'elementor' )
171
- }
172
- >
173
- { disabled ? <EyeOffIcon fontSize={ SIZE } /> : <EyeIcon fontSize={ SIZE } /> }
174
- </IconButton>
175
- <IconButton
176
- size={ SIZE }
177
- onClick={ removeItem }
178
- aria-label={ __( 'Remove item', 'elementor' ) }
179
- >
180
- <XIcon fontSize={ SIZE } />
181
- </IconButton>
182
- </>
183
- }
184
- />
185
- <Popover
186
- disablePortal
187
- slotProps={ {
188
- paper: { ref: setAnchorEl, sx: { width: tagRef.current?.getBoundingClientRect().width } },
189
- } }
190
- anchorOrigin={ { vertical: 'bottom', horizontal: 'left' } }
191
- { ...popoverProps }
192
- >
193
- <Box p={ 2 }>{ children( { anchorEl } ) }</Box>
194
- </Popover>
195
- </>
196
- );
197
- };
@@ -1,75 +0,0 @@
1
- import * as React from 'react';
2
- import { forwardRef, useId } from 'react';
3
- import { PropValue } from '@elementor/editor-props';
4
- import { bindMenu, bindTrigger, Button, InputAdornment, Menu, MenuItem, TextField, usePopupState } from '@elementor/ui';
5
-
6
- export type TextFieldInnerSelectionProps = {
7
- placeholder?: string;
8
- type: string;
9
- value: PropValue;
10
- onChange: ( event: React.ChangeEvent< HTMLInputElement > ) => void;
11
- endAdornment: React.ReactNode;
12
- startAdornment?: React.ReactNode;
13
- };
14
-
15
- export const TextFieldInnerSelection = forwardRef(
16
- ( { placeholder, type, value, onChange, endAdornment, startAdornment }: TextFieldInnerSelectionProps, ref ) => {
17
- return (
18
- <TextField
19
- size="tiny"
20
- type={ type }
21
- value={ value }
22
- onChange={ onChange }
23
- placeholder={ placeholder }
24
- InputProps={ {
25
- endAdornment,
26
- startAdornment,
27
- } }
28
- ref={ ref }
29
- />
30
- );
31
- }
32
- );
33
-
34
- export type SelectionEndAdornmentProps< T extends string > = {
35
- options: T[];
36
- onClick: ( value: T ) => void;
37
- value: T;
38
- };
39
-
40
- export const SelectionEndAdornment = < T extends string >( {
41
- options,
42
- onClick,
43
- value,
44
- }: SelectionEndAdornmentProps< T > ) => {
45
- const popupState = usePopupState( {
46
- variant: 'popover',
47
- popupId: useId(),
48
- } );
49
-
50
- const handleMenuItemClick = ( index: number ) => {
51
- onClick( options[ index ] );
52
- popupState.close();
53
- };
54
-
55
- return (
56
- <InputAdornment position="end">
57
- <Button
58
- size="small"
59
- color="inherit"
60
- sx={ { font: 'inherit', minWidth: 'initial' } }
61
- { ...bindTrigger( popupState ) }
62
- >
63
- { value.toUpperCase() }
64
- </Button>
65
-
66
- <Menu MenuListProps={ { dense: true } } { ...bindMenu( popupState ) }>
67
- { options.map( ( option, index ) => (
68
- <MenuItem key={ option } onClick={ () => handleMenuItemClick( index ) }>
69
- { option.toUpperCase() }
70
- </MenuItem>
71
- ) ) }
72
- </Menu>
73
- </InputAdornment>
74
- );
75
- };
@@ -1,27 +0,0 @@
1
- import * as React from 'react';
2
- import { createContext, PropsWithChildren, useContext } from 'react';
3
-
4
- type ControlActionsContext = {
5
- items: Array< {
6
- id: string;
7
- MenuItem: React.ComponentType;
8
- } >;
9
- };
10
-
11
- const Context = createContext< ControlActionsContext | null >( null );
12
-
13
- export type ControlActionsProviderProps = PropsWithChildren< ControlActionsContext >;
14
-
15
- export const ControlActionsProvider = ( { children, items }: ControlActionsProviderProps ) => (
16
- <Context.Provider value={ { items } }>{ children }</Context.Provider>
17
- );
18
-
19
- export const useControlActions = () => {
20
- const context = useContext( Context );
21
-
22
- if ( ! context ) {
23
- throw new Error( 'useControlActions must be used within a ControlActionsProvider' );
24
- }
25
-
26
- return context;
27
- };
@@ -1,7 +0,0 @@
1
- import { Components, createMenu } from '@elementor/menus';
2
-
3
- export const createControlActionsMenu = ( { components }: { components: Components } ) => {
4
- return createMenu( {
5
- components,
6
- } );
7
- };
@@ -1,31 +0,0 @@
1
- import * as React from 'react';
2
- import { PropsWithChildren } from 'react';
3
- import { styled, UnstableFloatingActionBar } from '@elementor/ui';
4
- import { useControlActions } from './control-actions-context';
5
-
6
- // CSS hack to hide empty floating bars.
7
- const FloatingBarContainer = styled( 'span' )`
8
- display: contents;
9
-
10
- .MuiFloatingActionBar-popper:has( .MuiFloatingActionBar-actions:empty ) {
11
- display: none;
12
- }
13
- `;
14
-
15
- export type ControlActionsProps = PropsWithChildren< object >;
16
-
17
- export default function ControlActions( { children }: ControlActionsProps ) {
18
- const { items } = useControlActions();
19
-
20
- if ( items.length === 0 ) {
21
- return children;
22
- }
23
-
24
- const menuItems = items.map( ( { MenuItem, id } ) => <MenuItem key={ id } /> );
25
-
26
- return (
27
- <FloatingBarContainer>
28
- <UnstableFloatingActionBar actions={ menuItems }>{ children }</UnstableFloatingActionBar>
29
- </FloatingBarContainer>
30
- );
31
- }
@@ -1,210 +0,0 @@
1
- import * as React from 'react';
2
- import { __ } from '@wordpress/i18n';
3
- import { PropValue, ShadowPropValue, BoxShadowPropValue } from '@elementor/editor-props';
4
- import { Grid, Stack, Typography, UnstableColorIndicator } from '@elementor/ui';
5
- import { Repeater } from '../components/repeater';
6
- import { SizeControl } from './size-control';
7
- import { ColorControl } from './color-control';
8
- import { BoundPropProvider, useBoundProp } from '../bound-prop-context';
9
- import { SelectControl } from './select-control';
10
- import { createControl } from '../create-control';
11
-
12
- type SetContextValue = ( v: PropValue ) => void;
13
-
14
- export const BoxShadowRepeaterControl = createControl( () => {
15
- const { value, setValue } = useBoundProp< BoxShadowPropValue >();
16
-
17
- const boxShadowValues = value?.value;
18
-
19
- const setBoxShadow = ( newValue: BoxShadowPropValue[ 'value' ] ) => {
20
- setValue( {
21
- $$type: 'box-shadow',
22
- value: newValue,
23
- } );
24
- };
25
-
26
- return (
27
- <Repeater
28
- values={ boxShadowValues }
29
- setValues={ setBoxShadow }
30
- label={ __( 'Box shadow', 'elementor' ) }
31
- itemSettings={ {
32
- Icon: ItemIcon,
33
- Label: ItemLabel,
34
- Content: ItemContent,
35
- initialValues: initialShadow,
36
- } }
37
- />
38
- );
39
- } );
40
-
41
- const ItemIcon = ( { value }: { value: ShadowPropValue } ) => (
42
- <UnstableColorIndicator size="inherit" component="span" value={ value.value.color.value } />
43
- );
44
-
45
- const ItemContent = ( {
46
- value,
47
- setValue,
48
- }: {
49
- value: ShadowPropValue;
50
- setValue: ( newValue: ShadowPropValue ) => void;
51
- } ) => {
52
- const setShadow = ( newValue: ShadowPropValue[ 'value' ] ) => {
53
- setValue( {
54
- $$type: 'shadow',
55
- value: newValue,
56
- } );
57
- };
58
-
59
- return (
60
- <Stack gap={ 1.5 }>
61
- <Grid container spacing={ 1 }>
62
- <Control
63
- bind="color"
64
- value={ value.value.color }
65
- label={ __( 'Color', 'elementor' ) }
66
- setValue={ ( v: ShadowPropValue[ 'value' ][ 'color' ] ) =>
67
- setShadow( { ...value.value, color: v } )
68
- }
69
- >
70
- <ColorControl />
71
- </Control>
72
- <Control
73
- bind="position"
74
- value={ value.value.position }
75
- label={ __( 'Position', 'elementor' ) }
76
- setValue={ ( v: ShadowPropValue[ 'value' ][ 'position' ] ) =>
77
- setShadow( { ...value.value, position: v || null } )
78
- }
79
- >
80
- <SelectControl
81
- options={ [
82
- { label: __( 'Inset', 'elementor' ), value: 'inset' },
83
- { label: __( 'Outset', 'elementor' ), value: '' },
84
- ] }
85
- />
86
- </Control>
87
- </Grid>
88
- <Grid container spacing={ 1 }>
89
- <Control
90
- bind="hOffset"
91
- label={ __( 'Horizontal', 'elementor' ) }
92
- value={ value.value.hOffset }
93
- setValue={ ( v: ShadowPropValue[ 'value' ][ 'hOffset' ] ) =>
94
- setShadow( { ...value.value, hOffset: v } )
95
- }
96
- >
97
- <SizeControl />
98
- </Control>
99
- <Control
100
- bind="vOffset"
101
- label={ __( 'Vertical', 'elementor' ) }
102
- value={ value.value.vOffset }
103
- setValue={ ( v: ShadowPropValue[ 'value' ][ 'vOffset' ] ) =>
104
- setShadow( { ...value.value, vOffset: v } )
105
- }
106
- >
107
- <SizeControl />
108
- </Control>
109
- </Grid>
110
- <Grid container spacing={ 1 }>
111
- <Control
112
- bind="blur"
113
- value={ value.value.blur }
114
- label={ __( 'Blur', 'elementor' ) }
115
- setValue={ ( v: ShadowPropValue[ 'value' ][ 'blur' ] ) => setShadow( { ...value.value, blur: v } ) }
116
- >
117
- <SizeControl />
118
- </Control>
119
- <Control
120
- bind="spread"
121
- label={ __( 'Spread', 'elementor' ) }
122
- value={ value.value.spread }
123
- setValue={ ( v: ShadowPropValue[ 'value' ][ 'spread' ] ) =>
124
- setShadow( { ...value.value, spread: v } )
125
- }
126
- >
127
- <SizeControl />
128
- </Control>
129
- </Grid>
130
- </Stack>
131
- );
132
- };
133
-
134
- const Control = < T extends PropValue >( {
135
- value,
136
- setValue,
137
- label,
138
- bind,
139
- children,
140
- }: {
141
- value: T;
142
- bind: string;
143
- label: string;
144
- children: React.ReactNode;
145
- setValue: ( v: T ) => void;
146
- } ) => (
147
- <BoundPropProvider value={ value } setValue={ setValue as SetContextValue } bind={ bind }>
148
- <Grid item xs={ 6 }>
149
- <Grid container spacing={ 1 } alignItems="center">
150
- <Grid item xs={ 12 }>
151
- <Typography component="label" variant="caption" color="text.secondary">
152
- { label }
153
- </Typography>
154
- </Grid>
155
- <Grid item xs={ 12 }>
156
- { children }
157
- </Grid>
158
- </Grid>
159
- </Grid>
160
- </BoundPropProvider>
161
- );
162
-
163
- const ItemLabel = ( { value }: { value: ShadowPropValue } ) => {
164
- const { position, hOffset, vOffset, blur, spread } = value.value;
165
-
166
- const { size: blurSize = '', unit: blurUnit = '' } = blur?.value || {};
167
- const { size: spreadSize = '', unit: spreadUnit = '' } = spread?.value || {};
168
- const { size: hOffsetSize = 'unset', unit: hOffsetUnit = '' } = hOffset?.value || {};
169
- const { size: vOffsetSize = 'unset', unit: vOffsetUnit = '' } = vOffset?.value || {};
170
-
171
- const sizes = [
172
- hOffsetSize + hOffsetUnit,
173
- vOffsetSize + vOffsetUnit,
174
- blurSize + blurUnit,
175
- spreadSize + spreadUnit,
176
- ].join( ' ' );
177
-
178
- return (
179
- <span style={ { textTransform: 'capitalize' } }>
180
- { position ?? 'outset' }: { sizes }
181
- </span>
182
- );
183
- };
184
-
185
- const initialShadow: ShadowPropValue = {
186
- $$type: 'shadow',
187
- value: {
188
- hOffset: {
189
- $$type: 'size',
190
- value: { unit: 'px', size: 0 },
191
- },
192
- vOffset: {
193
- $$type: 'size',
194
- value: { unit: 'px', size: 0 },
195
- },
196
- blur: {
197
- $$type: 'size',
198
- value: { unit: 'px', size: 10 },
199
- },
200
- spread: {
201
- $$type: 'size',
202
- value: { unit: 'px', size: 0 },
203
- },
204
- color: {
205
- $$type: 'color',
206
- value: 'rgba(0, 0, 0, 1)',
207
- },
208
- position: null,
209
- },
210
- };
@@ -1,25 +0,0 @@
1
- import * as React from 'react';
2
- import { UnstableColorField, UnstableColorFieldProps } from '@elementor/ui';
3
- import { useBoundProp } from '../bound-prop-context';
4
- import ControlActions from '../control-actions/control-actions';
5
- import { createControl } from '../create-control';
6
- import { ColorPropValue } from '@elementor/editor-props';
7
-
8
- export const ColorControl = createControl(
9
- ( props: Partial< Omit< UnstableColorFieldProps, 'value' | 'onChange' > > ) => {
10
- const { value, setValue } = useBoundProp< ColorPropValue >();
11
-
12
- const handleChange = ( selectedColor: string ) => {
13
- setValue( {
14
- $$type: 'color',
15
- value: selectedColor,
16
- } );
17
- };
18
-
19
- return (
20
- <ControlActions>
21
- <UnstableColorField size="tiny" { ...props } value={ value?.value } onChange={ handleChange } />
22
- </ControlActions>
23
- );
24
- }
25
- );