@elementor/editor-editing-panel 0.17.0 → 0.19.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 +45 -0
- package/dist/index.d.mts +28 -10
- package/dist/index.d.ts +28 -10
- package/dist/index.js +941 -398
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +918 -366
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -7
- package/src/components/editing-panel-error-fallback.tsx +12 -0
- package/src/components/editing-panel.tsx +23 -12
- package/src/components/settings-tab.tsx +8 -5
- package/src/components/style-sections/background-section/background-color-control.tsx +20 -0
- package/src/components/style-sections/background-section/background-section.tsx +15 -0
- package/src/components/style-sections/effects-section/box-shadow-repeater.tsx +224 -0
- package/src/components/style-sections/effects-section/effects-section.tsx +18 -0
- package/src/components/style-sections/position-section/z-index-control.tsx +11 -7
- package/src/components/style-sections/size-section.tsx +23 -20
- package/src/components/style-sections/spacing-section/linked-dimensions-control.tsx +62 -47
- package/src/components/style-sections/typography-section/font-size-control.tsx +10 -6
- package/src/components/style-sections/typography-section/font-weight-control.tsx +16 -12
- package/src/components/style-sections/typography-section/letter-spacing-control.tsx +10 -6
- package/src/components/style-sections/typography-section/text-alignment-control.tsx +12 -8
- package/src/components/style-sections/typography-section/text-color-control.tsx +10 -6
- package/src/components/style-sections/typography-section/text-direction-control.tsx +37 -0
- package/src/components/style-sections/typography-section/text-style-control.tsx +37 -34
- package/src/components/style-sections/typography-section/transform-control.tsx +14 -12
- package/src/components/style-sections/typography-section/typography-section.tsx +2 -0
- package/src/components/style-sections/typography-section/word-spacing-control.tsx +10 -6
- package/src/components/style-tab.tsx +10 -4
- package/src/control-replacement.tsx +3 -0
- package/src/controls/components/control-type-container.tsx +28 -0
- package/src/controls/components/repeater.tsx +197 -0
- package/src/controls/components/text-field-inner-selection.tsx +2 -2
- package/src/controls/control-actions/actions/popover-action.tsx +58 -0
- package/src/controls/control-actions/control-actions-menu.ts +8 -0
- package/src/controls/control-actions/control-actions.tsx +43 -0
- package/src/controls/control-context.tsx +1 -1
- package/src/controls/control-replacement.ts +16 -8
- package/src/controls/control-types/color-control.tsx +21 -18
- package/src/controls/control-types/image-control.tsx +56 -59
- package/src/controls/control-types/image-media-control.tsx +73 -0
- package/src/controls/control-types/number-control.tsx +13 -9
- package/src/controls/control-types/select-control.tsx +14 -10
- package/src/controls/control-types/size-control.tsx +18 -14
- package/src/controls/control-types/text-area-control.tsx +15 -11
- package/src/controls/control-types/text-control.tsx +9 -3
- package/src/controls/control-types/toggle-control.tsx +4 -3
- package/src/controls/control.tsx +1 -7
- package/src/controls/controls-registry.tsx +19 -10
- package/src/controls/create-control-replacement.tsx +53 -0
- package/src/controls/create-control.tsx +40 -0
- package/src/controls/hooks/use-style-control.ts +3 -3
- package/src/{hooks → controls/hooks}/use-widget-settings.ts +1 -1
- package/src/{props → controls/props}/is-transformable.ts +1 -2
- package/src/controls/props/types.ts +51 -0
- package/src/{contexts/element-context.tsx → controls/providers/element-provider.tsx} +4 -4
- package/src/controls/settings-control.tsx +7 -14
- package/src/controls/style-control.tsx +1 -1
- package/src/{sync → controls/sync}/get-container.ts +1 -1
- package/src/{sync → controls/sync}/update-settings.ts +1 -1
- package/src/controls/types.ts +39 -0
- package/src/dynamics/components/dynamic-selection-control.tsx +2 -2
- package/src/dynamics/components/dynamic-selection.tsx +6 -6
- package/src/dynamics/dynamic-control.tsx +2 -2
- package/src/dynamics/hooks/use-dynamic-tag.ts +2 -2
- package/src/dynamics/hooks/use-prop-dynamic-action.tsx +23 -0
- package/src/dynamics/hooks/use-prop-dynamic-tags.ts +7 -7
- package/src/dynamics/hooks/use-prop-value-history.ts +3 -3
- package/src/dynamics/init.ts +10 -1
- package/src/dynamics/types.ts +7 -3
- package/src/dynamics/utils.ts +17 -4
- package/src/hooks/use-element-style-prop.ts +3 -2
- package/src/hooks/use-element-styles.ts +1 -1
- package/src/hooks/use-element-type.ts +1 -1
- package/src/index.ts +3 -1
- package/src/sync/get-element-styles.ts +2 -2
- package/src/sync/get-selected-elements.ts +1 -1
- package/src/sync/types.ts +2 -1
- package/src/sync/update-style.ts +3 -2
- package/src/controls/components/control-container.tsx +0 -18
- package/src/types.ts +0 -68
|
@@ -3,17 +3,26 @@ import { TextControl } from './control-types/text-control';
|
|
|
3
3
|
import { TextAreaControl } from './control-types/text-area-control';
|
|
4
4
|
import { SizeControl } from './control-types/size-control';
|
|
5
5
|
import { SelectControl } from './control-types/select-control';
|
|
6
|
+
import { ControlComponent } from './create-control';
|
|
6
7
|
|
|
7
|
-
export
|
|
8
|
-
image: ImageControl,
|
|
9
|
-
text: TextControl,
|
|
10
|
-
textarea: TextAreaControl,
|
|
11
|
-
size: SizeControl,
|
|
12
|
-
select: SelectControl,
|
|
13
|
-
} as const;
|
|
8
|
+
export type ControlLayout = 'full' | 'two-columns';
|
|
14
9
|
|
|
15
|
-
|
|
10
|
+
type ControlRegistry = Record< string, { component: ControlComponent; layout: ControlLayout } >;
|
|
16
11
|
|
|
17
|
-
|
|
12
|
+
const controlTypes = {
|
|
13
|
+
image: { component: ImageControl, layout: 'full' },
|
|
14
|
+
text: { component: TextControl, layout: 'two-columns' },
|
|
15
|
+
textarea: { component: TextAreaControl, layout: 'full' },
|
|
16
|
+
size: { component: SizeControl, layout: 'two-columns' },
|
|
17
|
+
select: { component: SelectControl, layout: 'two-columns' },
|
|
18
|
+
} as const satisfies ControlRegistry;
|
|
18
19
|
|
|
19
|
-
export
|
|
20
|
+
export type ControlType = keyof typeof controlTypes;
|
|
21
|
+
|
|
22
|
+
export type ControlTypes = {
|
|
23
|
+
[ key in ControlType ]: ( typeof controlTypes )[ key ][ 'component' ];
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const getControlByType = ( type: ControlType ) => controlTypes[ type ]?.component;
|
|
27
|
+
|
|
28
|
+
export const getLayoutByType = ( type: ControlType ) => controlTypes[ type ].layout;
|
|
@@ -0,0 +1,53 @@
|
|
|
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
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
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,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useElement } from '../providers/element-provider';
|
|
2
2
|
import { useStyleContext } from '../../contexts/style-context';
|
|
3
3
|
import { useElementStyleProp } from '../../hooks/use-element-style-prop';
|
|
4
4
|
import { updateStyle } from '../../sync/update-style';
|
|
5
|
-
import { PropKey, PropValue } from '
|
|
5
|
+
import { PropKey, PropValue } from '../props/types';
|
|
6
6
|
|
|
7
7
|
export const useStyleControl = < T extends PropValue >( propName: PropKey ) => {
|
|
8
|
-
const { element } =
|
|
8
|
+
const { element } = useElement();
|
|
9
9
|
const { selectedStyleDef, selectedMeta, selectedClassesProp } = useStyleContext();
|
|
10
10
|
|
|
11
11
|
const value = useElementStyleProp< T >( {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { commandEndEvent, __privateUseListenTo as useListenTo } from '@elementor/editor-v1-adapters';
|
|
2
|
-
import { PropValue } from '../types';
|
|
3
2
|
import getContainer from '../sync/get-container';
|
|
3
|
+
import { PropValue } from '../props/types';
|
|
4
4
|
|
|
5
5
|
export const useWidgetSettings = ( { id, bind }: { id: string; bind: string } ): PropValue => {
|
|
6
6
|
return useListenTo(
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
type PropTypeKey = string;
|
|
2
|
+
|
|
3
|
+
type BasePropType = {
|
|
4
|
+
default: PropValue;
|
|
5
|
+
settings: Record< string, unknown >;
|
|
6
|
+
meta: Record< string, unknown >;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export type PlainPropType = BasePropType & {
|
|
10
|
+
kind: 'plain';
|
|
11
|
+
key: PropTypeKey;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type ArrayPropType = BasePropType & {
|
|
15
|
+
kind: 'array';
|
|
16
|
+
key: PropTypeKey;
|
|
17
|
+
item_prop_type: PropType | null;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type ObjectPropType = BasePropType & {
|
|
21
|
+
kind: 'object';
|
|
22
|
+
key: PropTypeKey;
|
|
23
|
+
shape: Record< string, PropType >;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export type TransformablePropType = PlainPropType | ArrayPropType | ObjectPropType;
|
|
27
|
+
|
|
28
|
+
export type UnionPropType = BasePropType & {
|
|
29
|
+
kind: 'union';
|
|
30
|
+
prop_types: Record< string, TransformablePropType >;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export type PropType = TransformablePropType | UnionPropType;
|
|
34
|
+
|
|
35
|
+
type MaybeArray< T > = T | T[];
|
|
36
|
+
|
|
37
|
+
export type TransformablePropValue< Type extends string, Value = unknown > = {
|
|
38
|
+
$$type: Type;
|
|
39
|
+
value: Value;
|
|
40
|
+
disabled?: boolean;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export type PlainPropValue = MaybeArray< string | number | boolean | object | null | undefined >;
|
|
44
|
+
|
|
45
|
+
export type PropValue = PlainPropValue | TransformablePropValue< string >;
|
|
46
|
+
|
|
47
|
+
export type PropKey = string;
|
|
48
|
+
|
|
49
|
+
export type Props = Record< PropKey, PropValue >;
|
|
50
|
+
|
|
51
|
+
export type PlainProps = Record< PropKey, PlainPropValue >;
|
|
@@ -11,19 +11,19 @@ const Context = createContext< ContextValue | null >( null );
|
|
|
11
11
|
|
|
12
12
|
type Props = {
|
|
13
13
|
element: Element;
|
|
14
|
-
elementType: ElementType;
|
|
15
14
|
children?: ReactNode;
|
|
15
|
+
elementType: ElementType;
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
export function
|
|
18
|
+
export function ElementProvider( { children, element, elementType }: Props ) {
|
|
19
19
|
return <Context.Provider value={ { element, elementType } }>{ children }</Context.Provider>;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
export function
|
|
22
|
+
export function useElement() {
|
|
23
23
|
const context = useContext( Context );
|
|
24
24
|
|
|
25
25
|
if ( ! context ) {
|
|
26
|
-
throw new Error( '
|
|
26
|
+
throw new Error( 'useElement must be used within a ElementProvider' );
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
return context;
|
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { ControlContext } from './control-context';
|
|
3
|
-
import { PropKey, PropValue } from '
|
|
4
|
-
import {
|
|
5
|
-
import { useWidgetSettings } from '
|
|
6
|
-
import { updateSettings } from '
|
|
3
|
+
import { PropKey, PropValue } from './props/types';
|
|
4
|
+
import { useElement } from './providers/element-provider';
|
|
5
|
+
import { useWidgetSettings } from './hooks/use-widget-settings';
|
|
6
|
+
import { updateSettings } from './sync/update-settings';
|
|
7
7
|
import { ControlLabel } from '../components/control-label';
|
|
8
|
-
import { ControlContainer } from './components/control-container';
|
|
9
8
|
|
|
10
9
|
type Props = {
|
|
11
10
|
bind: PropKey;
|
|
12
11
|
children: React.ReactNode;
|
|
13
12
|
};
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
const { element, elementType } =
|
|
14
|
+
const SettingsControl = ( { bind, children }: Props ) => {
|
|
15
|
+
const { element, elementType } = useElement();
|
|
17
16
|
|
|
18
|
-
const defaultValue = elementType.propsSchema[ bind ]?.
|
|
17
|
+
const defaultValue = elementType.propsSchema[ bind ]?.default;
|
|
19
18
|
const settingsValue = useWidgetSettings( { id: element.id, bind } );
|
|
20
19
|
const value = settingsValue ?? defaultValue ?? null;
|
|
21
20
|
|
|
@@ -31,12 +30,6 @@ export const SettingsControlProvider = ( { bind, children }: Props ) => {
|
|
|
31
30
|
return <ControlContext.Provider value={ { setValue, value, bind } }>{ children }</ControlContext.Provider>;
|
|
32
31
|
};
|
|
33
32
|
|
|
34
|
-
const SettingsControl = ( { children, bind }: Props ) => (
|
|
35
|
-
<SettingsControlProvider bind={ bind }>
|
|
36
|
-
<ControlContainer flexWrap="wrap">{ children }</ControlContainer>
|
|
37
|
-
</SettingsControlProvider>
|
|
38
|
-
);
|
|
39
|
-
|
|
40
33
|
// TODO: When we start using useControl inside the label component, we should create a new component for it,
|
|
41
34
|
// and keep ControlLabel as a simple label component without context.
|
|
42
35
|
SettingsControl.Label = ControlLabel;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { PropKey } from '
|
|
2
|
+
import { PropKey } from './props/types';
|
|
3
3
|
import { ControlContext } from '../controls/control-context';
|
|
4
4
|
import { ControlLabel } from '../components/control-label';
|
|
5
5
|
import { useStyleControl } from './hooks/use-style-control';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { __privateRunCommand as runCommand } from '@elementor/editor-v1-adapters';
|
|
2
|
-
import { Props } from '../types';
|
|
2
|
+
import { Props } from '../props/types';
|
|
3
3
|
import getContainer from './get-container';
|
|
4
4
|
|
|
5
5
|
export const updateSettings = ( { id, props }: { id: string; props: Props } ) => {
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { PropType } from './props/types';
|
|
2
|
+
|
|
3
|
+
export type ElementID = string;
|
|
4
|
+
|
|
5
|
+
export type Element = {
|
|
6
|
+
id: ElementID;
|
|
7
|
+
type: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export type ElementType = {
|
|
11
|
+
key: string;
|
|
12
|
+
controls: ControlItem[];
|
|
13
|
+
propsSchema: PropsSchema;
|
|
14
|
+
title: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type ControlsSection = {
|
|
18
|
+
type: 'section';
|
|
19
|
+
value: {
|
|
20
|
+
description?: string;
|
|
21
|
+
label: string;
|
|
22
|
+
items: ControlItem[];
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export type Control = {
|
|
27
|
+
type: 'control';
|
|
28
|
+
value: {
|
|
29
|
+
bind: string;
|
|
30
|
+
label?: string;
|
|
31
|
+
description?: string;
|
|
32
|
+
type: string;
|
|
33
|
+
props: Record< string, unknown >;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type ControlItem = ControlsSection | Control;
|
|
38
|
+
|
|
39
|
+
export type PropsSchema = Record< Control[ 'value' ][ 'bind' ], PropType >;
|
|
@@ -4,7 +4,7 @@ import { useControl } from '../../controls/control-context';
|
|
|
4
4
|
import { DynamicPropValue, DynamicTag } from '../types';
|
|
5
5
|
import { DynamicControl } from '../dynamic-control';
|
|
6
6
|
import { DatabaseIcon, SettingsIcon, XIcon } from '@elementor/icons';
|
|
7
|
-
import type { Control, ControlsSection } from '../../types';
|
|
7
|
+
import type { Control, ControlsSection } from '../../controls/types';
|
|
8
8
|
import { DynamicSelection } from './dynamic-selection';
|
|
9
9
|
import { ControlType, getControlByType } from '../../controls/controls-registry';
|
|
10
10
|
import { ControlLabel } from '../../components/control-label';
|
|
@@ -51,7 +51,7 @@ export const DynamicSelectionControl = () => {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
return (
|
|
54
|
-
<Box
|
|
54
|
+
<Box>
|
|
55
55
|
<Tag
|
|
56
56
|
fullWidth
|
|
57
57
|
showActionsOnHover
|
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { useState, Fragment } from 'react';
|
|
3
|
-
import { useControl } from '../../controls/control-context';
|
|
4
|
-
import { DynamicPropValue } from '../types';
|
|
5
|
-
import { usePropDynamicTags } from '../hooks/use-prop-dynamic-tags';
|
|
6
|
-
import { getAtomicDynamicTags } from '../sync/get-atomic-dynamic-tags';
|
|
7
3
|
import { SearchIcon, PhotoIcon } from '@elementor/icons';
|
|
8
4
|
import {
|
|
9
5
|
Box,
|
|
@@ -18,9 +14,13 @@ import {
|
|
|
18
14
|
Typography,
|
|
19
15
|
} from '@elementor/ui';
|
|
20
16
|
import { __ } from '@wordpress/i18n';
|
|
21
|
-
import {
|
|
17
|
+
import { useControl } from '../../controls/control-context';
|
|
18
|
+
import { usePropDynamicTags } from '../hooks/use-prop-dynamic-tags';
|
|
19
|
+
import { getAtomicDynamicTags } from '../sync/get-atomic-dynamic-tags';
|
|
22
20
|
import { isDynamicPropValue } from '../utils';
|
|
23
21
|
import { usePropValueHistory } from '../hooks/use-prop-value-history';
|
|
22
|
+
import { DynamicPropValue } from '../types';
|
|
23
|
+
import { PropKey, PropValue } from '../../controls/props/types';
|
|
24
24
|
|
|
25
25
|
type Option = {
|
|
26
26
|
label: string;
|
|
@@ -54,7 +54,7 @@ export const DynamicSelection = ( { onSelect }: DynamicSelectionProps ) => {
|
|
|
54
54
|
updatePropValueHistory( currentValue );
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
setValue( { $$type: 'dynamic', value: { name: value } } );
|
|
57
|
+
setValue( { $$type: 'dynamic', value: { name: value, settings: {} } } );
|
|
58
58
|
|
|
59
59
|
onSelect?.();
|
|
60
60
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { ControlContext, useControl } from '../controls/control-context';
|
|
3
|
-
import { PropKey, PropValue } from '../types';
|
|
3
|
+
import { PropKey, PropValue } from '../controls/props/types';
|
|
4
4
|
import { useDynamicTag } from './hooks/use-dynamic-tag';
|
|
5
5
|
import { DynamicPropValue } from './types';
|
|
6
6
|
|
|
@@ -18,7 +18,7 @@ export const DynamicControl = ( { bind, children }: DynamicControlProps ) => {
|
|
|
18
18
|
throw new Error( `Dynamic tag ${ name } not found` );
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
const defaultValue = dynamicTag.props_schema[ bind ]?.
|
|
21
|
+
const defaultValue = dynamicTag.props_schema[ bind ]?.default;
|
|
22
22
|
const dynamicValue = settings?.[ bind ] ?? defaultValue;
|
|
23
23
|
|
|
24
24
|
const setDynamicValue = ( newValue: PropValue ) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
1
2
|
import { usePropDynamicTags } from './use-prop-dynamic-tags';
|
|
3
|
+
import { PropKey } from '../../controls/props/types';
|
|
2
4
|
import { DynamicTag } from '../types';
|
|
3
|
-
import { PropKey } from '../../types';
|
|
4
|
-
import { useMemo } from 'react';
|
|
5
5
|
|
|
6
6
|
export const useDynamicTag = ( propName: PropKey, tagName: string ): DynamicTag | null => {
|
|
7
7
|
const dynamicTags = usePropDynamicTags( propName );
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useElement } from '../../controls/providers/element-provider';
|
|
3
|
+
import { supportsDynamic } from '../utils';
|
|
4
|
+
import { DynamicSelection } from '../components/dynamic-selection';
|
|
5
|
+
import { DatabaseIcon } from '@elementor/icons';
|
|
6
|
+
import { __ } from '@wordpress/i18n';
|
|
7
|
+
import { useControl } from '../../controls/control-context';
|
|
8
|
+
import { PopoverActionProps } from '../../controls/control-actions/actions/popover-action';
|
|
9
|
+
|
|
10
|
+
export const usePropDynamicAction = (): PopoverActionProps => {
|
|
11
|
+
const { bind } = useControl();
|
|
12
|
+
const { elementType } = useElement();
|
|
13
|
+
|
|
14
|
+
const propType = elementType.propsSchema[ bind ];
|
|
15
|
+
const visible = !! propType && supportsDynamic( propType );
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
visible,
|
|
19
|
+
icon: DatabaseIcon,
|
|
20
|
+
title: __( 'Dynamic Tags', 'elementor' ),
|
|
21
|
+
popoverContent: ( { closePopover } ) => <DynamicSelection onSelect={ closePopover } />,
|
|
22
|
+
};
|
|
23
|
+
};
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { useElement } from '../../controls/providers/element-provider';
|
|
3
3
|
import { getAtomicDynamicTags } from '../sync/get-atomic-dynamic-tags';
|
|
4
|
-
import { PropKey } from '../../types';
|
|
5
|
-
import {
|
|
4
|
+
import { PropKey } from '../../controls/props/types';
|
|
5
|
+
import { getDynamicPropType } from '../utils';
|
|
6
6
|
|
|
7
7
|
export const usePropDynamicTags = ( propName: PropKey ) => {
|
|
8
8
|
let categories: string[] = [];
|
|
9
9
|
|
|
10
|
-
const { elementType } =
|
|
10
|
+
const { elementType } = useElement();
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const propType = elementType.propsSchema?.[ propName ];
|
|
13
13
|
|
|
14
|
-
if (
|
|
15
|
-
const propDynamicType =
|
|
14
|
+
if ( propType ) {
|
|
15
|
+
const propDynamicType = getDynamicPropType( propType );
|
|
16
16
|
|
|
17
17
|
categories = propDynamicType?.settings.categories || [];
|
|
18
18
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { PropValue } from '../../controls/props/types';
|
|
2
|
+
import { useElement } from '../../controls/providers/element-provider';
|
|
3
3
|
|
|
4
4
|
export const PROPS_VALUES_HISTORY_KEY = 'elementor/dynamic/non-dynamic-values-history';
|
|
5
5
|
|
|
6
6
|
export const usePropValueHistory = ( path: string ) => {
|
|
7
7
|
const valuesHistory = getValues();
|
|
8
|
-
const { element } =
|
|
8
|
+
const { element } = useElement();
|
|
9
9
|
const key = `${ element.id }-${ path }`;
|
|
10
10
|
|
|
11
11
|
const value = valuesHistory[ key ] ?? null;
|
package/src/dynamics/init.ts
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import { DynamicSelectionControl } from './components/dynamic-selection-control';
|
|
2
|
-
import { replaceControl } from '../controls/control-replacement';
|
|
3
2
|
import { isDynamicPropValue } from './utils';
|
|
3
|
+
import { usePropDynamicAction } from './hooks/use-prop-dynamic-action';
|
|
4
|
+
import { controlActionsMenu } from '../controls/control-actions/control-actions-menu';
|
|
5
|
+
import { replaceControl } from '../control-replacement';
|
|
6
|
+
|
|
7
|
+
const { registerPopoverAction } = controlActionsMenu;
|
|
4
8
|
|
|
5
9
|
export const init = () => {
|
|
6
10
|
replaceControl( {
|
|
7
11
|
component: DynamicSelectionControl,
|
|
8
12
|
condition: ( { value } ) => isDynamicPropValue( value ),
|
|
9
13
|
} );
|
|
14
|
+
|
|
15
|
+
registerPopoverAction( {
|
|
16
|
+
id: 'dynamic-tags',
|
|
17
|
+
useProps: usePropDynamicAction,
|
|
18
|
+
} );
|
|
10
19
|
};
|
package/src/dynamics/types.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { ControlItem, PropsSchema
|
|
1
|
+
import { ControlItem, PropsSchema } from '../controls/types';
|
|
2
|
+
import { TransformablePropType, TransformablePropValue } from '../controls/props/types';
|
|
2
3
|
|
|
3
4
|
export type ExtendedWindow = Window & {
|
|
4
5
|
elementor?: {
|
|
@@ -22,11 +23,14 @@ export type DynamicTag = {
|
|
|
22
23
|
props_schema: PropsSchema;
|
|
23
24
|
};
|
|
24
25
|
|
|
25
|
-
export type DynamicPropType = {
|
|
26
|
+
export type DynamicPropType = TransformablePropType & {
|
|
26
27
|
key: 'dynamic';
|
|
27
28
|
settings: {
|
|
28
29
|
categories: string[];
|
|
29
30
|
};
|
|
30
31
|
};
|
|
31
32
|
|
|
32
|
-
export type DynamicPropValue = TransformablePropValue<
|
|
33
|
+
export type DynamicPropValue = TransformablePropValue<
|
|
34
|
+
'dynamic',
|
|
35
|
+
{ name: string; settings?: Record< string, unknown > }
|
|
36
|
+
>;
|
package/src/dynamics/utils.ts
CHANGED
|
@@ -1,9 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PropType, PropValue, TransformablePropType } from '../controls/props/types';
|
|
2
2
|
import { DynamicPropType, DynamicPropValue } from './types';
|
|
3
|
-
import { isTransformable } from '../props/is-transformable';
|
|
3
|
+
import { isTransformable } from '../controls/props/is-transformable';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
const DYNAMIC_PROP_TYPE_KEY = 'dynamic';
|
|
6
|
+
|
|
7
|
+
export const isDynamicPropType = ( prop: TransformablePropType ): prop is DynamicPropType =>
|
|
8
|
+
prop.key === DYNAMIC_PROP_TYPE_KEY;
|
|
9
|
+
|
|
10
|
+
export const getDynamicPropType = ( propType: PropType ): DynamicPropType | null => {
|
|
11
|
+
const dynamicPropType = propType.kind === 'union' && propType.prop_types[ DYNAMIC_PROP_TYPE_KEY ];
|
|
12
|
+
|
|
13
|
+
return dynamicPropType && isDynamicPropType( dynamicPropType ) ? dynamicPropType : null;
|
|
14
|
+
};
|
|
6
15
|
|
|
7
16
|
export const isDynamicPropValue = ( prop: PropValue ): prop is DynamicPropValue => {
|
|
8
|
-
return isTransformable( prop ) && prop.$$type ===
|
|
17
|
+
return isTransformable( prop ) && prop.$$type === DYNAMIC_PROP_TYPE_KEY;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const supportsDynamic = ( propType: PropType ): boolean => {
|
|
21
|
+
return !! getDynamicPropType( propType );
|
|
9
22
|
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { commandEndEvent, __privateUseListenTo as useListenTo } from '@elementor/editor-v1-adapters';
|
|
2
|
-
import { ElementID, PropKey, PropValue } from '../types';
|
|
3
|
-
import { getElementStyles } from '../sync/get-element-styles';
|
|
4
2
|
import { StyleDefinition, StyleDefinitionID, StyleVariant } from '@elementor/editor-style';
|
|
3
|
+
import { PropKey, PropValue } from '../controls/props/types';
|
|
4
|
+
import { ElementID } from '../controls/types';
|
|
5
|
+
import { getElementStyles } from '../sync/get-element-styles';
|
|
5
6
|
|
|
6
7
|
export type UseElementStylePropArgs = {
|
|
7
8
|
elementID: ElementID;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { __privateUseListenTo as useListenTo, commandEndEvent } from '@elementor/editor-v1-adapters';
|
|
2
2
|
import { getElementStyles } from '../sync/get-element-styles';
|
|
3
|
-
import { ElementID } from '../types';
|
|
3
|
+
import { ElementID } from '../controls/types';
|
|
4
4
|
|
|
5
5
|
export const useElementStyles = ( elementID: ElementID ) => {
|
|
6
6
|
return useListenTo(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { __privateUseListenTo as useListenTo, commandEndEvent } from '@elementor/editor-v1-adapters';
|
|
2
2
|
import getWidgetsCache from '../sync/get-widgets-cache';
|
|
3
|
-
import { ElementType } from '../types';
|
|
3
|
+
import { ElementType } from '../controls/types';
|
|
4
4
|
|
|
5
5
|
export default function useElementType( type?: string ) {
|
|
6
6
|
return useListenTo(
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export type { PopoverActionProps } from './controls/control-actions/actions/popover-action';
|
|
2
|
+
export { replaceControl } from './control-replacement';
|
|
2
3
|
export { useControl } from './controls/control-context';
|
|
4
|
+
export { controlActionsMenu } from './controls/control-actions/control-actions-menu';
|
|
3
5
|
|
|
4
6
|
import init from './init';
|
|
5
7
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import getContainer from './get-container';
|
|
2
|
-
import { ElementID } from '../types';
|
|
3
1
|
import { StyleDefinition } from '@elementor/editor-style';
|
|
2
|
+
import { ElementID } from '../controls/types';
|
|
3
|
+
import getContainer from '../controls/sync/get-container';
|
|
4
4
|
|
|
5
5
|
export const getElementStyles = ( elementID: ElementID ): Record< string, StyleDefinition > | null => {
|
|
6
6
|
const container = getContainer( elementID );
|
package/src/sync/types.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { ControlItem, PropsSchema, PropValue } from '../types';
|
|
2
1
|
import { StyleDefinition, StyleDefinitionID } from '@elementor/editor-style';
|
|
2
|
+
import { ControlItem, PropsSchema } from '../controls/types';
|
|
3
|
+
import { PropValue } from '../controls/props/types';
|
|
3
4
|
|
|
4
5
|
export type ExtendedWindow = Window & {
|
|
5
6
|
elementor?: {
|
package/src/sync/update-style.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { __privateRunCommand as runCommand } from '@elementor/editor-v1-adapters';
|
|
2
|
-
import { ElementID, PropKey, Props } from '../types';
|
|
3
|
-
import getContainer from './get-container';
|
|
4
2
|
import { StyleDefinitionID, StyleVariant } from '@elementor/editor-style';
|
|
3
|
+
import getContainer from '../controls/sync/get-container';
|
|
4
|
+
import { PropKey, Props } from '../controls/props/types';
|
|
5
|
+
import { ElementID } from '../controls/types';
|
|
5
6
|
|
|
6
7
|
export type UpdateStyleProps = {
|
|
7
8
|
elementID: ElementID;
|