@elementor/editor-editing-panel 1.2.0 → 1.3.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 +29 -0
- package/dist/index.js +657 -486
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +613 -433
- package/dist/index.mjs.map +1 -1
- package/package.json +12 -11
- package/src/components/style-sections/border-section/border-radius-field.tsx +4 -4
- package/src/components/style-sections/border-section/border-width-field.tsx +4 -4
- package/src/components/style-sections/layout-section/align-items-field.tsx +40 -60
- package/src/components/style-sections/layout-section/align-self-child-field.tsx +72 -0
- package/src/components/style-sections/layout-section/flex-direction-field.tsx +2 -2
- package/src/components/style-sections/layout-section/flex-order-field.tsx +14 -8
- package/src/components/style-sections/layout-section/flex-size-field.tsx +164 -0
- package/src/components/style-sections/layout-section/justify-content-field.tsx +51 -78
- package/src/components/style-sections/layout-section/layout-section.tsx +7 -2
- package/src/components/style-sections/layout-section/utils/rotated-icon.tsx +52 -0
- package/src/components/style-sections/layout-section/wrap-field.tsx +1 -1
- package/src/components/style-sections/position-section/position-section.tsx +3 -3
- package/src/components/style-sections/typography-section/line-height-field.tsx +21 -0
- package/src/components/style-sections/typography-section/text-style-field.tsx +31 -8
- package/src/components/style-sections/typography-section/typography-section.tsx +3 -1
- package/src/controls-registry/controls-registry.tsx +4 -0
- package/src/dynamics/components/dynamic-selection-control.tsx +8 -5
- package/src/dynamics/components/dynamic-selection.tsx +10 -8
- package/src/dynamics/dynamic-control.tsx +9 -11
- package/src/dynamics/utils.ts +20 -3
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { ControlLabel } from '@elementor/editor-controls';
|
|
3
|
+
import { type StringPropValue } from '@elementor/editor-props';
|
|
3
4
|
import { Divider, Stack } from '@elementor/ui';
|
|
4
5
|
import { __ } from '@wordpress/i18n';
|
|
5
6
|
|
|
6
7
|
import { useStylesField } from '../../../hooks/use-styles-field';
|
|
7
8
|
import { AlignItemsField } from './align-items-field';
|
|
9
|
+
import { AlignSelfChild } from './align-self-child-field';
|
|
8
10
|
import { DisplayField } from './display-field';
|
|
9
11
|
import { FlexDirectionField } from './flex-direction-field';
|
|
10
12
|
import { FlexOrderField } from './flex-order-field';
|
|
13
|
+
import { FlexSizeField } from './flex-size-field';
|
|
11
14
|
import { JustifyContentField } from './justify-content-field';
|
|
12
15
|
import { WrapField } from './wrap-field';
|
|
13
16
|
|
|
14
17
|
export const LayoutSection = () => {
|
|
15
|
-
const [ display ] = useStylesField( 'display' );
|
|
18
|
+
const [ display ] = useStylesField< StringPropValue >( 'display' );
|
|
16
19
|
|
|
17
20
|
return (
|
|
18
21
|
<Stack gap={ 2 }>
|
|
19
22
|
<DisplayField />
|
|
20
|
-
{ 'flex' === display && <FlexFields /> }
|
|
23
|
+
{ 'flex' === display?.value && <FlexFields /> }
|
|
21
24
|
</Stack>
|
|
22
25
|
);
|
|
23
26
|
};
|
|
@@ -31,6 +34,8 @@ const FlexFields = () => (
|
|
|
31
34
|
<WrapField />
|
|
32
35
|
<Divider />
|
|
33
36
|
<ControlLabel>{ __( 'Flex child', 'elementor' ) }</ControlLabel>
|
|
37
|
+
<AlignSelfChild />
|
|
34
38
|
<FlexOrderField />
|
|
39
|
+
<FlexSizeField />
|
|
35
40
|
</>
|
|
36
41
|
);
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useRef } from 'react';
|
|
3
|
+
import { type StringPropValue } from '@elementor/editor-props';
|
|
4
|
+
import { type ToggleButtonProps, useTheme } from '@elementor/ui';
|
|
5
|
+
|
|
6
|
+
import { useStylesField } from '../../../../hooks/use-styles-field';
|
|
7
|
+
import type { FlexDirection } from '../flex-direction-field';
|
|
8
|
+
|
|
9
|
+
type Props = {
|
|
10
|
+
icon: React.JSX.ElementType;
|
|
11
|
+
size: ToggleButtonProps[ 'size' ];
|
|
12
|
+
isClockwise?: boolean;
|
|
13
|
+
offset?: number;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const CLOCKWISE_ANGLES: Record< FlexDirection, number > = {
|
|
17
|
+
row: 0,
|
|
18
|
+
column: 90,
|
|
19
|
+
'row-reverse': 180,
|
|
20
|
+
'column-reverse': 270,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const COUNTER_CLOCKWISE_ANGLES: Record< FlexDirection, number > = {
|
|
24
|
+
row: 0,
|
|
25
|
+
column: -90,
|
|
26
|
+
'row-reverse': -180,
|
|
27
|
+
'column-reverse': -270,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const RotatedIcon = ( { icon: Icon, size, isClockwise = true, offset = 0 }: Props ) => {
|
|
31
|
+
const rotate = useRef( useGetTargetAngle( isClockwise, offset ) );
|
|
32
|
+
rotate.current = useGetTargetAngle( isClockwise, offset, rotate );
|
|
33
|
+
|
|
34
|
+
return <Icon fontSize={ size } sx={ { transition: '.3s', rotate: `${ rotate.current }deg` } } />;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const useGetTargetAngle = ( isClockwise: boolean, offset: number, existingRef?: React.MutableRefObject< number > ) => {
|
|
38
|
+
const [ direction ] = useStylesField< StringPropValue >( 'flex-direction' );
|
|
39
|
+
const isRtl = 'rtl' === useTheme().direction;
|
|
40
|
+
const rotationMultiplier = isRtl ? -1 : 1;
|
|
41
|
+
const angleMap = isClockwise ? CLOCKWISE_ANGLES : COUNTER_CLOCKWISE_ANGLES;
|
|
42
|
+
|
|
43
|
+
const currentAngle = existingRef
|
|
44
|
+
? existingRef.current * rotationMultiplier // Multiply by rotationMultiplier to get the correct angle for RTL, as it will have returned multiplied by this
|
|
45
|
+
: angleMap[ ( direction?.value as FlexDirection ) || 'row' ] + offset;
|
|
46
|
+
const targetAngle = angleMap[ ( direction?.value as FlexDirection ) || 'row' ] + offset;
|
|
47
|
+
|
|
48
|
+
const diffToTargetAngle = ( targetAngle - currentAngle + 360 ) % 360; // Make sure the diff is between 0, 360;
|
|
49
|
+
const formattedDiff = ( ( diffToTargetAngle + 180 ) % 360 ) - 180; // Get the angle to rotate as a value between -180, 180
|
|
50
|
+
|
|
51
|
+
return ( currentAngle + formattedDiff ) * rotationMultiplier;
|
|
52
|
+
};
|
|
@@ -24,7 +24,7 @@ const options: ToggleButtonGroupItem< FlexWrap >[] = [
|
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
26
|
value: 'wrap-reverse',
|
|
27
|
-
label: __( '
|
|
27
|
+
label: __( 'Reversed wrap', 'elementor' ),
|
|
28
28
|
renderContent: ( { size } ) => <ArrowForwardIcon fontSize={ size } />,
|
|
29
29
|
showTooltip: true,
|
|
30
30
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { useCallback } from 'react';
|
|
3
|
-
import type { PropValue } from '@elementor/editor-props';
|
|
3
|
+
import type { PropValue, StringPropValue } from '@elementor/editor-props';
|
|
4
4
|
import { Stack } from '@elementor/ui';
|
|
5
5
|
|
|
6
6
|
import { useStylePropsHistory } from '../../../hooks/use-style-prop-history';
|
|
@@ -12,10 +12,10 @@ import { ZIndexField } from './z-index-field';
|
|
|
12
12
|
const dimensionsPropKeys = [ 'top', 'bottom', 'left', 'right' ];
|
|
13
13
|
|
|
14
14
|
export const PositionSection = () => {
|
|
15
|
-
const [ positionValue ] = useStylesField( 'position' );
|
|
15
|
+
const [ positionValue ] = useStylesField< StringPropValue >( 'position' );
|
|
16
16
|
usePositionChangeHandler();
|
|
17
17
|
|
|
18
|
-
const isNotStatic = positionValue && positionValue !== 'static';
|
|
18
|
+
const isNotStatic = positionValue && positionValue?.value !== 'static';
|
|
19
19
|
|
|
20
20
|
return (
|
|
21
21
|
<Stack gap={ 1.5 }>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { ControlLabel, SizeControl } from '@elementor/editor-controls';
|
|
3
|
+
import { Grid } from '@elementor/ui';
|
|
4
|
+
import { __ } from '@wordpress/i18n';
|
|
5
|
+
|
|
6
|
+
import { StylesField } from '../../../controls-registry/styles-field';
|
|
7
|
+
|
|
8
|
+
export const LineHeightField = () => {
|
|
9
|
+
return (
|
|
10
|
+
<StylesField bind="line-height">
|
|
11
|
+
<Grid container gap={ 2 } alignItems="center" flexWrap="nowrap">
|
|
12
|
+
<Grid item xs={ 6 }>
|
|
13
|
+
<ControlLabel>{ __( 'Line Height', 'elementor' ) }</ControlLabel>
|
|
14
|
+
</Grid>
|
|
15
|
+
<Grid item xs={ 6 }>
|
|
16
|
+
<SizeControl />
|
|
17
|
+
</Grid>
|
|
18
|
+
</Grid>
|
|
19
|
+
</StylesField>
|
|
20
|
+
);
|
|
21
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { ControlLabel } from '@elementor/editor-controls';
|
|
3
|
+
import { type StringPropValue } from '@elementor/editor-props';
|
|
3
4
|
import { ItalicIcon, StrikethroughIcon, UnderlineIcon } from '@elementor/icons';
|
|
4
5
|
import { Grid, ToggleButton as ToggleButtonBase, ToggleButtonGroup, type ToggleButtonProps } from '@elementor/ui';
|
|
5
6
|
import { __ } from '@wordpress/i18n';
|
|
@@ -9,10 +10,32 @@ import { useStylesField } from '../../../hooks/use-styles-field';
|
|
|
9
10
|
const buttonSize = 'tiny';
|
|
10
11
|
|
|
11
12
|
export const TextStyleField = () => {
|
|
12
|
-
const [ fontStyle, setFontStyle ] = useStylesField<
|
|
13
|
-
const [ textDecoration, setTextDecoration ] = useStylesField<
|
|
13
|
+
const [ fontStyle, setFontStyle ] = useStylesField< StringPropValue | null >( 'font-style' );
|
|
14
|
+
const [ textDecoration, setTextDecoration ] = useStylesField< StringPropValue | null >( 'text-decoration' );
|
|
14
15
|
|
|
15
|
-
const formats = [ fontStyle, ...( textDecoration || '' ).split( ' ' ) ];
|
|
16
|
+
const formats = [ fontStyle?.value, ...( textDecoration?.value || '' ).split( ' ' ) ];
|
|
17
|
+
|
|
18
|
+
const handleSetFontStyle = ( newValue: string | null ) => {
|
|
19
|
+
if ( newValue === null ) {
|
|
20
|
+
return setFontStyle( null );
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
setFontStyle( {
|
|
24
|
+
$$type: 'string',
|
|
25
|
+
value: newValue,
|
|
26
|
+
} );
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const handleSetTextDecoration = ( newValue: string | null ) => {
|
|
30
|
+
if ( newValue === null ) {
|
|
31
|
+
return setTextDecoration( null );
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
setTextDecoration( {
|
|
35
|
+
$$type: 'string',
|
|
36
|
+
value: newValue,
|
|
37
|
+
} );
|
|
38
|
+
};
|
|
16
39
|
|
|
17
40
|
return (
|
|
18
41
|
<Grid container gap={ 2 } alignItems="center" flexWrap="nowrap">
|
|
@@ -23,7 +46,7 @@ export const TextStyleField = () => {
|
|
|
23
46
|
<ToggleButtonGroup value={ formats }>
|
|
24
47
|
<ToggleButton
|
|
25
48
|
value="italic"
|
|
26
|
-
onChange={ ( v ) =>
|
|
49
|
+
onChange={ ( v ) => handleSetFontStyle( fontStyle?.value === v ? null : v ) }
|
|
27
50
|
aria-label="italic"
|
|
28
51
|
sx={ { marginLeft: 'auto' } }
|
|
29
52
|
>
|
|
@@ -31,16 +54,16 @@ export const TextStyleField = () => {
|
|
|
31
54
|
</ToggleButton>
|
|
32
55
|
<ShorthandControl
|
|
33
56
|
value="line-through"
|
|
34
|
-
currentValues={ textDecoration || '' }
|
|
35
|
-
updateValues={
|
|
57
|
+
currentValues={ textDecoration?.value || '' }
|
|
58
|
+
updateValues={ handleSetTextDecoration }
|
|
36
59
|
aria-label="line-through"
|
|
37
60
|
>
|
|
38
61
|
<StrikethroughIcon fontSize={ buttonSize } />
|
|
39
62
|
</ShorthandControl>
|
|
40
63
|
<ShorthandControl
|
|
41
64
|
value="underline"
|
|
42
|
-
currentValues={ textDecoration || '' }
|
|
43
|
-
updateValues={
|
|
65
|
+
currentValues={ textDecoration?.value || '' }
|
|
66
|
+
updateValues={ handleSetTextDecoration }
|
|
44
67
|
aria-label="underline"
|
|
45
68
|
>
|
|
46
69
|
<UnderlineIcon fontSize={ buttonSize } />
|
|
@@ -6,6 +6,7 @@ import { FontFamilyField } from './font-family-field';
|
|
|
6
6
|
import { FontSizeField } from './font-size-field';
|
|
7
7
|
import { FontWeightField } from './font-weight-field';
|
|
8
8
|
import { LetterSpacingField } from './letter-spacing-field';
|
|
9
|
+
import { LineHeightField } from './line-height-field';
|
|
9
10
|
import { TextAlignmentField } from './text-alignment-field';
|
|
10
11
|
import { TextColorField } from './text-color-field';
|
|
11
12
|
import { TextDirectionField } from './text-direction-field';
|
|
@@ -21,13 +22,14 @@ export const TypographySection = () => {
|
|
|
21
22
|
<FontWeightField />
|
|
22
23
|
<FontSizeField />
|
|
23
24
|
<Divider />
|
|
25
|
+
<TextAlignmentField />
|
|
24
26
|
<TextColorField />
|
|
25
27
|
<CollapsibleContent>
|
|
26
28
|
<Stack gap={ 1.5 } sx={ { pt: 1.5 } }>
|
|
29
|
+
<LineHeightField />
|
|
27
30
|
<LetterSpacingField />
|
|
28
31
|
<WordSpacingField />
|
|
29
32
|
<Divider />
|
|
30
|
-
<TextAlignmentField />
|
|
31
33
|
<TextStyleField />
|
|
32
34
|
<TransformField />
|
|
33
35
|
<TextDirectionField />
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type ControlComponent,
|
|
3
3
|
ImageControl,
|
|
4
|
+
LinkControl,
|
|
4
5
|
SelectControl,
|
|
5
6
|
SizeControl,
|
|
6
7
|
TextAreaControl,
|
|
7
8
|
TextControl,
|
|
9
|
+
UrlControl,
|
|
8
10
|
} from '@elementor/editor-controls';
|
|
9
11
|
|
|
10
12
|
export type ControlLayout = 'full' | 'two-columns';
|
|
@@ -17,6 +19,8 @@ const controlTypes = {
|
|
|
17
19
|
textarea: { component: TextAreaControl, layout: 'full' },
|
|
18
20
|
size: { component: SizeControl, layout: 'two-columns' },
|
|
19
21
|
select: { component: SelectControl, layout: 'two-columns' },
|
|
22
|
+
link: { component: LinkControl, layout: 'full' },
|
|
23
|
+
url: { component: UrlControl, layout: 'full' },
|
|
20
24
|
} as const satisfies ControlRegistry;
|
|
21
25
|
|
|
22
26
|
export type ControlType = keyof typeof controlTypes;
|
|
@@ -27,15 +27,17 @@ import { type ControlType, getControlByType } from '../../controls-registry/cont
|
|
|
27
27
|
import { usePropValueHistory } from '../../hooks/use-prop-value-history';
|
|
28
28
|
import { DynamicControl } from '../dynamic-control';
|
|
29
29
|
import { useDynamicTag } from '../hooks/use-dynamic-tag';
|
|
30
|
-
import { type
|
|
30
|
+
import { type DynamicTag } from '../types';
|
|
31
|
+
import { dynamicPropTypeUtil } from '../utils';
|
|
31
32
|
import { DynamicSelection } from './dynamic-selection';
|
|
32
33
|
|
|
33
34
|
const SIZE = 'tiny';
|
|
34
35
|
|
|
35
36
|
export const DynamicSelectionControl = () => {
|
|
36
|
-
const {
|
|
37
|
+
const { setValue: setAnyValue } = useBoundProp();
|
|
38
|
+
const { bind, value } = useBoundProp( dynamicPropTypeUtil );
|
|
37
39
|
const { getPropValue: getPropValueFromHistory } = usePropValueHistory();
|
|
38
|
-
const { name: tagName = '' } = value
|
|
40
|
+
const { name: tagName = '' } = value;
|
|
39
41
|
|
|
40
42
|
const selectionPopoverId = useId();
|
|
41
43
|
const selectionPopoverState = usePopupState( { variant: 'popover', popupId: selectionPopoverId } );
|
|
@@ -43,8 +45,9 @@ export const DynamicSelectionControl = () => {
|
|
|
43
45
|
const dynamicTag = useDynamicTag( bind, tagName );
|
|
44
46
|
|
|
45
47
|
const removeDynamicTag = () => {
|
|
46
|
-
const propValue = getPropValueFromHistory
|
|
47
|
-
|
|
48
|
+
const propValue = getPropValueFromHistory( bind );
|
|
49
|
+
|
|
50
|
+
setAnyValue( propValue ?? null );
|
|
48
51
|
};
|
|
49
52
|
|
|
50
53
|
if ( ! dynamicTag ) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { Fragment, useState } from 'react';
|
|
3
3
|
import { useBoundProp } from '@elementor/editor-controls';
|
|
4
|
-
import { type PropKey
|
|
4
|
+
import { type PropKey } from '@elementor/editor-props';
|
|
5
5
|
import { PhotoIcon, SearchIcon } from '@elementor/icons';
|
|
6
6
|
import {
|
|
7
7
|
Box,
|
|
@@ -20,8 +20,7 @@ import { __ } from '@wordpress/i18n';
|
|
|
20
20
|
import { usePropValueHistory } from '../../hooks/use-prop-value-history';
|
|
21
21
|
import { usePropDynamicTags } from '../hooks/use-prop-dynamic-tags';
|
|
22
22
|
import { getAtomicDynamicTags } from '../sync/get-atomic-dynamic-tags';
|
|
23
|
-
import {
|
|
24
|
-
import { isDynamicPropValue } from '../utils';
|
|
23
|
+
import { dynamicPropTypeUtil } from '../utils';
|
|
25
24
|
|
|
26
25
|
type Option = {
|
|
27
26
|
label: string;
|
|
@@ -39,10 +38,13 @@ export type DynamicSelectionProps = {
|
|
|
39
38
|
export const DynamicSelection = ( { onSelect }: DynamicSelectionProps ) => {
|
|
40
39
|
const [ searchValue, setSearchValue ] = useState( '' );
|
|
41
40
|
const { groups: dynamicGroups } = getAtomicDynamicTags() || {};
|
|
42
|
-
|
|
41
|
+
|
|
42
|
+
const { value: anyValue } = useBoundProp();
|
|
43
|
+
const { bind, value: dynamicvalue, setValue } = useBoundProp( dynamicPropTypeUtil );
|
|
44
|
+
|
|
43
45
|
const { setPropValue: updatePropValueHistory } = usePropValueHistory();
|
|
44
46
|
|
|
45
|
-
const isCurrentValueDynamic =
|
|
47
|
+
const isCurrentValueDynamic = !! dynamicvalue;
|
|
46
48
|
|
|
47
49
|
const options = useFilteredOptions( bind, searchValue );
|
|
48
50
|
|
|
@@ -52,10 +54,10 @@ export const DynamicSelection = ( { onSelect }: DynamicSelectionProps ) => {
|
|
|
52
54
|
|
|
53
55
|
const handleSetDynamicTag = ( value: string ) => {
|
|
54
56
|
if ( ! isCurrentValueDynamic ) {
|
|
55
|
-
updatePropValueHistory( bind,
|
|
57
|
+
updatePropValueHistory( bind, anyValue );
|
|
56
58
|
}
|
|
57
59
|
|
|
58
|
-
setValue( {
|
|
60
|
+
setValue( { name: value, settings: {} } );
|
|
59
61
|
|
|
60
62
|
onSelect?.();
|
|
61
63
|
};
|
|
@@ -88,7 +90,7 @@ export const DynamicSelection = ( { onSelect }: DynamicSelectionProps ) => {
|
|
|
88
90
|
{ dynamicGroups?.[ category ]?.title || category }
|
|
89
91
|
</ListSubheader>
|
|
90
92
|
{ items.map( ( { value, label: tagLabel } ) => {
|
|
91
|
-
const isSelected = isCurrentValueDynamic && value ===
|
|
93
|
+
const isSelected = isCurrentValueDynamic && value === dynamicvalue?.name;
|
|
92
94
|
|
|
93
95
|
return (
|
|
94
96
|
<MenuItem
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { BoundPropProvider, useBoundProp } from '@elementor/editor-controls';
|
|
3
|
-
import { type PropKey, type PropValue } from '@elementor/editor-props';
|
|
3
|
+
import { isTransformable, type PropKey, type PropValue } from '@elementor/editor-props';
|
|
4
4
|
|
|
5
5
|
import { useDynamicTag } from './hooks/use-dynamic-tag';
|
|
6
|
-
import {
|
|
6
|
+
import { dynamicPropTypeUtil } from './utils';
|
|
7
7
|
|
|
8
8
|
export type DynamicControlProps = React.PropsWithChildren< {
|
|
9
9
|
bind: PropKey;
|
|
10
10
|
} >;
|
|
11
11
|
|
|
12
12
|
export const DynamicControl = ( { bind, children }: DynamicControlProps ) => {
|
|
13
|
-
const { value, setValue, bind: propName } = useBoundProp
|
|
14
|
-
const { name = '', settings } = value
|
|
13
|
+
const { value, setValue, bind: propName } = useBoundProp( dynamicPropTypeUtil );
|
|
14
|
+
const { name = '', settings } = value ?? {};
|
|
15
15
|
|
|
16
16
|
const dynamicTag = useDynamicTag( propName, name );
|
|
17
17
|
|
|
@@ -24,13 +24,11 @@ export const DynamicControl = ( { bind, children }: DynamicControlProps ) => {
|
|
|
24
24
|
|
|
25
25
|
const setDynamicValue = ( newValue: PropValue ) => {
|
|
26
26
|
setValue( {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
[ bind ]: newValue,
|
|
33
|
-
},
|
|
27
|
+
name,
|
|
28
|
+
settings: {
|
|
29
|
+
...settings,
|
|
30
|
+
// The value inside the dynamic is not a transformable value, so we need to store the whole object.
|
|
31
|
+
[ bind ]: isTransformable( newValue ) ? newValue.value : newValue,
|
|
34
32
|
},
|
|
35
33
|
} );
|
|
36
34
|
};
|
package/src/dynamics/utils.ts
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
createPropUtils,
|
|
3
|
+
isTransformable,
|
|
4
|
+
type PropType,
|
|
5
|
+
type PropValue,
|
|
6
|
+
type TransformablePropType,
|
|
7
|
+
} from '@elementor/editor-props';
|
|
8
|
+
import { z } from '@elementor/schema';
|
|
2
9
|
|
|
3
|
-
import { type DynamicPropType
|
|
10
|
+
import { type DynamicPropType } from './types';
|
|
4
11
|
|
|
5
|
-
const DYNAMIC_PROP_TYPE_KEY = 'dynamic';
|
|
12
|
+
export const DYNAMIC_PROP_TYPE_KEY = 'dynamic';
|
|
6
13
|
|
|
7
14
|
export const isDynamicPropType = ( prop: TransformablePropType ): prop is DynamicPropType =>
|
|
8
15
|
prop.key === DYNAMIC_PROP_TYPE_KEY;
|
|
@@ -20,3 +27,13 @@ export const isDynamicPropValue = ( prop: PropValue ): prop is DynamicPropValue
|
|
|
20
27
|
export const supportsDynamic = ( propType: PropType ): boolean => {
|
|
21
28
|
return !! getDynamicPropType( propType );
|
|
22
29
|
};
|
|
30
|
+
|
|
31
|
+
export const dynamicPropTypeUtil = createPropUtils(
|
|
32
|
+
DYNAMIC_PROP_TYPE_KEY,
|
|
33
|
+
z.strictObject( {
|
|
34
|
+
name: z.string(),
|
|
35
|
+
settings: z.record( z.any() ).optional(),
|
|
36
|
+
} )
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
export type DynamicPropValue = z.infer< typeof dynamicPropTypeUtil.schema >;
|