@wordpress/global-styles-engine 1.17.1-next.v.202607070741.0 → 1.18.0
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/CHANGELOG.md +2 -0
- package/build/core/render.cjs +36 -16
- package/build/core/render.cjs.map +2 -2
- package/build/index.cjs +3 -0
- package/build/index.cjs.map +2 -2
- package/build/lock-unlock.cjs +37 -0
- package/build/lock-unlock.cjs.map +7 -0
- package/build/private-apis.cjs +38 -0
- package/build/private-apis.cjs.map +7 -0
- package/build/settings/get-setting.cjs +3 -1
- package/build/settings/get-setting.cjs.map +2 -2
- package/build/types.cjs.map +1 -1
- package/build/utils/viewport.cjs +108 -0
- package/build/utils/viewport.cjs.map +7 -0
- package/build-module/core/render.mjs +36 -16
- package/build-module/core/render.mjs.map +2 -2
- package/build-module/index.mjs +2 -0
- package/build-module/index.mjs.map +2 -2
- package/build-module/lock-unlock.mjs +11 -0
- package/build-module/lock-unlock.mjs.map +7 -0
- package/build-module/private-apis.mjs +17 -0
- package/build-module/private-apis.mjs.map +7 -0
- package/build-module/settings/get-setting.mjs +3 -1
- package/build-module/settings/get-setting.mjs.map +2 -2
- package/build-module/utils/viewport.mjs +81 -0
- package/build-module/utils/viewport.mjs.map +7 -0
- package/build-types/core/render.d.ts +1 -1
- package/build-types/core/render.d.ts.map +1 -1
- package/build-types/index.d.ts +1 -0
- package/build-types/index.d.ts.map +1 -1
- package/build-types/lock-unlock.d.ts +2 -0
- package/build-types/lock-unlock.d.ts.map +1 -0
- package/build-types/private-apis.d.ts +2 -0
- package/build-types/private-apis.d.ts.map +1 -0
- package/build-types/settings/get-setting.d.ts.map +1 -1
- package/build-types/style-state-back-compat.d.ts.map +1 -1
- package/build-types/types.d.ts +4 -0
- package/build-types/types.d.ts.map +1 -1
- package/build-types/utils/fluid.d.ts +1 -1
- package/build-types/utils/fluid.d.ts.map +1 -1
- package/build-types/utils/viewport.d.ts +41 -0
- package/build-types/utils/viewport.d.ts.map +1 -0
- package/package.json +7 -6
- package/src/core/render.tsx +45 -21
- package/src/index.ts +1 -0
- package/src/lock-unlock.ts +10 -0
- package/src/private-apis.ts +16 -0
- package/src/settings/get-setting.ts +2 -0
- package/src/test/render.test.ts +182 -0
- package/src/test/viewport-utils.test.ts +168 -0
- package/src/types.ts +4 -0
- package/src/utils/viewport.ts +153 -0
package/src/test/render.test.ts
CHANGED
|
@@ -1040,6 +1040,47 @@ describe( 'global styles renderer', () => {
|
|
|
1040
1040
|
);
|
|
1041
1041
|
} );
|
|
1042
1042
|
|
|
1043
|
+
it( 'handles responsive block gap styles', () => {
|
|
1044
|
+
const tree = {
|
|
1045
|
+
styles: {
|
|
1046
|
+
blocks: {
|
|
1047
|
+
'core/group': {
|
|
1048
|
+
'@mobile': {
|
|
1049
|
+
spacing: {
|
|
1050
|
+
blockGap: '24px',
|
|
1051
|
+
},
|
|
1052
|
+
},
|
|
1053
|
+
},
|
|
1054
|
+
},
|
|
1055
|
+
},
|
|
1056
|
+
} as unknown as GlobalStylesConfig;
|
|
1057
|
+
|
|
1058
|
+
const blockSelectors = {
|
|
1059
|
+
'core/group': {
|
|
1060
|
+
selector: '.wp-block-group',
|
|
1061
|
+
hasLayoutSupport: true,
|
|
1062
|
+
},
|
|
1063
|
+
};
|
|
1064
|
+
|
|
1065
|
+
const result = transformToStyles(
|
|
1066
|
+
Object.freeze( tree ),
|
|
1067
|
+
blockSelectors,
|
|
1068
|
+
true,
|
|
1069
|
+
false,
|
|
1070
|
+
false,
|
|
1071
|
+
true,
|
|
1072
|
+
minimalStyleOptions
|
|
1073
|
+
);
|
|
1074
|
+
|
|
1075
|
+
expect( result ).toContain( '@media (width <= 480px)' );
|
|
1076
|
+
expect( result ).toContain(
|
|
1077
|
+
':root :where(.wp-block-group-is-layout-flow) > * { margin-block-start: 24px; margin-block-end: 0; }'
|
|
1078
|
+
);
|
|
1079
|
+
expect( result ).toContain(
|
|
1080
|
+
':root :where(.wp-block-group-is-layout-flex) { gap: 24px; }'
|
|
1081
|
+
);
|
|
1082
|
+
} );
|
|
1083
|
+
|
|
1043
1084
|
it( 'handles legacy responsive block styles', () => {
|
|
1044
1085
|
const tree = {
|
|
1045
1086
|
styles: {
|
|
@@ -1079,6 +1120,147 @@ describe( 'global styles renderer', () => {
|
|
|
1079
1120
|
);
|
|
1080
1121
|
} );
|
|
1081
1122
|
|
|
1123
|
+
it( 'uses custom viewport breakpoints for responsive block styles', () => {
|
|
1124
|
+
const tree = {
|
|
1125
|
+
settings: {
|
|
1126
|
+
viewport: {
|
|
1127
|
+
mobile: '640px',
|
|
1128
|
+
tablet: '960px',
|
|
1129
|
+
},
|
|
1130
|
+
},
|
|
1131
|
+
styles: {
|
|
1132
|
+
blocks: {
|
|
1133
|
+
'core/button': {
|
|
1134
|
+
'@mobile': {
|
|
1135
|
+
color: {
|
|
1136
|
+
text: 'blue',
|
|
1137
|
+
},
|
|
1138
|
+
},
|
|
1139
|
+
'@tablet': {
|
|
1140
|
+
color: {
|
|
1141
|
+
text: 'green',
|
|
1142
|
+
},
|
|
1143
|
+
},
|
|
1144
|
+
},
|
|
1145
|
+
},
|
|
1146
|
+
},
|
|
1147
|
+
} as unknown as GlobalStylesConfig;
|
|
1148
|
+
|
|
1149
|
+
const blockSelectors = {
|
|
1150
|
+
'core/button': {
|
|
1151
|
+
selector: '.wp-block-button',
|
|
1152
|
+
},
|
|
1153
|
+
};
|
|
1154
|
+
|
|
1155
|
+
const result = transformToStyles(
|
|
1156
|
+
Object.freeze( tree ),
|
|
1157
|
+
blockSelectors,
|
|
1158
|
+
false,
|
|
1159
|
+
false,
|
|
1160
|
+
true,
|
|
1161
|
+
true,
|
|
1162
|
+
minimalStyleOptions
|
|
1163
|
+
);
|
|
1164
|
+
|
|
1165
|
+
expect( result ).toEqual(
|
|
1166
|
+
'@media (width <= 640px){:root :where(.wp-block-button){color: blue;}}@media (640px < width <= 960px){:root :where(.wp-block-button){color: green;}}'
|
|
1167
|
+
);
|
|
1168
|
+
} );
|
|
1169
|
+
|
|
1170
|
+
it( 'omits tablet responsive styles when the tablet breakpoint is not larger than mobile', () => {
|
|
1171
|
+
const tree = {
|
|
1172
|
+
settings: {
|
|
1173
|
+
viewport: {
|
|
1174
|
+
mobile: '960px',
|
|
1175
|
+
tablet: '640px',
|
|
1176
|
+
},
|
|
1177
|
+
},
|
|
1178
|
+
styles: {
|
|
1179
|
+
blocks: {
|
|
1180
|
+
'core/button': {
|
|
1181
|
+
'@mobile': {
|
|
1182
|
+
color: {
|
|
1183
|
+
text: 'blue',
|
|
1184
|
+
},
|
|
1185
|
+
},
|
|
1186
|
+
'@tablet': {
|
|
1187
|
+
color: {
|
|
1188
|
+
text: 'green',
|
|
1189
|
+
},
|
|
1190
|
+
},
|
|
1191
|
+
},
|
|
1192
|
+
},
|
|
1193
|
+
},
|
|
1194
|
+
} as unknown as GlobalStylesConfig;
|
|
1195
|
+
|
|
1196
|
+
const blockSelectors = {
|
|
1197
|
+
'core/button': {
|
|
1198
|
+
selector: '.wp-block-button',
|
|
1199
|
+
},
|
|
1200
|
+
};
|
|
1201
|
+
|
|
1202
|
+
const result = transformToStyles(
|
|
1203
|
+
Object.freeze( tree ),
|
|
1204
|
+
blockSelectors,
|
|
1205
|
+
false,
|
|
1206
|
+
false,
|
|
1207
|
+
true,
|
|
1208
|
+
true,
|
|
1209
|
+
minimalStyleOptions
|
|
1210
|
+
);
|
|
1211
|
+
|
|
1212
|
+
expect( result ).toEqual(
|
|
1213
|
+
'@media (width <= 960px){:root :where(.wp-block-button){color: blue;}}'
|
|
1214
|
+
);
|
|
1215
|
+
} );
|
|
1216
|
+
|
|
1217
|
+
it( 'uses a single max-width tablet query when only the tablet breakpoint is valid', () => {
|
|
1218
|
+
const tree = {
|
|
1219
|
+
settings: {
|
|
1220
|
+
viewport: {
|
|
1221
|
+
mobile: '100%',
|
|
1222
|
+
tablet: '64rem',
|
|
1223
|
+
},
|
|
1224
|
+
},
|
|
1225
|
+
styles: {
|
|
1226
|
+
blocks: {
|
|
1227
|
+
'core/button': {
|
|
1228
|
+
'@mobile': {
|
|
1229
|
+
color: {
|
|
1230
|
+
text: 'blue',
|
|
1231
|
+
},
|
|
1232
|
+
},
|
|
1233
|
+
'@tablet': {
|
|
1234
|
+
color: {
|
|
1235
|
+
text: 'green',
|
|
1236
|
+
},
|
|
1237
|
+
},
|
|
1238
|
+
},
|
|
1239
|
+
},
|
|
1240
|
+
},
|
|
1241
|
+
} as unknown as GlobalStylesConfig;
|
|
1242
|
+
|
|
1243
|
+
const blockSelectors = {
|
|
1244
|
+
'core/button': {
|
|
1245
|
+
selector: '.wp-block-button',
|
|
1246
|
+
},
|
|
1247
|
+
};
|
|
1248
|
+
|
|
1249
|
+
const result = transformToStyles(
|
|
1250
|
+
Object.freeze( tree ),
|
|
1251
|
+
blockSelectors,
|
|
1252
|
+
false,
|
|
1253
|
+
false,
|
|
1254
|
+
true,
|
|
1255
|
+
true,
|
|
1256
|
+
minimalStyleOptions
|
|
1257
|
+
);
|
|
1258
|
+
|
|
1259
|
+
expect( result ).toEqual(
|
|
1260
|
+
'@media (width <= 64rem){:root :where(.wp-block-button){color: green;}}'
|
|
1261
|
+
);
|
|
1262
|
+
} );
|
|
1263
|
+
|
|
1082
1264
|
it( 'handles responsive pseudo selector styles', () => {
|
|
1083
1265
|
const tree = {
|
|
1084
1266
|
styles: {
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal dependencies
|
|
3
|
+
*/
|
|
4
|
+
import {
|
|
5
|
+
getResponsiveMediaQueries,
|
|
6
|
+
getViewportBreakpoints,
|
|
7
|
+
getViewportBreakpointValueInPixels,
|
|
8
|
+
} from '../utils/viewport';
|
|
9
|
+
|
|
10
|
+
describe( 'viewport utils', () => {
|
|
11
|
+
describe( 'getViewportBreakpointValueInPixels', () => {
|
|
12
|
+
it( 'returns numbers unchanged', () => {
|
|
13
|
+
expect( getViewportBreakpointValueInPixels( 640 ) ).toBe( 640 );
|
|
14
|
+
} );
|
|
15
|
+
|
|
16
|
+
it( 'returns pixel values as numbers', () => {
|
|
17
|
+
expect( getViewportBreakpointValueInPixels( '640px' ) ).toBe( 640 );
|
|
18
|
+
} );
|
|
19
|
+
|
|
20
|
+
it( 'converts em and rem values using a 16px base font size', () => {
|
|
21
|
+
expect( getViewportBreakpointValueInPixels( '40em' ) ).toBe( 640 );
|
|
22
|
+
expect( getViewportBreakpointValueInPixels( '64rem' ) ).toBe(
|
|
23
|
+
1024
|
|
24
|
+
);
|
|
25
|
+
} );
|
|
26
|
+
|
|
27
|
+
it( 'returns undefined for unsupported values', () => {
|
|
28
|
+
expect( getViewportBreakpointValueInPixels( undefined ) ).toBe(
|
|
29
|
+
undefined
|
|
30
|
+
);
|
|
31
|
+
expect( getViewportBreakpointValueInPixels( '100%' ) ).toBe(
|
|
32
|
+
undefined
|
|
33
|
+
);
|
|
34
|
+
expect( getViewportBreakpointValueInPixels( 'auto' ) ).toBe(
|
|
35
|
+
undefined
|
|
36
|
+
);
|
|
37
|
+
} );
|
|
38
|
+
} );
|
|
39
|
+
|
|
40
|
+
describe( 'getViewportBreakpoints', () => {
|
|
41
|
+
it( 'returns custom viewport breakpoints when they are ordered', () => {
|
|
42
|
+
expect(
|
|
43
|
+
getViewportBreakpoints( {
|
|
44
|
+
mobile: '40rem',
|
|
45
|
+
tablet: '64rem',
|
|
46
|
+
} )
|
|
47
|
+
).toEqual( {
|
|
48
|
+
mobile: '40rem',
|
|
49
|
+
tablet: '64rem',
|
|
50
|
+
} );
|
|
51
|
+
} );
|
|
52
|
+
|
|
53
|
+
it( 'returns default viewport breakpoints when no custom breakpoints are valid', () => {
|
|
54
|
+
expect(
|
|
55
|
+
getViewportBreakpoints( {
|
|
56
|
+
mobile: '100%',
|
|
57
|
+
tablet: 'auto',
|
|
58
|
+
} )
|
|
59
|
+
).toEqual( {
|
|
60
|
+
mobile: '480px',
|
|
61
|
+
tablet: '782px',
|
|
62
|
+
} );
|
|
63
|
+
} );
|
|
64
|
+
|
|
65
|
+
it( 'uses a valid custom breakpoint without merging defaults', () => {
|
|
66
|
+
const viewportSettings = {
|
|
67
|
+
mobile: ' 640px ',
|
|
68
|
+
tablet: 'calc(100% - 1rem)',
|
|
69
|
+
desktop: '1200px',
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
expect( getViewportBreakpoints( viewportSettings ) ).toEqual( {
|
|
73
|
+
mobile: '640px',
|
|
74
|
+
} );
|
|
75
|
+
} );
|
|
76
|
+
|
|
77
|
+
it( 'returns the configured viewport for a single breakpoint', () => {
|
|
78
|
+
expect(
|
|
79
|
+
getViewportBreakpoints( {
|
|
80
|
+
tablet: '64rem',
|
|
81
|
+
} )
|
|
82
|
+
).toEqual( {
|
|
83
|
+
tablet: '64rem',
|
|
84
|
+
} );
|
|
85
|
+
} );
|
|
86
|
+
|
|
87
|
+
it( 'preserves the tablet key when mobile is invalid', () => {
|
|
88
|
+
expect(
|
|
89
|
+
getViewportBreakpoints( {
|
|
90
|
+
mobile: '100%',
|
|
91
|
+
tablet: '64rem',
|
|
92
|
+
} )
|
|
93
|
+
).toEqual( {
|
|
94
|
+
tablet: '64rem',
|
|
95
|
+
} );
|
|
96
|
+
} );
|
|
97
|
+
|
|
98
|
+
it( 'omits tablet when it is not larger than mobile', () => {
|
|
99
|
+
expect(
|
|
100
|
+
getViewportBreakpoints( {
|
|
101
|
+
mobile: '64rem',
|
|
102
|
+
tablet: '40rem',
|
|
103
|
+
} )
|
|
104
|
+
).toEqual( {
|
|
105
|
+
mobile: '64rem',
|
|
106
|
+
} );
|
|
107
|
+
} );
|
|
108
|
+
} );
|
|
109
|
+
|
|
110
|
+
describe( 'getResponsiveMediaQueries', () => {
|
|
111
|
+
it( 'returns custom media queries when viewport breakpoints are ordered', () => {
|
|
112
|
+
expect(
|
|
113
|
+
getResponsiveMediaQueries( {
|
|
114
|
+
mobile: '640px',
|
|
115
|
+
tablet: '960px',
|
|
116
|
+
} )
|
|
117
|
+
).toEqual( {
|
|
118
|
+
'@mobile': '@media (width <= 640px)',
|
|
119
|
+
'@tablet': '@media (640px < width <= 960px)',
|
|
120
|
+
} );
|
|
121
|
+
} );
|
|
122
|
+
|
|
123
|
+
it( 'returns default media queries when no custom breakpoints are valid', () => {
|
|
124
|
+
expect(
|
|
125
|
+
getResponsiveMediaQueries( {
|
|
126
|
+
mobile: '100%',
|
|
127
|
+
tablet: 'auto',
|
|
128
|
+
} )
|
|
129
|
+
).toEqual( {
|
|
130
|
+
'@mobile': '@media (width <= 480px)',
|
|
131
|
+
'@tablet': '@media (480px < width <= 782px)',
|
|
132
|
+
} );
|
|
133
|
+
} );
|
|
134
|
+
|
|
135
|
+
it( 'uses a valid custom media query without merging defaults', () => {
|
|
136
|
+
expect(
|
|
137
|
+
getResponsiveMediaQueries( {
|
|
138
|
+
mobile: ' 640px ',
|
|
139
|
+
tablet: 'calc(100% - 1rem)',
|
|
140
|
+
} )
|
|
141
|
+
).toEqual( {
|
|
142
|
+
'@mobile': '@media (width <= 640px)',
|
|
143
|
+
} );
|
|
144
|
+
} );
|
|
145
|
+
|
|
146
|
+
it( 'uses a single max-width tablet media query when only tablet is valid', () => {
|
|
147
|
+
expect(
|
|
148
|
+
getResponsiveMediaQueries( {
|
|
149
|
+
mobile: '100%',
|
|
150
|
+
tablet: '64rem',
|
|
151
|
+
} )
|
|
152
|
+
).toEqual( {
|
|
153
|
+
'@tablet': '@media (width <= 64rem)',
|
|
154
|
+
} );
|
|
155
|
+
} );
|
|
156
|
+
|
|
157
|
+
it( 'omits the tablet media query when the tablet breakpoint is not larger than mobile', () => {
|
|
158
|
+
expect(
|
|
159
|
+
getResponsiveMediaQueries( {
|
|
160
|
+
mobile: '960px',
|
|
161
|
+
tablet: '640px',
|
|
162
|
+
} )
|
|
163
|
+
).toEqual( {
|
|
164
|
+
'@mobile': '@media (width <= 960px)',
|
|
165
|
+
} );
|
|
166
|
+
} );
|
|
167
|
+
} );
|
|
168
|
+
} );
|
package/src/types.ts
CHANGED
|
@@ -193,6 +193,10 @@ export interface SpacingSettings {
|
|
|
193
193
|
*/
|
|
194
194
|
export interface GlobalStylesSettings {
|
|
195
195
|
useRootPaddingAwareAlignments?: boolean;
|
|
196
|
+
viewport?: {
|
|
197
|
+
mobile?: string;
|
|
198
|
+
tablet?: string;
|
|
199
|
+
};
|
|
196
200
|
typography?: TypographySettings;
|
|
197
201
|
layout?: LayoutSettings;
|
|
198
202
|
spacing?: SpacingSettings;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import type { GlobalStylesConfig } from '../types';
|
|
2
|
+
|
|
3
|
+
const DEFAULT_VIEWPORT_BREAKPOINTS = {
|
|
4
|
+
mobile: '480px',
|
|
5
|
+
tablet: '782px',
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
type ViewportBreakpoint = keyof typeof DEFAULT_VIEWPORT_BREAKPOINTS;
|
|
9
|
+
type ViewportSettings = Partial< Record< ViewportBreakpoint, string > >;
|
|
10
|
+
type ViewportBreakpoints = Partial< Record< ViewportBreakpoint, string > >;
|
|
11
|
+
|
|
12
|
+
// Matches positive CSS length values supported for viewport breakpoints, and
|
|
13
|
+
// captures the numeric value and unit for conversion to pixels.
|
|
14
|
+
const VIEWPORT_SIZE_REGEXP = /^(\d+|\d*\.\d+)(px|em|rem)$/;
|
|
15
|
+
const DEFAULT_FONT_SIZE = 16;
|
|
16
|
+
|
|
17
|
+
function isViewportSettings(
|
|
18
|
+
configOrSettings: GlobalStylesConfig | ViewportSettings
|
|
19
|
+
): configOrSettings is ViewportSettings {
|
|
20
|
+
return 'mobile' in configOrSettings || 'tablet' in configOrSettings;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function getViewportSettings(
|
|
24
|
+
configOrSettings?: GlobalStylesConfig | ViewportSettings
|
|
25
|
+
): ViewportSettings {
|
|
26
|
+
if ( ! configOrSettings || typeof configOrSettings !== 'object' ) {
|
|
27
|
+
return {};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if ( isViewportSettings( configOrSettings ) ) {
|
|
31
|
+
return configOrSettings;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return configOrSettings.settings?.viewport ?? {};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function isValidViewportSize( value: unknown ): value is string {
|
|
38
|
+
return (
|
|
39
|
+
typeof value === 'string' && VIEWPORT_SIZE_REGEXP.test( value.trim() )
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Converts a viewport breakpoint value to pixels.
|
|
45
|
+
*
|
|
46
|
+
* Numeric values are returned as-is. CSS length values are only supported when
|
|
47
|
+
* expressed in px, em, or rem units.
|
|
48
|
+
*
|
|
49
|
+
* @param value Breakpoint value as a number or CSS length.
|
|
50
|
+
* @return The breakpoint value in pixels, or undefined when invalid.
|
|
51
|
+
*/
|
|
52
|
+
export function getViewportBreakpointValueInPixels(
|
|
53
|
+
value: number | string | undefined
|
|
54
|
+
): number | undefined {
|
|
55
|
+
if ( typeof value === 'number' ) {
|
|
56
|
+
return value;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if ( typeof value !== 'string' ) {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const match = value.trim().match( VIEWPORT_SIZE_REGEXP );
|
|
64
|
+
if ( ! match ) {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const numericValue = Number.parseFloat( match[ 1 ] );
|
|
69
|
+
const unit = match[ 2 ];
|
|
70
|
+
|
|
71
|
+
// Use the most common browser default font size as the base for em/rem
|
|
72
|
+
// media query conversions. This pixel value is used to compare breakpoint
|
|
73
|
+
// order and calculate preview sizes; generated media queries keep the
|
|
74
|
+
// original units.
|
|
75
|
+
return unit === 'px' ? numericValue : numericValue * DEFAULT_FONT_SIZE;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Returns sanitized viewport breakpoints keyed by viewport state.
|
|
80
|
+
*
|
|
81
|
+
* Falls back to default breakpoints when no valid values are provided. If the
|
|
82
|
+
* mobile breakpoint is missing, a valid tablet breakpoint remains keyed as
|
|
83
|
+
* tablet so the editor can present it as a tablet breakpoint. If the tablet
|
|
84
|
+
* breakpoint is missing, invalid, or not larger than the mobile breakpoint, the
|
|
85
|
+
* result only includes the mobile breakpoint.
|
|
86
|
+
*
|
|
87
|
+
* @param configOrSettings Global styles config or viewport settings.
|
|
88
|
+
* @return Sanitized viewport breakpoints.
|
|
89
|
+
*/
|
|
90
|
+
export function getViewportBreakpoints(
|
|
91
|
+
configOrSettings?: GlobalStylesConfig | ViewportSettings
|
|
92
|
+
): ViewportBreakpoints {
|
|
93
|
+
const viewportSettings = getViewportSettings( configOrSettings );
|
|
94
|
+
const breakpoints: ViewportBreakpoints = {};
|
|
95
|
+
const breakpointValuesInPixels: Partial<
|
|
96
|
+
Record< ViewportBreakpoint, number >
|
|
97
|
+
> = {};
|
|
98
|
+
|
|
99
|
+
Object.keys( DEFAULT_VIEWPORT_BREAKPOINTS ).forEach( ( breakpoint ) => {
|
|
100
|
+
const key = breakpoint as ViewportBreakpoint;
|
|
101
|
+
const value = viewportSettings[ key ];
|
|
102
|
+
const px = getViewportBreakpointValueInPixels( value );
|
|
103
|
+
if ( px !== undefined && isValidViewportSize( value ) ) {
|
|
104
|
+
breakpoints[ key ] = value.trim();
|
|
105
|
+
breakpointValuesInPixels[ key ] = px;
|
|
106
|
+
}
|
|
107
|
+
} );
|
|
108
|
+
|
|
109
|
+
const breakpointNames = Object.keys( breakpoints );
|
|
110
|
+
if ( ! breakpointNames.length ) {
|
|
111
|
+
return { ...DEFAULT_VIEWPORT_BREAKPOINTS };
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if ( 1 === breakpointNames.length ) {
|
|
115
|
+
return breakpoints;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const mobile = breakpoints.mobile!;
|
|
119
|
+
const tablet = breakpoints.tablet!;
|
|
120
|
+
if (
|
|
121
|
+
breakpointValuesInPixels.mobile! >= breakpointValuesInPixels.tablet!
|
|
122
|
+
) {
|
|
123
|
+
return { mobile };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return { mobile, tablet };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Returns responsive media query aliases for the configured viewport
|
|
131
|
+
* breakpoints.
|
|
132
|
+
*
|
|
133
|
+
* @param configOrSettings Global styles config or viewport settings.
|
|
134
|
+
* @return Responsive media queries keyed by alias.
|
|
135
|
+
*/
|
|
136
|
+
export function getResponsiveMediaQueries(
|
|
137
|
+
configOrSettings?: GlobalStylesConfig | ViewportSettings
|
|
138
|
+
): Record< string, string > {
|
|
139
|
+
const breakpoints = getViewportBreakpoints( configOrSettings );
|
|
140
|
+
const mediaQueries: Record< string, string > = {};
|
|
141
|
+
|
|
142
|
+
if ( breakpoints.mobile ) {
|
|
143
|
+
mediaQueries[ '@mobile' ] = `@media (width <= ${ breakpoints.mobile })`;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if ( breakpoints.tablet ) {
|
|
147
|
+
mediaQueries[ '@tablet' ] = breakpoints.mobile
|
|
148
|
+
? `@media (${ breakpoints.mobile } < width <= ${ breakpoints.tablet })`
|
|
149
|
+
: `@media (width <= ${ breakpoints.tablet })`;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return mediaQueries;
|
|
153
|
+
}
|