@elementor/editor-controls 3.33.0-98 → 3.34.2
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/dist/index.d.mts +264 -74
- package/dist/index.d.ts +264 -74
- package/dist/index.js +2541 -1861
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2344 -1660
- package/dist/index.mjs.map +1 -1
- package/package.json +31 -17
- package/src/bound-prop-context/prop-context.tsx +8 -1
- package/src/bound-prop-context/use-bound-prop.ts +19 -5
- package/src/components/autocomplete.tsx +34 -3
- package/src/components/conditional-control-infotip.tsx +64 -0
- package/src/components/{unstable-repeater → control-repeater}/actions/disable-item-action.tsx +2 -2
- package/src/components/{unstable-repeater → control-repeater}/actions/duplicate-item-action.tsx +10 -4
- package/src/components/{unstable-repeater → control-repeater}/actions/remove-item-action.tsx +2 -2
- package/src/components/control-repeater/context/item-context.tsx +8 -0
- package/src/components/{unstable-repeater → control-repeater}/context/repeater-context.tsx +24 -15
- package/src/components/control-repeater/control-repeater.tsx +29 -0
- package/src/components/{unstable-repeater → control-repeater}/index.ts +1 -2
- package/src/components/{unstable-repeater → control-repeater}/items/edit-item-popover.tsx +6 -20
- package/src/components/control-repeater/items/item.tsx +75 -0
- package/src/components/{unstable-repeater → control-repeater}/items/items-container.tsx +8 -13
- package/src/components/{unstable-repeater → control-repeater}/locations.ts +0 -4
- package/src/components/{unstable-repeater → control-repeater}/types.ts +1 -2
- package/src/components/control-toggle-button-group.tsx +79 -69
- package/src/components/enable-unfiltered-modal.tsx +1 -26
- package/src/components/icon-buttons/clear-icon-button.tsx +23 -0
- package/src/components/inline-editor-toolbar.tsx +137 -0
- package/src/components/inline-editor.tsx +111 -0
- package/src/components/item-selector.tsx +10 -4
- package/src/components/{unstable-repeater/header/header.tsx → repeater/repeater-header.tsx} +4 -12
- package/src/components/repeater/repeater-popover.tsx +19 -0
- package/src/components/repeater/repeater-tag.tsx +16 -0
- package/src/components/repeater/repeater.tsx +405 -0
- package/src/components/{sortable.tsx → repeater/sortable.tsx} +1 -1
- package/src/components/size-control/size-input.tsx +20 -14
- package/src/components/size-control/text-field-inner-selection.tsx +15 -2
- package/src/control-adornments/control-adornments-context.tsx +5 -4
- package/src/control-replacements.tsx +3 -43
- package/src/controls/background-control/background-control.tsx +43 -12
- package/src/controls/background-control/background-gradient-color-control.tsx +5 -8
- package/src/controls/background-control/background-overlay/background-image-overlay/background-image-overlay-position.tsx +18 -13
- package/src/controls/background-control/background-overlay/background-overlay-repeater-control.tsx +25 -16
- package/src/controls/box-shadow-repeater-control.tsx +38 -21
- package/src/controls/color-control.tsx +3 -1
- package/src/controls/date-time-control.tsx +108 -0
- package/src/controls/filter-control/drop-shadow/drop-shadow-item-content.tsx +1 -0
- package/src/controls/filter-control/drop-shadow/drop-shadow-item-label.tsx +10 -6
- package/src/controls/filter-control/filter-content.tsx +1 -1
- package/src/controls/filter-control/filter-repeater-control.tsx +24 -21
- package/src/controls/filter-control/single-size/single-size-item-content.tsx +1 -1
- package/src/controls/filter-control/single-size/single-size-item-label.tsx +2 -1
- package/src/controls/font-family-control/font-family-control.tsx +66 -55
- package/src/controls/html-tag-control.tsx +90 -0
- package/src/controls/image-media-control.tsx +2 -2
- package/src/controls/inline-editing-control.tsx +18 -0
- package/src/controls/key-value-control.tsx +8 -2
- package/src/controls/link-control.tsx +23 -123
- package/src/controls/linked-dimensions-control.tsx +71 -33
- package/src/controls/query-control.tsx +168 -0
- package/src/controls/repeatable-control.tsx +62 -27
- package/src/controls/select-control-wrapper.tsx +57 -0
- package/src/controls/select-control.tsx +9 -5
- package/src/controls/selection-size-control.tsx +13 -2
- package/src/controls/size-control.tsx +32 -59
- package/src/controls/svg-media-control.tsx +33 -10
- package/src/controls/text-area-control.tsx +5 -1
- package/src/controls/text-control.tsx +5 -0
- package/src/controls/toggle-control.tsx +11 -2
- package/src/controls/transform-control/functions/axis-row.tsx +1 -0
- package/src/controls/transform-control/transform-icon.tsx +2 -2
- package/src/controls/transform-control/transform-label.tsx +15 -32
- package/src/controls/transform-control/transform-repeater-control.tsx +42 -36
- package/src/controls/transform-control/{transform-base-control.tsx → transform-settings-control.tsx} +2 -2
- package/src/controls/transform-control/use-transform-tabs-history.tsx +1 -1
- package/src/controls/transition-control/data.ts +16 -1
- package/src/controls/transition-control/trainsition-events.ts +2 -2
- package/src/controls/transition-control/transition-repeater-control.tsx +137 -13
- package/src/controls/transition-control/transition-selector.tsx +37 -14
- package/src/controls/url-control.tsx +21 -16
- package/src/hooks/use-filtered-items-list.ts +3 -2
- package/src/hooks/use-repeatable-control-context.ts +3 -0
- package/src/hooks/use-sync-external-state.tsx +0 -1
- package/src/index.ts +21 -5
- package/src/utils/convert-toggle-options-to-atomic.tsx +33 -0
- package/src/utils/escape-html-attr.ts +11 -0
- package/src/components/css-code-editor/css-editor.styles.ts +0 -52
- package/src/components/css-code-editor/css-editor.tsx +0 -142
- package/src/components/css-code-editor/css-validation.ts +0 -75
- package/src/components/css-code-editor/resize-handle.tsx +0 -55
- package/src/components/css-code-editor/visual-content-change-protection.ts +0 -69
- package/src/components/repeater.tsx +0 -343
- package/src/components/unstable-repeater/items/item.tsx +0 -77
- package/src/components/unstable-repeater/unstable-repeater.tsx +0 -26
- /package/src/components/{unstable-repeater → control-repeater}/actions/tooltip-add-item-action.tsx +0 -0
|
@@ -1,17 +1,30 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { useEffect, useState } from 'react';
|
|
3
|
-
import {
|
|
2
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
3
|
+
import {
|
|
4
|
+
createArrayPropUtils,
|
|
5
|
+
type KeyValuePropValue,
|
|
6
|
+
selectionSizePropTypeUtil,
|
|
7
|
+
type SelectionSizePropValue,
|
|
8
|
+
} from '@elementor/editor-props';
|
|
4
9
|
import { type StyleDefinitionState } from '@elementor/editor-styles';
|
|
5
10
|
import { InfoCircleFilledIcon } from '@elementor/icons';
|
|
6
11
|
import { Alert, AlertTitle, Box, Typography } from '@elementor/ui';
|
|
7
12
|
import { __ } from '@wordpress/i18n';
|
|
8
13
|
|
|
14
|
+
import { useBoundProp } from '../../bound-prop-context';
|
|
15
|
+
import { type Item, type RepeatablePropValue } from '../../components/control-repeater/types';
|
|
9
16
|
import { createControl } from '../../create-control';
|
|
10
17
|
import { RepeatableControl } from '../repeatable-control';
|
|
11
18
|
import { SelectionSizeControl } from '../selection-size-control';
|
|
12
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
initialTransitionValue,
|
|
21
|
+
type TransitionItem,
|
|
22
|
+
transitionProperties,
|
|
23
|
+
type TransitionProperty,
|
|
24
|
+
type TransitionValue,
|
|
25
|
+
} from './data';
|
|
13
26
|
import { subscribeToTransitionEvent } from './trainsition-events';
|
|
14
|
-
import { TransitionSelector } from './transition-selector';
|
|
27
|
+
import { getTransitionPropertyByValue, TransitionSelector } from './transition-selector';
|
|
15
28
|
|
|
16
29
|
const DURATION_CONFIG = {
|
|
17
30
|
variant: 'time',
|
|
@@ -19,9 +32,34 @@ const DURATION_CONFIG = {
|
|
|
19
32
|
defaultUnit: 'ms',
|
|
20
33
|
};
|
|
21
34
|
|
|
35
|
+
const childArrayPropTypeUtil = createArrayPropUtils(
|
|
36
|
+
selectionSizePropTypeUtil.key,
|
|
37
|
+
selectionSizePropTypeUtil.schema,
|
|
38
|
+
'transition'
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
subscribeToTransitionEvent();
|
|
42
|
+
|
|
43
|
+
const areAllPropertiesUsed = ( value: SelectionSizePropValue[] = [] ) => {
|
|
44
|
+
return value?.length
|
|
45
|
+
? transitionProperties.every( ( category ) => {
|
|
46
|
+
return category.properties.every( ( property ) => {
|
|
47
|
+
return (
|
|
48
|
+
property.isDisabled ||
|
|
49
|
+
!! value?.find( ( item ) => {
|
|
50
|
+
return (
|
|
51
|
+
( item.value?.selection?.value as KeyValuePropValue )?.value?.value === property.value
|
|
52
|
+
);
|
|
53
|
+
} )
|
|
54
|
+
);
|
|
55
|
+
} );
|
|
56
|
+
} )
|
|
57
|
+
: false;
|
|
58
|
+
};
|
|
59
|
+
|
|
22
60
|
// this config needs to be loaded at runtime/render since it's the transitionProperties object will be mutated by the pro plugin.
|
|
23
61
|
// See: https://elementor.atlassian.net/browse/ED-20285
|
|
24
|
-
const getSelectionSizeProps = ( recentlyUsedList: string[] ) => {
|
|
62
|
+
const getSelectionSizeProps = ( recentlyUsedList: string[], disabledItems?: string[] ) => {
|
|
25
63
|
return {
|
|
26
64
|
selectionLabel: __( 'Type', 'elementor' ),
|
|
27
65
|
sizeLabel: __( 'Duration', 'elementor' ),
|
|
@@ -29,8 +67,10 @@ const getSelectionSizeProps = ( recentlyUsedList: string[] ) => {
|
|
|
29
67
|
component: TransitionSelector,
|
|
30
68
|
props: {
|
|
31
69
|
recentlyUsedList,
|
|
70
|
+
disabledItems,
|
|
32
71
|
},
|
|
33
72
|
},
|
|
73
|
+
isRepeaterControl: true,
|
|
34
74
|
sizeConfigMap: {
|
|
35
75
|
...transitionProperties.reduce(
|
|
36
76
|
( acc, category ) => {
|
|
@@ -45,13 +85,69 @@ const getSelectionSizeProps = ( recentlyUsedList: string[] ) => {
|
|
|
45
85
|
};
|
|
46
86
|
};
|
|
47
87
|
|
|
48
|
-
|
|
88
|
+
const isItemDisabled = ( item: TransitionItem[ 'value' ] ) => {
|
|
89
|
+
const property = getTransitionPropertyByValue( item.value.selection.value?.value );
|
|
90
|
+
|
|
91
|
+
return ! property ? false : !! property.isDisabled;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const getChildControlConfig = ( recentlyUsedList: string[], disabledItems?: string[] ) => {
|
|
49
95
|
return {
|
|
50
96
|
propTypeUtil: selectionSizePropTypeUtil,
|
|
51
97
|
component: SelectionSizeControl as unknown as React.ComponentType< Record< string, unknown > >,
|
|
52
|
-
props: getSelectionSizeProps( recentlyUsedList ),
|
|
98
|
+
props: getSelectionSizeProps( recentlyUsedList, disabledItems ),
|
|
99
|
+
isItemDisabled: isItemDisabled as ( item: Item< RepeatablePropValue > ) => boolean,
|
|
53
100
|
};
|
|
54
|
-
}
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const isPropertyUsed = ( value: SelectionSizePropValue[], property: TransitionProperty ) => {
|
|
104
|
+
return ( value ?? [] ).some( ( item ) => {
|
|
105
|
+
return ( item?.value?.selection?.value as KeyValuePropValue )?.value?.value === property.value;
|
|
106
|
+
} );
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const getDisabledItemLabels = ( values: SelectionSizePropValue[] = [] ) => {
|
|
110
|
+
const disabledLabels: string[] = ( values || [] ).map(
|
|
111
|
+
( item ) => ( item.value?.selection as KeyValuePropValue )?.value?.key?.value
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
transitionProperties.forEach( ( category ) => {
|
|
115
|
+
const disabledProperties = category.properties
|
|
116
|
+
.filter( ( property ) => property.isDisabled && ! disabledLabels.includes( property.label ) )
|
|
117
|
+
.map( ( property ) => property.label );
|
|
118
|
+
|
|
119
|
+
disabledLabels.push( ...disabledProperties );
|
|
120
|
+
} );
|
|
121
|
+
|
|
122
|
+
return disabledLabels;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const getInitialValue = ( values: SelectionSizePropValue[] = [] ): TransitionValue => {
|
|
126
|
+
if ( ! values?.length ) {
|
|
127
|
+
return initialTransitionValue;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
for ( const category of transitionProperties ) {
|
|
131
|
+
for ( const property of category.properties ) {
|
|
132
|
+
if ( isPropertyUsed( values, property ) ) {
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return {
|
|
137
|
+
...initialTransitionValue,
|
|
138
|
+
selection: {
|
|
139
|
+
$$type: 'key-value',
|
|
140
|
+
value: {
|
|
141
|
+
key: { value: property.label, $$type: 'string' },
|
|
142
|
+
value: { value: property.value, $$type: 'string' },
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return initialTransitionValue;
|
|
150
|
+
};
|
|
55
151
|
|
|
56
152
|
const disableAddItemTooltipContent = (
|
|
57
153
|
<Alert
|
|
@@ -71,8 +167,6 @@ const disableAddItemTooltipContent = (
|
|
|
71
167
|
</Alert>
|
|
72
168
|
);
|
|
73
169
|
|
|
74
|
-
subscribeToTransitionEvent();
|
|
75
|
-
|
|
76
170
|
export const TransitionRepeaterControl = createControl(
|
|
77
171
|
( {
|
|
78
172
|
recentlyUsedListGetter,
|
|
@@ -84,10 +178,40 @@ export const TransitionRepeaterControl = createControl(
|
|
|
84
178
|
const currentStyleIsNormal = currentStyleState === null;
|
|
85
179
|
const [ recentlyUsedList, setRecentlyUsedList ] = useState< string[] >( [] );
|
|
86
180
|
|
|
181
|
+
const { value, setValue } = useBoundProp( childArrayPropTypeUtil );
|
|
182
|
+
const disabledItems = useMemo( () => getDisabledItemLabels( value ), [ value ] );
|
|
183
|
+
|
|
184
|
+
const allowedTransitionSet = useMemo( () => {
|
|
185
|
+
const set = new Set< string >();
|
|
186
|
+
transitionProperties.forEach( ( category ) => {
|
|
187
|
+
category.properties.forEach( ( prop ) => set.add( prop.value ) );
|
|
188
|
+
} );
|
|
189
|
+
return set;
|
|
190
|
+
}, [] );
|
|
191
|
+
|
|
192
|
+
useEffect( () => {
|
|
193
|
+
if ( ! value || value.length === 0 ) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const sanitized = value.filter( ( item ) => {
|
|
198
|
+
const selectionValue = ( item?.value?.selection?.value as KeyValuePropValue )?.value?.value ?? '';
|
|
199
|
+
return allowedTransitionSet.has( selectionValue );
|
|
200
|
+
} );
|
|
201
|
+
|
|
202
|
+
if ( sanitized.length !== value.length ) {
|
|
203
|
+
setValue( sanitized );
|
|
204
|
+
}
|
|
205
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
206
|
+
}, [ allowedTransitionSet ] );
|
|
207
|
+
|
|
87
208
|
useEffect( () => {
|
|
88
209
|
recentlyUsedListGetter().then( setRecentlyUsedList );
|
|
89
210
|
}, [ recentlyUsedListGetter ] );
|
|
90
211
|
|
|
212
|
+
const allPropertiesUsed = useMemo( () => areAllPropertiesUsed( value ), [ value ] );
|
|
213
|
+
const isAddItemDisabled = ! currentStyleIsNormal || allPropertiesUsed;
|
|
214
|
+
|
|
91
215
|
return (
|
|
92
216
|
<RepeatableControl
|
|
93
217
|
label={ __( 'Transitions', 'elementor' ) }
|
|
@@ -96,11 +220,11 @@ export const TransitionRepeaterControl = createControl(
|
|
|
96
220
|
placeholder={ __( 'Empty Transition', 'elementor' ) }
|
|
97
221
|
showDuplicate={ false }
|
|
98
222
|
showToggle={ true }
|
|
99
|
-
initialValues={
|
|
100
|
-
childControlConfig={ getChildControlConfig( recentlyUsedList ) }
|
|
223
|
+
initialValues={ getInitialValue( value ) }
|
|
224
|
+
childControlConfig={ getChildControlConfig( recentlyUsedList, disabledItems ) }
|
|
101
225
|
propKey="transition"
|
|
102
226
|
addItemTooltipProps={ {
|
|
103
|
-
disabled:
|
|
227
|
+
disabled: isAddItemDisabled,
|
|
104
228
|
enableTooltip: ! currentStyleIsNormal,
|
|
105
229
|
tooltipContent: disableAddItemTooltipContent,
|
|
106
230
|
} }
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { useRef } from 'react';
|
|
3
|
-
import { keyValuePropTypeUtil } from '@elementor/editor-props';
|
|
3
|
+
import { keyValuePropTypeUtil, type KeyValuePropValue, type StringPropValue } from '@elementor/editor-props';
|
|
4
4
|
import { ChevronDownIcon, VariationsIcon } from '@elementor/icons';
|
|
5
5
|
import { bindPopover, bindTrigger, Box, Popover, UnstableTag, usePopupState } from '@elementor/ui';
|
|
6
6
|
import { __ } from '@wordpress/i18n';
|
|
7
7
|
|
|
8
8
|
import { useBoundProp } from '../../bound-prop-context';
|
|
9
9
|
import { ItemSelector } from '../../components/item-selector';
|
|
10
|
+
import ControlActions from '../../control-actions/control-actions';
|
|
10
11
|
import { transitionProperties, transitionsItemsList } from './data';
|
|
11
12
|
|
|
12
13
|
const toTransitionSelectorValue = ( label: string ) => {
|
|
@@ -23,16 +24,35 @@ const toTransitionSelectorValue = ( label: string ) => {
|
|
|
23
24
|
return null;
|
|
24
25
|
};
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
export function getTransitionPropertyByValue( item?: StringPropValue | null ) {
|
|
28
|
+
if ( ! item?.value ) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
|
|
27
32
|
for ( const category of transitionProperties ) {
|
|
28
|
-
const property
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
for ( const property of category.properties ) {
|
|
34
|
+
if ( property.value === item.value ) {
|
|
35
|
+
return property;
|
|
36
|
+
}
|
|
31
37
|
}
|
|
32
38
|
}
|
|
39
|
+
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const includeCurrentValueInOptions = ( value: KeyValuePropValue[ 'value' ], disabledItems: string[] ) => {
|
|
44
|
+
return disabledItems.filter( ( item ) => {
|
|
45
|
+
return item !== value.key.value;
|
|
46
|
+
} );
|
|
33
47
|
};
|
|
34
48
|
|
|
35
|
-
export const TransitionSelector = ( {
|
|
49
|
+
export const TransitionSelector = ( {
|
|
50
|
+
recentlyUsedList = [],
|
|
51
|
+
disabledItems = [],
|
|
52
|
+
}: {
|
|
53
|
+
recentlyUsedList: string[];
|
|
54
|
+
disabledItems?: string[];
|
|
55
|
+
} ) => {
|
|
36
56
|
const { value, setValue } = useBoundProp( keyValuePropTypeUtil );
|
|
37
57
|
const {
|
|
38
58
|
key: { value: transitionLabel },
|
|
@@ -42,7 +62,7 @@ export const TransitionSelector = ( { recentlyUsedList = [] }: { recentlyUsedLis
|
|
|
42
62
|
|
|
43
63
|
const getItemList = () => {
|
|
44
64
|
const recentItems = recentlyUsedList
|
|
45
|
-
.map( ( item ) =>
|
|
65
|
+
.map( ( item ) => getTransitionPropertyByValue( { value: item, $$type: 'string' } )?.label )
|
|
46
66
|
.filter( ( item ) => !! item ) as string[];
|
|
47
67
|
const filteredItems = transitionsItemsList.map( ( category ) => {
|
|
48
68
|
return {
|
|
@@ -89,13 +109,15 @@ export const TransitionSelector = ( { recentlyUsedList = [] }: { recentlyUsedLis
|
|
|
89
109
|
|
|
90
110
|
return (
|
|
91
111
|
<Box ref={ defaultRef }>
|
|
92
|
-
<
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
112
|
+
<ControlActions>
|
|
113
|
+
<UnstableTag
|
|
114
|
+
variant="outlined"
|
|
115
|
+
label={ transitionLabel }
|
|
116
|
+
endIcon={ <ChevronDownIcon fontSize="tiny" /> }
|
|
117
|
+
{ ...bindTrigger( popoverState ) }
|
|
118
|
+
fullWidth
|
|
119
|
+
/>
|
|
120
|
+
</ControlActions>
|
|
99
121
|
<Popover
|
|
100
122
|
disablePortal
|
|
101
123
|
disableScrollLock
|
|
@@ -113,6 +135,7 @@ export const TransitionSelector = ( { recentlyUsedList = [] }: { recentlyUsedLis
|
|
|
113
135
|
sectionWidth={ 268 }
|
|
114
136
|
title={ __( 'Transition Property', 'elementor' ) }
|
|
115
137
|
icon={ VariationsIcon as React.ElementType< { fontSize: string } > }
|
|
138
|
+
disabledItems={ includeCurrentValueInOptions( value, disabledItems ) }
|
|
116
139
|
/>
|
|
117
140
|
</Popover>
|
|
118
141
|
</Box>
|
|
@@ -6,20 +6,25 @@ import { useBoundProp } from '../bound-prop-context';
|
|
|
6
6
|
import ControlActions from '../control-actions/control-actions';
|
|
7
7
|
import { createControl } from '../create-control';
|
|
8
8
|
|
|
9
|
-
export const UrlControl = createControl(
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
export const UrlControl = createControl(
|
|
10
|
+
( { placeholder, ariaLabel }: { placeholder?: string; ariaLabel?: string } ) => {
|
|
11
|
+
const { value, setValue, disabled } = useBoundProp( urlPropTypeUtil );
|
|
12
|
+
const handleChange = ( event: React.ChangeEvent< HTMLInputElement > ) => setValue( event.target.value );
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
14
|
+
return (
|
|
15
|
+
<ControlActions>
|
|
16
|
+
<TextField
|
|
17
|
+
size="tiny"
|
|
18
|
+
fullWidth
|
|
19
|
+
value={ value ?? '' }
|
|
20
|
+
disabled={ disabled }
|
|
21
|
+
onChange={ handleChange }
|
|
22
|
+
placeholder={ placeholder }
|
|
23
|
+
inputProps={ {
|
|
24
|
+
...( ariaLabel ? { 'aria-label': ariaLabel } : {} ),
|
|
25
|
+
} }
|
|
26
|
+
/>
|
|
27
|
+
</ControlActions>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
);
|
|
@@ -3,9 +3,10 @@ import { type Category } from '../components/item-selector';
|
|
|
3
3
|
export type SelectableItem = {
|
|
4
4
|
type: 'item' | 'category';
|
|
5
5
|
value: string;
|
|
6
|
+
disabled?: boolean;
|
|
6
7
|
};
|
|
7
8
|
|
|
8
|
-
export const useFilteredItemsList = ( itemsList: Category[], searchValue: string ) => {
|
|
9
|
+
export const useFilteredItemsList = ( itemsList: Category[], searchValue: string, disabledItems?: string[] ) => {
|
|
9
10
|
return itemsList.reduce< SelectableItem[] >( ( acc, category ) => {
|
|
10
11
|
const filteredItems = category.items.filter( ( item ) =>
|
|
11
12
|
item.toLowerCase().includes( searchValue.toLowerCase() )
|
|
@@ -15,7 +16,7 @@ export const useFilteredItemsList = ( itemsList: Category[], searchValue: string
|
|
|
15
16
|
acc.push( { type: 'category', value: category.label } );
|
|
16
17
|
|
|
17
18
|
filteredItems.forEach( ( item ) => {
|
|
18
|
-
acc.push( { type: 'item', value: item } );
|
|
19
|
+
acc.push( { type: 'item', value: item, disabled: disabledItems?.includes( item ) ?? false } );
|
|
19
20
|
} );
|
|
20
21
|
}
|
|
21
22
|
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { createContext, useContext } from 'react';
|
|
2
2
|
import { type PropTypeUtil } from '@elementor/editor-props';
|
|
3
3
|
|
|
4
|
+
import type { Item, RepeatablePropValue } from '../components/control-repeater/types';
|
|
5
|
+
|
|
4
6
|
export type ChildControlConfig = {
|
|
5
7
|
component: React.ComponentType;
|
|
6
8
|
props?: Record< string, unknown >;
|
|
7
9
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8
10
|
propTypeUtil: PropTypeUtil< string, any >;
|
|
9
11
|
label?: string;
|
|
12
|
+
isItemDisabled?: ( item: Item< RepeatablePropValue > ) => boolean;
|
|
10
13
|
};
|
|
11
14
|
|
|
12
15
|
type RepeatableControlContextType = ChildControlConfig & {
|
|
@@ -37,7 +37,6 @@ export const useSyncExternalState = < TValue, >( {
|
|
|
37
37
|
useEffect( () => {
|
|
38
38
|
setInternal( ( prevInternal ) => toInternal( external, prevInternal ) );
|
|
39
39
|
|
|
40
|
-
// eslint-disable-next-line react-compiler/react-compiler
|
|
41
40
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
42
41
|
}, [ external ] );
|
|
43
42
|
|
package/src/index.ts
CHANGED
|
@@ -7,6 +7,7 @@ export { StrokeControl } from './controls/stroke-control';
|
|
|
7
7
|
export { BoxShadowRepeaterControl } from './controls/box-shadow-repeater-control';
|
|
8
8
|
export { FilterRepeaterControl } from './controls/filter-control/filter-repeater-control';
|
|
9
9
|
export { SelectControl } from './controls/select-control';
|
|
10
|
+
export { SelectControlWrapper } from './controls/select-control-wrapper';
|
|
10
11
|
export { ColorControl } from './controls/color-control';
|
|
11
12
|
export { ToggleControl } from './controls/toggle-control';
|
|
12
13
|
export { NumberControl } from './controls/number-control';
|
|
@@ -16,6 +17,8 @@ export { FontFamilyControl } from './controls/font-family-control/font-family-co
|
|
|
16
17
|
export { ItemSelector } from './components/item-selector';
|
|
17
18
|
export { UrlControl } from './controls/url-control';
|
|
18
19
|
export { LinkControl } from './controls/link-control';
|
|
20
|
+
export { HtmlTagControl } from './controls/html-tag-control';
|
|
21
|
+
export { QueryControl } from './controls/query-control';
|
|
19
22
|
export { GapControl } from './controls/gap-control';
|
|
20
23
|
export { AspectRatioControl } from './controls/aspect-ratio-control';
|
|
21
24
|
export { SvgMediaControl } from './controls/svg-media-control';
|
|
@@ -25,24 +28,38 @@ export { RepeatableControl } from './controls/repeatable-control';
|
|
|
25
28
|
export { KeyValueControl } from './controls/key-value-control';
|
|
26
29
|
export { PositionControl } from './controls/position-control';
|
|
27
30
|
export { TransformRepeaterControl } from './controls/transform-control/transform-repeater-control';
|
|
28
|
-
export {
|
|
31
|
+
export { TransformSettingsControl } from './controls/transform-control/transform-settings-control';
|
|
29
32
|
export { TransitionRepeaterControl } from './controls/transition-control/transition-repeater-control';
|
|
30
33
|
export { PopoverContent } from './components/popover-content';
|
|
31
34
|
export { enqueueFont } from './controls/font-family-control/enqueue-font';
|
|
32
35
|
export { transitionProperties, transitionsItemsList } from './controls/transition-control/data';
|
|
36
|
+
export { DateTimeControl } from './controls/date-time-control';
|
|
37
|
+
export { InlineEditingControl } from './controls/inline-editing-control';
|
|
38
|
+
export { InlineEditor } from './components/inline-editor';
|
|
39
|
+
export { InlineEditorToolbar } from './components/inline-editor-toolbar';
|
|
33
40
|
|
|
34
41
|
// components
|
|
35
42
|
export { ControlFormLabel } from './components/control-form-label';
|
|
36
43
|
export { ControlToggleButtonGroup } from './components/control-toggle-button-group';
|
|
37
|
-
export {
|
|
44
|
+
export { ToggleButtonGroupUi } from './components/control-toggle-button-group';
|
|
45
|
+
export { ClearIconButton } from './components/icon-buttons/clear-icon-button';
|
|
46
|
+
export {
|
|
47
|
+
Repeater,
|
|
48
|
+
type SetRepeaterValuesMeta,
|
|
49
|
+
type ItemsActionPayload,
|
|
50
|
+
type RepeaterItem,
|
|
51
|
+
} from './components/repeater/repeater';
|
|
52
|
+
export { FloatingActionsBar } from './components/floating-bar';
|
|
53
|
+
export { PopoverGridContainer } from './components/popover-grid-container';
|
|
38
54
|
|
|
39
55
|
// types
|
|
40
56
|
export type { ControlComponent } from './create-control';
|
|
41
57
|
export type { ToggleButtonGroupItem } from './components/control-toggle-button-group';
|
|
42
58
|
export type { EqualUnequalItems } from './controls/equal-unequal-sizes-control';
|
|
43
59
|
export type { ControlActionsItems } from './control-actions/control-actions-context';
|
|
60
|
+
export type { AdornmentComponent } from './control-adornments/control-adornments-context';
|
|
44
61
|
export type { PropProviderProps } from './bound-prop-context';
|
|
45
|
-
export type { SetValue } from './bound-prop-context/prop-context';
|
|
62
|
+
export type { SetValue, SetValueMeta } from './bound-prop-context/prop-context';
|
|
46
63
|
export type { ExtendedOption, Unit, LengthUnit, AngleUnit, TimeUnit } from './utils/size-control';
|
|
47
64
|
export type { ToggleControlProps } from './controls/toggle-control';
|
|
48
65
|
export type { FontCategory } from './controls/font-family-control/font-family-control';
|
|
@@ -59,9 +76,8 @@ export { createControl } from './create-control';
|
|
|
59
76
|
export {
|
|
60
77
|
injectIntoRepeaterItemIcon,
|
|
61
78
|
injectIntoRepeaterItemLabel,
|
|
62
|
-
injectIntoRepeaterHeaderActions,
|
|
63
79
|
injectIntoRepeaterItemActions,
|
|
64
|
-
} from './components/
|
|
80
|
+
} from './components/control-repeater/locations';
|
|
65
81
|
|
|
66
82
|
// hooks
|
|
67
83
|
export { useSyncExternalState } from './hooks/use-sync-external-state';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { ToggleButtonGroupItem } from '@elementor/editor-controls';
|
|
3
|
+
import * as Icons from '@elementor/icons';
|
|
4
|
+
|
|
5
|
+
export type DynamicToggleOption = {
|
|
6
|
+
value: string;
|
|
7
|
+
label: string;
|
|
8
|
+
icon?: string;
|
|
9
|
+
showTooltip?: boolean;
|
|
10
|
+
exclusive?: boolean;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const convertToggleOptionsToAtomic = (
|
|
14
|
+
options: DynamicToggleOption[]
|
|
15
|
+
): Array< ToggleButtonGroupItem< string > & { exclusive?: boolean } > => {
|
|
16
|
+
return options.map( ( option ) => {
|
|
17
|
+
const iconName = option.icon;
|
|
18
|
+
const IconComponent = Icons[ iconName as keyof typeof Icons ];
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
value: option.value,
|
|
22
|
+
label: option.label,
|
|
23
|
+
renderContent: ( { size } ) => {
|
|
24
|
+
if ( IconComponent ) {
|
|
25
|
+
return <IconComponent fontSize={ size } />;
|
|
26
|
+
}
|
|
27
|
+
return option.label;
|
|
28
|
+
},
|
|
29
|
+
showTooltip: option.showTooltip,
|
|
30
|
+
exclusive: option.exclusive,
|
|
31
|
+
};
|
|
32
|
+
} );
|
|
33
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const escapeHtmlAttr = ( value: string ): string => {
|
|
2
|
+
const specialChars: Record< string, string > = {
|
|
3
|
+
'&': '&',
|
|
4
|
+
'<': '<',
|
|
5
|
+
'>': '>',
|
|
6
|
+
"'": ''',
|
|
7
|
+
'"': '"',
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
return value.replace( /[&<>'"]/g, ( char ) => specialChars[ char ] || char );
|
|
11
|
+
};
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { Box, Button, styled } from '@elementor/ui';
|
|
2
|
-
|
|
3
|
-
export const EditorWrapper = styled( Box )`
|
|
4
|
-
border: 1px solid var( --e-a-border-color );
|
|
5
|
-
border-radius: 8px;
|
|
6
|
-
padding: 10px 12px;
|
|
7
|
-
position: relative;
|
|
8
|
-
height: 200px;
|
|
9
|
-
|
|
10
|
-
.monaco-editor .suggest-widget {
|
|
11
|
-
width: 220px !important;
|
|
12
|
-
max-width: 220px !important;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
.visual-content-dimmed {
|
|
16
|
-
opacity: 0.6;
|
|
17
|
-
color: #aaa !important;
|
|
18
|
-
pointer-events: none;
|
|
19
|
-
}
|
|
20
|
-
`;
|
|
21
|
-
|
|
22
|
-
export const ResizeHandle = styled( Button )`
|
|
23
|
-
position: absolute;
|
|
24
|
-
bottom: 0;
|
|
25
|
-
left: 0;
|
|
26
|
-
right: 0;
|
|
27
|
-
height: 6px;
|
|
28
|
-
cursor: ns-resize;
|
|
29
|
-
background: transparent;
|
|
30
|
-
border: none;
|
|
31
|
-
padding: 0;
|
|
32
|
-
|
|
33
|
-
&:hover {
|
|
34
|
-
background: rgba( 0, 0, 0, 0.05 );
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
&:active {
|
|
38
|
-
background: rgba( 0, 0, 0, 0.1 );
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
&::after {
|
|
42
|
-
content: '';
|
|
43
|
-
position: absolute;
|
|
44
|
-
top: 50%;
|
|
45
|
-
left: 50%;
|
|
46
|
-
transform: translate( -50%, -50% );
|
|
47
|
-
width: 30px;
|
|
48
|
-
height: 2px;
|
|
49
|
-
background: var( --e-a-border-color );
|
|
50
|
-
border-radius: 1px;
|
|
51
|
-
}
|
|
52
|
-
`;
|