@elementor/editor-controls 4.4.0-beta1 → 4.4.0-beta3
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 +12 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.js +1202 -1098
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +887 -784
- package/dist/index.mjs.map +1 -1
- package/package.json +16 -16
- package/src/controls/icon-library/icon-library-grid.tsx +18 -25
- package/src/controls/icon-library/icon-library-popover.tsx +27 -9
- package/src/controls/query-select-control.tsx +104 -0
- package/src/controls/size-control/hooks/use-size-value.ts +2 -2
- package/src/controls/size-control/unstable-size-control.tsx +19 -1
- package/src/controls/size-control/utils/resolve-size-value.ts +14 -0
- package/src/controls/size-control.tsx +5 -5
- package/src/hooks/use-query-autocomplete.ts +7 -3
- package/src/index.ts +1 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/editor-controls",
|
|
3
3
|
"description": "This package contains the controls model and utils for the Elementor editor",
|
|
4
|
-
"version": "4.4.0-
|
|
4
|
+
"version": "4.4.0-beta3",
|
|
5
5
|
"private": false,
|
|
6
6
|
"author": "Elementor Team",
|
|
7
7
|
"homepage": "https://elementor.com/",
|
|
@@ -40,23 +40,23 @@
|
|
|
40
40
|
"dev": "tsup --config=../../tsup.dev.ts"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@elementor/editor-current-user": "4.4.0-
|
|
44
|
-
"@elementor/editor-elements": "4.4.0-
|
|
45
|
-
"@elementor/editor-props": "4.4.0-
|
|
46
|
-
"@elementor/editor-responsive": "4.4.0-
|
|
47
|
-
"@elementor/editor-ui": "4.4.0-
|
|
48
|
-
"@elementor/editor-v1-adapters": "4.4.0-
|
|
49
|
-
"@elementor/env": "4.4.0-
|
|
50
|
-
"@elementor/events": "4.4.0-
|
|
51
|
-
"@elementor/http-client": "4.4.0-
|
|
43
|
+
"@elementor/editor-current-user": "4.4.0-beta3",
|
|
44
|
+
"@elementor/editor-elements": "4.4.0-beta3",
|
|
45
|
+
"@elementor/editor-props": "4.4.0-beta3",
|
|
46
|
+
"@elementor/editor-responsive": "4.4.0-beta3",
|
|
47
|
+
"@elementor/editor-ui": "4.4.0-beta3",
|
|
48
|
+
"@elementor/editor-v1-adapters": "4.4.0-beta3",
|
|
49
|
+
"@elementor/env": "4.4.0-beta3",
|
|
50
|
+
"@elementor/events": "4.4.0-beta3",
|
|
51
|
+
"@elementor/http-client": "4.4.0-beta3",
|
|
52
52
|
"@elementor/icons": "~1.78.1",
|
|
53
|
-
"@elementor/locations": "4.4.0-
|
|
54
|
-
"@elementor/query": "4.4.0-
|
|
55
|
-
"@elementor/schema": "4.4.0-
|
|
56
|
-
"@elementor/session": "4.4.0-
|
|
53
|
+
"@elementor/locations": "4.4.0-beta3",
|
|
54
|
+
"@elementor/query": "4.4.0-beta3",
|
|
55
|
+
"@elementor/schema": "4.4.0-beta3",
|
|
56
|
+
"@elementor/session": "4.4.0-beta3",
|
|
57
57
|
"@elementor/ui": "1.41.4",
|
|
58
|
-
"@elementor/utils": "4.4.0-
|
|
59
|
-
"@elementor/wp-media": "4.4.0-
|
|
58
|
+
"@elementor/utils": "4.4.0-beta3",
|
|
59
|
+
"@elementor/wp-media": "4.4.0-beta3",
|
|
60
60
|
"@monaco-editor/react": "^4.7.0",
|
|
61
61
|
"@tanstack/react-virtual": "^3.13.3",
|
|
62
62
|
"@tiptap/extension-bold": "^3.11.1",
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { useLayoutEffect, useRef, useState } from 'react';
|
|
3
|
+
import { useRovingFocus } from '@elementor/editor-ui';
|
|
3
4
|
import { Box, Tooltip, useTheme } from '@elementor/ui';
|
|
4
|
-
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
5
|
+
import { defaultRangeExtractor, useVirtualizer } from '@tanstack/react-virtual';
|
|
5
6
|
import { __ } from '@wordpress/i18n';
|
|
6
7
|
|
|
7
8
|
import { type FontAwesome7Icon } from './font-awesome-7-catalog';
|
|
@@ -63,8 +64,6 @@ export const IconLibraryGrid = ( {
|
|
|
63
64
|
}: IconLibraryGridProps ) => {
|
|
64
65
|
const theme = useTheme();
|
|
65
66
|
const containerRef = useRef< HTMLDivElement >( null );
|
|
66
|
-
const cellRefs = useRef( new Map< string, HTMLButtonElement >() );
|
|
67
|
-
const shouldRestoreFocusRef = useRef( false );
|
|
68
67
|
const selectedIndex = items.findIndex( ( item ) => item.id === selectedValue );
|
|
69
68
|
const [ focusedIndex, setFocusedIndex ] = useState( selectedIndex >= 0 ? selectedIndex : 0 );
|
|
70
69
|
const [ { columnCount, cellSize }, setGridMetrics ] = useState( () => getGridMetrics( 0, 0, 0 ) );
|
|
@@ -79,6 +78,16 @@ export const IconLibraryGrid = ( {
|
|
|
79
78
|
paddingStart: verticalPadding,
|
|
80
79
|
paddingEnd: verticalPadding,
|
|
81
80
|
overscan: GRID_OVERSCAN,
|
|
81
|
+
rangeExtractor: ( range ) => {
|
|
82
|
+
const rowIndexes = defaultRangeExtractor( range );
|
|
83
|
+
const focusedRow = Math.floor( focusedIndex / columnCount );
|
|
84
|
+
|
|
85
|
+
if ( items.length === 0 || rowIndexes.includes( focusedRow ) ) {
|
|
86
|
+
return rowIndexes;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return [ ...rowIndexes, focusedRow ].sort( ( a, b ) => a - b );
|
|
90
|
+
},
|
|
82
91
|
} );
|
|
83
92
|
const focusedItem = items[ focusedIndex ];
|
|
84
93
|
const visibleRowIndexes = virtualizer.getVirtualIndexes().join( ',' );
|
|
@@ -103,20 +112,10 @@ export const IconLibraryGrid = ( {
|
|
|
103
112
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
104
113
|
}, [ cellSize, columnCount, items, selectedIndex, selectedValue ] );
|
|
105
114
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const cell = cellRefs.current.get( focusedItem.id );
|
|
112
|
-
|
|
113
|
-
if ( ! cell ) {
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
cell.focus();
|
|
118
|
-
shouldRestoreFocusRef.current = false;
|
|
119
|
-
}, [ focusedItem, visibleRowIndexes ] );
|
|
115
|
+
const { registerRef, requestFocus } = useRovingFocus< HTMLButtonElement >( {
|
|
116
|
+
tabbableKey: focusedItem?.id,
|
|
117
|
+
mountedSignature: visibleRowIndexes,
|
|
118
|
+
} );
|
|
120
119
|
|
|
121
120
|
useLayoutEffect( () => {
|
|
122
121
|
const container = containerRef.current;
|
|
@@ -152,7 +151,7 @@ export const IconLibraryGrid = ( {
|
|
|
152
151
|
return;
|
|
153
152
|
}
|
|
154
153
|
|
|
155
|
-
|
|
154
|
+
requestFocus();
|
|
156
155
|
setFocusedIndex( nextIndex );
|
|
157
156
|
virtualizer.scrollToIndex( Math.floor( nextIndex / columnCount ) );
|
|
158
157
|
};
|
|
@@ -281,13 +280,7 @@ export const IconLibraryGrid = ( {
|
|
|
281
280
|
aria-label={ item.label }
|
|
282
281
|
aria-selected={ isSelected }
|
|
283
282
|
tabIndex={ tabIndex }
|
|
284
|
-
ref={ (
|
|
285
|
-
if ( node ) {
|
|
286
|
-
cellRefs.current.set( item.id, node );
|
|
287
|
-
} else {
|
|
288
|
-
cellRefs.current.delete( item.id );
|
|
289
|
-
}
|
|
290
|
-
} }
|
|
283
|
+
ref={ registerRef( item.id ) }
|
|
291
284
|
onClick={ () => {
|
|
292
285
|
onSelect( item.id );
|
|
293
286
|
onClose();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { useMemo, useState } from 'react';
|
|
2
|
+
import { useMemo, useRef, useState } from 'react';
|
|
3
3
|
import {
|
|
4
4
|
PopoverBody,
|
|
5
5
|
PopoverHeader,
|
|
@@ -103,6 +103,8 @@ export const IconLibraryPopover = ( {
|
|
|
103
103
|
[ icons, selectedIconClass, selectedIconLibrary ]
|
|
104
104
|
);
|
|
105
105
|
|
|
106
|
+
const contentRef = useRef< HTMLDivElement >( null );
|
|
107
|
+
|
|
106
108
|
const handleClose = () => {
|
|
107
109
|
setSearchValue( '' );
|
|
108
110
|
setActiveLibraries( [] );
|
|
@@ -122,6 +124,19 @@ export const IconLibraryPopover = ( {
|
|
|
122
124
|
} );
|
|
123
125
|
};
|
|
124
126
|
|
|
127
|
+
const handleSearchKeyDown = ( event: React.KeyboardEvent ) => {
|
|
128
|
+
if ( event.key !== 'ArrowDown' || view !== 'list' ) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const option = contentRef.current?.querySelector< HTMLElement >( '[role="option"][tabindex="0"]' );
|
|
133
|
+
|
|
134
|
+
if ( option ) {
|
|
135
|
+
event.preventDefault();
|
|
136
|
+
option.focus();
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
125
140
|
const handleClearSearch = () => {
|
|
126
141
|
setSearchValue( '' );
|
|
127
142
|
};
|
|
@@ -150,17 +165,19 @@ export const IconLibraryPopover = ( {
|
|
|
150
165
|
gap={ 1 }
|
|
151
166
|
sx={ { px: ICON_LIBRARY_INLINE_SPACING, pb: ICON_LIBRARY_SEARCH_PADDING_BOTTOM } }
|
|
152
167
|
>
|
|
153
|
-
<
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
168
|
+
<Box onKeyDown={ handleSearchKeyDown } sx={ { flex: 1, minWidth: 0 } }>
|
|
169
|
+
<SearchField
|
|
170
|
+
value={ searchInputValue }
|
|
171
|
+
onSearch={ handleSearchChange }
|
|
172
|
+
placeholder={ __( 'Search', 'elementor' ) }
|
|
173
|
+
id="icon-library-search"
|
|
174
|
+
sx={ { width: '100%', px: 0, pb: 0 } }
|
|
175
|
+
/>
|
|
176
|
+
</Box>
|
|
160
177
|
<IconLibraryFilter value={ activeLibraries } onChange={ setActiveLibraries } />
|
|
161
178
|
</Stack>
|
|
162
179
|
<Divider />
|
|
163
|
-
<Box sx={ { flex: 1, overflow: 'hidden', minHeight: 0, minWidth: 0 } }>
|
|
180
|
+
<Box ref={ contentRef } sx={ { flex: 1, overflow: 'hidden', minHeight: 0, minWidth: 0 } }>
|
|
164
181
|
<IconLibraryContent
|
|
165
182
|
isLoading={ isLoading }
|
|
166
183
|
items={ items }
|
|
@@ -235,6 +252,7 @@ const IconLibraryContent = ( {
|
|
|
235
252
|
onClose={ onClose }
|
|
236
253
|
itemHeight={ ICON_LIBRARY_ROW_HEIGHT }
|
|
237
254
|
menuItemContentTemplate={ IconLibraryRow }
|
|
255
|
+
rovingFocus
|
|
238
256
|
noResultsComponent={ emptyState }
|
|
239
257
|
data-testid="icon-library-list"
|
|
240
258
|
/>
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type SyntheticEvent, useMemo } from 'react';
|
|
3
|
+
import { numberPropTypeUtil, queryPropTypeUtil, stringPropTypeUtil } from '@elementor/editor-props';
|
|
4
|
+
import { Autocomplete, TextField } from '@elementor/ui';
|
|
5
|
+
import { __ } from '@wordpress/i18n';
|
|
6
|
+
|
|
7
|
+
import { useBoundProp } from '../bound-prop-context';
|
|
8
|
+
import { type FlatOption } from '../components/autocomplete';
|
|
9
|
+
import ControlActions from '../control-actions/control-actions';
|
|
10
|
+
import { createControl } from '../create-control';
|
|
11
|
+
import { extractFlatOptionFromQueryValue, useQueryAutocomplete } from '../hooks/use-query-autocomplete';
|
|
12
|
+
|
|
13
|
+
type QuerySelectControlProps = {
|
|
14
|
+
queryOptions: {
|
|
15
|
+
params: Record< string, unknown >;
|
|
16
|
+
url: string;
|
|
17
|
+
};
|
|
18
|
+
placeholder?: string;
|
|
19
|
+
minInputLength?: number;
|
|
20
|
+
ariaLabel?: string;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const SIZE = 'tiny';
|
|
24
|
+
|
|
25
|
+
export const QuerySelectControl = createControl( ( props: QuerySelectControlProps ) => {
|
|
26
|
+
const { queryOptions, placeholder, minInputLength = 0, ariaLabel } = props;
|
|
27
|
+
const { value, setValue, disabled } = useBoundProp( queryPropTypeUtil );
|
|
28
|
+
|
|
29
|
+
const selectedOption = useMemo( () => extractFlatOptionFromQueryValue( value ), [ value ] );
|
|
30
|
+
|
|
31
|
+
const { options, updateOptions } = useQueryAutocomplete( {
|
|
32
|
+
url: queryOptions.url,
|
|
33
|
+
params: queryOptions.params,
|
|
34
|
+
minInputLength,
|
|
35
|
+
initialQueryValue: value,
|
|
36
|
+
} );
|
|
37
|
+
|
|
38
|
+
const optionsWithSelected = useMemo(
|
|
39
|
+
() => withSelectedOption( options as FlatOption[], selectedOption ),
|
|
40
|
+
[ options, selectedOption ]
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const handleChange = ( _: SyntheticEvent, newValue: FlatOption | null ) => {
|
|
44
|
+
if ( ! newValue ) {
|
|
45
|
+
setValue( null );
|
|
46
|
+
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
setValue( {
|
|
51
|
+
id: numberPropTypeUtil.create( Number( newValue.id ) ),
|
|
52
|
+
label: stringPropTypeUtil.create( newValue.label ),
|
|
53
|
+
} );
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const handleInputChange = ( _: SyntheticEvent, term: string, reason: string ) => {
|
|
57
|
+
if ( 'reset' === reason || 'clear' === reason ) {
|
|
58
|
+
updateOptions( null );
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if ( 'input' !== reason ) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
updateOptions( term || null );
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<ControlActions>
|
|
71
|
+
<Autocomplete
|
|
72
|
+
fullWidth
|
|
73
|
+
openOnFocus
|
|
74
|
+
disabled={ disabled }
|
|
75
|
+
size={ SIZE }
|
|
76
|
+
value={ selectedOption }
|
|
77
|
+
options={ optionsWithSelected }
|
|
78
|
+
onChange={ handleChange }
|
|
79
|
+
onInputChange={ handleInputChange }
|
|
80
|
+
getOptionLabel={ ( option ) => option.label }
|
|
81
|
+
isOptionEqualToValue={ ( option, val ) => option.id === val.id }
|
|
82
|
+
filterOptions={ ( opts ) => opts }
|
|
83
|
+
renderInput={ ( params ) => (
|
|
84
|
+
<TextField
|
|
85
|
+
{ ...params }
|
|
86
|
+
placeholder={ placeholder ?? __( 'Search', 'elementor' ) }
|
|
87
|
+
inputProps={ {
|
|
88
|
+
...params.inputProps,
|
|
89
|
+
...( ariaLabel ? { 'aria-label': ariaLabel } : {} ),
|
|
90
|
+
} }
|
|
91
|
+
/>
|
|
92
|
+
) }
|
|
93
|
+
/>
|
|
94
|
+
</ControlActions>
|
|
95
|
+
);
|
|
96
|
+
} );
|
|
97
|
+
|
|
98
|
+
function withSelectedOption( options: FlatOption[], selectedOption: FlatOption | null ): FlatOption[] {
|
|
99
|
+
if ( ! selectedOption || options.some( ( option ) => option.id === selectedOption.id ) ) {
|
|
100
|
+
return options;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return [ selectedOption, ...options ];
|
|
104
|
+
}
|
|
@@ -4,7 +4,7 @@ import { type SizePropValue } from '@elementor/editor-props';
|
|
|
4
4
|
import { useSyncExternalState } from '../../../hooks/use-sync-external-state';
|
|
5
5
|
import { type SetSizeValue } from '../types';
|
|
6
6
|
import { isExtendedUnit } from '../utils/is-extended-unit';
|
|
7
|
-
import {
|
|
7
|
+
import { createEmptySizeValue, resolveSizeOnUnitChange, resolveSizeValue } from '../utils/resolve-size-value';
|
|
8
8
|
import { useUnitSync } from './use-unit-sync';
|
|
9
9
|
|
|
10
10
|
type SizeValue = SizePropValue[ 'value' ];
|
|
@@ -36,7 +36,7 @@ export const useSizeValue = < T extends SizeValue, U extends SizeValue[ 'unit' ]
|
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
persistWhen: ( next ) => hasChanged( next, resolvedValue ),
|
|
39
|
-
fallback: () =>
|
|
39
|
+
fallback: ( previousValue ) => createEmptySizeValue( previousValue, units, defaultUnit ),
|
|
40
40
|
} );
|
|
41
41
|
|
|
42
42
|
const [ unit, setUnit ] = useUnitSync( {
|
|
@@ -33,13 +33,16 @@ export const UnstableSizeControl = createControl(
|
|
|
33
33
|
restoreValue,
|
|
34
34
|
} = useBoundProp( sizePropTypeUtil );
|
|
35
35
|
const lastNonAutoValue = useRef< SizePropValue[ 'value' ] | null >( null );
|
|
36
|
+
const clearedUnit = useRef< SizePropValue[ 'value' ][ 'unit' ] | null >( null );
|
|
36
37
|
|
|
37
|
-
const { sizeValue, placeholder } = resolveBoundPropValue(
|
|
38
|
+
const { sizeValue: resolvedSizeValue, placeholder } = resolveBoundPropValue(
|
|
38
39
|
value ?? lastNonAutoValue.current,
|
|
39
40
|
boundPropPlaceholder,
|
|
40
41
|
propPlaceholder
|
|
41
42
|
);
|
|
42
43
|
|
|
44
|
+
const sizeValue = applyClearedUnit( resolvedSizeValue, value, clearedUnit.current );
|
|
45
|
+
|
|
43
46
|
const units = getSizeUnits( propType, variant );
|
|
44
47
|
const defaultUnit = getDefaultUnit( propType );
|
|
45
48
|
|
|
@@ -47,6 +50,7 @@ export const UnstableSizeControl = createControl(
|
|
|
47
50
|
const isRequired = propType.settings.required;
|
|
48
51
|
|
|
49
52
|
if ( shouldNullifyValue( value ) && ! isRequired ) {
|
|
53
|
+
clearedUnit.current = value?.unit ?? null;
|
|
50
54
|
setValue( null );
|
|
51
55
|
}
|
|
52
56
|
|
|
@@ -56,6 +60,8 @@ export const UnstableSizeControl = createControl(
|
|
|
56
60
|
};
|
|
57
61
|
|
|
58
62
|
const handleChange = ( newValue: SizePropValue[ 'value' ], options?: CreateOptions, meta?: SetValueMeta ) => {
|
|
63
|
+
clearedUnit.current = null;
|
|
64
|
+
|
|
59
65
|
if ( isTransitioningFromExtendedUnit( newValue, value ) ) {
|
|
60
66
|
lastNonAutoValue.current = newValue;
|
|
61
67
|
|
|
@@ -93,6 +99,18 @@ export const UnstableSizeControl = createControl(
|
|
|
93
99
|
}
|
|
94
100
|
);
|
|
95
101
|
|
|
102
|
+
const applyClearedUnit = (
|
|
103
|
+
resolvedValue: SizePropValue[ 'value' ] | null,
|
|
104
|
+
boundValue: SizePropValue[ 'value' ] | null,
|
|
105
|
+
clearedUnit: SizePropValue[ 'value' ][ 'unit' ] | null
|
|
106
|
+
): SizePropValue[ 'value' ] | null => {
|
|
107
|
+
if ( boundValue || ! resolvedValue || ! clearedUnit ) {
|
|
108
|
+
return resolvedValue;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return { ...resolvedValue, unit: clearedUnit } as SizePropValue[ 'value' ];
|
|
112
|
+
};
|
|
113
|
+
|
|
96
114
|
const isTransitioningFromExtendedUnit = (
|
|
97
115
|
nextValue: SizePropValue[ 'value' ],
|
|
98
116
|
previousValue: SizePropValue[ 'value' ]
|
|
@@ -60,6 +60,20 @@ export const createDefaultSizeValue = < T extends SizeValue >( units: SizeUnit[]
|
|
|
60
60
|
return { size: DEFAULT_SIZE, unit } as T;
|
|
61
61
|
};
|
|
62
62
|
|
|
63
|
+
export const createEmptySizeValue = < T extends SizeValue >(
|
|
64
|
+
previousValue: T | null,
|
|
65
|
+
units: SizeUnit[],
|
|
66
|
+
defaultUnit?: SizeUnit
|
|
67
|
+
): T => {
|
|
68
|
+
const previousUnit = previousValue?.unit;
|
|
69
|
+
|
|
70
|
+
if ( ! previousUnit || isExtendedUnit( previousUnit ) || ! units.includes( previousUnit ) ) {
|
|
71
|
+
return createDefaultSizeValue< T >( units, defaultUnit );
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return { size: DEFAULT_SIZE, unit: previousUnit } as T;
|
|
75
|
+
};
|
|
76
|
+
|
|
63
77
|
const resolveFallbackUnit = < TUnit extends SizeUnit >(
|
|
64
78
|
unit: TUnit,
|
|
65
79
|
units: readonly TUnit[],
|
|
@@ -116,7 +116,7 @@ export const SizeControl = createControl(
|
|
|
116
116
|
const popupState = usePopupState( { variant: 'popover' } );
|
|
117
117
|
|
|
118
118
|
const memorizedExternalState = useMemo(
|
|
119
|
-
() => createStateFromSizeProp( sizeValue, actualDefaultUnit ),
|
|
119
|
+
() => ( sizeValue ? createStateFromSizeProp( sizeValue, actualDefaultUnit ) : null ),
|
|
120
120
|
[ sizeValue, actualDefaultUnit ]
|
|
121
121
|
);
|
|
122
122
|
|
|
@@ -125,10 +125,10 @@ export const SizeControl = createControl(
|
|
|
125
125
|
setExternal: ( newState: State | null, options, meta ) =>
|
|
126
126
|
setSizeValue( extractValueFromState( newState ), options, meta ),
|
|
127
127
|
persistWhen: ( newState ) => !! extractValueFromState( newState ),
|
|
128
|
-
fallback: (
|
|
129
|
-
unit:
|
|
130
|
-
numeric:
|
|
131
|
-
custom:
|
|
128
|
+
fallback: ( prevState ) => ( {
|
|
129
|
+
unit: prevState?.unit && ! isUnitExtendedOption( prevState.unit ) ? prevState.unit : actualDefaultUnit,
|
|
130
|
+
numeric: DEFAULT_SIZE,
|
|
131
|
+
custom: '',
|
|
132
132
|
} ),
|
|
133
133
|
} );
|
|
134
134
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useMemo, useState } from 'react';
|
|
1
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
2
2
|
import { numberPropTypeUtil, type QueryPropValue, stringPropTypeUtil } from '@elementor/editor-props';
|
|
3
3
|
import { type HttpResponse, httpService } from '@elementor/http-client';
|
|
4
4
|
import { debounce } from '@elementor/utils';
|
|
@@ -47,13 +47,17 @@ export function useQueryAutocomplete( {
|
|
|
47
47
|
[ url, excludeIdSet ]
|
|
48
48
|
);
|
|
49
49
|
|
|
50
|
+
const paramsKey = useMemo( () => JSON.stringify( params ), [ params ] );
|
|
51
|
+
const paramsRef = useRef( params );
|
|
52
|
+
paramsRef.current = params;
|
|
53
|
+
|
|
50
54
|
useEffect( () => {
|
|
51
55
|
if ( minInputLength === 0 && url ) {
|
|
52
|
-
fetchOptions( url, { ...
|
|
56
|
+
fetchOptions( url, { ...paramsRef.current, term: '' } ).then( ( newOptions ) => {
|
|
53
57
|
setOptions( formatOptions( filterExcludedOptions( newOptions, excludeIdSet ) ) );
|
|
54
58
|
} );
|
|
55
59
|
}
|
|
56
|
-
}, [ url, minInputLength, excludeIdSet,
|
|
60
|
+
}, [ url, minInputLength, excludeIdSet, paramsKey ] );
|
|
57
61
|
|
|
58
62
|
const updateOptions = ( term: string | null ) => {
|
|
59
63
|
const termStr = term ?? '';
|
package/src/index.ts
CHANGED
|
@@ -23,6 +23,7 @@ export { HtmlTagControl } from './controls/html-tag-control';
|
|
|
23
23
|
export { QueryChipsControl } from './controls/query-chips-control';
|
|
24
24
|
export { QueryControl } from './controls/query-control';
|
|
25
25
|
export { QueryFilterRepeaterControl } from './controls/query-filter-repeater-control';
|
|
26
|
+
export { QuerySelectControl } from './controls/query-select-control';
|
|
26
27
|
export { GapControl } from './controls/gap-control';
|
|
27
28
|
export { AspectRatioControl } from './controls/aspect-ratio-control';
|
|
28
29
|
export { SvgMediaControl } from './controls/svg-media-control';
|