@elementor/editor-global-classes 4.1.0-822 → 4.1.0-824
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 +132 -80
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +131 -79
- package/dist/index.mjs.map +1 -1
- package/package.json +21 -20
- package/src/components/class-manager/class-manager-panel.tsx +6 -16
- package/src/components/class-manager/global-classes-list.tsx +62 -14
- package/src/components/class-manager/sortable.tsx +9 -3
- package/src/components/global-styles-import-listener.tsx +3 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/editor-global-classes",
|
|
3
|
-
"version": "4.1.0-
|
|
3
|
+
"version": "4.1.0-824",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Elementor Team",
|
|
6
6
|
"homepage": "https://elementor.com/",
|
|
@@ -39,28 +39,29 @@
|
|
|
39
39
|
"dev": "tsup --config=../../tsup.dev.ts"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@elementor/editor": "4.1.0-
|
|
43
|
-
"@elementor/editor-current-user": "4.1.0-
|
|
44
|
-
"@elementor/editor-documents": "4.1.0-
|
|
45
|
-
"@elementor/editor-editing-panel": "4.1.0-
|
|
46
|
-
"@elementor/editor-mcp": "4.1.0-
|
|
47
|
-
"@elementor/editor-panels": "4.1.0-
|
|
48
|
-
"@elementor/editor-props": "4.1.0-
|
|
49
|
-
"@elementor/editor-variables": "4.1.0-
|
|
50
|
-
"@elementor/editor-styles": "4.1.0-
|
|
51
|
-
"@elementor/editor-canvas": "4.1.0-
|
|
52
|
-
"@elementor/editor-styles-repository": "4.1.0-
|
|
53
|
-
"@elementor/editor-ui": "4.1.0-
|
|
54
|
-
"@elementor/editor-v1-adapters": "4.1.0-
|
|
55
|
-
"@elementor/http-client": "4.1.0-
|
|
42
|
+
"@elementor/editor": "4.1.0-824",
|
|
43
|
+
"@elementor/editor-current-user": "4.1.0-824",
|
|
44
|
+
"@elementor/editor-documents": "4.1.0-824",
|
|
45
|
+
"@elementor/editor-editing-panel": "4.1.0-824",
|
|
46
|
+
"@elementor/editor-mcp": "4.1.0-824",
|
|
47
|
+
"@elementor/editor-panels": "4.1.0-824",
|
|
48
|
+
"@elementor/editor-props": "4.1.0-824",
|
|
49
|
+
"@elementor/editor-variables": "4.1.0-824",
|
|
50
|
+
"@elementor/editor-styles": "4.1.0-824",
|
|
51
|
+
"@elementor/editor-canvas": "4.1.0-824",
|
|
52
|
+
"@elementor/editor-styles-repository": "4.1.0-824",
|
|
53
|
+
"@elementor/editor-ui": "4.1.0-824",
|
|
54
|
+
"@elementor/editor-v1-adapters": "4.1.0-824",
|
|
55
|
+
"@elementor/http-client": "4.1.0-824",
|
|
56
56
|
"@elementor/icons": "^1.68.0",
|
|
57
|
-
"@elementor/query": "4.1.0-
|
|
58
|
-
"@elementor/schema": "4.1.0-
|
|
59
|
-
"@elementor/store": "4.1.0-
|
|
57
|
+
"@elementor/query": "4.1.0-824",
|
|
58
|
+
"@elementor/schema": "4.1.0-824",
|
|
59
|
+
"@elementor/store": "4.1.0-824",
|
|
60
60
|
"@elementor/ui": "1.37.5",
|
|
61
|
-
"@elementor/utils": "4.1.0-
|
|
61
|
+
"@elementor/utils": "4.1.0-824",
|
|
62
|
+
"@tanstack/react-virtual": "^3.13.24",
|
|
62
63
|
"@wordpress/i18n": "^5.13.0",
|
|
63
|
-
"@elementor/events": "4.1.0-
|
|
64
|
+
"@elementor/events": "4.1.0-824"
|
|
64
65
|
},
|
|
65
66
|
"peerDependencies": {
|
|
66
67
|
"react": "^18.3.1",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { useCallback, useEffect, useState } from 'react';
|
|
3
3
|
import { useSuppressedMessage } from '@elementor/editor-current-user';
|
|
4
|
-
import {
|
|
4
|
+
import { reloadCurrentDocument, setDocumentModifiedStatus } from '@elementor/editor-documents';
|
|
5
5
|
import {
|
|
6
6
|
__createPanel as createPanel,
|
|
7
7
|
Panel,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
PanelHeaderTitle,
|
|
12
12
|
} from '@elementor/editor-panels';
|
|
13
13
|
import { ConfirmationDialog, SaveChangesDialog, ThemeProvider, useDialog } from '@elementor/editor-ui';
|
|
14
|
-
import {
|
|
14
|
+
import { changeEditMode } from '@elementor/editor-v1-adapters';
|
|
15
15
|
import { XIcon } from '@elementor/icons';
|
|
16
16
|
import { useMutation } from '@elementor/query';
|
|
17
17
|
import { __dispatch as dispatch } from '@elementor/store';
|
|
@@ -56,19 +56,6 @@ type StopSyncConfirmationDialogProps = {
|
|
|
56
56
|
|
|
57
57
|
const id = 'global-classes-manager';
|
|
58
58
|
|
|
59
|
-
const reloadDocument = () => {
|
|
60
|
-
const currentDocument = getCurrentDocument();
|
|
61
|
-
const documentsManager = getV1DocumentsManager();
|
|
62
|
-
|
|
63
|
-
documentsManager.invalidateCache();
|
|
64
|
-
|
|
65
|
-
return runCommand( 'editor/documents/switch', {
|
|
66
|
-
id: currentDocument?.id,
|
|
67
|
-
shouldScroll: false,
|
|
68
|
-
shouldNavigateToDefaultRoute: false,
|
|
69
|
-
} );
|
|
70
|
-
};
|
|
71
|
-
|
|
72
59
|
// We need to disable the app-bar buttons, and the elements overlays when opening the classes manager panel.
|
|
73
60
|
// The buttons and overlays are enabled only in edit mode, so we're creating a custom new edit mode that
|
|
74
61
|
// will force them to be disabled. We can't use the `preview` edit mode in this case since it'll force
|
|
@@ -84,7 +71,7 @@ export const { panel, usePanelActions } = createPanel( {
|
|
|
84
71
|
},
|
|
85
72
|
onClose: async () => {
|
|
86
73
|
changeEditMode( 'edit' );
|
|
87
|
-
await
|
|
74
|
+
await reloadCurrentDocument();
|
|
88
75
|
unblockPanelInteractions();
|
|
89
76
|
},
|
|
90
77
|
isOpenPreviousElement: true,
|
|
@@ -97,6 +84,7 @@ export function ClassManagerPanel() {
|
|
|
97
84
|
const [ stopSyncConfirmation, setStopSyncConfirmation ] = useState< string | null >( null );
|
|
98
85
|
const [ startSyncConfirmation, setStartSyncConfirmation ] = useState< string | null >( null );
|
|
99
86
|
const [ isStopSyncSuppressed ] = useSuppressedMessage( STOP_SYNC_MESSAGE_KEY );
|
|
87
|
+
const [ scrollElement, setScrollElement ] = useState< HTMLElement | null >( null );
|
|
100
88
|
|
|
101
89
|
const { mutateAsync: publish, isPending: isPublishing } = usePublish();
|
|
102
90
|
|
|
@@ -190,6 +178,7 @@ export function ClassManagerPanel() {
|
|
|
190
178
|
</Box>
|
|
191
179
|
<Divider />
|
|
192
180
|
<Box
|
|
181
|
+
ref={ setScrollElement }
|
|
193
182
|
px={ 2 }
|
|
194
183
|
sx={ {
|
|
195
184
|
flexGrow: 1,
|
|
@@ -198,6 +187,7 @@ export function ClassManagerPanel() {
|
|
|
198
187
|
>
|
|
199
188
|
<GlobalClassesList
|
|
200
189
|
disabled={ isPublishing }
|
|
190
|
+
scrollElement={ scrollElement }
|
|
201
191
|
onStopSyncRequest={ handleStopSyncRequest }
|
|
202
192
|
onStartSyncRequest={ ( classId ) => setStartSyncConfirmation( classId ) }
|
|
203
193
|
/>
|
|
@@ -3,6 +3,7 @@ import { useEffect, useMemo, useState } from 'react';
|
|
|
3
3
|
import { type StyleDefinition, type StyleDefinitionID } from '@elementor/editor-styles';
|
|
4
4
|
import { __useDispatch as useDispatch } from '@elementor/store';
|
|
5
5
|
import { List, Stack, styled, Typography, type TypographyProps } from '@elementor/ui';
|
|
6
|
+
import { defaultRangeExtractor, useVirtualizer } from '@tanstack/react-virtual';
|
|
6
7
|
import { __ } from '@wordpress/i18n';
|
|
7
8
|
|
|
8
9
|
import { useClassesOrder } from '../../hooks/use-classes-order';
|
|
@@ -17,13 +18,22 @@ import { FlippedColorSwatchIcon } from './flipped-color-swatch-icon';
|
|
|
17
18
|
import { getNotFoundType, NotFound } from './not-found';
|
|
18
19
|
import { SortableItem, SortableProvider } from './sortable';
|
|
19
20
|
|
|
21
|
+
const ROW_HEIGHT = 40;
|
|
22
|
+
const OVERSCAN = 6;
|
|
23
|
+
|
|
20
24
|
type GlobalClassesListProps = {
|
|
21
25
|
disabled?: boolean;
|
|
26
|
+
scrollElement?: HTMLElement | null;
|
|
22
27
|
onStopSyncRequest?: ( id: string ) => void;
|
|
23
28
|
onStartSyncRequest?: ( id: string ) => void;
|
|
24
29
|
};
|
|
25
30
|
|
|
26
|
-
export const GlobalClassesList = ( {
|
|
31
|
+
export const GlobalClassesList = ( {
|
|
32
|
+
disabled,
|
|
33
|
+
scrollElement,
|
|
34
|
+
onStopSyncRequest,
|
|
35
|
+
onStartSyncRequest,
|
|
36
|
+
}: GlobalClassesListProps ) => {
|
|
27
37
|
const {
|
|
28
38
|
search: { debouncedValue: searchValue },
|
|
29
39
|
} = useSearchAndFilters();
|
|
@@ -35,6 +45,27 @@ export const GlobalClassesList = ( { disabled, onStopSyncRequest, onStartSyncReq
|
|
|
35
45
|
const [ classesOrder, reorderClasses ] = useReorder( draggedItemId, setDraggedItemId, draggedItemLabel ?? '' );
|
|
36
46
|
const filteredCssClasses = useFilteredCssClasses();
|
|
37
47
|
|
|
48
|
+
const virtualizer = useVirtualizer( {
|
|
49
|
+
count: filteredCssClasses.length,
|
|
50
|
+
getScrollElement: () => scrollElement ?? null,
|
|
51
|
+
estimateSize: () => ROW_HEIGHT,
|
|
52
|
+
overscan: OVERSCAN,
|
|
53
|
+
getItemKey: ( index ) => filteredCssClasses[ index ].id,
|
|
54
|
+
// Keep the actively dragged row mounted even when scrolled out of view.
|
|
55
|
+
// SortableItem unregisters its render on unmount, which would make the
|
|
56
|
+
// DragOverlay clone disappear mid-drag.
|
|
57
|
+
rangeExtractor: ( range ) => {
|
|
58
|
+
const indices = new Set( defaultRangeExtractor( range ) );
|
|
59
|
+
if ( draggedItemId ) {
|
|
60
|
+
const draggedItemIndex = filteredCssClasses.findIndex( ( cssClass ) => cssClass.id === draggedItemId );
|
|
61
|
+
if ( draggedItemIndex >= 0 ) {
|
|
62
|
+
indices.add( draggedItemIndex );
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return [ ...indices ].sort( ( a, b ) => a - b );
|
|
66
|
+
},
|
|
67
|
+
} );
|
|
68
|
+
|
|
38
69
|
useEffect( () => {
|
|
39
70
|
const handler = ( event: KeyboardEvent ) => {
|
|
40
71
|
if ( event.key === 'z' && ( event.ctrlKey || event.metaKey ) ) {
|
|
@@ -69,19 +100,36 @@ export const GlobalClassesList = ( { disabled, onStopSyncRequest, onStartSyncReq
|
|
|
69
100
|
|
|
70
101
|
return (
|
|
71
102
|
<DeleteConfirmationProvider>
|
|
72
|
-
<List
|
|
103
|
+
<List
|
|
104
|
+
sx={ {
|
|
105
|
+
position: 'relative',
|
|
106
|
+
display: 'block',
|
|
107
|
+
height: virtualizer.getTotalSize(),
|
|
108
|
+
padding: 0,
|
|
109
|
+
} }
|
|
110
|
+
>
|
|
73
111
|
<SortableProvider
|
|
74
112
|
value={ classesOrder }
|
|
75
113
|
onChange={ reorderClasses }
|
|
114
|
+
onDragStart={ ( event ) => setDraggedItemId( event.active.id as StyleDefinitionID ) }
|
|
115
|
+
onDragEnd={ () => setDraggedItemId( null ) }
|
|
116
|
+
onDragCancel={ () => setDraggedItemId( null ) }
|
|
76
117
|
disableDragOverlay={ ! allowSorting }
|
|
77
118
|
>
|
|
78
|
-
{
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
|
|
119
|
+
{ virtualizer.getVirtualItems().map( ( virtualRow ) => {
|
|
120
|
+
const cssClass = filteredCssClasses[ virtualRow.index ];
|
|
121
|
+
return (
|
|
122
|
+
<SortableItem
|
|
123
|
+
key={ virtualRow.key }
|
|
124
|
+
id={ cssClass.id }
|
|
125
|
+
style={ {
|
|
126
|
+
position: 'absolute',
|
|
127
|
+
top: virtualRow.start,
|
|
128
|
+
left: 0,
|
|
129
|
+
width: '100%',
|
|
130
|
+
} }
|
|
131
|
+
>
|
|
132
|
+
{ ( { isDragged, isDragPlaceholder, triggerProps, triggerStyle } ) => (
|
|
85
133
|
<ClassItem
|
|
86
134
|
id={ cssClass.id }
|
|
87
135
|
label={ cssClass.label }
|
|
@@ -127,10 +175,10 @@ export const GlobalClassesList = ( { disabled, onStopSyncRequest, onStartSyncReq
|
|
|
127
175
|
}
|
|
128
176
|
} }
|
|
129
177
|
/>
|
|
130
|
-
)
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
178
|
+
) }
|
|
179
|
+
</SortableItem>
|
|
180
|
+
);
|
|
181
|
+
} ) }
|
|
134
182
|
</SortableProvider>
|
|
135
183
|
</List>
|
|
136
184
|
</DeleteConfirmationProvider>
|
|
@@ -176,7 +224,7 @@ const useReorder = (
|
|
|
176
224
|
classId: draggedItemId,
|
|
177
225
|
classTitle: draggedItemLabel,
|
|
178
226
|
} );
|
|
179
|
-
setDraggedItemId( null );
|
|
227
|
+
setDraggedItemId( null );
|
|
180
228
|
}
|
|
181
229
|
};
|
|
182
230
|
|
|
@@ -11,7 +11,12 @@ import {
|
|
|
11
11
|
} from '@elementor/ui';
|
|
12
12
|
|
|
13
13
|
export const SortableProvider = < T extends string >( props: UnstableSortableProviderProps< T > ) => (
|
|
14
|
-
<UnstableSortableProvider
|
|
14
|
+
<UnstableSortableProvider
|
|
15
|
+
restrictAxis
|
|
16
|
+
variant="static"
|
|
17
|
+
dragPlaceholderStyle={ { visibility: 'hidden' } }
|
|
18
|
+
{ ...props }
|
|
19
|
+
/>
|
|
15
20
|
);
|
|
16
21
|
|
|
17
22
|
export type SortableTriggerProps = React.HTMLAttributes< HTMLDivElement >;
|
|
@@ -24,10 +29,11 @@ export const SortableTrigger = ( props: SortableTriggerProps ) => (
|
|
|
24
29
|
|
|
25
30
|
type SortableItemProps = {
|
|
26
31
|
id: UnstableSortableItemProps[ 'id' ];
|
|
32
|
+
style?: React.CSSProperties;
|
|
27
33
|
children: ( props: Partial< UnstableSortableItemRenderProps > ) => React.ReactNode;
|
|
28
34
|
};
|
|
29
35
|
|
|
30
|
-
export const SortableItem = ( { children, id, ...props }: SortableItemProps ) => {
|
|
36
|
+
export const SortableItem = ( { children, id, style, ...props }: SortableItemProps ) => {
|
|
31
37
|
return (
|
|
32
38
|
<UnstableSortableItem
|
|
33
39
|
{ ...props }
|
|
@@ -46,7 +52,7 @@ export const SortableItem = ( { children, id, ...props }: SortableItemProps ) =>
|
|
|
46
52
|
return (
|
|
47
53
|
<Box
|
|
48
54
|
{ ...itemProps }
|
|
49
|
-
style={ itemStyle }
|
|
55
|
+
style={ { ...itemStyle, ...( ! isDragOverlay ? style : null ) } }
|
|
50
56
|
component={ 'li' }
|
|
51
57
|
role="listitem"
|
|
52
58
|
sx={ {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useEffect } from 'react';
|
|
2
|
+
import { GLOBAL_STYLES_IMPORTED_EVENT } from '@elementor/editor-canvas';
|
|
2
3
|
import { __useDispatch as useDispatch } from '@elementor/store';
|
|
3
4
|
|
|
4
5
|
import { apiClient } from '../api';
|
|
@@ -47,13 +48,10 @@ export function GlobalStylesImportListener() {
|
|
|
47
48
|
.catch( () => {} );
|
|
48
49
|
};
|
|
49
50
|
|
|
50
|
-
window.addEventListener(
|
|
51
|
+
window.addEventListener( GLOBAL_STYLES_IMPORTED_EVENT, handleGlobalStylesImported as EventListener );
|
|
51
52
|
|
|
52
53
|
return () => {
|
|
53
|
-
window.removeEventListener(
|
|
54
|
-
'elementor/global-styles/imported',
|
|
55
|
-
handleGlobalStylesImported as EventListener
|
|
56
|
-
);
|
|
54
|
+
window.removeEventListener( GLOBAL_STYLES_IMPORTED_EVENT, handleGlobalStylesImported as EventListener );
|
|
57
55
|
};
|
|
58
56
|
}, [ dispatch ] );
|
|
59
57
|
|