diff --git a/languages/stackable-ultimate-gutenberg-blocks.pot b/languages/stackable-ultimate-gutenberg-blocks.pot index 4fc70fd10..3e22dc573 100644 --- a/languages/stackable-ultimate-gutenberg-blocks.pot +++ b/languages/stackable-ultimate-gutenberg-blocks.pot @@ -2,14 +2,14 @@ # This file is distributed under the same license as the Stackable - Gutenberg Blocks plugin. msgid "" msgstr "" -"Project-Id-Version: Stackable - Gutenberg Blocks 3.1.1\n" +"Project-Id-Version: Stackable - Gutenberg Blocks 3.1.2\n" "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/stackable-ultimate-gutenberg-blocks\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"POT-Creation-Date: 2022-01-12T08:13:03+00:00\n" +"POT-Creation-Date: 2022-01-19T05:49:03+00:00\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "X-Generator: WP-CLI 2.5.0\n" @@ -126,8 +126,8 @@ msgstr "" #: pro__premium_only/src/dynamic-content/sources/acf.php:315 #: pro__premium_only/src/dynamic-content/sources/acf.php:494 -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:298 -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:527 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:305 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:534 #: pro__premium_only/src/dynamic-content/sources/site.php:129 msgid "Text input is empty" msgstr "" @@ -197,18 +197,18 @@ msgstr "" #. translators: first %s is an ordinal number (e.g. 1st, 2nd), second %s is the name of the entity (e.g. Post, Page) #: pro__premium_only/src/dynamic-content/sources/latest-post.php:52 #: pro__premium_only/src/dynamic-content/sources/latest-post.php:54 -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:153 -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:157 -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:162 -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:166 -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:170 -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:174 -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:178 -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:182 -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:186 -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:190 -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:194 -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:198 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:160 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:164 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:169 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:173 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:177 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:181 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:185 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:189 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:193 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:197 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:201 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:205 msgid "Post" msgstr "" @@ -298,122 +298,122 @@ msgstr "" msgid "Search for posts/pages" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:103 -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:115 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:110 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:122 msgid "Detected Custom Fields" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:152 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:159 msgid "Post Title" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:156 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:163 msgid "Post URL" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:161 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:168 msgid "Post ID" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:165 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:172 msgid "Post Slug" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:169 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:176 #: pro__premium_only/src/conditional-display/condition-types.js:23 msgid "Post Taxonomy" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:173 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:180 msgid "Post Excerpt" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:177 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:184 msgid "Post Date" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:181 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:188 msgid "Post Date GMT" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:185 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:192 msgid "Post Modified" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:189 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:196 msgid "Post Modified GMT" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:193 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:200 #: pro__premium_only/src/conditional-display/condition-types.js:22 #: src/components/taxonomy-control/index.js:139 msgid "Post Type" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:197 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:204 msgid "Post Status" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:202 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:209 msgid "Author Name" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:203 -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:207 -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:211 -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:216 -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:221 -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:225 -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:229 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:210 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:214 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:218 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:223 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:228 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:232 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:236 msgid "Author" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:206 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:213 msgid "Author ID" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:210 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:217 msgid "Author Posts URL" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:215 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:222 msgid "Author Profile Picture URL" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:220 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:227 msgid "Author Posts" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:224 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:231 msgid "Author First Name" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:228 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:235 msgid "Author Last Name" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:233 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:240 msgid "Comment Number" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:234 -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:238 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:241 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:245 msgid "Comment" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:237 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:244 msgid "Comment Status" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:242 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:249 msgid "Featured Image URL" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:243 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:250 msgid "Media" msgstr "" -#: pro__premium_only/src/dynamic-content/sources/other-posts.php:377 +#: pro__premium_only/src/dynamic-content/sources/other-posts.php:384 msgid "Post not found." msgstr "" @@ -894,7 +894,7 @@ msgid "230+ Additional Library Designs" msgstr "" #: src/welcome/index.php:237 -#: pro__premium_only/src/format-types/dynamic-content/index.js:146 +#: pro__premium_only/src/format-types/dynamic-content/index.js:179 msgid "Dynamic Content" msgstr "" @@ -1208,7 +1208,7 @@ msgstr "" #: src/block-components/advanced/edit.js:81 #: src/block-components/button/edit.js:55 #: src/block-components/helpers/borders/edit.js:25 -#: src/block-components/image/edit.js:223 +#: src/block-components/image/edit.js:352 #: src/block-components/typography/edit.js:199 #: src/components/blend-mode-control/index.js:23 #: src/components/border-controls/index.js:26 @@ -1343,7 +1343,7 @@ msgstr "" #: src/components/typography-control/index.js:116 #: src/deprecated/v2/block/columns/edit.js:331 #: src/deprecated/v2/block/container/edit.js:154 -#: src/format-types/highlight/index.js:192 +#: src/format-types/highlight/index.js:202 msgid "Normal" msgstr "" @@ -1487,6 +1487,7 @@ msgstr "" #: pro__premium_only/src/features/icon-controls/index.js:225 #: src/block-components/button/edit.js:148 #: src/block-components/helpers/backgrounds/edit.js:115 +#: src/block-components/image/edit.js:297 #: src/block-components/typography/edit.js:296 #: src/components/background-controls/index.js:111 #: src/components/button-controls/index.js:171 @@ -1500,6 +1501,7 @@ msgstr "" #: pro__premium_only/src/features/icon-controls/index.js:192 #: src/block-components/button/edit.js:123 #: src/block-components/helpers/backgrounds/edit.js:59 +#: src/block-components/image/edit.js:225 #: src/block-components/typography/edit.js:259 #: src/components/background-controls/index.js:53 #: src/components/button-controls/index.js:138 @@ -1658,7 +1660,7 @@ msgstr "" #: src/block-components/helpers/backgrounds/edit.js:228 #: src/block-components/helpers/backgrounds/edit.js:247 #: src/block-components/helpers/backgrounds/edit.js:261 -#: src/block-components/image/edit.js:219 +#: src/block-components/image/edit.js:348 #: src/block-components/typography/edit.js:186 #: src/block-components/typography/edit.js:195 #: src/block-components/typography/edit.js:206 @@ -1896,10 +1898,10 @@ msgstr "" #: pro__premium_only/src/block/hero/index.js:66 #: pro__premium_only/src/block/hero/index.js:101 #: pro__premium_only/src/block/hero/index.js:134 -#: pro__premium_only/src/block/image-box/index.js:62 -#: pro__premium_only/src/block/image-box/index.js:114 -#: pro__premium_only/src/block/image-box/index.js:168 -#: pro__premium_only/src/block/image-box/index.js:228 +#: pro__premium_only/src/block/image-box/index.js:63 +#: pro__premium_only/src/block/image-box/index.js:116 +#: pro__premium_only/src/block/image-box/index.js:171 +#: pro__premium_only/src/block/image-box/index.js:232 #: pro__premium_only/src/block/notification/index.js:93 #: pro__premium_only/src/block/notification/index.js:143 #: pro__premium_only/src/block/notification/index.js:188 @@ -1919,8 +1921,8 @@ msgstr "" #: src/block/feature/variations.js:76 #: src/block/hero/variations.js:42 #: src/block/hero/variations.js:81 -#: src/block/image-box/variations.js:53 -#: src/block/image-box/variations.js:107 +#: src/block/image-box/variations.js:57 +#: src/block/image-box/variations.js:112 #: src/block/notification/variations.js:45 #: src/block/notification/variations.js:90 #: src/block/pricing-box/variations.js:40 @@ -2002,16 +2004,16 @@ msgstr "" #: pro__premium_only/src/block/card/index.js:25 #: pro__premium_only/src/block/card/index.js:39 #: pro__premium_only/src/block/card/index.js:56 -#: pro__premium_only/src/block/image-box/index.js:50 -#: pro__premium_only/src/block/image-box/index.js:106 -#: pro__premium_only/src/block/image-box/index.js:159 -#: pro__premium_only/src/block/image-box/index.js:216 +#: pro__premium_only/src/block/image-box/index.js:51 +#: pro__premium_only/src/block/image-box/index.js:108 +#: pro__premium_only/src/block/image-box/index.js:162 +#: pro__premium_only/src/block/image-box/index.js:220 #: pro__premium_only/src/block/pricing-box/index.js:53 #: pro__premium_only/src/block/pricing-box/index.js:118 #: pro__premium_only/src/block/pricing-box/index.js:172 #: src/block/card/variations.js:42 -#: src/block/image-box/variations.js:45 -#: src/block/image-box/variations.js:99 +#: src/block/image-box/variations.js:49 +#: src/block/image-box/variations.js:104 #: src/block/pricing-box/variations.js:43 #: src/block/pricing-box/variations.js:74 msgctxt "Subtitle placeholder" @@ -2148,12 +2150,12 @@ msgstr "" msgid "Title" msgstr "" -#: pro__premium_only/src/block/image-box/index.js:70 -#: pro__premium_only/src/block/image-box/index.js:120 -#: pro__premium_only/src/block/image-box/index.js:178 -#: pro__premium_only/src/block/image-box/index.js:240 -#: src/block/image-box/variations.js:59 -#: src/block/image-box/variations.js:115 +#: pro__premium_only/src/block/image-box/index.js:71 +#: pro__premium_only/src/block/image-box/index.js:122 +#: pro__premium_only/src/block/image-box/index.js:181 +#: pro__premium_only/src/block/image-box/index.js:244 +#: src/block/image-box/variations.js:63 +#: src/block/image-box/variations.js:120 msgctxt "Text placeholder" msgid "Text for This Block" msgstr "" @@ -3045,7 +3047,7 @@ msgstr "" #: pro__premium_only/src/deprecated/v2/block/testimonial/index.js:88 #: pro__premium_only/src/deprecated/v2/block/testimonial/index.js:133 #: pro__premium_only/src/deprecated/v2/block/testimonial/index.js:194 -#: src/block-components/image/edit.js:332 +#: src/block-components/image/edit.js:461 #: src/components/image-background-controls/index.js:26 #: src/components/image-controls/index.js:47 #: src/components/resizer-tooltip/index.js:279 @@ -3108,7 +3110,7 @@ msgstr "" #: pro__premium_only/src/deprecated/v2/block/pricing-box/index.js:72 #: pro__premium_only/src/deprecated/v2/block/team-member/index.js:100 #: pro__premium_only/src/deprecated/v2/block/testimonial/index.js:71 -#: src/components/resizable-column/index.js:527 +#: src/components/resizable-column/index.js:529 msgid "Column" msgstr "" @@ -3233,7 +3235,7 @@ msgstr "" #: pro__premium_only/src/deprecated/v2/block/pricing-box/index.js:172 #: pro__premium_only/src/dynamic-content/components/image-size-control.js:17 #: src/block-components/helpers/backgrounds/edit.js:258 -#: src/block-components/image/edit.js:176 +#: src/block-components/image/edit.js:184 #: src/block/posts/edit.js:553 #: src/components/background-controls/index.js:363 #: src/components/background-controls/index.js:378 @@ -3318,7 +3320,7 @@ msgstr "" #: pro__premium_only/src/deprecated/v2/block/testimonial/bubble.js:49 #: pro__premium_only/src/deprecated/v2/block/testimonial/vertical.js:52 #: src/block-components/helpers/borders/edit.js:84 -#: src/block-components/image/edit.js:196 +#: src/block-components/image/edit.js:204 #: src/components/button-controls/index.js:321 #: src/components/image-controls/index.js:210 #: src/deprecated/v2/block/accordion/edit.js:195 @@ -3355,7 +3357,7 @@ msgstr "" #: src/block-components/typography/edit.js:312 #: src/components/icon-controls/index.js:191 #: src/components/image-controls/index.js:223 -#: src/components/shadow-control/index.js:290 +#: src/components/shadow-control/index.js:305 #: src/deprecated/v2/block/accordion/edit.js:214 #: src/deprecated/v2/block/blockquote/edit.js:190 #: src/deprecated/v2/block/blog-posts/edit.js:227 @@ -3462,6 +3464,7 @@ msgstr "" #: src/components/background-controls/index.js:384 #: src/components/background-controls/index.js:399 #: src/components/image-background-controls/index.js:109 +#: src/components/shadow-control/index.js:277 msgid "Custom" msgstr "" @@ -3482,7 +3485,7 @@ msgid "Learn more about date formats" msgstr "" #: pro__premium_only/src/dynamic-content/components/dynamic-content-fields.js:255 -#: pro__premium_only/src/format-types/dynamic-content/index.js:97 +#: pro__premium_only/src/format-types/dynamic-content/index.js:120 #: src/components/dynamic-content-control/index.js:289 msgid "Dynamic Fields" msgstr "" @@ -3587,6 +3590,7 @@ msgstr "" #: src/block-components/helpers/backgrounds/edit.js:55 #: src/block-components/icon/edit.js:32 #: src/block-components/icon/edit.js:48 +#: src/block-components/image/edit.js:221 #: src/block-components/typography/edit.js:255 #: src/components/background-controls/index.js:49 #: src/components/button-controls/index.js:134 @@ -4018,9 +4022,9 @@ msgstr "" #: src/components/background-controls/index.js:381 #: src/components/background-controls/index.js:396 #: src/components/image-background-controls/index.js:106 -#: src/components/resizable-column/index.js:449 -#: src/components/resizable-column/index.js:461 -#: src/components/resizable-column/index.js:471 +#: src/components/resizable-column/index.js:451 +#: src/components/resizable-column/index.js:463 +#: src/components/resizable-column/index.js:473 msgid "Auto" msgstr "" @@ -4246,7 +4250,7 @@ msgstr "" #: src/deprecated/v2/block/pricing-box/edit.js:556 #: src/deprecated/v2/block/testimonial/edit.js:471 #: src/deprecated/v2/block/text/edit.js:247 -#: src/format-types/highlight/index.js:218 +#: src/format-types/highlight/index.js:229 msgid "Text Color" msgstr "" @@ -4394,6 +4398,8 @@ msgstr "" #: src/block-components/helpers/backgrounds/edit.js:70 #: src/block-components/helpers/backgrounds/edit.js:92 +#: src/block-components/image/edit.js:236 +#: src/block-components/image/edit.js:245 msgctxt "option title" msgid "%s #%d" msgstr "" @@ -4421,6 +4427,8 @@ msgstr "" #: src/block-components/helpers/backgrounds/edit.js:126 #: src/block-components/helpers/backgrounds/edit.js:137 +#: src/block-components/image/edit.js:309 +#: src/block-components/image/edit.js:321 #: src/components/background-controls/index.js:125 #: src/components/background-controls/index.js:139 msgid "Color %d Location" @@ -4520,7 +4528,7 @@ msgid "Repeat-Y" msgstr "" #: src/block-components/helpers/backgrounds/edit.js:263 -#: src/block-components/image/edit.js:221 +#: src/block-components/image/edit.js:350 #: src/block/team-member/variations.js:119 #: src/block/team-member/variations.js:120 #: src/components/background-controls/index.js:367 @@ -4531,7 +4539,7 @@ msgid "Cover" msgstr "" #: src/block-components/helpers/backgrounds/edit.js:264 -#: src/block-components/image/edit.js:220 +#: src/block-components/image/edit.js:349 #: src/components/background-controls/index.js:368 #: src/components/background-controls/index.js:383 #: src/components/background-controls/index.js:398 @@ -4717,11 +4725,11 @@ msgstr "" msgid "Say Hello to Background Shapes 👋" msgstr "" -#: src/block-components/image/edit.js:83 +#: src/block-components/image/edit.js:91 msgid "Select Image" msgstr "" -#: src/block-components/image/edit.js:119 +#: src/block-components/image/edit.js:127 #: src/block-components/separator/edit.js:75 #: src/block/divider/edit.js:87 #: src/block/heading/edit.js:116 @@ -4739,7 +4747,7 @@ msgstr "" msgid "Width" msgstr "" -#: src/block-components/image/edit.js:134 +#: src/block-components/image/edit.js:142 #: src/block-components/separator/edit.js:67 #: src/block/heading/edit.js:125 #: src/block/heading/edit.js:171 @@ -4766,51 +4774,73 @@ msgstr "" msgid "Height" msgstr "" -#: src/block-components/image/edit.js:148 +#: src/block-components/image/edit.js:156 msgid "Image Alt" msgstr "" -#: src/block-components/image/edit.js:155 +#: src/block-components/image/edit.js:163 msgid "Zoom" msgstr "" -#: src/block-components/image/edit.js:209 +#: src/block-components/image/edit.js:236 +#: src/block-components/image/edit.js:237 +#: src/block-components/image/edit.js:245 +#: src/deprecated/v2/block/image-box/edit.js:350 +#: src/deprecated/v2/block/image-box/edit.js:365 +#: src/deprecated/v2/block/image-box/edit.js:399 +#: src/help/videos.js:732 +msgid "Overlay Color" +msgstr "" + +#: src/block-components/image/edit.js:253 +msgid "Overlay Opacity" +msgstr "" + +#: src/block-components/image/edit.js:263 +msgid "Overlay Blend Mode" +msgstr "" + +#: src/block-components/image/edit.js:270 +msgid "Gradient Overlay Settings" +msgstr "" + +#: src/block-components/image/edit.js:338 msgid "Focal point" msgstr "" -#: src/block-components/image/edit.js:216 +#: src/block-components/image/edit.js:345 msgid "Image Fit" msgstr "" -#: src/block-components/image/edit.js:222 +#: src/block-components/image/edit.js:351 msgid "Fill" msgstr "" -#: src/block-components/image/edit.js:224 +#: src/block-components/image/edit.js:353 msgid "Scale Down" msgstr "" -#: src/block-components/image/edit.js:232 +#: src/block-components/image/edit.js:361 msgid "Image Shape" msgstr "" -#: src/block-components/image/edit.js:253 +#: src/block-components/image/edit.js:382 #: src/components/image-shape-controls/index.js:32 msgid "Flip Shape Horizontally" msgstr "" -#: src/block-components/image/edit.js:257 +#: src/block-components/image/edit.js:386 #: src/components/image-shape-controls/index.js:40 msgid "Flip Shape Vertically" msgstr "" -#: src/block-components/image/edit.js:261 +#: src/block-components/image/edit.js:390 #: src/components/image-shape-controls/index.js:48 msgid "Stretch Shape Mask" msgstr "" -#: src/block-components/image/edit.js:269 -#: src/block-components/image/edit.js:277 +#: src/block-components/image/edit.js:398 +#: src/block-components/image/edit.js:406 msgid "Image Filter" msgstr "" @@ -5105,11 +5135,11 @@ msgstr "" #: src/block/hero/variations.js:115 #: src/block/hero/variations.js:123 #: src/block/image-box/variations.js:35 -#: src/block/image-box/variations.js:83 -#: src/block/image-box/variations.js:136 -#: src/block/image-box/variations.js:144 -#: src/block/image-box/variations.js:152 -#: src/block/image-box/variations.js:160 +#: src/block/image-box/variations.js:87 +#: src/block/image-box/variations.js:141 +#: src/block/image-box/variations.js:149 +#: src/block/image-box/variations.js:157 +#: src/block/image-box/variations.js:165 #: src/block/notification/variations.js:35 #: src/block/notification/variations.js:70 #: src/block/notification/variations.js:118 @@ -5148,8 +5178,8 @@ msgstr "" #: src/block/accordion/variations.js:65 #: src/block/button/block-styles.js:83 #: src/block/icon-button/block-styles.js:89 -#: src/block/image-box/variations.js:82 -#: src/block/image-box/variations.js:83 +#: src/block/image-box/variations.js:86 +#: src/block/image-box/variations.js:87 #: src/block/notification/variations.js:69 #: src/block/notification/variations.js:70 #: src/block/team-member/variations.js:83 @@ -5503,7 +5533,7 @@ msgstr "" #: src/block/design-library/edit.js:74 #: src/deprecated/v2/components/design-library-control/index.js:57 #: src/deprecated/v2/components/design-library-control/index.js:61 -#: src/plugins/design-library-button/design-library-button.js:32 +#: src/plugins/design-library-button/design-library-button.js:38 msgid "Open Design Library" msgstr "" @@ -5788,26 +5818,26 @@ msgstr "" msgid "Accessibility" msgstr "" -#: src/block/image-box/variations.js:135 -#: src/block/image-box/variations.js:136 +#: src/block/image-box/variations.js:140 +#: src/block/image-box/variations.js:141 #: src/deprecated/v2/block/image-box/edit.js:80 msgid "Box" msgstr "" -#: src/block/image-box/variations.js:143 -#: src/block/image-box/variations.js:144 +#: src/block/image-box/variations.js:148 +#: src/block/image-box/variations.js:149 #: src/deprecated/v2/block/image-box/edit.js:83 msgid "Captioned" msgstr "" -#: src/block/image-box/variations.js:151 -#: src/block/image-box/variations.js:152 +#: src/block/image-box/variations.js:156 +#: src/block/image-box/variations.js:157 #: src/deprecated/v2/block/image-box/edit.js:86 msgid "Fade" msgstr "" -#: src/block/image-box/variations.js:159 -#: src/block/image-box/variations.js:160 +#: src/block/image-box/variations.js:164 +#: src/block/image-box/variations.js:165 #: src/deprecated/v2/block/image-box/edit.js:89 #: src/deprecated/v2/block/image-box/edit.js:286 #: src/deprecated/v2/block/image-box/edit.js:438 @@ -5979,7 +6009,7 @@ msgid "Apply hover effect when container is hovered" msgstr "" #: src/block/posts/edit.js:462 -#: src/format-types/highlight/index.js:228 +#: src/format-types/highlight/index.js:239 msgid "Highlight Color" msgstr "" @@ -6384,7 +6414,7 @@ msgstr "" msgid "Selected image" msgstr "" -#: src/components/button-icon-popover-control/index.js:197 +#: src/components/button-icon-popover-control/index.js:205 msgid "Edit" msgstr "" @@ -6868,7 +6898,7 @@ msgstr "" msgid "Advanced Shadow Options" msgstr "" -#: src/components/shadow-control/index.js:270 +#: src/components/shadow-control/index.js:285 msgid "Shadow Settings" msgstr "" @@ -6992,7 +7022,7 @@ msgid "Border" msgstr "" #: src/deprecated/v2/block/blockquote/edit.js:75 -#: src/format-types/highlight/index.js:196 +#: src/format-types/highlight/index.js:206 msgid "Highlight" msgstr "" @@ -7307,13 +7337,6 @@ msgstr "" msgid "Title on Top" msgstr "" -#: src/deprecated/v2/block/image-box/edit.js:350 -#: src/deprecated/v2/block/image-box/edit.js:365 -#: src/deprecated/v2/block/image-box/edit.js:399 -#: src/help/videos.js:732 -msgid "Overlay Color" -msgstr "" - #: src/deprecated/v2/block/image-box/edit.js:364 #: src/deprecated/v2/block/image-box/edit.js:398 msgid "Overlay Color Type" @@ -7986,17 +8009,17 @@ msgstr "" msgid "Please enable the option below" msgstr "" -#: src/format-types/highlight/index.js:169 -#: src/format-types/highlight/index.js:173 +#: src/format-types/highlight/index.js:177 +#: src/format-types/highlight/index.js:181 msgid "Color & Highlight" msgstr "" -#: src/format-types/highlight/index.js:200 +#: src/format-types/highlight/index.js:210 msgid "Low" msgstr "" -#: src/format-types/highlight/index.js:246 -#: src/format-types/highlight/index.js:259 +#: src/format-types/highlight/index.js:257 +#: src/format-types/highlight/index.js:270 msgid "Highlight Text" msgstr "" @@ -8875,7 +8898,7 @@ msgstr "" msgid "Rearrange and move columns around by dragging each handle" msgstr "" -#: src/plugins/design-library-button/design-library-button.js:34 +#: src/plugins/design-library-button/design-library-button.js:40 #: src/welcome/admin.js:267 msgid "Design Library" msgstr "" diff --git a/package-lock.json b/package-lock.json index b62cb254d..7e6dab507 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "stackable", - "version": "3.0.6", + "version": "3.1.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -10729,9 +10729,9 @@ } }, "follow-redirects": { - "version": "1.14.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz", - "integrity": "sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==", + "version": "1.14.7", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz", + "integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==", "dev": true }, "for-in": { diff --git a/package.json b/package.json index 11af41d4c..114c9d5f0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "stackable", - "version": "3.1.1", + "version": "3.1.2", "private": true, "description": "Blocks for everyone", "author": "Benjamin Intal of Gambit", diff --git a/plugin.php b/plugin.php index 42a457e32..2cbb836b0 100644 --- a/plugin.php +++ b/plugin.php @@ -6,7 +6,7 @@ * Author: Gambit Technologies, Inc * Author URI: http://gambit.ph * Text Domain: stackable-ultimate-gutenberg-blocks - * Version: 3.1.1 + * Version: 3.1.2 * * @package Stackable */ @@ -23,7 +23,7 @@ } defined( 'STACKABLE_SHOW_PRO_NOTICES' ) || define( 'STACKABLE_SHOW_PRO_NOTICES', true ); -defined( 'STACKABLE_VERSION' ) || define( 'STACKABLE_VERSION', '3.1.1' ); +defined( 'STACKABLE_VERSION' ) || define( 'STACKABLE_VERSION', '3.1.2' ); defined( 'STACKABLE_FILE' ) || define( 'STACKABLE_FILE', __FILE__ ); defined( 'STACKABLE_I18N' ) || define( 'STACKABLE_I18N', 'stackable-ultimate-gutenberg-blocks' ); // Plugin slug. defined( 'STACKABLE_CLOUDFRONT_URL' ) || define( 'STACKABLE_CLOUDFRONT_URL', 'https://d3gt1urn7320t9.cloudfront.net' ); // CloudFront CDN URL diff --git a/readme.txt b/readme.txt index f63bf141c..a44762a56 100644 --- a/readme.txt +++ b/readme.txt @@ -1,10 +1,10 @@ === Stackable - Page Builder Gutenberg Blocks === Contributors: bfintal, gambitph, freemius Tags: blocks, gutenberg, gutenberg blocks, page builder, WordPress blocks -Requires at least: 5.6.5 -Tested up to: 5.8.2 +Requires at least: 5.8.2 +Tested up to: 5.9 Requires PHP: 5.6 -Stable tag: 3.1.1 +Stable tag: 3.1.2 License: GPLv3 License URI: https://www.gnu.org/licenses/gpl-3.0.html @@ -238,6 +238,14 @@ Nope. Stackable only works with Gutenberg, the new WordPress editor. == Changelog == += 3.1.2 = +* New: WordPress 5.9 compatibility & FSE compatibility +* New: Added Overlay Colors to the Image block - now you can add solid or gradient colored overlays! +* Fixed: Clicking the expand block link scrolls the screen down +* Fixed: Inspector tabs went behind the visible area when scrolling down +* Fixed: Clearing a text highlight color, resets the highlight type. +* Fixed: Possible PHP error when a custom post used in Dynamic Content becomes unavailable + = 3.1.1 = * New: Added link option to the Image Block * New: Added back ability to change the column order when columns collapse in mobile (premium) diff --git a/src/block-components/icon/index.js b/src/block-components/icon/index.js index 0746dfa02..7fd7119da 100644 --- a/src/block-components/icon/index.js +++ b/src/block-components/icon/index.js @@ -71,7 +71,7 @@ export const Icon = props => { if ( event.target.closest( '.stk--inner-svg' ) ) { event.stopPropagation() } - if ( ! isElementDescendant( popoverEl.current, event.target ) && ! event.target.closest( '.components-popover' ) ) { + if ( ! event.target.closest( '.stk--inner-svg' ) && ! isElementDescendant( popoverEl.current, event.target ) && ! event.target.closest( '.components-popover' ) ) { setIsOpen( false ) } } diff --git a/src/block-components/image/attributes.js b/src/block-components/image/attributes.js index 8979bfc8f..5d9b7861d 100644 --- a/src/block-components/image/attributes.js +++ b/src/block-components/image/attributes.js @@ -46,6 +46,46 @@ export const addAttributes = ( attrObject, options = {} ) => { type: 'number', default: '', }, + + imageOverlayColorType: { + type: 'string', + default: '', + }, + imageOverlayColor: { + type: 'string', + default: '', + stkHover: true, + }, + imageOverlayColor2: { + type: 'string', + default: '', + stkHover: true, + }, + imageOverlayOpacity: { + type: 'number', + default: '', + stkHover: true, + }, + imageOverlayBlendMode: { + type: 'string', + default: '', + }, + imageOverlayGradientDirection: { + type: 'number', + default: '', + stkHover: true, + }, + imageOverlayGradientLocation1: { + type: 'number', + default: '', + stkHover: true, + }, + imageOverlayGradientLocation2: { + type: 'number', + default: '', + stkHover: true, + }, + imageFocalPoint: { stkResponsive: true, stkHover: true, diff --git a/src/block-components/image/edit.js b/src/block-components/image/edit.js index 5523d217e..efe2386e0 100644 --- a/src/block-components/image/edit.js +++ b/src/block-components/image/edit.js @@ -16,17 +16,24 @@ import { InspectorStyleControls, PanelAdvancedSettings, ShadowControl, + ColorPaletteControl, + AdvancedToolbarControl, + BlendModeControl, + ControlSeparator, } from '~stackable/components' import { - useBlockAttributes, + useBlockAttributes, useBlockHoverState, } from '~stackable/hooks' +import { getAttributeName } from '~stackable/util' /** * WordPress dependencies */ import { useBlockEditContext } from '@wordpress/block-editor' import { useDispatch, useSelect } from '@wordpress/data' -import { __ } from '@wordpress/i18n' +import { + sprintf, _x, __, +} from '@wordpress/i18n' import { applyFilters } from '@wordpress/hooks' import { useMemo } from '@wordpress/element' @@ -49,6 +56,7 @@ const Controls = props => { const { updateBlockAttributes } = useDispatch( 'core/block-editor' ) const attributes = useBlockAttributes( clientId ) + const [ state ] = useBlockHoverState() // Get the image size urls. const { imageData } = useSelect( select => { @@ -204,6 +212,127 @@ const Controls = props => { /> } + + + + + + { attributes.imageOverlayColorType === 'gradient' && ( + + ) } + + + + + + { attributes.imageOverlayColorType === 'gradient' && ( + { + updateBlockAttributes( clientId, { + [ getAttributeName( 'imageOverlayGradientDirection', 'desktop', state ) ]: '', + [ getAttributeName( 'imageOverlayGradientLocation1', 'desktop', state ) ]: '', + [ getAttributeName( 'imageOverlayGradientLocation2', 'desktop', state ) ]: '', + [ getAttributeName( 'imageOverlayGradientDirection', 'tablet', state ) ]: '', + [ getAttributeName( 'imageOverlayGradientLocation1', 'tablet', state ) ]: '', + [ getAttributeName( 'imageOverlayGradientLocation2', 'tablet', state ) ]: '', + [ getAttributeName( 'imageOverlayGradientDirection', 'mobile', state ) ]: '', + [ getAttributeName( 'imageOverlayGradientLocation1', 'mobile', state ) ]: '', + [ getAttributeName( 'imageOverlayGradientLocation2', 'mobile', state ) ]: '', + } ) + } } + allowReset={ + attributes[ getAttributeName( 'imageOverlayGradientDirection', 'desktop', state ) ] || + attributes[ getAttributeName( 'imageOverlayGradientLocation1', 'desktop', state ) ] || + attributes[ getAttributeName( 'imageOverlayGradientLocation2', 'desktop', state ) ] || + attributes[ getAttributeName( 'imageOverlayGradientDirection', 'tablet', state ) ] || + attributes[ getAttributeName( 'imageOverlayGradientLocation1', 'tablet', state ) ] || + attributes[ getAttributeName( 'imageOverlayGradientLocation2', 'tablet', state ) ] || + attributes[ getAttributeName( 'imageOverlayGradientDirection', 'mobile', state ) ] || + attributes[ getAttributeName( 'imageOverlayGradientLocation1', 'mobile', state ) ] || + attributes[ getAttributeName( 'imageOverlayGradientLocation2', 'mobile', state ) ] + } + > + + + + + + + ) } + + + .stk-img-wrapper { + // If not hovered, hide the overlay hover state. + &.stk-img--gradient-overlay:not(:hover) .stk-img-resizer-wrapper::before { + opacity: 0 !important; + } + &.stk-img--gradient-overlay:hover .stk-img-resizer-wrapper::after { + opacity: 0 !important; } // Firefox doesn't stretch SVG masks via attributes, stretching is done here. Fixes #246. &.stk-image--shape-stretch .stk-img-resizer-wrapper { diff --git a/src/block-components/image/image.js b/src/block-components/image/image.js index b07330066..fea53402c 100644 --- a/src/block-components/image/image.js +++ b/src/block-components/image/image.js @@ -45,6 +45,8 @@ const getImageWrapperClasses = props => { // Shadow is only available when there is no shape. [ `stk--shadow-${ props.shadow }` ]: ! props.shape && props.shadow, + + 'stk-img--gradient-overlay': props.hasGradientOverlay, } ) } @@ -164,7 +166,8 @@ const Image = memo( props => { if ( props.enableClickToEdit ) { if ( event.target?.classList?.contains( 'stk-img' ) || event.target?.classList?.contains( 'stk-img-placeholder' ) || - event.target?.classList?.contains( 'stk-img-resizer-wrapper' ) + event.target?.classList?.contains( 'stk-img-resizer-wrapper' ) || + event.target?.classList?.contains( 'stk-img-resizer' ) ) { obj.open() } @@ -350,6 +353,7 @@ Image.defaultProps = { heightResizePosition: 'bottom', allowReset: true, + hasGradientOverlay: false, hasRemove: true, hasTooltip: true, onChange: () => {}, @@ -481,6 +485,7 @@ ImageContent.defaultProps = { shapeStretch: false, shadow: '', + hasGradientOverlay: false, customWrapper: null, } diff --git a/src/block-components/image/index.js b/src/block-components/image/index.js index 0a31cc3b6..14d664e26 100644 --- a/src/block-components/image/index.js +++ b/src/block-components/image/index.js @@ -54,6 +54,14 @@ export const Image = props => { return () => clearTimeout( t ) }, [ isSelected ] ) + const hasHoverOverlay = attributes.imageOverlayColorType === 'gradient' && + ( attributes.imageOverlayColorHover || attributes.imageOverlayColorParentHover || + attributes.imageOverlayColor2Hover || attributes.imageOverlayColor2ParentHover || + attributes.imageOverlayOpacityHover || attributes.imageOverlayOpacityParentHover || + attributes.imageOverlayGradientLocation1Hover || attributes.imageOverlayGradientLocation1ParentHover || + attributes.imageOverlayGradientLocation2Hover || attributes.imageOverlayGradientLocation2ParentHover || + attributes.imageOverlayGradientDirectionHover || attributes.imageOverlayGradientDirectionParentHover ) + return { shapeStretch={ attributes.imageShapeStretch } shadow={ attributes.imageShadow } + hasGradientOverlay={ hasHoverOverlay } + defaultWidth={ props.defaultWidth } defaultHeight={ props.defaultHeight } @@ -108,6 +118,14 @@ Image.Content = props => { const defaultHeight = _defaultHeight === 'auto' && attributes.imageUrl ? 'auto' : 300 + const hasHoverOverlay = attributes.imageOverlayColorType === 'gradient' && + ( attributes.imageOverlayColorHover || attributes.imageOverlayColorParentHover || + attributes.imageOverlayColor2Hover || attributes.imageOverlayColor2ParentHover || + attributes.imageOverlayOpacityHover || attributes.imageOverlayOpacityParentHover || + attributes.imageOverlayGradientLocation1Hover || attributes.imageOverlayGradientLocation1ParentHover || + attributes.imageOverlayGradientLocation2Hover || attributes.imageOverlayGradientLocation2ParentHover || + attributes.imageOverlayGradientDirectionHover || attributes.imageOverlayGradientDirectionParentHover ) + return { shapeStretch={ attributes.imageShapeStretch } shadow={ attributes.imageShadow } + hasGradientOverlay={ hasHoverOverlay } + { ...propsToPass } /> } diff --git a/src/block-components/image/style.js b/src/block-components/image/style.js index 9830821bd..d77f5a1e5 100644 --- a/src/block-components/image/style.js +++ b/src/block-components/image/style.js @@ -8,7 +8,9 @@ import { getShapeCSS } from './get-shape-css' */ import { toNumber } from 'lodash' import { Style as StyleComponent } from '~stackable/components' -import { getStyles, useStyles } from '~stackable/util' +import { + getStyles, hexToRgba, useStyles, +} from '~stackable/util' /** * WordPress dependencies @@ -154,7 +156,11 @@ const getStyleParams = ( options = {} ) => { { renderIn: 'edit', // This is so that the resizer won't get clipped. - selector: `${ selector } .stk-img-resizer-wrapper img`, + selector: [ + `${ selector } .stk-img-resizer-wrapper img`, + `${ selector } .stk-img-resizer-wrapper::after`, + `${ selector } .stk-img-resizer-wrapper::before`, + ], styleRule: 'mask-image', vendorPrefixes: [ '-webkit-' ], attrName: 'imageShape', @@ -167,7 +173,11 @@ const getStyleParams = ( options = {} ) => { }, { renderIn: 'save', - selector: `${ selector } img`, + selector: [ + `${ selector } img`, + `${ selector }::after`, + `${ selector }::before`, + ], styleRule: 'mask-image', vendorPrefixes: [ '-webkit-' ], attrName: 'imageShape', @@ -178,6 +188,190 @@ const getStyleParams = ( options = {} ) => { }, dependencies: [ 'imageShapeFlipX', 'imageShapeFlipY', 'imageShapeStretch' ], }, + { + renderIn: 'save', + selector: `${ selector }::after`, + hoverSelector: `${ hoverSelector }::after`, + hoverSelectorCallback, + styleRule: 'backgroundColor', + attrName: 'imageOverlayColor', + hover: 'all', + enabledCallback: getAttribute => getAttribute( 'imageOverlayColorType' ) !== 'gradient', + }, + { + renderIn: 'edit', + selector: `${ selector } .stk-img-resizer-wrapper::after`, + hoverSelector: `${ hoverSelector } .stk-img-resizer-wrapper::after`, + hoverSelectorCallback, + styleRule: 'backgroundColor', + attrName: 'imageOverlayColor', + hover: 'all', + enabledCallback: getAttribute => getAttribute( 'imageOverlayColorType' ) !== 'gradient', + }, + { + renderIn: 'save', + selector: `${ selector }::after`, + hoverSelector: `${ selector }::before`, + styleRule: 'backgroundImage', + attrName: 'imageOverlayColor', + hover: 'all', + enabledCallback: getAttribute => getAttribute( 'imageOverlayColorType' ) === 'gradient', + valuePreCallback: ( value, getAttribute, device, state ) => { + if ( state !== 'normal' ) { + if ( getAttribute( 'imageOverlayColor2', 'desktop', 'normal' ) || getAttribute( 'imageOverlayColor', 'desktop', 'normal' ) ) { + return '1' + } + } + return value + }, + valueCallback: ( value, getAttribute, device, state ) => { + // The default color is the same as the other one but transparent. Same so that there won't be a weird transition to transparent. + let defaultColor1 = getAttribute( 'imageOverlayColor2', 'desktop', state ) + if ( state !== 'normal' && ! defaultColor1 ) { // For hover state, use the default if not set. + defaultColor1 = getAttribute( 'imageOverlayColor2', 'desktop', 'normal' ) + } + defaultColor1 = hexToRgba( defaultColor1 || '#ffffff', 0 ) + + let defaultColor2 = getAttribute( 'imageOverlayColor', 'desktop', state ) + if ( state !== 'normal' && ! defaultColor2 ) { // For hover state, use the default if not set. + defaultColor2 = getAttribute( 'imageOverlayColor', 'desktop', 'normal' ) + } + defaultColor2 = hexToRgba( defaultColor2 || '#ffffff', 0 ) + + // Gradient location. + let color1Location = getAttribute( 'imageOverlayGradientLocation1', 'desktop', state ) + if ( state !== 'normal' && color1Location === '' ) { + color1Location = getAttribute( 'imageOverlayGradientLocation1', 'desktop', 'normal' ) + } + color1Location = `${ color1Location || '0' }%` + + let color2Location = getAttribute( 'imageOverlayGradientLocation2', 'desktop', state ) + if ( state !== 'normal' && color2Location === '' ) { + color2Location = getAttribute( 'imageOverlayGradientLocation2', 'desktop', 'normal' ) + } + color2Location = `${ color2Location || '100' }%` + + let angle = getAttribute( 'imageOverlayGradientDirection', 'desktop', state ) + // For hover state, use the default if not set. + if ( state !== 'normal' && angle === '' ) { + angle = getAttribute( 'imageOverlayGradientDirection', 'desktop', 'normal' ) + } + + if ( angle === '' ) { + angle = '90' + } + angle = `${ angle }deg` + + let color1 = getAttribute( 'imageOverlayColor', 'desktop', state ) + if ( state !== 'normal' && ! color1 ) { // For hover state, use the default if not set. + color1 = getAttribute( 'imageOverlayColor', 'desktop', 'normal' ) + } + let color2 = getAttribute( 'imageOverlayColor2', 'desktop', state ) + if ( state !== 'normal' && ! color2 ) { // For hover state, use the default if not set. + color2 = getAttribute( 'imageOverlayColor2', 'desktop', 'normal' ) + } + + return `linear-gradient(${ angle }, ${ color1 || defaultColor1 } ${ color1Location }, ${ color2 || defaultColor2 } ${ color2Location })` + }, + dependencies: [ 'imageOverlayColorType', 'imageOverlayColor2', 'imageOverlayColor', 'imageOverlayGradientLocation1', 'imageOverlayGradientLocation2', 'imageOverlayGradientDirection', 'imageOverlayOpacity' ], + }, + { + renderIn: 'edit', + selector: `${ selector } .stk-img-resizer-wrapper::after`, + hoverSelector: `${ selector } .stk-img-resizer-wrapper::before`, + hoverSelectorCallback, + styleRule: 'backgroundImage', + attrName: 'imageOverlayColor', + hover: 'all', + enabledCallback: getAttribute => getAttribute( 'imageOverlayColorType' ) === 'gradient', + valuePreCallback: ( value, getAttribute, device, state ) => { + if ( state !== 'normal' ) { + if ( getAttribute( 'imageOverlayColor2', 'desktop', 'normal' ) || getAttribute( 'imageOverlayColor', 'desktop', 'normal' ) ) { + return '1' + } + } + return value + }, + valueCallback: ( value, getAttribute, device, state ) => { + // The default color is the same as the other one but transparent. Same so that there won't be a weird transition to transparent. + let defaultColor1 = getAttribute( 'imageOverlayColor2', 'desktop', state ) + if ( state !== 'normal' && ! defaultColor1 ) { // For hover state, use the default if not set. + defaultColor1 = getAttribute( 'imageOverlayColor2', 'desktop', 'normal' ) + } + defaultColor1 = hexToRgba( defaultColor1 || '#ffffff', 0 ) + + let defaultColor2 = getAttribute( 'imageOverlayColor', 'desktop', state ) + if ( state !== 'normal' && ! defaultColor2 ) { // For hover state, use the default if not set. + defaultColor2 = getAttribute( 'imageOverlayColor', 'desktop', 'normal' ) + } + defaultColor2 = hexToRgba( defaultColor2 || '#ffffff', 0 ) + + // Gradient location. + let color1Location = getAttribute( 'imageOverlayGradientLocation1', 'desktop', state ) + if ( state !== 'normal' && color1Location === '' ) { + color1Location = getAttribute( 'imageOverlayGradientLocation1', 'desktop', 'normal' ) + } + color1Location = `${ color1Location || '0' }%` + + let color2Location = getAttribute( 'imageOverlayGradientLocation2', 'desktop', state ) + if ( state !== 'normal' && color2Location === '' ) { + color2Location = getAttribute( 'imageOverlayGradientLocation2', 'desktop', 'normal' ) + } + color2Location = `${ color2Location || '100' }%` + + let angle = getAttribute( 'imageOverlayGradientDirection', 'desktop', state ) + // For hover state, use the default if not set. + if ( state !== 'normal' && angle === '' ) { + angle = getAttribute( 'imageOverlayGradientDirection', 'desktop', 'normal' ) + } + + if ( angle === '' ) { + angle = '90' + } + angle = `${ angle }deg` + + let color1 = getAttribute( 'imageOverlayColor', 'desktop', state ) + if ( state !== 'normal' && ! color1 ) { // For hover state, use the default if not set. + color1 = getAttribute( 'imageOverlayColor', 'desktop', 'normal' ) + } + let color2 = getAttribute( 'imageOverlayColor2', 'desktop', state ) + if ( state !== 'normal' && ! color2 ) { // For hover state, use the default if not set. + color2 = getAttribute( 'imageOverlayColor2', 'desktop', 'normal' ) + } + + return `linear-gradient(${ angle }, ${ color1 || defaultColor1 } ${ color1Location }, ${ color2 || defaultColor2 } ${ color2Location })` + }, + dependencies: [ 'imageOverlayColorType', 'imageOverlayColor2', 'imageOverlayColor', 'imageOverlayGradientLocation1', 'imageOverlayGradientLocation2', 'imageOverlayGradientDirection', 'imageOverlayOpacity' ], + }, + { + renderIn: 'save', + selector: `${ selector }`, + hoverSelector: `${ selector }::before`, + styleRule: '--stk-gradient-overlay', + attrName: 'imageOverlayOpacity', + hover: 'all', + }, + { + renderIn: 'edit', + selector: `${ selector } .stk-img-resizer-wrapper`, + hoverSelector: `${ selector } .stk-img-resizer-wrapper::before`, + styleRule: '--stk-gradient-overlay', + attrName: 'imageOverlayOpacity', + hover: 'all', + }, + { + renderIn: 'save', + selector: `${ selector }::after, ${ selector }::before`, + styleRule: 'mix-blend-mode', + attrName: 'imageOverlayBlendMode', + }, + { + renderIn: 'edit', + selector: `${ selector } .stk-img-resizer-wrapper::after, ${ selector } .stk-img-resizer-wrapper::before`, + hoverSelectorCallback, + styleRule: 'mix-blend-mode', + attrName: 'imageOverlayBlendMode', + }, ] } diff --git a/src/block-components/image/style.scss b/src/block-components/image/style.scss index 5cf9e9e2c..452d1c7c7 100644 --- a/src/block-components/image/style.scss +++ b/src/block-components/image/style.scss @@ -1,10 +1,29 @@ .stk-img-wrapper { + position: relative; width: 100%; // max-width: 100%; margin: 0 auto; display: block; overflow: hidden; // This is needed for zooming the image. + &::after, + &.stk-img--gradient-overlay::before { + content: ""; + position: absolute; + inset: 0; + opacity: var(--stk-gradient-overlay, 0.3); + z-index: 1; + } + &.stk-img--gradient-overlay { + // If not hovered, hide the overlay hover state. + &:not(:hover)::before { + opacity: 0 !important; + } + &:hover::after { + opacity: 0 !important; + } + } + img { object-fit: cover; width: 100% !important; @@ -15,6 +34,8 @@ // Shapes. &.stk-img--shape { + &::after, + &::before, img { mask-mode: alpha; mask-repeat: no-repeat; @@ -25,7 +46,11 @@ } // Firefox doesn't stretch SVG masks via attributes, stretching is done here. Fixes #246. &.stk-image--shape-stretch { - mask-size: 100% 100%; + &, + &::after, + &::before { + mask-size: 100% 100%; + } } } diff --git a/src/block/expand/frontend-expand.js b/src/block/expand/frontend-expand.js index 5856c79c1..80cabd208 100644 --- a/src/block/expand/frontend-expand.js +++ b/src/block/expand/frontend-expand.js @@ -18,7 +18,9 @@ class StackableExpand { visibles.forEach( el => el.setAttribute( 'aria-hidden', 'true' ) ) // Refocus on the hide/show button. - el.querySelector( `.stk-button[aria-hidden="false"]` ).focus() + el.querySelector( `.stk-button[aria-hidden="false"]` ).focus( { + preventScroll: true, + } ) event.preventDefault() } diff --git a/src/block/image-box/editor.scss b/src/block/image-box/editor.scss index 0f63f5888..25d63db65 100644 --- a/src/block/image-box/editor.scss +++ b/src/block/image-box/editor.scss @@ -26,7 +26,7 @@ .editor-styles-wrapper .stk-block-image-box { .stk-block, .stk-img-wrapper img { - transition-duration: 0.32s; + transition-duration: var(--stk-transition-duration, 0.32s); } } diff --git a/src/block/image-box/style.scss b/src/block/image-box/style.scss index c0fe15f3d..cb32c64c8 100644 --- a/src/block/image-box/style.scss +++ b/src/block/image-box/style.scss @@ -25,8 +25,10 @@ } &.stk-block .stk-block.stk-block, - &.stk-block .stk-img-wrapper > img.stk-img { - transition-duration: 0.32s; + &.stk-block .stk-img-wrapper > img.stk-img, + &.stk-block .stk-img-wrapper::after, + &.stk-block .stk-img-wrapper::before { + transition-duration: var(--stk-transition-duration, 0.32s); } } .stk-block-image-box__content { diff --git a/src/block/image-box/variations.js b/src/block/image-box/variations.js index e2408118d..204a195dd 100644 --- a/src/block/image-box/variations.js +++ b/src/block/image-box/variations.js @@ -36,7 +36,11 @@ const variations = applyFilters( icon: ImageDefault, attributes: { className: 'is-style-default' }, innerBlocks: [ - [ 'stackable/image', { imageHeight: 350, imageFilterParentHover: 'brightness(0.3)' } ], + [ 'stackable/image', { + imageHeight: 350, + imageOverlayColorParentHover: '#000000', + imageOverlayOpacityParentHover: 0.7, + } ], [ 'stackable/column', { templateLock: false, blockVerticalAlign: 'center', @@ -86,7 +90,8 @@ const variations = applyFilters( innerBlocks: [ [ 'stackable/image', { imageHeight: 350, - imageFilterParentHover: 'brightness(0.3)', + imageOverlayColorParentHover: '#000000', + imageOverlayOpacityParentHover: 0.7, } ], [ 'stackable/column', { containerPadding: { diff --git a/src/compatibility/twenty-twenty-two/editor.scss b/src/compatibility/twenty-twenty-two/editor.scss new file mode 100644 index 000000000..ec890cc2f --- /dev/null +++ b/src/compatibility/twenty-twenty-two/editor.scss @@ -0,0 +1,4 @@ +// Remove top margins of our blocks. +[data-type^="stackable/"] { + --wp--style--block-gap: 0; +} diff --git a/src/components/advanced-range-control/editor.scss b/src/components/advanced-range-control/editor.scss index 4fa0b0f70..22feec74c 100644 --- a/src/components/advanced-range-control/editor.scss +++ b/src/components/advanced-range-control/editor.scss @@ -4,9 +4,9 @@ &.ugb-range-control--blank { .components-range-control__track { width: var(--ugb-advanced-range-control--width) !important; - } - [class*="ThumbWrapper"] { - left: var(--ugb-advanced-range-control--width) !important; + + span { + left: var(--ugb-advanced-range-control--width) !important; + } } } } diff --git a/src/components/button-icon-popover-control/index.js b/src/components/button-icon-popover-control/index.js index 3c6746ff7..ea62c4624 100644 --- a/src/components/button-icon-popover-control/index.js +++ b/src/components/button-icon-popover-control/index.js @@ -27,11 +27,15 @@ import { BaseControl } from '..' // Keep the instance ID. let buttonInstance = 1 +// Keep track of whether popovers are open or closed, so when the editor +// abruptly unmounts/mounts, then we can bring back the popover status. +const instancesStatus = {} + class ButtonIconPopoverControl extends Component { constructor() { super( ...arguments ) this.state = { - open: false, + open: instancesStatus[ this.props.label ] || false, isMouseOutside: false, showResetPopover: false, } @@ -95,6 +99,15 @@ class ButtonIconPopoverControl extends Component { } componentWillUnmount() { + // Keep track of whether the popover is open or not when unmounting. + instancesStatus[ this.props.label ] = this.state.open + // Don't hold on to this value for too long, we only need this because + // in WP 5.9, the blocks become unmounted when previewing from desktop + // to tablet/mobile and back. + setTimeout( () => { + delete instancesStatus[ this.props.label ] + }, 500 ) + removeFilter( 'stackable.setAttributes', `stackable/button-icon-popover-control-${ this.instanceId }` ) // Remove event listener for moousedown @@ -139,13 +152,8 @@ class ButtonIconPopoverControl extends Component { return } - // If the click isn't from our button, close the popup. - if ( this.state.isMouseOutside && ( - ev.target.closest( 'button' ) !== this.buttonRef.current && - ev.target.closest( 'button' ) !== this.buttonRefColorPreview.current && - ev.target.closest( 'button' ) !== this.buttonRefImagePreview.current - ) ) { - if ( ! ev.target.closest( '.ugb-button-icon-control__popover' ) ) { + if ( this.state.open ) { + if ( ! ev.target.closest( '.ugb-button-icon-control__popover' ) && ! ev.target.closest( '.ugb-button-icon-control__edit' ) ) { this.handleClose() } } @@ -204,7 +212,6 @@ class ButtonIconPopoverControl extends Component { diff --git a/src/components/dynamic-content-control/index.js b/src/components/dynamic-content-control/index.js index ef1cfa461..74abc0557 100644 --- a/src/components/dynamic-content-control/index.js +++ b/src/components/dynamic-content-control/index.js @@ -56,7 +56,7 @@ export const useDynamicContentControlProps = props => { if ( isPopoverOpen ) { if ( ! event.target.closest( '.stackable-dynamic-content__popover' ) && - ! event.target.closest( '.stackable-dynamic-content__popover' ) + ! event.target.closest( '.stk-dynamic-content-control__button' ) ) { setIsPopoverOpen( false ) } @@ -64,8 +64,8 @@ export const useDynamicContentControlProps = props => { } ) useEffect( () => { - document.body.addEventListener( 'click', clickOutsideListener ) - return () => document.body.removeEventListener( 'click', clickOutsideListener ) + document.body.addEventListener( 'mousedown', clickOutsideListener ) + return () => document.body.removeEventListener( 'mousedown', clickOutsideListener ) }, [ clickOutsideListener ] ) useEffect( () => { diff --git a/src/components/icon-search-popover/index.js b/src/components/icon-search-popover/index.js index d50ea3fa2..ece70b4e7 100644 --- a/src/components/icon-search-popover/index.js +++ b/src/components/icon-search-popover/index.js @@ -160,7 +160,7 @@ const IconSearchPopover = props => { onClickOutside={ props.onClickOutside } position={ props.position } anchorRef={ props.anchorRef } - useRef={ props.useRef } + ref={ props.useRef } > .block-editor-link-control { min-width: auto; width: 100%; + + .block-editor-link-control__field { + margin: 0; + } + + .block-editor-link-control__search-item-header { + overflow: hidden; + white-space: nowrap; + } + } + .block-editor-url-input__input { margin: 0 !important; width: 100% !important; @@ -28,11 +39,15 @@ // Adjust the location of the dynamic and reset buttons since our control is taller. .stk-link-control { - .stk-link-control__input + .stk-dynamic-content-control__button { + .block-editor-link-control__field { + margin: auto; + } + .stk-dynamic-content-control__button { margin-top: 6px; + margin-left: 3px; } &.stk--has-value .stk-link-control__input + .stk-dynamic-content-control__button { - margin-top: 3px; + margin-top: 6px; } .stk-control__reset-button { top: 6px; diff --git a/src/components/panel-tabs/editor.scss b/src/components/panel-tabs/editor.scss index 996c74280..d4a6e820d 100644 --- a/src/components/panel-tabs/editor.scss +++ b/src/components/panel-tabs/editor.scss @@ -1,6 +1,6 @@ .ugb-panel-tabs { position: sticky; - top: -1px; + top: 47px; z-index: 5; .ugb-panel-tabs__wrapper { display: flex !important; @@ -49,8 +49,7 @@ .ugb-panel-tabs { border-bottom: 1px solid #e2e4e7 !important; } -.edit-post-sidebar.ugb--has-panel-tabs, -.edit-widgets-sidebar.ugb--has-panel-tabs { +.interface-complementary-area.ugb--has-panel-tabs { background-color: #f0f3f5; .edit-post-settings-sidebar__panel-block .components-panel__body:last-child { margin-bottom: 0; @@ -79,7 +78,7 @@ border-bottom: 1px solid #e1e1e1; // Sticky. position: sticky; - top: 81px; + top: 128px; z-index: 4; } background: #fafafa; diff --git a/src/components/panel-tabs/index.js b/src/components/panel-tabs/index.js index 813cb5c5d..f166414d6 100644 --- a/src/components/panel-tabs/index.js +++ b/src/components/panel-tabs/index.js @@ -80,7 +80,7 @@ class PanelTabs extends Component { setTimeout( () => { if ( sidebarPanel ) { sidebarPanel.setAttribute( 'data-ugb-tab', tab ) - sidebarPanel.closest( '.edit-post-sidebar, .edit-widgets-sidebar' )?.classList.add( 'ugb--has-panel-tabs' ) + sidebarPanel.closest( '.edit-post-sidebar, .edit-widgets-sidebar, .interface-complementary-area' )?.classList.add( 'ugb--has-panel-tabs' ) } }, 1 ) } @@ -99,7 +99,7 @@ class PanelTabs extends Component { const sidebarPanel = document.querySelector( '[data-ugb-tab]' ) if ( sidebarPanel ) { sidebarPanel.removeAttribute( 'data-ugb-tab' ) - sidebarPanel.closest( '.edit-post-sidebar, .edit-widgets-sidebar' ).classList.remove( 'ugb--has-panel-tabs' ) + sidebarPanel.closest( '.edit-post-sidebar, .edit-widgets-sidebar, .interface-complementary-area' ).classList.remove( 'ugb--has-panel-tabs' ) } // Remove listener to panel closes diff --git a/src/components/resizable-column/index.js b/src/components/resizable-column/index.js index 887a28822..c586290d9 100644 --- a/src/components/resizable-column/index.js +++ b/src/components/resizable-column/index.js @@ -12,6 +12,7 @@ import { ColumnShowTooltipContext } from '../column-inner-blocks' import { useBlockContext, useDeviceType, + useEditorDom, useWithShift, } from '~stackable/hooks' import { clamp, isEqual } from 'lodash' @@ -40,6 +41,7 @@ const MIN_COLUMN_WIDTH_PERCENTAGE = { const ResizableColumn = props => { const { clientId } = useBlockEditContext() const blockContext = useBlockContext() + const editorDom = useEditorDom() const { isFirstBlock, isLastBlock, isOnlyBlock, adjacentBlocks, blockIndex, parentBlock, @@ -134,7 +136,7 @@ const ResizableColumn = props => { const totalColumnGap = parentColumnGaps.desktop * ( adjacentBlocks.length - 1 ) // Get the current pixel width of the columns. - const parentEl = document.querySelector( `.editor-styles-wrapper [data-block="${ parentBlock.clientId }"]` ) + const parentEl = editorDom.querySelector( `[data-block="${ parentBlock.clientId }"]` ) const parentWidth = parentEl.clientWidth - totalColumnGap const isFirstResize = adjacentBlocks.every( ( { attributes } ) => ! attributes.columnWidth ) const columnWidths = adjacentBlocks.map( ( { clientId, attributes } ) => { @@ -146,7 +148,7 @@ const ResizableColumn = props => { if ( attributes.columnWidth ) { return parentWidth * attributes.columnWidth / 100 } - const blockEl = document.querySelector( `.editor-styles-wrapper [data-block="${ clientId }"]` ) + const blockEl = editorDom.querySelector( `[data-block="${ clientId }"]` ) return blockEl?.clientWidth || 0 } ) setCurrentWidths( columnWidths ) @@ -167,18 +169,18 @@ const ResizableColumn = props => { setCurrentWidths( columnWidths ) // Get the current pixel width of the columns. - const blockEl = document.querySelector( `.editor-styles-wrapper [data-block="${ clientId }"]` ) + const blockEl = editorDom.querySelector( `[data-block="${ clientId }"]` ) const columnWidth = blockEl?.clientWidth || 0 setCurrentWidth( columnWidth ) // The maximum width is the total width of the row. - const parentEl = document.querySelector( `.editor-styles-wrapper [data-block="${ parentBlock.clientId }"]` ) + const parentEl = editorDom.querySelector( `[data-block="${ parentBlock.clientId }"]` ) const maxWidth = parentEl?.clientWidth || 0 setMaxWidth( maxWidth ) } setIsTooltipOver( true ) - }, [ isDesktop, parentBlock?.clientId, adjacentBlocks, blockIndex, clientId, columnGap, columnGapTablet, columnGapMobile ] ) + }, [ isDesktop, parentBlock?.clientId, adjacentBlocks, blockIndex, clientId, columnGap, columnGapTablet, columnGapMobile, editorDom ] ) const onResize = useCallback( ( _event, _direction, elt, delta ) => { let columnPercentages = [] @@ -391,7 +393,7 @@ const ResizableColumn = props => { { - const editorEl = document.querySelector( '.editor-styles-wrapper' ) +const addDeviceTypeClass = throttle( ( previewDeviceType = '', editorEl ) => { if ( editorEl && ! editorEl.classList.contains( `stk-preview-device-${ previewDeviceType.toLowerCase() }` ) ) { editorEl.classList.remove( 'stk-preview-device-desktop', 'stk-preview-device-tablet', 'stk-preview-device-mobile' ) editorEl.classList.add( `stk-preview-device-${ previewDeviceType.toLowerCase() }` ) @@ -12,7 +11,8 @@ const addDeviceTypeClass = throttle( ( previewDeviceType = '' ) => { export const useDeviceEditorClasses = () => { const deviceType = useDeviceType() + const editorDom = useEditorDom() useEffect( () => { - addDeviceTypeClass( deviceType ) - }, [ deviceType ] ) + addDeviceTypeClass( deviceType, editorDom ) + }, [ deviceType, editorDom ] ) } diff --git a/src/components/shadow-control/index.js b/src/components/shadow-control/index.js index a5b0ac249..8ad50d141 100644 --- a/src/components/shadow-control/index.js +++ b/src/components/shadow-control/index.js @@ -243,6 +243,20 @@ const ShadowControl = props => { const value = typeof props.value === 'undefined' ? _value : props.value const [ propsToPass ] = extractControlProps( _props ) + const clickOutsideListener = useCallback( event => { + if ( isPopoverOpen ) { + if ( ! event.target.closest( '.shadow-control__popover' ) && + ! event.target.closest( '.stk-shadow-control__more-button' ) ) { + setIsPopoverOpen( false ) + } + } + } ) + + useEffect( () => { + document.body.addEventListener( 'mousedown', clickOutsideListener ) + return () => document.body.removeEventListener( 'mousedown', clickOutsideListener ) + }, [ clickOutsideListener ] ) + useEffect( () => { if ( isPopoverOpen ) { } @@ -260,6 +274,7 @@ const ShadowControl = props => { allowReset={ true } className="ugb--help-tip-general-shadow" hover={ props.hover } + placeholder={ value === 'custom' ? __( 'Custom', i18n ) : '' } after={ (