| 1 |
( function( blocks, element, blockEditor, components ) { |
| 2 |
const { registerBlockType } = blocks; |
| 3 |
const { createElement: el, useState, useEffect } = element; |
| 4 |
const { InspectorControls, useBlockProps } = blockEditor; |
| 5 |
const { TextControl, PanelBody, Placeholder, Button, Spinner } = components; |
| 6 |
|
| 7 |
registerBlockType( 'wpcoder/shortcode', { |
| 8 |
title: 'WP Coder Snippet', |
| 9 |
icon: { |
| 10 |
src: el( |
| 11 |
'svg', |
| 12 |
{ |
| 13 |
xmlns: "http://www.w3.org/2000/svg", |
| 14 |
width: 20, |
| 15 |
height: 20, |
| 16 |
viewBox: "0 0 512 512" |
| 17 |
}, |
| 18 |
el( |
| 19 |
'g', |
| 20 |
{}, |
| 21 |
el('path', { |
| 22 |
fill: "#2b7fff", |
| 23 |
fillRule: "evenodd", |
| 24 |
stroke: "none", |
| 25 |
d: "M 496 101 C 496 128.614227 473.614227 151 446 151 C 418.385773 151 396 128.614227 396 101 C 396 73.385773 418.385773 51 446 51 C 473.614227 51 496 73.385773 496 101 Z" |
| 26 |
}), |
| 27 |
el( |
| 28 |
'g', |
| 29 |
{}, |
| 30 |
el('path', { |
| 31 |
fill: "#212121", |
| 32 |
stroke: "none", |
| 33 |
d: "M 245.714279 232.714294 L 74.285713 61.285736 C 60.571426 47.571411 40 47.571411 26.285713 61.285736 C 12.571427 75 12.571427 95.571442 26.285713 109.285706 L 173.714279 256.714294 L 26.285713 404.142853 C 12.571427 417.857147 12.571427 438.428589 26.285713 452.142853 C 33.142857 459 40 462.428558 50.285713 462.428558 C 60.571426 462.428558 67.428574 459 74.285713 452.142853 L 245.714279 280.714294 C 259.428589 267 259.428589 246.428558 245.714279 232.714294 Z" |
| 34 |
}), |
| 35 |
el('path', { |
| 36 |
fill: "#212121", |
| 37 |
fillRule: "evenodd", |
| 38 |
stroke: "none", |
| 39 |
d: "M 256 431 C 256 448.673096 270.326874 463 288 463 L 464 463 C 481.673096 463 496 448.673096 496 431 L 496 429 C 496 411.326904 481.673096 397 464 397 L 288 397 C 270.326874 397 256 411.326904 256 429 Z" |
| 40 |
}) |
| 41 |
) |
| 42 |
) |
| 43 |
) |
| 44 |
}, |
| 45 |
category: 'widgets', |
| 46 |
attributes: { |
| 47 |
id: { type: 'string', default: '' }, |
| 48 |
extraAttrs: { type: 'array', default: [] } |
| 49 |
}, |
| 50 |
supports: { |
| 51 |
html: false |
| 52 |
}, |
| 53 |
|
| 54 |
edit: ( props ) => { |
| 55 |
const blockProps = useBlockProps(); |
| 56 |
const [ localId, setLocalId ] = useState( props.attributes.id || '' ); |
| 57 |
const [ preview, setPreview ] = useState( '' ); |
| 58 |
const [ loading, setLoading ] = useState( false ); |
| 59 |
const [ availableAttrs, setAvailableAttrs ] = useState( [] ); |
| 60 |
|
| 61 |
const loadPreview = () => { |
| 62 |
if ( ! localId ) { |
| 63 |
setPreview('<em>Please enter Snippet ID</em>'); |
| 64 |
return; |
| 65 |
} |
| 66 |
|
| 67 |
props.setAttributes( { id: localId } ); |
| 68 |
setLoading( true ); |
| 69 |
|
| 70 |
wp.apiFetch({ |
| 71 |
path: '/wpcoder/v1/preview', |
| 72 |
method: 'POST', |
| 73 |
data: { id: localId, extraAttrs: props.attributes.extraAttrs } |
| 74 |
}).then((response) => { |
| 75 |
setPreview( response.html || '<em>No preview</em>' ); |
| 76 |
setLoading( false ); |
| 77 |
|
| 78 |
if (response.css) { |
| 79 |
let styleId = 'wpcoder-style-' + localId; |
| 80 |
if ( ! document.getElementById(styleId) ) { |
| 81 |
const style = document.createElement('style'); |
| 82 |
style.id = styleId; |
| 83 |
style.innerHTML = response.css; |
| 84 |
document.head.appendChild(style); |
| 85 |
} |
| 86 |
} |
| 87 |
|
| 88 |
}); |
| 89 |
}; |
| 90 |
|
| 91 |
useEffect( () => { |
| 92 |
if ( ! props.attributes.id ) return; |
| 93 |
|
| 94 |
setLoading( true ); |
| 95 |
wp.apiFetch({ |
| 96 |
path: '/wpcoder/v1/preview', |
| 97 |
method: 'POST', |
| 98 |
data: { |
| 99 |
id: localId, |
| 100 |
extraAttrs: props.attributes.extraAttrs |
| 101 |
} |
| 102 |
}).then((response) => { |
| 103 |
setPreview( response.html || '<em>No preview</em>' ); |
| 104 |
setLoading( false ); |
| 105 |
|
| 106 |
// CSS |
| 107 |
if (response.css) { |
| 108 |
let styleId = 'wpcoder-style-' + localId; |
| 109 |
if ( ! document.getElementById(styleId) ) { |
| 110 |
const style = document.createElement('style'); |
| 111 |
style.id = styleId; |
| 112 |
style.innerHTML = response.css; |
| 113 |
document.head.appendChild(style); |
| 114 |
} |
| 115 |
} |
| 116 |
|
| 117 |
}); |
| 118 |
|
| 119 |
wp.apiFetch({ |
| 120 |
path: '/wpcoder/v1/attributes', |
| 121 |
method: 'POST', |
| 122 |
data: { id: props.attributes.id } |
| 123 |
}).then((attrs) => { |
| 124 |
setAvailableAttrs(attrs || []); |
| 125 |
if (attrs.length > 0 && props.attributes.extraAttrs.length === 0) { |
| 126 |
const init = attrs.map(a => ({ key: a.key, value: '' })); |
| 127 |
props.setAttributes({ extraAttrs: init }); |
| 128 |
} |
| 129 |
}); |
| 130 |
|
| 131 |
|
| 132 |
}, [ props.attributes.id ] ) |
| 133 |
|
| 134 |
if ( ! props.attributes.id ) { |
| 135 |
return el( Placeholder, |
| 136 |
{ |
| 137 |
label: 'WP Coder Snippet', |
| 138 |
instructions: 'Enter snippet ID and click Load' |
| 139 |
}, |
| 140 |
el( 'div', { |
| 141 |
style: { |
| 142 |
display: 'flex', |
| 143 |
gap: '10px', |
| 144 |
alignItems: 'baseline', |
| 145 |
maxWidth: '400px' |
| 146 |
} |
| 147 |
}, [ |
| 148 |
el( TextControl, { |
| 149 |
label: '', |
| 150 |
placeholder: 'Snippet ID', |
| 151 |
value: localId, |
| 152 |
onChange: ( value ) => setLocalId( value ), |
| 153 |
style: { flex: '1' } |
| 154 |
}), |
| 155 |
el( Button, { |
| 156 |
isPrimary: true, |
| 157 |
onClick: loadPreview |
| 158 |
}, 'Load Preview') |
| 159 |
]) |
| 160 |
); |
| 161 |
} |
| 162 |
|
| 163 |
return el( 'div', blockProps, [ |
| 164 |
el( InspectorControls, {}, |
| 165 |
el( PanelBody, { title: 'WP Coder Settings' }, [ |
| 166 |
el( TextControl, { |
| 167 |
label: 'Snippet ID', |
| 168 |
value: localId, |
| 169 |
onChange: ( value ) => setLocalId( value ) |
| 170 |
}), |
| 171 |
el( 'div', { style: { display: 'flex', gap: '10px', marginTop: '10px' } }, [ |
| 172 |
el( Button, { |
| 173 |
isPrimary: true, |
| 174 |
onClick: loadPreview |
| 175 |
}, 'Reload Preview'), |
| 176 |
props.attributes.id && el( Button, { |
| 177 |
isSecondary: true, |
| 178 |
href: `${ wpcoderBlockData.editBaseUrl }&action=update&id=${ props.attributes.id }`, |
| 179 |
target: '_blank' |
| 180 |
}, 'Edit Snippet') |
| 181 |
]), |
| 182 |
availableAttrs.length > 0 && el( 'div', { style: { marginTop: '15px' } }, |
| 183 |
el( PanelBody, { title: 'Shortcode Attributes', initialOpen: true }, |
| 184 |
availableAttrs.map( (attr, i) => |
| 185 |
el( TextControl, { |
| 186 |
label: attr.key, |
| 187 |
value: (props.attributes.extraAttrs.find(a => a.key === attr.key)?.value) || '', |
| 188 |
onChange: ( val ) => { |
| 189 |
const newAttrs = props.attributes.extraAttrs.map(a => |
| 190 |
a.key === attr.key ? { ...a, value: val } : a |
| 191 |
); |
| 192 |
props.setAttributes({ extraAttrs: newAttrs }); |
| 193 |
} |
| 194 |
}) |
| 195 |
) |
| 196 |
) |
| 197 |
) |
| 198 |
]) |
| 199 |
), |
| 200 |
loading |
| 201 |
? el( Spinner, {} ) |
| 202 |
: el( 'div', { |
| 203 |
className: 'wpcoder-preview', |
| 204 |
dangerouslySetInnerHTML: { __html: preview } |
| 205 |
}) |
| 206 |
] ); |
| 207 |
}, |
| 208 |
|
| 209 |
save: () => null |
| 210 |
} ); |
| 211 |
} )( window.wp.blocks, window.wp.element, window.wp.blockEditor, window.wp.components ); |