index.js
376 lines
| 1 | /** |
| 2 | * WordPress dependencies |
| 3 | */ |
| 4 | import { __ } from '@wordpress/i18n'; |
| 5 | import { addFilter } from '@wordpress/hooks'; |
| 6 | import { PanelBody, BaseControl, ToggleControl } from '@wordpress/components'; |
| 7 | import { InspectorControls } from '@wordpress/block-editor'; |
| 8 | import { createHigherOrderComponent } from '@wordpress/compose'; |
| 9 | import { useEffect } from '@wordpress/element'; |
| 10 | import { hasBlockSupport } from '@wordpress/blocks'; |
| 11 | |
| 12 | /** |
| 13 | * External dependencies |
| 14 | */ |
| 15 | import classnames from 'classnames'; |
| 16 | |
| 17 | /** |
| 18 | * Internal dependencies |
| 19 | */ |
| 20 | import { emptyStringToUndefined } from '@vkblocks/utils/empty-string-to-undefined'; |
| 21 | import { VkPanelIcon } from '@vkblocks/components/vk-icon'; |
| 22 | |
| 23 | // Check the keyword including str or not |
| 24 | // eslint-disable-next-line camelcase |
| 25 | export const in_string = (str, keyword) => { |
| 26 | // If keyword was included that return ( true or false ) |
| 27 | return str.indexOf(keyword) !== -1; |
| 28 | }; |
| 29 | |
| 30 | // The checking block is hidden function target or not |
| 31 | // eslint-disable-next-line camelcase |
| 32 | export const is_hidden = (blockName) => { |
| 33 | // Target of hidden function active |
| 34 | const allowed = ['core', 'vk-blocks']; |
| 35 | // name には allowed の� |
| 36 | 目が一つずつ� |
| 37 | �る |
| 38 | // 判断中のブロック名の中にname( core or vk-blocks )がある( undefinedじゃない )場合 |
| 39 | // true を返す |
| 40 | let hiddenReturn = |
| 41 | allowed.find((name) => in_string(blockName, name)) !== undefined; |
| 42 | |
| 43 | const excludes = [ |
| 44 | 'vk-blocks/card-item', |
| 45 | 'vk-blocks/icon-card-item', |
| 46 | 'vk-blocks/select-post-list-item', |
| 47 | 'vk-blocks/tab-item', |
| 48 | 'vk-blocks/accordion-trigger', |
| 49 | 'vk-blocks/accordion-target', |
| 50 | 'vk-blocks/faq2-q', |
| 51 | 'vk-blocks/faq2-a', |
| 52 | 'vk-blocks/dynamic-if', |
| 53 | ]; |
| 54 | const excludeBlock = |
| 55 | excludes.find((excludeName) => in_string(blockName, excludeName)) !== |
| 56 | undefined; |
| 57 | |
| 58 | if (excludeBlock) { |
| 59 | hiddenReturn = false; |
| 60 | } |
| 61 | |
| 62 | // classNameをサポートしているか |
| 63 | const hasCustomClassName = hasBlockSupport( |
| 64 | blockName, |
| 65 | 'customClassName', |
| 66 | true |
| 67 | ); |
| 68 | if (!hasCustomClassName) { |
| 69 | hiddenReturn = false; |
| 70 | } |
| 71 | return hiddenReturn; |
| 72 | }; |
| 73 | |
| 74 | // deprecated用 非表示設定を使用している可能性があるdynamic block |
| 75 | const mayUsedDynamicBlock = [ |
| 76 | 'vk-blocks/breadcrumb', |
| 77 | 'vk-blocks/child-page', |
| 78 | 'vk-blocks/post-list', |
| 79 | 'vk-blocks/page-content', |
| 80 | 'vk-blocks/ancestor-page-list', |
| 81 | // ExUnitに� |
| 82 | �っているvk blocksブロック, |
| 83 | 'vk-blocks/share-button', |
| 84 | 'vk-blocks/child-page-index', |
| 85 | 'vk-blocks/contact-section', |
| 86 | 'vk-blocks/page-list-ancestor', |
| 87 | 'vk-blocks/sitemap', |
| 88 | ]; |
| 89 | |
| 90 | /* Filter of editor.BlockEdit |
| 91 | /*-----------------------------------*/ |
| 92 | addFilter( |
| 93 | 'editor.BlockEdit', |
| 94 | 'vk-blocks/hidden-extension', |
| 95 | createHigherOrderComponent((BlockEdit) => { |
| 96 | return (props) => { |
| 97 | if (is_hidden(props.name)) { |
| 98 | //xxl用、deprecated追加 |
| 99 | if ( |
| 100 | props.attributes.vkb_hidden_xl && |
| 101 | !props.attributes.vkb_hidden_xxl |
| 102 | ) { |
| 103 | props.attributes.vkb_hidden_xxl = true; |
| 104 | props.attributes.vkb_hidden_xl_v2 = true; |
| 105 | props.attributes.vkb_hidden_xl = false; |
| 106 | } |
| 107 | const { name, attributes, setAttributes } = props; |
| 108 | const { |
| 109 | vkb_hidden, |
| 110 | vkb_hidden_xxl, |
| 111 | vkb_hidden_xl_v2, |
| 112 | vkb_hidden_xl, |
| 113 | vkb_hidden_lg, |
| 114 | vkb_hidden_md, |
| 115 | vkb_hidden_sm, |
| 116 | vkb_hidden_xs, |
| 117 | className, |
| 118 | } = attributes; |
| 119 | |
| 120 | /** |
| 121 | * dynamic block deprecated |
| 122 | * 非表示用のattributeが使用されていたらclassNameに� |
| 123 | �れ,過去のattributeをundefinedにする |
| 124 | * dynamic block以外はコアの仕様で追加 CSS クラスに自動的に追加される |
| 125 | */ |
| 126 | useEffect(() => { |
| 127 | if (mayUsedDynamicBlock.includes(name)) { |
| 128 | if ( |
| 129 | vkb_hidden || |
| 130 | vkb_hidden_xxl || |
| 131 | vkb_hidden_xl_v2 || |
| 132 | vkb_hidden_xl || |
| 133 | vkb_hidden_lg || |
| 134 | vkb_hidden_md || |
| 135 | vkb_hidden_sm || |
| 136 | vkb_hidden_xs |
| 137 | ) { |
| 138 | setAttributes({ |
| 139 | className: classnames({ |
| 140 | [className]: className, |
| 141 | [`vk_hidden`]: vkb_hidden, |
| 142 | [`vk_hidden-xxl`]: vkb_hidden_xxl, |
| 143 | [`vk_hidden-xl-v2`]: vkb_hidden_xl_v2, |
| 144 | [`vk_hidden-xl`]: vkb_hidden_xl, |
| 145 | [`vk_hidden-lg`]: vkb_hidden_lg, |
| 146 | [`vk_hidden-md`]: vkb_hidden_md, |
| 147 | [`vk_hidden-sm`]: vkb_hidden_sm, |
| 148 | [`vk_hidden-xs`]: vkb_hidden_xs, |
| 149 | }), |
| 150 | vkb_hidden: undefined, |
| 151 | vkb_hidden_xxl: undefined, |
| 152 | vkb_hidden_xl_v2: undefined, |
| 153 | vkb_hidden_xl: undefined, |
| 154 | vkb_hidden_lg: undefined, |
| 155 | vkb_hidden_md: undefined, |
| 156 | vkb_hidden_sm: undefined, |
| 157 | vkb_hidden_xs: undefined, |
| 158 | }); |
| 159 | } |
| 160 | } |
| 161 | // vk_hidden-xl_v2をvk_hidden-xl-v2にする |
| 162 | if (/vk_hidden-xl_v2/.test(className)) { |
| 163 | setAttributes({ |
| 164 | className: className.replace( |
| 165 | /vk_hidden-xl_v2/, |
| 166 | 'vk_hidden-xl-v2' |
| 167 | ), |
| 168 | }); |
| 169 | } |
| 170 | }, []); |
| 171 | |
| 172 | // 追加CSSクラスを半角文字列で分けて� |
| 173 | �列化 |
| 174 | const nowClassArray = className ? className.split(' ') : []; |
| 175 | |
| 176 | // アクティブなクラスかどうか |
| 177 | const isActiveClass = (targetClass) => { |
| 178 | const activeClassArray = []; |
| 179 | nowClassArray.forEach((item) => { |
| 180 | if (item === targetClass) { |
| 181 | activeClassArray.push(targetClass); |
| 182 | } |
| 183 | }); |
| 184 | return activeClassArray[0] === targetClass ? true : false; |
| 185 | }; |
| 186 | |
| 187 | // classNameをセット |
| 188 | const setNewClass = (checked, targetClass) => { |
| 189 | if (checked) { |
| 190 | nowClassArray.push(targetClass); |
| 191 | } else { |
| 192 | const clickIndex = nowClassArray.indexOf(targetClass); |
| 193 | nowClassArray.splice(clickIndex, 1); |
| 194 | } |
| 195 | setAttributes({ |
| 196 | className: emptyStringToUndefined( |
| 197 | nowClassArray.join(' ') |
| 198 | ), |
| 199 | }); |
| 200 | }; |
| 201 | // アイコンのスタイル |
| 202 | const isAnyHiddenActive = |
| 203 | isActiveClass('vk_hidden') || |
| 204 | isActiveClass('vk_hidden-xxl') || |
| 205 | isActiveClass('vk_hidden-xl-v2') || |
| 206 | isActiveClass('vk_hidden-xl') || |
| 207 | isActiveClass('vk_hidden-lg') || |
| 208 | isActiveClass('vk_hidden-md') || |
| 209 | isActiveClass('vk_hidden-sm') || |
| 210 | isActiveClass('vk_hidden-xs'); |
| 211 | |
| 212 | return ( |
| 213 | <> |
| 214 | <BlockEdit {...props} /> |
| 215 | <InspectorControls> |
| 216 | <PanelBody |
| 217 | title={__('Hidden Settings', 'vk-blocks')} |
| 218 | icon={ |
| 219 | <VkPanelIcon isActive={isAnyHiddenActive} /> |
| 220 | } |
| 221 | initialOpen={false} |
| 222 | > |
| 223 | <BaseControl |
| 224 | label={__( |
| 225 | 'Hidden at screen size', |
| 226 | 'vk-blocks' |
| 227 | )} |
| 228 | id={`vk_hiddenControl-hiddenScreenSize`} |
| 229 | > |
| 230 | <p> |
| 231 | {__( |
| 232 | "Note : This function is display hidden only. Actually Block is output to HTML. Please don't use you must not visible item. Don't use it for blocks you really don't want to display.", |
| 233 | 'vk-blocks' |
| 234 | )} |
| 235 | </p> |
| 236 | <ToggleControl |
| 237 | label={__( |
| 238 | 'Hidden ( Screen size : all )', |
| 239 | 'vk-blocks' |
| 240 | )} |
| 241 | checked={isActiveClass('vk_hidden')} |
| 242 | onChange={(checked) => { |
| 243 | setNewClass(checked, 'vk_hidden'); |
| 244 | }} |
| 245 | /> |
| 246 | <ToggleControl |
| 247 | label={__( |
| 248 | 'Hidden ( Screen size : xs )', |
| 249 | 'vk-blocks' |
| 250 | )} |
| 251 | checked={isActiveClass('vk_hidden-xs')} |
| 252 | onChange={(checked) => { |
| 253 | setNewClass( |
| 254 | checked, |
| 255 | 'vk_hidden-xs' |
| 256 | ); |
| 257 | }} |
| 258 | /> |
| 259 | <ToggleControl |
| 260 | label={__( |
| 261 | 'Hidden ( Screen size : sm )', |
| 262 | 'vk-blocks' |
| 263 | )} |
| 264 | checked={isActiveClass('vk_hidden-sm')} |
| 265 | onChange={(checked) => { |
| 266 | setNewClass( |
| 267 | checked, |
| 268 | 'vk_hidden-sm' |
| 269 | ); |
| 270 | }} |
| 271 | /> |
| 272 | <ToggleControl |
| 273 | label={__( |
| 274 | 'Hidden ( Screen size : md )', |
| 275 | 'vk-blocks' |
| 276 | )} |
| 277 | checked={isActiveClass('vk_hidden-md')} |
| 278 | onChange={(checked) => { |
| 279 | setNewClass( |
| 280 | checked, |
| 281 | 'vk_hidden-md' |
| 282 | ); |
| 283 | }} |
| 284 | /> |
| 285 | <ToggleControl |
| 286 | label={__( |
| 287 | 'Hidden ( Screen size : lg )', |
| 288 | 'vk-blocks' |
| 289 | )} |
| 290 | checked={isActiveClass('vk_hidden-lg')} |
| 291 | onChange={(checked) => { |
| 292 | setNewClass( |
| 293 | checked, |
| 294 | 'vk_hidden-lg' |
| 295 | ); |
| 296 | }} |
| 297 | /> |
| 298 | <ToggleControl |
| 299 | label={__( |
| 300 | 'Hidden ( Screen size : xl )', |
| 301 | 'vk-blocks' |
| 302 | )} |
| 303 | checked={isActiveClass( |
| 304 | 'vk_hidden-xl-v2' |
| 305 | )} |
| 306 | onChange={(checked) => { |
| 307 | setNewClass( |
| 308 | checked, |
| 309 | 'vk_hidden-xl-v2' |
| 310 | ); |
| 311 | }} |
| 312 | /> |
| 313 | <ToggleControl |
| 314 | label={__( |
| 315 | 'Hidden ( Screen size : xxl )', |
| 316 | 'vk-blocks' |
| 317 | )} |
| 318 | checked={isActiveClass('vk_hidden-xxl')} |
| 319 | onChange={(checked) => { |
| 320 | setNewClass( |
| 321 | checked, |
| 322 | 'vk_hidden-xxl' |
| 323 | ); |
| 324 | }} |
| 325 | /> |
| 326 | <p> |
| 327 | {__( |
| 328 | 'If you want to hide multiple blocks, that first you set to group block and the next, hide for the that group block.', |
| 329 | 'vk-blocks' |
| 330 | )} |
| 331 | </p> |
| 332 | </BaseControl> |
| 333 | </PanelBody> |
| 334 | </InspectorControls> |
| 335 | </> |
| 336 | ); |
| 337 | } |
| 338 | // IF not hidden function target block that return original BlockEdit |
| 339 | return <BlockEdit {...props} />; |
| 340 | }; |
| 341 | }, 'addHiddenSection') |
| 342 | ); |
| 343 | |
| 344 | /* Filter of editor.BlockListBlock |
| 345 | /*-----------------------------------*/ |
| 346 | addFilter( |
| 347 | 'editor.BlockListBlock', |
| 348 | 'vk-blocks/hidden-extension', |
| 349 | createHigherOrderComponent((BlockListBlock) => { |
| 350 | return (props) => { |
| 351 | const { attributes } = props; |
| 352 | const { className } = attributes; |
| 353 | |
| 354 | // 追加CSSクラスを半角文字列で分けて� |
| 355 | �列化 |
| 356 | const nowClassArray = className ? className.split(' ') : []; |
| 357 | |
| 358 | // Add hidden common class |
| 359 | const hiddenSomething = /vk_hidden/.test(nowClassArray) |
| 360 | ? 'vk_edit_hidden_warning' |
| 361 | : ''; |
| 362 | |
| 363 | // Add hidden all class |
| 364 | const hiddenClassName = |
| 365 | nowClassArray.indexOf('vk_hidden') !== -1 |
| 366 | ? hiddenSomething + ' vk_edit_hidden_all' |
| 367 | : hiddenSomething; |
| 368 | |
| 369 | // Add default class too. |
| 370 | const attachedClass = classnames(hiddenClassName, props.className); |
| 371 | |
| 372 | return <BlockListBlock {...props} className={attachedClass} />; |
| 373 | }; |
| 374 | }, 'addHiddenWarning') |
| 375 | ); |
| 376 |