77 */
88
99/**
10- * Render nothing if the block is hidden.
10+ * Render nothing if the block is hidden, or add viewport visibility styles .
1111 *
1212 * @since 6.9.0
13+ * @since 7.0.0 Added support for viewport visibility.
1314 * @access private
1415 *
1516 * @param string $block_content Rendered block content.
@@ -23,10 +24,126 @@ function wp_render_block_visibility_support( $block_content, $block ) {
2324 return $ block_content ;
2425 }
2526
26- if ( isset ( $ block ['attrs ' ]['metadata ' ]['blockVisibility ' ] ) && false === $ block ['attrs ' ]['metadata ' ]['blockVisibility ' ] ) {
27+ $ block_visibility = $ block ['attrs ' ]['metadata ' ]['blockVisibility ' ] ?? null ;
28+
29+ if ( false === $ block_visibility ) {
2730 return '' ;
2831 }
2932
33+ if ( is_array ( $ block_visibility ) && ! empty ( $ block_visibility ) ) {
34+ $ viewport_config = $ block_visibility ['viewport ' ] ?? null ;
35+
36+ if ( ! is_array ( $ viewport_config ) || empty ( $ viewport_config ) ) {
37+ return $ block_content ;
38+ }
39+ /*
40+ * Viewport size definitions are in several places in WordPress packages.
41+ * The following are taken from: https://github.com/WordPress/gutenberg/blob/trunk/packages/base-styles/_breakpoints.scss
42+ * The array is in a future, potential JSON format, and will be centralized
43+ * as the feature is developed.
44+ *
45+ * Viewport sizes as array items are defined sequentially. The first item's size is the max value.
46+ * Each subsequent item starts after the previous size (using > operator), and its size is the max.
47+ * The last item starts after the previous size (using > operator), and it has no max.
48+ */
49+ $ viewport_sizes = array (
50+ array (
51+ 'name ' => 'Mobile ' ,
52+ 'slug ' => 'mobile ' ,
53+ 'size ' => '480px ' ,
54+ ),
55+ array (
56+ 'name ' => 'Tablet ' ,
57+ 'slug ' => 'tablet ' ,
58+ 'size ' => '782px ' ,
59+ ),
60+ array (
61+ 'name ' => 'Desktop ' ,
62+ 'slug ' => 'desktop ' ,
63+ /*
64+ * Note: the last item in the $viewport_sizes array does not technically require a 'size' key,
65+ * as the last item's media query is calculated using `width > previous size`.
66+ * The last item is present for validating the attribute values, and in order to indicate
67+ * that this is the final viewport size, and to calculate the previous media query accordingly.
68+ */
69+ ),
70+ );
71+
72+ /*
73+ * Build media queries from viewport size definitions using the CSS range syntax.
74+ * Could be absorbed into the style engine,
75+ * as well as classname building, and declaration of the display property, if required.
76+ */
77+ $ viewport_media_queries = array ();
78+ $ previous_size = null ;
79+ foreach ( $ viewport_sizes as $ index => $ viewport_size ) {
80+ // First item: width <= size.
81+ if ( 0 === $ index ) {
82+ $ viewport_media_queries [ $ viewport_size ['slug ' ] ] = "@media (width <= {$ viewport_size ['size ' ]}) " ;
83+ } elseif ( count ( $ viewport_sizes ) - 1 === $ index && $ previous_size ) {
84+ // Last item: width > previous size.
85+ $ viewport_media_queries [ $ viewport_size ['slug ' ] ] = "@media (width > $ previous_size) " ;
86+ } else {
87+ // Middle items: previous size < width <= size.
88+ $ viewport_media_queries [ $ viewport_size ['slug ' ] ] = "@media ( {$ previous_size } < width <= {$ viewport_size ['size ' ]}) " ;
89+ }
90+
91+ $ previous_size = $ viewport_size ['size ' ] ?? null ;
92+ }
93+
94+ $ hidden_on = array ();
95+
96+ // Collect which viewport the block is hidden on (only known viewport sizes).
97+ foreach ( $ viewport_config as $ viewport_config_size => $ is_visible ) {
98+ if ( false === $ is_visible && isset ( $ viewport_media_queries [ $ viewport_config_size ] ) ) {
99+ $ hidden_on [] = $ viewport_config_size ;
100+ }
101+ }
102+
103+ // If no viewport sizes have visibility set to false, return unchanged.
104+ if ( empty ( $ hidden_on ) ) {
105+ return $ block_content ;
106+ }
107+
108+ // Maintain consistent order of viewport sizes for class name generation.
109+ sort ( $ hidden_on );
110+
111+ $ css_rules = array ();
112+ $ class_names = array ();
113+
114+ foreach ( $ hidden_on as $ hidden_viewport_size ) {
115+ /*
116+ * If these values ever become user-defined,
117+ * they should be sanitized and kebab-cased.
118+ */
119+ $ visibility_class = 'wp-block-hidden- ' . $ hidden_viewport_size ;
120+ $ class_names [] = $ visibility_class ;
121+ $ css_rules [] = array (
122+ 'selector ' => '. ' . $ visibility_class ,
123+ 'declarations ' => array (
124+ 'display ' => 'none !important ' ,
125+ ),
126+ 'rules_group ' => $ viewport_media_queries [ $ hidden_viewport_size ],
127+ );
128+ }
129+
130+ wp_style_engine_get_stylesheet_from_css_rules (
131+ $ css_rules ,
132+ array (
133+ 'context ' => 'block-supports ' ,
134+ 'prettify ' => false ,
135+ )
136+ );
137+
138+ if ( ! empty ( $ block_content ) ) {
139+ $ processor = new WP_HTML_Tag_Processor ( $ block_content );
140+ if ( $ processor ->next_tag () ) {
141+ $ processor ->add_class ( implode ( ' ' , $ class_names ) );
142+ $ block_content = $ processor ->get_updated_html ();
143+ }
144+ }
145+ }
146+
30147 return $ block_content ;
31148}
32149
0 commit comments