@@ -7,14 +7,61 @@ import {
7
7
getBlockMenuDefaultClassName ,
8
8
switchToBlockType ,
9
9
} from '@wordpress/blocks' ;
10
- import { useState } from '@wordpress/element' ;
10
+ import { useState , useMemo } from '@wordpress/element' ;
11
11
12
12
/**
13
13
* Internal dependencies
14
14
*/
15
15
import BlockIcon from '../block-icon' ;
16
16
import PreviewBlockPopover from './preview-block-popover' ;
17
17
18
+ /**
19
+ * Helper hook to group transformations to display them in a specific order in the UI.
20
+ * For now we group only priority content driven transformations(ex. paragraph -> heading).
21
+ *
22
+ * Later on we could also group 'layout' transformations(ex. paragraph -> group) and
23
+ * display them in different sections.
24
+ *
25
+ * @param {Object[] } possibleBlockTransformations The available block transformations.
26
+ * @return {Record<string, Object[]> } The grouped block transformations.
27
+ */
28
+ function useGroupedTransforms ( possibleBlockTransformations ) {
29
+ const priorityContentTranformationBlocks = {
30
+ 'core/paragraph' : 1 ,
31
+ 'core/heading' : 2 ,
32
+ 'core/list' : 3 ,
33
+ 'core/quote' : 4 ,
34
+ } ;
35
+ const transformations = useMemo ( ( ) => {
36
+ const priorityTextTranformsNames = Object . keys (
37
+ priorityContentTranformationBlocks
38
+ ) ;
39
+ return possibleBlockTransformations . reduce (
40
+ ( accumulator , item ) => {
41
+ const { name } = item ;
42
+ if ( priorityTextTranformsNames . includes ( name ) ) {
43
+ accumulator . priorityTextTransformations . push ( item ) ;
44
+ } else {
45
+ accumulator . restTransformations . push ( item ) ;
46
+ }
47
+ return accumulator ;
48
+ } ,
49
+ { priorityTextTransformations : [ ] , restTransformations : [ ] }
50
+ ) ;
51
+ } , [ possibleBlockTransformations ] ) ;
52
+
53
+ // Order the priority text transformations.
54
+ transformations . priorityTextTransformations . sort (
55
+ ( { name : currentName } , { name : nextName } ) => {
56
+ return priorityContentTranformationBlocks [ currentName ] <
57
+ priorityContentTranformationBlocks [ nextName ]
58
+ ? - 1
59
+ : 1 ;
60
+ }
61
+ ) ;
62
+ return transformations ;
63
+ }
64
+
18
65
const BlockTransformationsMenu = ( {
19
66
className,
20
67
possibleBlockTransformations,
@@ -23,6 +70,11 @@ const BlockTransformationsMenu = ( {
23
70
} ) => {
24
71
const [ hoveredTransformItemName , setHoveredTransformItemName ] =
25
72
useState ( ) ;
73
+
74
+ const { priorityTextTransformations, restTransformations } =
75
+ useGroupedTransforms ( possibleBlockTransformations ) ;
76
+ const needsTextTransformationsSeparator =
77
+ priorityTextTransformations . length && restTransformations . length ;
26
78
return (
27
79
< MenuGroup label = { __ ( 'Transform to' ) } className = { className } >
28
80
{ hoveredTransformItemName && (
@@ -33,31 +85,48 @@ const BlockTransformationsMenu = ( {
33
85
) }
34
86
/>
35
87
) }
36
- { possibleBlockTransformations . map ( ( item ) => {
37
- const { name, icon, title, isDisabled } = item ;
38
- return (
39
- < MenuItem
40
- key = { name }
41
- className = { getBlockMenuDefaultClassName ( name ) }
42
- onClick = { ( event ) => {
43
- event . preventDefault ( ) ;
44
- onSelect ( name ) ;
45
- } }
46
- disabled = { isDisabled }
47
- onMouseLeave = { ( ) =>
48
- setHoveredTransformItemName ( null )
49
- }
50
- onMouseEnter = { ( ) =>
51
- setHoveredTransformItemName ( name )
52
- }
53
- >
54
- < BlockIcon icon = { icon } showColors />
55
- { title }
56
- </ MenuItem >
57
- ) ;
58
- } ) }
88
+ { priorityTextTransformations . map ( ( item ) => (
89
+ < BlockTranformationItem
90
+ key = { item . name }
91
+ item = { item }
92
+ onSelect = { onSelect }
93
+ setHoveredTransformItemName = { setHoveredTransformItemName }
94
+ />
95
+ ) ) }
96
+ { ! ! needsTextTransformationsSeparator && < hr /> }
97
+ { restTransformations . map ( ( item ) => (
98
+ < BlockTranformationItem
99
+ key = { item . name }
100
+ item = { item }
101
+ onSelect = { onSelect }
102
+ setHoveredTransformItemName = { setHoveredTransformItemName }
103
+ />
104
+ ) ) }
59
105
</ MenuGroup >
60
106
) ;
61
107
} ;
62
108
109
+ function BlockTranformationItem ( {
110
+ item,
111
+ onSelect,
112
+ setHoveredTransformItemName,
113
+ } ) {
114
+ const { name, icon, title, isDisabled } = item ;
115
+ return (
116
+ < MenuItem
117
+ className = { getBlockMenuDefaultClassName ( name ) }
118
+ onClick = { ( event ) => {
119
+ event . preventDefault ( ) ;
120
+ onSelect ( name ) ;
121
+ } }
122
+ disabled = { isDisabled }
123
+ onMouseLeave = { ( ) => setHoveredTransformItemName ( null ) }
124
+ onMouseEnter = { ( ) => setHoveredTransformItemName ( name ) }
125
+ >
126
+ < BlockIcon icon = { icon } showColors />
127
+ { title }
128
+ </ MenuItem >
129
+ ) ;
130
+ }
131
+
63
132
export default BlockTransformationsMenu ;
0 commit comments