deprecated
2 months ago
block.json
1 day ago
edit.js
2 months ago
icon.svg
2 months ago
index.js
2 months ago
index.php
2 months ago
save.js
2 months ago
style.scss
2 months ago
edit.js
329 lines
| 1 | /** |
| 2 | * External dependencies |
| 3 | */ |
| 4 | import classnames from 'classnames'; |
| 5 | |
| 6 | /** |
| 7 | * WordPress dependencies |
| 8 | */ |
| 9 | import { __ } from '@wordpress/i18n'; |
| 10 | import { FontAwesome } from '@vkblocks/utils/font-awesome-new'; |
| 11 | import { PanelBody, BaseControl, SelectControl } from '@wordpress/components'; |
| 12 | import { |
| 13 | InspectorControls, |
| 14 | InnerBlocks, |
| 15 | RichText, |
| 16 | useBlockProps, |
| 17 | BlockControls, |
| 18 | BlockAlignmentControl, |
| 19 | } from '@wordpress/block-editor'; |
| 20 | import parse from 'html-react-parser'; |
| 21 | |
| 22 | /** |
| 23 | * Internal dependencies |
| 24 | */ |
| 25 | import { AdvancedColorPalette } from '@vkblocks/components/advanced-color-palette'; |
| 26 | import { isHexColor } from '@vkblocks/utils/is-hex-color'; |
| 27 | import { iconLabel } from '@vkblocks/utils/icon-label'; |
| 28 | import { sanitizeSlug } from '@vkblocks/utils/sanitizeSlug'; |
| 29 | import { useEffect, useRef } from '@wordpress/element'; |
| 30 | import { fixBrokenUnicode } from '@vkblocks/utils/fixBrokenUnicode'; |
| 31 | |
| 32 | export default function BorderBoxEdit(props) { |
| 33 | const { attributes, setAttributes } = props; |
| 34 | const { |
| 35 | heading, |
| 36 | headingTag, |
| 37 | anchor, |
| 38 | includeInToc, |
| 39 | faIcon, |
| 40 | color, |
| 41 | bgColor, |
| 42 | borderColor, |
| 43 | bodyAlign, |
| 44 | } = attributes; |
| 45 | |
| 46 | const fixedFaIcon = faIcon ? fixBrokenUnicode(faIcon) : faIcon; |
| 47 | |
| 48 | // 新しく作成されたブロックのみ目次に含める(既存ブロックは除外のまま) |
| 49 | const hasInitialized = useRef(false); |
| 50 | useEffect(() => { |
| 51 | if (!hasInitialized.current) { |
| 52 | // 新しく作成されたブロック(headingが空)の場合は目次に含める |
| 53 | if (!heading || heading.trim() === '') { |
| 54 | setAttributes({ includeInToc: true }); |
| 55 | } |
| 56 | hasInitialized.current = true; |
| 57 | } |
| 58 | }, [includeInToc, setAttributes, heading]); |
| 59 | useEffect(() => { |
| 60 | if (faIcon) { |
| 61 | const fixed = fixBrokenUnicode(faIcon); |
| 62 | if (fixed !== faIcon) { |
| 63 | setAttributes({ faIcon: fixed }); |
| 64 | } |
| 65 | } |
| 66 | }, [faIcon]); |
| 67 | const inner = ( |
| 68 | <InnerBlocks templateLock={false} template={[['core/paragraph']]} /> |
| 69 | ); |
| 70 | const title = ( |
| 71 | <RichText |
| 72 | tagName={headingTag} |
| 73 | identifier="heading" |
| 74 | className={'vk_borderBox_title'} |
| 75 | onChange={(value) => setAttributes({ heading: value })} |
| 76 | value={heading} |
| 77 | placeholder={__('Please enter a title.', 'vk-blocks')} |
| 78 | id={headingTag === 'p' ? undefined : anchor} |
| 79 | /> |
| 80 | ); |
| 81 | |
| 82 | // カラーパレットに対応 |
| 83 | const wrapperClasses = classnames('vk_borderBox', { |
| 84 | [`vk_borderBox-color-${sanitizeSlug(color)}`]: !!color, |
| 85 | [`vk_borderBox-background-${sanitizeSlug(bgColor)}`]: !!bgColor, |
| 86 | [`has-text-color`]: !!borderColor, |
| 87 | [`has-${sanitizeSlug(borderColor)}-color`]: |
| 88 | !!borderColor && !isHexColor(borderColor), |
| 89 | }); |
| 90 | let wrapperStyle = {}; |
| 91 | if (borderColor !== undefined && isHexColor(borderColor)) { |
| 92 | // custom color |
| 93 | wrapperStyle = { |
| 94 | color: `${borderColor}`, |
| 95 | }; |
| 96 | } |
| 97 | const blockProps = useBlockProps({ |
| 98 | className: classnames(wrapperClasses), |
| 99 | style: wrapperStyle, |
| 100 | }); |
| 101 | |
| 102 | //Defaultクラスを設定 |
| 103 | if (-1 === blockProps.className.indexOf('is-style-')) { |
| 104 | blockProps.className += |
| 105 | ' is-style-vk_borderBox-style-solid-kado-tit-tab'; |
| 106 | } |
| 107 | |
| 108 | // 旧カラーを差し替え |
| 109 | const pre_colors = { |
| 110 | red: '#dc3545', |
| 111 | orange: '#ffa536', |
| 112 | blue: '#4267b2', |
| 113 | green: '#28a745', |
| 114 | black: '#222222', |
| 115 | }; |
| 116 | |
| 117 | if (color) { |
| 118 | // 旧カラーで color が指定されている場合 |
| 119 | // hexカラーに置き換え |
| 120 | setAttributes({ borderColor: pre_colors[color] }); |
| 121 | setAttributes({ color: '' }); |
| 122 | } else if ( |
| 123 | attributes.className && |
| 124 | attributes.className.match(/vk_borderBox-color-\w*/) |
| 125 | ) { |
| 126 | // 旧カラーで color がない場合(旧Default対応) |
| 127 | // className から vk_borderBox-color- を削除 |
| 128 | // 文字列を空白文字を区切りとして� |
| 129 | �列化 |
| 130 | const palletClasses = attributes.className.split(' '); |
| 131 | |
| 132 | // preColorClass の値の要素を取り除き、空白文字を区切りとして join(結合) |
| 133 | const palletClass = palletClasses.filter((className) => { |
| 134 | return !className.match(/vk_borderBox-color-\w*/); |
| 135 | }); |
| 136 | |
| 137 | setAttributes({ |
| 138 | className: classnames(palletClass), |
| 139 | }); |
| 140 | |
| 141 | // hexカラー(赤)に置き換え |
| 142 | setAttributes({ borderColor: pre_colors.red }); |
| 143 | } |
| 144 | |
| 145 | //枠パターン |
| 146 | let isFill_title = false; |
| 147 | if ( |
| 148 | -1 < |
| 149 | blockProps.className.indexOf( |
| 150 | 'is-style-vk_borderBox-style-solid-kado-tit-tab' |
| 151 | ) || |
| 152 | -1 < |
| 153 | blockProps.className.indexOf( |
| 154 | 'is-style-vk_borderBox-style-solid-kado-tit-banner' |
| 155 | ) || |
| 156 | -1 < |
| 157 | blockProps.className.indexOf( |
| 158 | 'is-style-vk_borderBox-style-solid-round-tit-tab' |
| 159 | ) |
| 160 | ) { |
| 161 | // タイトル背景塗り 白文字パターン |
| 162 | isFill_title = true; |
| 163 | } |
| 164 | |
| 165 | // title背景 |
| 166 | const titleClasses = classnames('vk_borderBox_title_container', { |
| 167 | [`has-background`]: isFill_title && !!borderColor, |
| 168 | [`has-${sanitizeSlug(borderColor)}-background-color`]: |
| 169 | isFill_title && !!borderColor && !isHexColor(borderColor), |
| 170 | }); |
| 171 | let titleStyle = {}; |
| 172 | if (isFill_title && borderColor !== undefined && isHexColor(borderColor)) { |
| 173 | // custom color |
| 174 | titleStyle = { |
| 175 | backgroundColor: `${borderColor}`, |
| 176 | }; |
| 177 | } |
| 178 | |
| 179 | // アイコン |
| 180 | let icon; |
| 181 | if ( |
| 182 | -1 < |
| 183 | blockProps.className.indexOf( |
| 184 | 'vk_borderBox-style-solid-kado-iconFeature' |
| 185 | ) && |
| 186 | !color |
| 187 | ) { |
| 188 | // 直線 ピン角 アイコン |
| 189 | let iconStyle = ``; |
| 190 | const iconClasses = classnames('vk_borderBox_icon_border', { |
| 191 | [`has-background`]: !!borderColor, |
| 192 | [`has-${sanitizeSlug(borderColor)}-background-color`]: |
| 193 | !!borderColor && !isHexColor(borderColor), |
| 194 | }); |
| 195 | |
| 196 | if (borderColor !== undefined && isHexColor(borderColor)) { |
| 197 | // custom color |
| 198 | iconStyle = `background-color: ${borderColor};`; |
| 199 | } |
| 200 | |
| 201 | // iタグ� |
| 202 | 須 |
| 203 | icon = `<div class="${classnames( |
| 204 | iconClasses |
| 205 | )}" style="${iconStyle}">${fixedFaIcon}</div>`; |
| 206 | } else if ( |
| 207 | fixedFaIcon !== null && |
| 208 | fixedFaIcon !== undefined && |
| 209 | fixedFaIcon.indexOf('<i class="') === -1 |
| 210 | ) { |
| 211 | //iタグでdeprecatedが効かなかったので追加。 |
| 212 | // アイコンなし |
| 213 | icon = `<i class="${fixedFaIcon}"></i>`; |
| 214 | } else { |
| 215 | // アイコンあり |
| 216 | icon = fixedFaIcon; |
| 217 | } |
| 218 | |
| 219 | const bodyClasses = classnames('vk_borderBox_body', { |
| 220 | [`vk_borderBox_body-align-${bodyAlign}`]: !!bodyAlign, |
| 221 | }); |
| 222 | |
| 223 | return ( |
| 224 | <> |
| 225 | <BlockControls group="block"> |
| 226 | <BlockAlignmentControl |
| 227 | value={bodyAlign} |
| 228 | onChange={(value) => setAttributes({ bodyAlign: value })} |
| 229 | controls={['left', 'center', 'right']} |
| 230 | /> |
| 231 | </BlockControls> |
| 232 | <InspectorControls> |
| 233 | <PanelBody |
| 234 | title={__('Margin', 'vk-blocks')} |
| 235 | initialOpen={false} |
| 236 | > |
| 237 | <BaseControl> |
| 238 | <p> |
| 239 | {__( |
| 240 | 'The margin-top of the first element and the margin-bottom of the last element in the border block will be automatically set to 0.If you want to add margins at the beginning and end, use a spacer block to specify height instead of margin.', |
| 241 | 'vk-blocks' |
| 242 | )} |
| 243 | </p> |
| 244 | </BaseControl> |
| 245 | </PanelBody> |
| 246 | <PanelBody |
| 247 | title={__('HTML element of the title', 'vk-blocks')} |
| 248 | initialOpen={false} |
| 249 | > |
| 250 | <BaseControl> |
| 251 | <SelectControl |
| 252 | label={__('HTML element of the title', 'vk-blocks')} |
| 253 | value={headingTag} |
| 254 | options={[ |
| 255 | { label: 'H3', value: 'h3' }, |
| 256 | { label: 'H4', value: 'h4' }, |
| 257 | { label: 'H5', value: 'h5' }, |
| 258 | { label: 'H6', value: 'h6' }, |
| 259 | { label: 'p', value: 'p' }, |
| 260 | ]} |
| 261 | onChange={(value) => { |
| 262 | const newAttributes = { headingTag: value }; |
| 263 | // 見出しタグがpに変更された場合はアンカーIDを削除 |
| 264 | if (value === 'p' && anchor) { |
| 265 | newAttributes.anchor = ''; |
| 266 | } |
| 267 | setAttributes(newAttributes); |
| 268 | }} |
| 269 | /> |
| 270 | </BaseControl> |
| 271 | </PanelBody> |
| 272 | <PanelBody title={__('Color', 'vk-blocks')}> |
| 273 | <BaseControl |
| 274 | id="border-color" |
| 275 | label={__('Border Color', 'vk-blocks')} |
| 276 | > |
| 277 | <AdvancedColorPalette |
| 278 | schema={'borderColor'} |
| 279 | {...props} |
| 280 | /> |
| 281 | </BaseControl> |
| 282 | <BaseControl |
| 283 | id="background-color" |
| 284 | label={__('Background Color', 'vk-blocks')} |
| 285 | > |
| 286 | <SelectControl |
| 287 | value={bgColor} |
| 288 | onChange={(value) => |
| 289 | setAttributes({ bgColor: value }) |
| 290 | } |
| 291 | options={[ |
| 292 | { |
| 293 | value: 'transparent', |
| 294 | label: __('Transparent', 'vk-blocks'), |
| 295 | }, |
| 296 | { |
| 297 | value: 'white', |
| 298 | label: __('White', 'vk-blocks'), |
| 299 | }, |
| 300 | ]} |
| 301 | /> |
| 302 | </BaseControl> |
| 303 | </PanelBody> |
| 304 | <PanelBody title={__('Icon', 'vk-blocks')}> |
| 305 | <BaseControl |
| 306 | id="dot-fa" |
| 307 | label={iconLabel(__('Icon', 'vk-blocks'))} |
| 308 | > |
| 309 | <FontAwesome |
| 310 | attributeName={'faIcon'} |
| 311 | {...{ |
| 312 | attributes, |
| 313 | setAttributes, |
| 314 | }} |
| 315 | /> |
| 316 | </BaseControl> |
| 317 | </PanelBody> |
| 318 | </InspectorControls> |
| 319 | <div {...blockProps}> |
| 320 | <div className={classnames(titleClasses)} style={titleStyle}> |
| 321 | {parse(icon)} |
| 322 | {title} |
| 323 | </div> |
| 324 | <div className={bodyClasses}>{inner}</div> |
| 325 | </div> |
| 326 | </> |
| 327 | ); |
| 328 | } |
| 329 |