@elementor/editor-controls 4.4.0-beta2 → 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.js +64 -58
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +75 -69
- 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/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
|
/>
|