@elementor/editor-editing-panel 0.19.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.
- package/CHANGELOG.md +97 -0
- package/dist/index.d.mts +10 -36
- package/dist/index.d.ts +10 -36
- package/dist/index.js +1256 -1445
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1311 -1482
- package/dist/index.mjs.map +1 -1
- package/package.json +15 -14
- package/src/components/add-or-remove-content.tsx +42 -0
- package/src/components/collapse-icon.tsx +12 -0
- package/src/components/collapsible-content.tsx +5 -14
- package/src/components/collapsible-field.tsx +36 -0
- package/src/components/css-class-selector-section.tsx +76 -0
- package/src/components/editing-panel-hooks.tsx +2 -0
- package/src/components/editing-panel-tabs.tsx +23 -13
- package/src/components/editing-panel.tsx +21 -21
- package/src/components/multi-combobox/index.ts +3 -0
- package/src/components/multi-combobox/multi-combobox.tsx +120 -0
- package/src/components/multi-combobox/types.ts +26 -0
- package/src/components/multi-combobox/use-combobox-actions.ts +62 -0
- package/src/components/section.tsx +37 -0
- package/src/components/sections-list.tsx +6 -0
- package/src/components/settings-tab.tsx +17 -16
- package/src/components/style-sections/background-section/background-color-field.tsx +21 -0
- package/src/components/style-sections/background-section/background-section.tsx +10 -8
- package/src/components/style-sections/border-section/border-color-field.tsx +21 -0
- package/src/components/style-sections/border-section/border-field.tsx +48 -0
- package/src/components/style-sections/border-section/border-radius-field.tsx +49 -0
- package/src/components/style-sections/border-section/border-section.tsx +13 -0
- package/src/components/style-sections/border-section/border-style-field.tsx +32 -0
- package/src/components/style-sections/border-section/border-width-field.tsx +43 -0
- package/src/components/style-sections/effects-section/effects-section.tsx +8 -11
- package/src/components/style-sections/layout-section/display-field.tsx +32 -0
- package/src/components/style-sections/layout-section/justify-content-field.tsx +82 -0
- package/src/components/style-sections/layout-section/layout-section.tsx +17 -0
- package/src/components/style-sections/layout-section/utils/rotate-flex-icon.ts +12 -0
- package/src/components/style-sections/position-section/dimensions-field.tsx +46 -0
- package/src/components/style-sections/position-section/position-field.tsx +28 -0
- package/src/components/style-sections/position-section/position-section.tsx +51 -8
- package/src/components/style-sections/position-section/z-index-field.tsx +21 -0
- package/src/components/style-sections/size-section/overflow-field.tsx +45 -0
- package/src/components/style-sections/size-section/size-section.tsx +62 -0
- package/src/components/style-sections/spacing-section/spacing-section.tsx +12 -14
- package/src/components/style-sections/typography-section/font-family-field.tsx +40 -0
- package/src/components/style-sections/typography-section/font-size-field.tsx +21 -0
- package/src/components/style-sections/typography-section/{font-weight-control.tsx → font-weight-field.tsx} +9 -8
- package/src/components/style-sections/typography-section/letter-spacing-field.tsx +21 -0
- package/src/components/style-sections/typography-section/text-alignment-field.tsx +47 -0
- package/src/components/style-sections/typography-section/text-color-field.tsx +21 -0
- package/src/components/style-sections/typography-section/{text-direction-control.tsx → text-direction-field.tsx} +12 -12
- package/src/components/style-sections/typography-section/text-stroke-field.tsx +16 -0
- package/src/components/style-sections/typography-section/{text-style-control.tsx → text-style-field.tsx} +9 -8
- package/src/components/style-sections/typography-section/transform-field.tsx +40 -0
- package/src/components/style-sections/typography-section/typography-section.tsx +31 -30
- package/src/components/style-sections/typography-section/word-spacing-field.tsx +21 -0
- package/src/components/style-tab.tsx +82 -29
- package/src/contexts/classes-prop-context.tsx +24 -0
- package/src/{controls/providers/element-provider.tsx → contexts/element-context.tsx} +3 -7
- package/src/contexts/style-context.tsx +10 -23
- package/src/control-replacement.tsx +1 -1
- package/src/{controls/control-actions/control-actions-menu.ts → controls-actions.ts} +2 -1
- package/src/{controls/components → controls-registry}/control-type-container.tsx +3 -2
- package/src/{controls → controls-registry}/control.tsx +2 -1
- package/src/{controls → controls-registry}/controls-registry.tsx +8 -6
- package/src/controls-registry/settings-field.tsx +36 -0
- package/src/controls-registry/styles-field.tsx +20 -0
- package/src/dynamics/components/dynamic-selection-control.tsx +18 -17
- package/src/dynamics/components/dynamic-selection.tsx +10 -9
- package/src/dynamics/dynamic-control.tsx +7 -6
- package/src/dynamics/hooks/use-dynamic-tag.ts +3 -2
- package/src/dynamics/hooks/use-prop-dynamic-action.tsx +7 -6
- package/src/dynamics/hooks/use-prop-dynamic-tags.ts +3 -2
- package/src/dynamics/init.ts +3 -3
- package/src/dynamics/sync/get-elementor-config.ts +1 -1
- package/src/dynamics/types.ts +2 -2
- package/src/dynamics/utils.ts +3 -3
- package/src/hooks/use-close-editor-panel.ts +23 -0
- package/src/hooks/use-direction.ts +13 -0
- package/src/hooks/use-open-editor-panel.ts +4 -3
- package/src/hooks/use-prop-value-history.ts +45 -0
- package/src/hooks/use-style-prop-history.ts +75 -0
- package/src/hooks/use-styles-field.ts +51 -0
- package/src/index.ts +2 -3
- package/src/init.ts +5 -4
- package/src/panel.ts +1 -0
- package/src/{controls/control-actions/actions/popover-action.tsx → popover-action.tsx} +2 -2
- package/src/sync/enqueue-font.ts +7 -0
- package/src/sync/get-elementor-config.ts +7 -0
- package/src/sync/{should-use-v2-panel.ts → is-atomic-widget-selected.ts} +2 -3
- package/src/sync/types.ts +20 -21
- package/src/components/accordion-section.tsx +0 -25
- package/src/components/control-label.tsx +0 -10
- package/src/components/style-sections/background-section/background-color-control.tsx +0 -20
- package/src/components/style-sections/effects-section/box-shadow-repeater.tsx +0 -224
- package/src/components/style-sections/position-section/z-index-control.tsx +0 -20
- package/src/components/style-sections/size-section.tsx +0 -49
- package/src/components/style-sections/spacing-section/linked-dimensions-control.tsx +0 -155
- package/src/components/style-sections/typography-section/font-size-control.tsx +0 -20
- package/src/components/style-sections/typography-section/letter-spacing-control.tsx +0 -20
- package/src/components/style-sections/typography-section/text-alignment-control.tsx +0 -47
- package/src/components/style-sections/typography-section/text-color-control.tsx +0 -20
- package/src/components/style-sections/typography-section/transform-control.tsx +0 -25
- package/src/components/style-sections/typography-section/word-spacing-control.tsx +0 -20
- package/src/controls/components/control-toggle-button-group.tsx +0 -59
- package/src/controls/components/repeater.tsx +0 -197
- package/src/controls/components/text-field-inner-selection.tsx +0 -79
- package/src/controls/control-actions/control-actions.tsx +0 -43
- package/src/controls/control-context.tsx +0 -22
- package/src/controls/control-replacement.ts +0 -34
- package/src/controls/control-types/color-control.tsx +0 -27
- package/src/controls/control-types/image-control.tsx +0 -66
- package/src/controls/control-types/image-media-control.tsx +0 -73
- package/src/controls/control-types/number-control.tsx +0 -29
- package/src/controls/control-types/select-control.tsx +0 -30
- package/src/controls/control-types/size-control.tsx +0 -71
- package/src/controls/control-types/text-area-control.tsx +0 -31
- package/src/controls/control-types/text-control.tsx +0 -17
- package/src/controls/control-types/toggle-control.tsx +0 -26
- package/src/controls/create-control-replacement.tsx +0 -53
- package/src/controls/create-control.tsx +0 -40
- package/src/controls/hooks/use-style-control.ts +0 -29
- package/src/controls/hooks/use-sync-external-state.tsx +0 -51
- package/src/controls/hooks/use-widget-settings.ts +0 -16
- package/src/controls/props/is-transformable.ts +0 -13
- package/src/controls/props/types.ts +0 -51
- package/src/controls/settings-control.tsx +0 -37
- package/src/controls/style-control.tsx +0 -20
- package/src/controls/sync/get-container.ts +0 -8
- package/src/controls/sync/update-settings.ts +0 -14
- package/src/controls/types.ts +0 -39
- package/src/dynamics/hooks/use-prop-value-history.ts +0 -26
- package/src/hooks/use-element-style-prop.ts +0 -46
- package/src/hooks/use-element-styles.ts +0 -13
- package/src/hooks/use-element-type.ts +0 -33
- package/src/hooks/use-selected-elements.ts +0 -9
- package/src/sync/get-element-styles.ts +0 -9
- package/src/sync/get-selected-elements.ts +0 -21
- package/src/sync/get-widgets-cache.ts +0 -7
- package/src/sync/update-style.ts +0 -25
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { createContext, useContext } from 'react';
|
|
2
|
-
import { PropKey, PropValue } from './props/types';
|
|
3
|
-
|
|
4
|
-
export type ControlContext< T extends PropValue > = {
|
|
5
|
-
bind: PropKey;
|
|
6
|
-
setValue: ( value: T | undefined ) => void;
|
|
7
|
-
value: T | undefined;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export const ControlContext = createContext< ControlContext< PropValue > | null >( null );
|
|
11
|
-
|
|
12
|
-
export function useControl< T extends PropValue >(): ControlContext< T | undefined >;
|
|
13
|
-
export function useControl< T extends PropValue >( defaultValue: T ): ControlContext< T >;
|
|
14
|
-
export function useControl< T extends PropValue >( defaultValue?: T ) {
|
|
15
|
-
const controlContext = useContext< ControlContext< T > >( ControlContext as never );
|
|
16
|
-
|
|
17
|
-
if ( ! controlContext ) {
|
|
18
|
-
throw new Error( 'useControl must be used within a ControlContext' );
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return { ...controlContext, value: controlContext.value ?? defaultValue };
|
|
22
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { ComponentType } from 'react';
|
|
2
|
-
import { PropValue } from './props/types';
|
|
3
|
-
import { useControl } from './control-context';
|
|
4
|
-
|
|
5
|
-
type ReplaceWhenParams = {
|
|
6
|
-
value: PropValue;
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
type ControlReplacement = {
|
|
10
|
-
component: ComponentType;
|
|
11
|
-
condition: ( { value }: ReplaceWhenParams ) => boolean;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
let controlReplacement: ControlReplacement | undefined;
|
|
15
|
-
|
|
16
|
-
const getControlReplacement = ( { value }: ReplaceWhenParams ) => {
|
|
17
|
-
let shouldReplace = false;
|
|
18
|
-
|
|
19
|
-
try {
|
|
20
|
-
shouldReplace = !! controlReplacement?.condition( { value } ) && !! controlReplacement?.component;
|
|
21
|
-
} catch {}
|
|
22
|
-
|
|
23
|
-
return shouldReplace ? controlReplacement?.component : undefined;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export function replaceControl( { component, condition }: ControlReplacement ) {
|
|
27
|
-
controlReplacement = { component, condition };
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function useControlReplacement() {
|
|
31
|
-
const { value } = useControl();
|
|
32
|
-
|
|
33
|
-
return getControlReplacement( { value } );
|
|
34
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { UnstableColorPicker, UnstableColorPickerProps } from '@elementor/ui';
|
|
3
|
-
import { useControl } from '../control-context';
|
|
4
|
-
import ControlActions from '../control-actions/control-actions';
|
|
5
|
-
import { createControl } from '../create-control';
|
|
6
|
-
import { TransformablePropValue } from '../props/types';
|
|
7
|
-
|
|
8
|
-
export type ColorPropValue = TransformablePropValue< 'color', string >;
|
|
9
|
-
|
|
10
|
-
export const ColorControl = createControl(
|
|
11
|
-
( props: Partial< Omit< UnstableColorPickerProps, 'value' | 'onChange' > > ) => {
|
|
12
|
-
const { value, setValue } = useControl< ColorPropValue >();
|
|
13
|
-
|
|
14
|
-
const handleChange = ( selectedColor: string ) => {
|
|
15
|
-
setValue( {
|
|
16
|
-
$$type: 'color',
|
|
17
|
-
value: selectedColor,
|
|
18
|
-
} );
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
return (
|
|
22
|
-
<ControlActions>
|
|
23
|
-
<UnstableColorPicker size="tiny" { ...props } value={ value?.value } onChange={ handleChange } />
|
|
24
|
-
</ControlActions>
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
);
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { Grid, Stack } from '@elementor/ui';
|
|
3
|
-
import { __ } from '@wordpress/i18n';
|
|
4
|
-
import { ControlContext, useControl } from '../control-context';
|
|
5
|
-
import { type ImageSrc, ImageMediaControl } from './image-media-control';
|
|
6
|
-
import { PropValue, TransformablePropValue } from '../props/types';
|
|
7
|
-
import { SettingsControl } from '../settings-control';
|
|
8
|
-
import { SelectControl } from './select-control';
|
|
9
|
-
import { createControl } from '../create-control';
|
|
10
|
-
|
|
11
|
-
type Image = TransformablePropValue<
|
|
12
|
-
'image',
|
|
13
|
-
{
|
|
14
|
-
src?: ImageSrc;
|
|
15
|
-
size?: string;
|
|
16
|
-
}
|
|
17
|
-
>;
|
|
18
|
-
|
|
19
|
-
type SetContextValue = ( v: PropValue ) => void;
|
|
20
|
-
|
|
21
|
-
export type ImageControlProps = {
|
|
22
|
-
sizes: { label: string; value: string }[];
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export const ImageControl = createControl( ( props: ImageControlProps ) => {
|
|
26
|
-
const { value, setValue } = useControl< Image >();
|
|
27
|
-
const { src, size } = value?.value || {};
|
|
28
|
-
|
|
29
|
-
const setImageSrc = ( newValue: ImageSrc ) => {
|
|
30
|
-
setValue( {
|
|
31
|
-
$$type: 'image',
|
|
32
|
-
value: {
|
|
33
|
-
src: newValue,
|
|
34
|
-
size,
|
|
35
|
-
},
|
|
36
|
-
} );
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
const setImageSize = ( newValue: string ) => {
|
|
40
|
-
setValue( {
|
|
41
|
-
$$type: 'image',
|
|
42
|
-
value: {
|
|
43
|
-
src,
|
|
44
|
-
size: newValue,
|
|
45
|
-
},
|
|
46
|
-
} );
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
return (
|
|
50
|
-
<Stack gap={ 2 }>
|
|
51
|
-
<ControlContext.Provider value={ { setValue: setImageSrc as SetContextValue, value: src, bind: 'src' } }>
|
|
52
|
-
<ImageMediaControl />
|
|
53
|
-
</ControlContext.Provider>
|
|
54
|
-
<ControlContext.Provider value={ { setValue: setImageSize as SetContextValue, value: size, bind: 'size' } }>
|
|
55
|
-
<Grid container spacing={ 1 } alignItems="center">
|
|
56
|
-
<Grid item xs={ 6 }>
|
|
57
|
-
<SettingsControl.Label> { __( 'Image Resolution', 'elementor' ) }</SettingsControl.Label>
|
|
58
|
-
</Grid>
|
|
59
|
-
<Grid item xs={ 6 }>
|
|
60
|
-
<SelectControl options={ props.sizes } />
|
|
61
|
-
</Grid>
|
|
62
|
-
</Grid>
|
|
63
|
-
</ControlContext.Provider>
|
|
64
|
-
</Stack>
|
|
65
|
-
);
|
|
66
|
-
} );
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { Button, Card, CardMedia, CardOverlay, Stack } from '@elementor/ui';
|
|
3
|
-
import { UploadIcon } from '@elementor/icons';
|
|
4
|
-
import { useWpMediaAttachment, useWpMediaFrame } from '@elementor/wp-media';
|
|
5
|
-
import { __ } from '@wordpress/i18n';
|
|
6
|
-
import { useControl } from '../control-context';
|
|
7
|
-
import ControlActions from '../control-actions/control-actions';
|
|
8
|
-
import { createControl } from '../create-control';
|
|
9
|
-
import { TransformablePropValue } from '../props/types';
|
|
10
|
-
|
|
11
|
-
type ImageAttachmentID = TransformablePropValue< 'image-attachment-id', number >;
|
|
12
|
-
|
|
13
|
-
type Url = TransformablePropValue< 'url', string >;
|
|
14
|
-
|
|
15
|
-
export type ImageSrc = TransformablePropValue<
|
|
16
|
-
'image-src',
|
|
17
|
-
{ id: ImageAttachmentID; url: null } | { url: Url; id: null }
|
|
18
|
-
>;
|
|
19
|
-
|
|
20
|
-
export const ImageMediaControl = createControl( () => {
|
|
21
|
-
const { value, setValue } = useControl< ImageSrc >();
|
|
22
|
-
const { id, url } = value?.value ?? {};
|
|
23
|
-
|
|
24
|
-
const { data: attachment } = useWpMediaAttachment( id?.value || null );
|
|
25
|
-
const src = attachment?.url ?? url;
|
|
26
|
-
|
|
27
|
-
const { open } = useWpMediaFrame( {
|
|
28
|
-
types: [ 'image' ],
|
|
29
|
-
multiple: false,
|
|
30
|
-
selected: id?.value || null,
|
|
31
|
-
onSelect: ( selectedAttachment ) => {
|
|
32
|
-
setValue( {
|
|
33
|
-
$$type: 'image-src',
|
|
34
|
-
value: {
|
|
35
|
-
id: {
|
|
36
|
-
$$type: 'image-attachment-id',
|
|
37
|
-
value: selectedAttachment.id,
|
|
38
|
-
},
|
|
39
|
-
url: null,
|
|
40
|
-
},
|
|
41
|
-
} );
|
|
42
|
-
},
|
|
43
|
-
} );
|
|
44
|
-
|
|
45
|
-
return (
|
|
46
|
-
<Card variant="outlined">
|
|
47
|
-
<CardMedia image={ src } sx={ { height: 150 } } />
|
|
48
|
-
<CardOverlay>
|
|
49
|
-
<ControlActions>
|
|
50
|
-
<Stack gap={ 0.5 }>
|
|
51
|
-
<Button
|
|
52
|
-
size="tiny"
|
|
53
|
-
color="inherit"
|
|
54
|
-
variant="outlined"
|
|
55
|
-
onClick={ () => open( { mode: 'browse' } ) }
|
|
56
|
-
>
|
|
57
|
-
{ __( 'Select Image', 'elementor' ) }
|
|
58
|
-
</Button>
|
|
59
|
-
<Button
|
|
60
|
-
size="tiny"
|
|
61
|
-
variant="text"
|
|
62
|
-
color="inherit"
|
|
63
|
-
startIcon={ <UploadIcon /> }
|
|
64
|
-
onClick={ () => open( { mode: 'upload' } ) }
|
|
65
|
-
>
|
|
66
|
-
{ __( 'Upload Image', 'elementor' ) }
|
|
67
|
-
</Button>
|
|
68
|
-
</Stack>
|
|
69
|
-
</ControlActions>
|
|
70
|
-
</CardOverlay>
|
|
71
|
-
</Card>
|
|
72
|
-
);
|
|
73
|
-
} );
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { TextField } from '@elementor/ui';
|
|
3
|
-
import { useControl } from '../control-context';
|
|
4
|
-
import ControlActions from '../control-actions/control-actions';
|
|
5
|
-
import { createControl } from '../create-control';
|
|
6
|
-
|
|
7
|
-
const isEmptyOrNaN = ( value?: string | number ) =>
|
|
8
|
-
value === undefined || value === '' || Number.isNaN( Number( value ) );
|
|
9
|
-
|
|
10
|
-
export const NumberControl = createControl( ( { placeholder }: { placeholder?: string } ) => {
|
|
11
|
-
const { value, setValue } = useControl< number | undefined >();
|
|
12
|
-
|
|
13
|
-
const handleChange = ( event: React.ChangeEvent< HTMLInputElement > ) => {
|
|
14
|
-
const eventValue: string = event.target.value;
|
|
15
|
-
setValue( isEmptyOrNaN( eventValue ) ? undefined : Number( eventValue ) );
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
return (
|
|
19
|
-
<ControlActions>
|
|
20
|
-
<TextField
|
|
21
|
-
size="tiny"
|
|
22
|
-
type="number"
|
|
23
|
-
value={ isEmptyOrNaN( value ) ? '' : value }
|
|
24
|
-
onChange={ handleChange }
|
|
25
|
-
placeholder={ placeholder }
|
|
26
|
-
/>
|
|
27
|
-
</ControlActions>
|
|
28
|
-
);
|
|
29
|
-
} );
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { MenuItem, Select, SelectChangeEvent } from '@elementor/ui';
|
|
3
|
-
import { useControl } from '../control-context';
|
|
4
|
-
import { PropValue } from '../props/types';
|
|
5
|
-
import ControlActions from '../control-actions/control-actions';
|
|
6
|
-
import { createControl } from '../create-control';
|
|
7
|
-
|
|
8
|
-
type Props< T > = {
|
|
9
|
-
options: Array< { label: string; value: T; disabled?: boolean } >;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export const SelectControl = createControl( < T extends PropValue >( { options }: Props< T > ) => {
|
|
13
|
-
const { value, setValue } = useControl< T >();
|
|
14
|
-
|
|
15
|
-
const handleChange = ( event: SelectChangeEvent< T > ) => {
|
|
16
|
-
setValue( event.target.value as T );
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
return (
|
|
20
|
-
<ControlActions>
|
|
21
|
-
<Select size="tiny" value={ value ?? '' } onChange={ handleChange }>
|
|
22
|
-
{ options.map( ( { label, ...props } ) => (
|
|
23
|
-
<MenuItem key={ props.value } { ...props }>
|
|
24
|
-
{ label }
|
|
25
|
-
</MenuItem>
|
|
26
|
-
) ) }
|
|
27
|
-
</Select>
|
|
28
|
-
</ControlActions>
|
|
29
|
-
);
|
|
30
|
-
} );
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { InputAdornment } from '@elementor/ui';
|
|
3
|
-
import { TransformablePropValue } from '../props/types';
|
|
4
|
-
import { useControl } from '../control-context';
|
|
5
|
-
import { useSyncExternalState } from '../hooks/use-sync-external-state';
|
|
6
|
-
import { SelectionEndAdornment, TextFieldInnerSelection } from '../components/text-field-inner-selection';
|
|
7
|
-
import ControlActions from '../control-actions/control-actions';
|
|
8
|
-
import { createControl } from '../create-control';
|
|
9
|
-
|
|
10
|
-
export type Unit = 'px' | '%' | 'em' | 'rem' | 'vw';
|
|
11
|
-
|
|
12
|
-
const defaultUnits: Unit[] = [ 'px', '%', 'em', 'rem', 'vw' ];
|
|
13
|
-
|
|
14
|
-
export type SizeControlValue = TransformablePropValue< 'size', { unit: Unit; size: number } >;
|
|
15
|
-
|
|
16
|
-
export type SizeControlProps = {
|
|
17
|
-
placeholder?: string;
|
|
18
|
-
startIcon?: React.ReactNode;
|
|
19
|
-
units?: Unit[];
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export const SizeControl = createControl( ( { units = defaultUnits, placeholder, startIcon }: SizeControlProps ) => {
|
|
23
|
-
const { value, setValue } = useControl< SizeControlValue >();
|
|
24
|
-
|
|
25
|
-
const [ state, setState ] = useSyncExternalState< SizeControlValue >( {
|
|
26
|
-
external: value,
|
|
27
|
-
setExternal: setValue,
|
|
28
|
-
persistWhen: ( controlValue ) => !! controlValue?.value.size || controlValue?.value.size === 0,
|
|
29
|
-
fallback: ( controlValue ) => ( {
|
|
30
|
-
$$type: 'size',
|
|
31
|
-
value: { unit: controlValue?.value.unit || 'px', size: NaN },
|
|
32
|
-
} ),
|
|
33
|
-
} );
|
|
34
|
-
|
|
35
|
-
const handleUnitChange = ( unit: Unit ) => {
|
|
36
|
-
setState( ( prev ) => ( {
|
|
37
|
-
...prev,
|
|
38
|
-
value: {
|
|
39
|
-
...prev.value,
|
|
40
|
-
unit,
|
|
41
|
-
},
|
|
42
|
-
} ) );
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const handleSizeChange = ( event: React.ChangeEvent< HTMLInputElement > ) => {
|
|
46
|
-
const { value: size } = event.target;
|
|
47
|
-
|
|
48
|
-
setState( ( prev ) => ( {
|
|
49
|
-
...prev,
|
|
50
|
-
value: {
|
|
51
|
-
...prev.value,
|
|
52
|
-
size: size || size === '0' ? parseFloat( size ) : NaN,
|
|
53
|
-
},
|
|
54
|
-
} ) );
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
return (
|
|
58
|
-
<ControlActions>
|
|
59
|
-
<TextFieldInnerSelection
|
|
60
|
-
endAdornment={
|
|
61
|
-
<SelectionEndAdornment options={ units } onClick={ handleUnitChange } value={ state.value.unit } />
|
|
62
|
-
}
|
|
63
|
-
placeholder={ placeholder }
|
|
64
|
-
startAdornment={ startIcon ?? <InputAdornment position="start">{ startIcon }</InputAdornment> }
|
|
65
|
-
type="number"
|
|
66
|
-
value={ Number.isNaN( state.value.size ) ? '' : state.value.size }
|
|
67
|
-
onChange={ handleSizeChange }
|
|
68
|
-
/>
|
|
69
|
-
</ControlActions>
|
|
70
|
-
);
|
|
71
|
-
} );
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { TextField } from '@elementor/ui';
|
|
3
|
-
import { useControl } from '../control-context';
|
|
4
|
-
import ControlActions from '../control-actions/control-actions';
|
|
5
|
-
import { createControl } from '../create-control';
|
|
6
|
-
|
|
7
|
-
type Props = {
|
|
8
|
-
placeholder?: string;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export const TextAreaControl = createControl( ( { placeholder }: Props ) => {
|
|
12
|
-
const { value, setValue } = useControl< string >();
|
|
13
|
-
|
|
14
|
-
const handleChange = ( event: React.ChangeEvent< HTMLInputElement > ) => {
|
|
15
|
-
setValue( event.target.value );
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
return (
|
|
19
|
-
<ControlActions fullWidth>
|
|
20
|
-
<TextField
|
|
21
|
-
size="tiny"
|
|
22
|
-
multiline
|
|
23
|
-
fullWidth
|
|
24
|
-
rows={ 5 }
|
|
25
|
-
value={ value }
|
|
26
|
-
onChange={ handleChange }
|
|
27
|
-
placeholder={ placeholder }
|
|
28
|
-
/>
|
|
29
|
-
</ControlActions>
|
|
30
|
-
);
|
|
31
|
-
} );
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { TextField } from '@elementor/ui';
|
|
3
|
-
import { useControl } from '../control-context';
|
|
4
|
-
import ControlActions from '../control-actions/control-actions';
|
|
5
|
-
import { createControl } from '../create-control';
|
|
6
|
-
|
|
7
|
-
export const TextControl = createControl( ( { placeholder }: { placeholder?: string } ) => {
|
|
8
|
-
const { value, setValue } = useControl< string >( '' );
|
|
9
|
-
|
|
10
|
-
const handleChange = ( event: React.ChangeEvent< HTMLInputElement > ) => setValue( event.target.value );
|
|
11
|
-
|
|
12
|
-
return (
|
|
13
|
-
<ControlActions fullWidth>
|
|
14
|
-
<TextField type="text" size="tiny" value={ value } onChange={ handleChange } placeholder={ placeholder } />
|
|
15
|
-
</ControlActions>
|
|
16
|
-
);
|
|
17
|
-
} );
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { useControl } from '../control-context';
|
|
3
|
-
import { ControlToggleButtonGroup, ToggleButtonGroupItem } from '../components/control-toggle-button-group';
|
|
4
|
-
import { PropValue } from '../props/types';
|
|
5
|
-
import { createControl } from '../create-control';
|
|
6
|
-
|
|
7
|
-
type ToggleControlProps< T extends PropValue > = {
|
|
8
|
-
options: ToggleButtonGroupItem< T >[];
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export const ToggleControl = createControl( < T extends PropValue >( { options }: ToggleControlProps< T > ) => {
|
|
12
|
-
const { value, setValue } = useControl< T >();
|
|
13
|
-
|
|
14
|
-
const handleToggle = ( option: T | null ) => {
|
|
15
|
-
setValue( option || undefined );
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
return (
|
|
19
|
-
<ControlToggleButtonGroup
|
|
20
|
-
items={ options }
|
|
21
|
-
value={ value || null }
|
|
22
|
-
onChange={ handleToggle }
|
|
23
|
-
exclusive={ true }
|
|
24
|
-
/>
|
|
25
|
-
);
|
|
26
|
-
} );
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { PropValue } from './props/types';
|
|
3
|
-
import { ComponentType, createContext, useContext } from 'react';
|
|
4
|
-
import { useControl } from './control-context';
|
|
5
|
-
|
|
6
|
-
export type ReplaceWhenParams = {
|
|
7
|
-
value: PropValue;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export type CreateControlReplacement = {
|
|
11
|
-
component: ComponentType;
|
|
12
|
-
condition: ( { value }: ReplaceWhenParams ) => boolean;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
const ControlReplacementContext = createContext< CreateControlReplacement | undefined >( undefined );
|
|
16
|
-
|
|
17
|
-
export const ControlReplacementProvider = ( {
|
|
18
|
-
component,
|
|
19
|
-
condition,
|
|
20
|
-
children,
|
|
21
|
-
}: React.PropsWithChildren< CreateControlReplacement > ) => {
|
|
22
|
-
return (
|
|
23
|
-
<ControlReplacementContext.Provider value={ { component, condition } }>
|
|
24
|
-
{ children }
|
|
25
|
-
</ControlReplacementContext.Provider>
|
|
26
|
-
);
|
|
27
|
-
};
|
|
28
|
-
export const useControlReplacement = () => {
|
|
29
|
-
const { value } = useControl();
|
|
30
|
-
const controlReplacement = useContext( ControlReplacementContext );
|
|
31
|
-
|
|
32
|
-
let shouldReplace = false;
|
|
33
|
-
|
|
34
|
-
try {
|
|
35
|
-
shouldReplace = !! controlReplacement?.condition( { value } ) && !! controlReplacement.component;
|
|
36
|
-
} catch {}
|
|
37
|
-
|
|
38
|
-
return shouldReplace ? controlReplacement?.component : undefined;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export const createControlReplacement = () => {
|
|
42
|
-
let controlReplacement: CreateControlReplacement;
|
|
43
|
-
|
|
44
|
-
function replaceControl( { component, condition }: CreateControlReplacement ) {
|
|
45
|
-
controlReplacement = { component, condition };
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function getControlReplacement() {
|
|
49
|
-
return controlReplacement;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return { replaceControl, getControlReplacement };
|
|
53
|
-
};
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { ComponentProps, ComponentType } from 'react';
|
|
3
|
-
import { useControlReplacement } from './create-control-replacement';
|
|
4
|
-
import { ErrorBoundary } from '@elementor/ui';
|
|
5
|
-
|
|
6
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7
|
-
type AnyComponentType = ComponentType< any >;
|
|
8
|
-
|
|
9
|
-
type Options = {
|
|
10
|
-
supportsReplacements?: boolean;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
const brandSymbol = Symbol( 'control' );
|
|
14
|
-
|
|
15
|
-
export type ControlComponent< TComponent extends AnyComponentType = AnyComponentType > = TComponent & {
|
|
16
|
-
[ brandSymbol ]: true;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export function createControl< T extends AnyComponentType >(
|
|
20
|
-
Component: T,
|
|
21
|
-
{ supportsReplacements = true }: Options = {}
|
|
22
|
-
) {
|
|
23
|
-
return ( ( props: ComponentProps< T > ) => {
|
|
24
|
-
const ControlReplacement = useControlReplacement();
|
|
25
|
-
|
|
26
|
-
if ( ControlReplacement && supportsReplacements ) {
|
|
27
|
-
return (
|
|
28
|
-
<ErrorBoundary fallback={ null }>
|
|
29
|
-
<ControlReplacement { ...props } />
|
|
30
|
-
</ErrorBoundary>
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return (
|
|
35
|
-
<ErrorBoundary fallback={ null }>
|
|
36
|
-
<Component { ...props } />
|
|
37
|
-
</ErrorBoundary>
|
|
38
|
-
);
|
|
39
|
-
} ) as ControlComponent< T >;
|
|
40
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { useElement } from '../providers/element-provider';
|
|
2
|
-
import { useStyleContext } from '../../contexts/style-context';
|
|
3
|
-
import { useElementStyleProp } from '../../hooks/use-element-style-prop';
|
|
4
|
-
import { updateStyle } from '../../sync/update-style';
|
|
5
|
-
import { PropKey, PropValue } from '../props/types';
|
|
6
|
-
|
|
7
|
-
export const useStyleControl = < T extends PropValue >( propName: PropKey ) => {
|
|
8
|
-
const { element } = useElement();
|
|
9
|
-
const { selectedStyleDef, selectedMeta, selectedClassesProp } = useStyleContext();
|
|
10
|
-
|
|
11
|
-
const value = useElementStyleProp< T >( {
|
|
12
|
-
elementID: element.id,
|
|
13
|
-
styleDefID: selectedStyleDef?.id,
|
|
14
|
-
meta: selectedMeta,
|
|
15
|
-
propName,
|
|
16
|
-
} );
|
|
17
|
-
|
|
18
|
-
const setValue = ( newValue: T ) => {
|
|
19
|
-
updateStyle( {
|
|
20
|
-
elementID: element.id,
|
|
21
|
-
styleDefID: selectedStyleDef?.id,
|
|
22
|
-
props: { [ propName ]: newValue },
|
|
23
|
-
meta: selectedMeta,
|
|
24
|
-
bind: selectedClassesProp,
|
|
25
|
-
} );
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
return [ value, setValue ] as const;
|
|
29
|
-
};
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState } from 'react';
|
|
2
|
-
|
|
3
|
-
type UseInternalStateOptions< TValue > = {
|
|
4
|
-
external: TValue | undefined;
|
|
5
|
-
setExternal: ( value: TValue | undefined ) => void;
|
|
6
|
-
persistWhen: ( value: TValue | undefined ) => boolean;
|
|
7
|
-
fallback: ( value: TValue | undefined ) => TValue;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export const useSyncExternalState = < TValue, >( {
|
|
11
|
-
external,
|
|
12
|
-
setExternal,
|
|
13
|
-
persistWhen,
|
|
14
|
-
fallback,
|
|
15
|
-
}: UseInternalStateOptions< TValue > ) => {
|
|
16
|
-
function toExternal( internalValue: TValue | undefined ) {
|
|
17
|
-
if ( persistWhen( internalValue ) ) {
|
|
18
|
-
return internalValue;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return undefined;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function toInternal( externalValue: TValue | undefined, internalValue: TValue | undefined ) {
|
|
25
|
-
if ( ! externalValue ) {
|
|
26
|
-
return fallback( internalValue );
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return externalValue;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const [ internal, setInternal ] = useState< TValue >( toInternal( external, undefined ) );
|
|
33
|
-
|
|
34
|
-
useEffect( () => {
|
|
35
|
-
setInternal( ( prevInternal ) => toInternal( external, prevInternal ) );
|
|
36
|
-
|
|
37
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
38
|
-
}, [ external ] );
|
|
39
|
-
|
|
40
|
-
type SetterFunc = ( value: TValue ) => TValue;
|
|
41
|
-
|
|
42
|
-
const setInternalValue = ( setter: SetterFunc | TValue ) => {
|
|
43
|
-
const setterFn = ( typeof setter === 'function' ? setter : () => setter ) as SetterFunc;
|
|
44
|
-
const updated = setterFn( internal );
|
|
45
|
-
|
|
46
|
-
setInternal( updated );
|
|
47
|
-
setExternal( toExternal( updated ) );
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
return [ internal, setInternalValue ] as const;
|
|
51
|
-
};
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { commandEndEvent, __privateUseListenTo as useListenTo } from '@elementor/editor-v1-adapters';
|
|
2
|
-
import getContainer from '../sync/get-container';
|
|
3
|
-
import { PropValue } from '../props/types';
|
|
4
|
-
|
|
5
|
-
export const useWidgetSettings = ( { id, bind }: { id: string; bind: string } ): PropValue => {
|
|
6
|
-
return useListenTo(
|
|
7
|
-
commandEndEvent( 'document/elements/settings' ),
|
|
8
|
-
() => {
|
|
9
|
-
const container = getContainer( id );
|
|
10
|
-
const value = container?.settings?.get( bind ) ?? null;
|
|
11
|
-
|
|
12
|
-
return value;
|
|
13
|
-
},
|
|
14
|
-
[ id, bind ]
|
|
15
|
-
);
|
|
16
|
-
};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { z } from '@elementor/schema';
|
|
2
|
-
|
|
3
|
-
// TODO: Move this file content a shared package.
|
|
4
|
-
const transformableSchema = z.object( {
|
|
5
|
-
$$type: z.string(),
|
|
6
|
-
value: z.any(),
|
|
7
|
-
} );
|
|
8
|
-
|
|
9
|
-
export type TransformablePropValue = z.infer< typeof transformableSchema >;
|
|
10
|
-
|
|
11
|
-
export const isTransformable = ( value: unknown ): value is TransformablePropValue => {
|
|
12
|
-
return transformableSchema.safeParse( value ).success;
|
|
13
|
-
};
|