PluginProbe
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder / 2.13.1
aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder v2.13.1
2.13.0 2.13.1 2.12.0 2.11.1 2.11.0 2.10.0 2.9.0 2.7.4 2.7.5 2.7.6 2.7.7 2.8.0 2.8.1 2.9.1 trunk 1.0 1.0-beta1 1.0-beta2 1.0-beta3 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 All 80 releases
ablocks / includes / classes / style-buckets.php

style-buckets.php in aBlocks – Gutenberg Blocks, User Dashboard Builder, Popup Builder, Form Builder & Animation Builder 2.13.1, at includes/classes/style-buckets.php

176 lines 5.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace ABlocks\Classes;
3
4 if ( ! defined( 'ABSPATH' ) ) {
5 exit;
6 }
7
8 /**
9 * The bucket namespace for the atomic `styles` attribute.
10 *
11 * Mirror of `src/blocks/atomic-shared/buckets.js`. Where StylesSchema answers
12 * "which props exist and what CSS do they become", this answers "where is a
13 * value stored and in what order does it emit".
14 *
15 * Shape (schema v3):
16 *
17 * [
18 * 'v' => 3,
19 * '' => [ …props ], // desktop, normal
20 * ':hover' => [ …props ], // desktop, hover
21 * '@tablet' => [ '' => [ …props ], ':hover' => [ … ] ], // tablet, per state
22 * ]
23 *
24 * Two levels, never mixed: the top level is keyed by state OR breakpoint, and a
25 * breakpoint's value is keyed by state only. Props never carry a device suffix —
26 * the bucket key is the device — so registering a new breakpoint adds exactly
27 * one key rather than one key per prop.
28 */
29 class StyleBuckets {
30
31 /** Bumped only when the stored shape changes incompatibly. */
32 const SCHEMA_VERSION = 3;
33
34 /** The key holding the schema version (not a bucket). */
35 const VERSION_KEY = 'v';
36
37 /**
38 * Interaction states, in emission order. The stored key IS the CSS
39 * pseudo-selector, so no translation table is needed at compile time.
40 * `:focus-visible` follows `:focus` so it wins where both are set.
41 */
42 public static function states() {
43 return [
44 [ 'key' => '', 'label' => 'Normal' ],
45 [ 'key' => ':hover', 'label' => 'Hover' ],
46 [ 'key' => ':focus', 'label' => 'Focus' ],
47 [ 'key' => ':focus-visible', 'label' => 'Focus (keyboard)' ],
48 [ 'key' => ':active', 'label' => 'Active' ],
49 ];
50 }
51
52 /** Just the state keys, in emission order. */
53 public static function state_keys() {
54 return array_column( self::states(), 'key' );
55 }
56
57 public static function is_state_key( $key ) {
58 return '' === $key || 0 === strpos( (string) $key, ':' );
59 }
60
61 public static function is_breakpoint_key( $key ) {
62 return 0 === strpos( (string) $key, '@' );
63 }
64
65 /**
66 * Reserved for class-driven states (`-current`, `-open`). Parsed and
67 * preserved so they can be added later without a storage change; the
68 * compilers skip them.
69 *
70 * @param string $key Bucket key.
71 * @return bool Whether the key is a reserved class-state bucket.
72 */
73 public static function is_reserved_key( $key ) {
74 return 0 === strpos( (string) $key, '-' );
75 }
76
77 /**
78 * The bucket key for a responsive device entry. The base device has no key
79 * of its own — its states live at the top level.
80 *
81 * @param array $device A device entry from the responsive device list.
82 * @return string '' for the base device, else '@<lcfirst id>'.
83 */
84 public static function device_bucket_key( $device ) {
85 $device = (array) $device;
86 if ( empty( $device['min'] ) && empty( $device['max'] ) ) {
87 return '';
88 }
89 return '@' . lcfirst( (string) ( isset( $device['id'] ) ? $device['id'] : '' ) );
90 }
91
92 /** A styles array at the current schema version. */
93 public static function empty_styles() {
94 return [ self::VERSION_KEY => self::SCHEMA_VERSION ];
95 }
96
97 /**
98 * Whether a stored styles array is readable by this compiler. An array
99 * without the marker is treated as unreadable rather than interpreted, so a
100 * pre-v3 shape can never be half-compiled into wrong CSS.
101 *
102 * @param mixed $styles Stored styles value.
103 * @return bool Whether it carries the current schema version.
104 */
105 public static function has_schema_version( $styles ) {
106 return is_array( $styles )
107 && isset( $styles[ self::VERSION_KEY ] )
108 && self::SCHEMA_VERSION === (int) $styles[ self::VERSION_KEY ];
109 }
110
111 /**
112 * Every non-empty (device, state, props) triple in canonical emission
113 * order: devices widest-first (the order Helper::get_responsive_devices()
114 * already returns), and within a device, states in states() order.
115 *
116 * Reserved `-` buckets are skipped — they are storage-only this release.
117 *
118 * @param array $styles Stored styles array.
119 * @param array $devices Ordered responsive device list.
120 * @return array[] Entries of [ 'device' => …, 'state' => …, 'props' => … ].
121 */
122 public static function ordered_buckets( $styles, $devices ) {
123 $out = [];
124 if ( ! self::has_schema_version( $styles ) ) {
125 return $out;
126 }
127
128 foreach ( (array) $devices as $device ) {
129 $key = self::device_bucket_key( $device );
130 $level = ( '' === $key )
131 ? $styles
132 : ( isset( $styles[ $key ] ) ? $styles[ $key ] : null );
133
134 if ( ! is_array( $level ) ) {
135 continue;
136 }
137
138 foreach ( self::state_keys() as $state ) {
139 $props = isset( $level[ $state ] ) ? $level[ $state ] : null;
140 if ( is_array( $props ) && ! empty( $props ) ) {
141 $out[] = [
142 'device' => $device,
143 'state' => $state,
144 'props' => $props,
145 ];
146 }
147 }
148 }//end foreach
149
150 return $out;
151 }
152
153 /**
154 * Read one bucket's own props (no inheritance) — what this device/state
155 * actually overrides, as opposed to what it renders as.
156 *
157 * @param array $styles Stored styles array.
158 * @param string $bucket Breakpoint bucket key ('' for base).
159 * @param string $state State key.
160 * @return array The bucket's props, or an empty array.
161 */
162 public static function read_bucket( $styles, $bucket, $state ) {
163 if ( ! is_array( $styles ) ) {
164 return [];
165 }
166 $level = ( '' === $bucket )
167 ? $styles
168 : ( isset( $styles[ $bucket ] ) ? $styles[ $bucket ] : null );
169
170 if ( ! is_array( $level ) || ! isset( $level[ $state ] ) || ! is_array( $level[ $state ] ) ) {
171 return [];
172 }
173 return $level[ $state ];
174 }
175 }
176