PluginProbe ʕ •ᴥ•ʔ
GenerateBlocks / 2.0.0
GenerateBlocks v2.0.0
trunk 1.0 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.2.0 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.7.0 1.7.1 1.7.2 1.7.3 1.8.0 1.8.1 1.8.2 1.8.3 1.9.0 1.9.1 2.0.0 2.0.1 2.0.2 2.1.0 2.1.1 2.1.2 2.2.0 2.2.1 2.3.0
generateblocks / src / blocks / grid / transforms.js
generateblocks / src / blocks / grid Last commit date
components 1 year ago css 3 years ago attributes.js 2 years ago block.js 1 year ago deprecated.js 3 years ago edit.js 2 years ago editor.scss 4 years ago transforms.js 1 year ago
transforms.js
208 lines
1 import { convertLegacyHtmlAttributes } from '@utils/convertLegacyHtmlAttributes';
2 import { convertLocalToStyles } from '@utils/legacyStyleUtils';
3 import { createBlock, getBlockType } from '@wordpress/blocks';
4 import { getAtRuleValue } from '@edge22/styles-builder';
5 import hasNumericValue from '@utils/has-numeric-value';
6
7 const GRID_MAPPINGS = {
8 '40,60': '2fr 3fr',
9 '60,40': '3fr 2fr',
10 '30,70': '3fr 7fr',
11 '70,30': '7fr 3fr',
12 '20,80': '2fr 8fr',
13 '80,20': '8fr 2fr',
14 };
15
16 function getMostCommon( widths ) {
17 if ( widths.length === 0 ) {
18 return '';
19 }
20
21 const frequencyMap = {};
22 let maxFrequency = 0;
23 let mostCommonElement = widths[ 0 ];
24
25 for ( const item of widths ) {
26 frequencyMap[ item ] = ( frequencyMap[ item ] || 0 ) + 1;
27
28 if ( frequencyMap[ item ] > maxFrequency ) {
29 maxFrequency = frequencyMap[ item ];
30 mostCommonElement = item;
31 }
32 }
33
34 return mostCommonElement;
35 }
36
37 function getGridValue( width ) {
38 let gridValue = '';
39
40 switch ( width ) {
41 case '100%':
42 gridValue = '1fr';
43 break;
44 case '50%':
45 gridValue = 'repeat(2, minmax(0, 1fr))';
46 break;
47 case '33.33%':
48 case '33%':
49 gridValue = 'repeat(3, minmax(0, 1fr))';
50 break;
51 case '25%':
52 gridValue = 'repeat(4, minmax(0, 1fr))';
53 break;
54 case '20%':
55 gridValue = 'repeat(5, minmax(0, 1fr))';
56 break;
57 case '16.66%':
58 case '16%':
59 gridValue = 'repeat(6, minmax(0, 1fr))';
60 break;
61 default:
62 gridValue = 'repeat(2, minmax(0, 1fr))';
63 break;
64 }
65
66 return gridValue;
67 }
68
69 function getGapValue( value ) {
70 return hasNumericValue( value ) ? `${ value }px` : '';
71 }
72
73 function convertToGridValue( widths ) {
74 // Early return if not exactly 2 widths
75 if ( ! Array.isArray( widths ) || widths.length !== 2 ) {
76 return null;
77 }
78
79 // Normalize widths by removing '%' and creating a key
80 const normalizedKey = widths
81 .map( ( width ) => width.replace( '%', '' ) )
82 .join( ',' );
83
84 return GRID_MAPPINGS[ normalizedKey ] || null;
85 }
86
87 export const transforms = {
88 to: [
89 {
90 type: 'block',
91 blocks: [ 'generateblocks/element' ],
92 isMatch: ( {
93 isQueryLoop,
94 } ) => {
95 if (
96 isQueryLoop
97 ) {
98 return false;
99 }
100
101 return true;
102 },
103 transform: ( attributes, blocks ) => {
104 const {
105 htmlAttributes,
106 blockLabel,
107 globalClasses,
108 anchor,
109 className,
110 verticalGap,
111 verticalGapTablet,
112 verticalGapMobile,
113 horizontalGap,
114 horizontalGapTablet,
115 horizontalGapMobile,
116 } = attributes;
117 const attributeData = getBlockType( 'generateblocks/grid' )?.attributes;
118 const styles = convertLocalToStyles( attributeData, attributes, '&:is(:hover, :focus)' );
119 const newHtmlAttributes = convertLegacyHtmlAttributes( htmlAttributes );
120
121 if ( anchor ) {
122 newHtmlAttributes.id = anchor;
123 }
124
125 const metaData = {};
126
127 if ( blockLabel ) {
128 metaData.name = blockLabel;
129 }
130
131 const blockWidths = {
132 desktop: [],
133 tablet: [],
134 mobile: [],
135 };
136
137 blocks.forEach( ( block ) => {
138 blockWidths.desktop.push( block.attributes.sizing?.width );
139 blockWidths.tablet.push( block.attributes.sizing?.widthTablet );
140 blockWidths.mobile.push( block.attributes.sizing?.widthMobile );
141 } );
142
143 // Get the most common width for each device.
144 const mostCommonDesktopWidth = getMostCommon( blockWidths.desktop );
145 const mostCommonTabletWidth = getMostCommon( blockWidths.tablet );
146 const mostCommonMobileWidth = getMostCommon( blockWidths.mobile );
147
148 // Clone the Blocks to be Grouped
149 // Failing to create new block references causes the original blocks
150 // to be replaced in the switchToBlockType call thereby meaning they
151 // are removed both from their original location and within the
152 // new group block.
153 const groupInnerBlocks = blocks.map( ( block ) => {
154 return createBlock(
155 block.name,
156 {
157 ...block.attributes,
158 sizing: {},
159 },
160 block.innerBlocks
161 );
162 } );
163
164 const tabletAtRule = getAtRuleValue( 'mediumSmallWidth' );
165 const mobileAtRule = getAtRuleValue( 'smallWidth' );
166 const tabletGridValue = getGridValue( mostCommonTabletWidth );
167 const mobileGridValue = getGridValue( mostCommonMobileWidth );
168
169 const desktopWidths = blockWidths.desktop;
170 const desktopGridValue = convertToGridValue( desktopWidths ) || getGridValue( mostCommonDesktopWidth );
171
172 return createBlock(
173 'generateblocks/element',
174 {
175 tagName: 'div',
176 styles: {
177 ...styles,
178 display: 'grid',
179 gridTemplateColumns: desktopGridValue,
180 columnGap: getGapValue( horizontalGap ),
181 rowGap: getGapValue( verticalGap ),
182 [ tabletAtRule ]: {
183 ...styles[ tabletAtRule ],
184 gridTemplateColumns: tabletGridValue,
185 columnGap: getGapValue( horizontalGapTablet ),
186 rowGap: getGapValue( verticalGapTablet ),
187 },
188 [ mobileAtRule ]: {
189 ...styles[ mobileAtRule ],
190 gridTemplateColumns: tabletGridValue !== mobileGridValue
191 ? mobileGridValue
192 : '',
193 columnGap: getGapValue( horizontalGapMobile ),
194 rowGap: getGapValue( verticalGapMobile ),
195 },
196 },
197 htmlAttributes: newHtmlAttributes,
198 metadata: metaData,
199 globalClasses,
200 className,
201 },
202 groupInnerBlocks
203 );
204 },
205 },
206 ],
207 };
208