PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.7
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.7
2.0.13 2.0.12 2.0.11 2.0.10 2.0.9 trunk 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8
blockenberg / blocks / values-circle / index.js

index.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.7, at blocks/values-circle/index.js

246 lines 13.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 ( function () {
2 var el = wp.element.createElement;
3 var __ = wp.i18n.__;
4 var registerBlockType = wp.blocks.registerBlockType;
5 var useBlockProps = wp.blockEditor.useBlockProps;
6 var InspectorControls = wp.blockEditor.InspectorControls;
7 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
8 var PanelBody = wp.components.PanelBody;
9 var RangeControl = wp.components.RangeControl;
10 var ToggleControl = wp.components.ToggleControl;
11 var SelectControl = wp.components.SelectControl;
12 var TextControl = wp.components.TextControl;
13 var Button = wp.components.Button;
14 var IP = function () { return window.bkbgIconPicker; };
15
16 function buildCircleSVG(attr, size) {
17 var values = attr.values;
18 var n = values.length;
19 if (n === 0) return null;
20
21 var cx = size / 2;
22 var cy = size / 2;
23 var OR = (size / 2) * (attr.orbitRadius / 100);
24 var CR = (size / 2) * (attr.centerRadius / 100);
25 var nodeR = CR * 0.75;
26 var lineStyle = attr.lineStyle === 'solid' ? '' : '6 4';
27
28 var svgNS = 'http://www.w3.org/2000/svg';
29
30 var nodes = values.map(function (v, i) {
31 var angle = (2 * Math.PI * i / n) - Math.PI / 2;
32 return {
33 x: cx + OR * Math.cos(angle),
34 y: cy + OR * Math.sin(angle),
35 value: v, angle: angle
36 };
37 });
38
39 var svgEl = el('svg', {
40 xmlns: svgNS,
41 viewBox: '0 0 ' + size + ' ' + size,
42 width: '100%',
43 height: 'auto',
44 style: { maxWidth: size + 'px', overflow: 'visible', display: 'block', margin: '0 auto' }
45 },
46 /* connector lines */
47 nodes.map(function (node, i) {
48 return el('line', { key: 'l' + i,
49 x1: cx, y1: cy, x2: node.x, y2: node.y,
50 stroke: attr.lineColor, strokeWidth: 1.5,
51 strokeDasharray: lineStyle, opacity: 0.7
52 });
53 }),
54 /* orbit ring */
55 el('circle', { cx: cx, cy: cy, r: OR,
56 fill: 'none', stroke: attr.lineColor, strokeWidth: 1,
57 strokeDasharray: '4 6', opacity: 0.4
58 }),
59 /* center circle */
60 el('circle', { cx: cx, cy: cy, r: CR, fill: attr.centerBg }),
61 el('text', { x: cx, y: cy + (attr.centerTextSize * 0.35),
62 textAnchor: 'middle', dominantBaseline: 'middle',
63 fontSize: attr.centerTextSize, fontWeight: 700,
64 fill: attr.centerColor, fontFamily: 'inherit'
65 }, attr.centerText),
66 /* value nodes */
67 nodes.map(function (node, i) {
68 var labelX = node.x + (node.x > cx ? 1 : -1) * (nodeR + 8);
69 var ta = node.x > cx + 5 ? 'start' : node.x < cx - 5 ? 'end' : 'middle';
70 var _iType = node.value.iconType || 'custom-char';
71 var _iconEl;
72 if (_iType !== 'custom-char' && IP()) {
73 var _built = IP().buildEditorIcon(_iType, node.value.icon, node.value.iconDashicon, node.value.iconImageUrl, node.value.iconDashiconColor);
74 if (_built) {
75 _iconEl = el('foreignObject', { x: node.x - nodeR * 0.5, y: node.y - nodeR * 0.5, width: nodeR, height: nodeR },
76 el('div', { style: { width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: (attr.iconSize * 0.55) + 'px', lineHeight: '1' } }, _built));
77 }
78 }
79 if (!_iconEl) {
80 _iconEl = el('text', { x: node.x, y: node.y + (attr.iconSize * 0.35),
81 textAnchor: 'middle', dominantBaseline: 'middle',
82 fontSize: attr.iconSize * 0.55, fontFamily: 'inherit'
83 }, node.value.icon);
84 }
85 return el('g', { key: 'n' + i },
86 el('circle', { cx: node.x, cy: node.y, r: nodeR, fill: attr.nodeBg }),
87 _iconEl,
88 el('text', { x: labelX, y: node.y - (attr.descSize + 2),
89 textAnchor: ta, fontSize: attr.labelSize, fontWeight: 700,
90 fill: attr.labelColor, fontFamily: 'inherit'
91 }, node.value.label),
92 attr.showDescription && el('text', { x: labelX, y: node.y + attr.descSize,
93 textAnchor: ta, fontSize: attr.descSize,
94 fill: attr.descColor, fontFamily: 'inherit'
95 }, node.value.description)
96 );
97 })
98 );
99
100 return svgEl;
101 }
102
103 registerBlockType('blockenberg/values-circle', {
104 title: __('Values Circle'),
105 icon: 'chart-pie',
106 category: 'bkbg-business',
107
108 edit: function (props) {
109 var attr = props.attributes;
110 var setAttr = props.setAttributes;
111 var bp = useBlockProps({ className: 'bkbg-vc-wrap' });
112
113 function updateValue(idx, field, val) {
114 var values = attr.values.map(function (v, i) {
115 return i === idx ? Object.assign({}, v, { [field]: val }) : v;
116 });
117 setAttr({ values: values });
118 }
119 function addValue() {
120 setAttr({ values: attr.values.concat([{ icon: '', iconType: 'custom-char', iconDashicon: '', iconImageUrl: '', label: 'New Value', description: 'Description' }]) });
121 }
122 function removeValue(idx) {
123 if (attr.values.length <= 2) return;
124 setAttr({ values: attr.values.filter(function (_, i) { return i !== idx; }) });
125 }
126
127 var inspector = el(InspectorControls, {},
128 el(PanelBody, { title: __('Values'), initialOpen: true },
129 attr.values.map(function (v, idx) {
130 return el(PanelBody, { key: idx, title: v.label || 'Value ' + (idx + 1), initialOpen: false },
131 el(IP().IconPickerControl, IP().iconPickerProps(v, function(patch) {
132 var values = attr.values.map(function(val, i) { return i === idx ? Object.assign({}, val, patch) : val; });
133 setAttr({ values: values });
134 }, { label: __('Icon (emoji)'), charAttr: 'icon', typeAttr: 'iconType', dashiconAttr: 'iconDashicon', imageUrlAttr: 'iconImageUrl' })),
135 el(TextControl, { label: __('Label'), value: v.label || '',
136 onChange: function (val) { updateValue(idx, 'label', val); },
137 __nextHasNoMarginBottom: true }),
138 el(TextControl, { label: __('Description'), value: v.description || '',
139 onChange: function (val) { updateValue(idx, 'description', val); },
140 __nextHasNoMarginBottom: true }),
141 attr.values.length > 2 && el(Button, {
142 isDestructive: true, variant: 'secondary',
143 onClick: function () { removeValue(idx); },
144 style: { marginTop: 8 }
145 }, __('Remove'))
146 );
147 }),
148 el(Button, { variant: 'primary', onClick: addValue,
149 style: { marginTop: 8, width: '100%' }
150 }, __('+ Add Value'))
151 ),
152
153 el(PanelBody, { title: __('Center'), initialOpen: false },
154 el(TextControl, { label: __('Center Text'), value: attr.centerText,
155 onChange: function (v) { setAttr({ centerText: v }); },
156 __nextHasNoMarginBottom: true }),
157 el(RangeControl, { label: __('Center Radius (% of half)'), value: attr.centerRadius,
158 min: 10, max: 35,
159 onChange: function (v) { setAttr({ centerRadius: v }); },
160 __nextHasNoMarginBottom: true })
161 ),
162
163 el(PanelBody, { title: __('Layout'), initialOpen: false },
164 el(RangeControl, { label: __('Diagram Size (px)'), value: attr.size,
165 min: 300, max: 900, step: 20,
166 onChange: function (v) { setAttr({ size: v }); },
167 __nextHasNoMarginBottom: true }),
168 el(RangeControl, { label: __('Orbit Radius (% of half)'), value: attr.orbitRadius,
169 min: 25, max: 60,
170 onChange: function (v) { setAttr({ orbitRadius: v }); },
171 __nextHasNoMarginBottom: true }),
172 el(RangeControl, { label: __('Icon Size (px)'), value: attr.iconSize,
173 min: 16, max: 64,
174 onChange: function (v) { setAttr({ iconSize: v }); },
175 __nextHasNoMarginBottom: true }),
176 el(ToggleControl, { label: __('Show Descriptions'), checked: attr.showDescription,
177 onChange: function (v) { setAttr({ showDescription: v }); },
178 __nextHasNoMarginBottom: true }),
179 el(SelectControl, { label: __('Connector Style'), value: attr.lineStyle,
180 options: [
181 { label: __('Dashed'), value: 'dashed' },
182 { label: __('Solid'), value: 'solid' }
183 ],
184 onChange: function (v) { setAttr({ lineStyle: v }); },
185 __nextHasNoMarginBottom: true }),
186 el(ToggleControl, { label: __('Animate on Scroll'), checked: attr.animate,
187 onChange: function (v) { setAttr({ animate: v }); },
188 __nextHasNoMarginBottom: true }),
189 attr.animate && el(RangeControl, { label: __('Animation Duration (ms)'), value: attr.animateDuration,
190 min: 200, max: 2000, step: 100,
191 onChange: function (v) { setAttr({ animateDuration: v }); },
192 __nextHasNoMarginBottom: true })
193 ),
194
195
196 el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
197 el(RangeControl, { label: __('Center Text Size (px)'), value: attr.centerTextSize,
198 min: 10, max: 40,
199 onChange: function (v) { setAttr({ centerTextSize: v }); },
200 __nextHasNoMarginBottom: true }),
201 el(RangeControl, { label: __('Label Size (px)'), value: attr.labelSize,
202 min: 10, max: 22,
203 onChange: function (v) { setAttr({ labelSize: v }); },
204 __nextHasNoMarginBottom: true }),
205 el(RangeControl, { label: __('Description Size (px)'), value: attr.descSize,
206 min: 8, max: 16,
207 onChange: function (v) { setAttr({ descSize: v }); },
208 __nextHasNoMarginBottom: true })
209 ),
210 el(PanelColorSettings, {
211 title: __('Colors'), initialOpen: false,
212 colorSettings: [
213 { label: __('Node BG'), value: attr.nodeBg,
214 onChange: function (v) { setAttr({ nodeBg: v || '#6366f1' }); } },
215 { label: __('Center BG'), value: attr.centerBg,
216 onChange: function (v) { setAttr({ centerBg: v || '#0f172a' }); } },
217 { label: __('Center Text'), value: attr.centerColor,
218 onChange: function (v) { setAttr({ centerColor: v || '#ffffff' }); } },
219 { label: __('Connector Lines'), value: attr.lineColor,
220 onChange: function (v) { setAttr({ lineColor: v || '#cbd5e1' }); } },
221 { label: __('Label Text'), value: attr.labelColor,
222 onChange: function (v) { setAttr({ labelColor: v || '#0f172a' }); } },
223 { label: __('Description Text'), value: attr.descColor,
224 onChange: function (v) { setAttr({ descColor: v || '#64748b' }); } }
225 ]
226 })
227 );
228
229 return el(wp.element.Fragment, {}, inspector,
230 el('div', bp,
231 attr.sectionBg && el('style', {}, '.bkbg-vc-wrap{background:' + attr.sectionBg + '}'),
232 buildCircleSVG(attr, attr.size)
233 )
234 );
235 },
236
237 save: function (props) {
238 var attr = props.attributes;
239 var bp = useBlockProps.save();
240 return el('div', bp,
241 el('div', { className: 'bkbg-vc-app', 'data-opts': JSON.stringify(attr) })
242 );
243 }
244 });
245 }() );
246