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 / venn-diagram / index.js

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

211 lines 15.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 ( function () {
2 const el = window.wp.element.createElement;
3 const { registerBlockType } = window.wp.blocks;
4 const { InspectorControls, useBlockProps, PanelColorSettings } = window.wp.blockEditor;
5 const { PanelBody, RangeControl, SelectControl, ToggleControl, TextControl, TextareaControl } = window.wp.components;
6 const { __ } = window.wp.i18n;
7
8 var _tc, _tvf;
9 Object.defineProperty(window, '_tc', { get: function () { return _tc || (_tc = window.bkbgTypographyControl); } });
10 Object.defineProperty(window, '_tvf', { get: function () { return _tvf || (_tvf = window.bkbgTypoCssVars); } });
11 function getTypoControl(label, key, attrs, setA) { return _tc(label, key, attrs, setA); }
12 function getTypoCssVars(attrs) {
13 var v = {};
14 _tvf(v, 'titleTypo', attrs, '--bkvenn-tt-');
15 _tvf(v, 'subtitleTypo', attrs, '--bkvenn-st-');
16 return v;
17 }
18
19 // ── SVG geometry ──────────────────────────────────────────────────
20 // Two-circle venn
21 function renderVenn2(a) {
22 const S = a.svgSize;
23 const r = S * 0.36;
24 const cy = S * 0.5;
25 const cx1 = S * 0.35, cx2 = S * 0.65;
26 const op = a.circleOpacity;
27 const fs = a.fontSize;
28
29 return el('svg', { viewBox: `0 0 ${S} ${S}`, width: '100%', style: { maxWidth: S + 'px', display: 'block', margin: '0 auto' } },
30 // Circles
31 el('circle', { cx: cx1, cy, r, fill: a.circleA.color, opacity: op }),
32 el('circle', { cx: cx2, cy, r, fill: a.circleB.color, opacity: op }),
33 // Outlines
34 el('circle', { cx: cx1, cy, r, fill: 'none', stroke: a.circleA.color, strokeWidth: 2, opacity: 0.6 }),
35 el('circle', { cx: cx2, cy, r, fill: 'none', stroke: a.circleB.color, strokeWidth: 2, opacity: 0.6 }),
36 // Labels
37 a.showCircleLabels && el('text', { x: cx1 - r * 0.35, y: cy, textAnchor: 'middle', fill: a.circleA.color, fontSize: a.labelSize, fontWeight: 700, fontFamily: 'inherit', dominantBaseline: 'middle' }, a.circleA.label),
38 a.showCircleLabels && el('text', { x: cx2 + r * 0.35, y: cy, textAnchor: 'middle', fill: a.circleB.color, fontSize: a.labelSize, fontWeight: 700, fontFamily: 'inherit', dominantBaseline: 'middle' }, a.circleB.label),
39 // Overlap text
40 a.showOverlapText && el('text', { x: S * 0.5, y: cy, textAnchor: 'middle', fill: a.textColor, fontSize: a.overlapSize, fontWeight: 700, fontFamily: 'inherit', dominantBaseline: 'middle' }, a.overlapAB),
41 );
42 }
43
44 // Three-circle venn
45 function renderVenn3(a) {
46 const S = a.svgSize;
47 const r = S * 0.34;
48 // Centres of 3 circles arranged in a triangle
49 const cpx = S / 2;
50 const cpy = S / 2 - S * 0.04;
51 const angle = [-Math.PI / 2, -Math.PI / 2 + (2 * Math.PI / 3), -Math.PI / 2 + (4 * Math.PI / 3)];
52 const dist = r * 0.6;
53 const cx = [cpx + dist * Math.cos(angle[0]), cpx + dist * Math.cos(angle[1]), cpx + dist * Math.cos(angle[2])];
54 const cy = [cpy + dist * Math.sin(angle[0]), cpy + dist * Math.sin(angle[1]), cpy + dist * Math.sin(angle[2])];
55 const op = a.circleOpacity;
56 const circles = [
57 { cx: cx[0], cy: cy[0], color: a.circleA.color, label: a.circleA.label },
58 { cx: cx[1], cy: cy[1], color: a.circleB.color, label: a.circleB.label },
59 { cx: cx[2], cy: cy[2], color: a.circleC.color, label: a.circleC.label },
60 ];
61 // Overlap label positions (midpoint between circle centres + slightly toward centre)
62 function midOut(i, j, pullFrac) {
63 const mx = (cx[i] + cx[j]) / 2;
64 const my = (cy[i] + cy[j]) / 2;
65 return { x: mx + (cpx - mx) * pullFrac, y: my + (cpy - my) * pullFrac };
66 }
67 const pAB = midOut(0, 1, 0.3);
68 const pBC = midOut(1, 2, 0.3);
69 const pAC = midOut(0, 2, 0.3);
70 const pABC = { x: cpx, y: cpy + r * 0.05 };
71
72 // Label positions (outside the overlapping area)
73 function labelPos(i) {
74 const fromCenter = r * 1.05;
75 return { x: cpx + fromCenter * Math.cos(angle[i]), y: cpy + fromCenter * Math.sin(angle[i]) };
76 }
77
78 return el('svg', { viewBox: `0 0 ${S} ${S}`, width: '100%', style: { maxWidth: S + 'px', display: 'block', margin: '0 auto' } },
79 // Filled circles
80 circles.map((c, i) => el('circle', { key: 'f' + i, cx: c.cx, cy: c.cy, r, fill: c.color, opacity: op })),
81 // Stroke outlines
82 circles.map((c, i) => el('circle', { key: 'o' + i, cx: c.cx, cy: c.cy, r, fill: 'none', stroke: c.color, strokeWidth: 2, opacity: 0.6 })),
83 // Circle main labels
84 a.showCircleLabels && circles.map((c, i) => {
85 const lp = labelPos(i);
86 return el('text', {
87 key: 'lbl' + i, x: lp.x, y: lp.y,
88 textAnchor: 'middle', dominantBaseline: 'middle',
89 fill: c.color, fontSize: a.labelSize, fontWeight: 700, fontFamily: 'inherit'
90 }, c.label);
91 }),
92 // Overlap labels
93 a.showOverlapText && [
94 el('text', { key: 'oAB', x: pAB.x, y: pAB.y, textAnchor: 'middle', dominantBaseline: 'middle', fill: a.textColor, fontSize: a.overlapSize, fontWeight: 600, fontFamily: 'inherit', opacity: 0.85 }, a.overlapAB),
95 el('text', { key: 'oBC', x: pBC.x, y: pBC.y, textAnchor: 'middle', dominantBaseline: 'middle', fill: a.textColor, fontSize: a.overlapSize, fontWeight: 600, fontFamily: 'inherit', opacity: 0.85 }, a.overlapBC),
96 el('text', { key: 'oAC', x: pAC.x, y: pAC.y, textAnchor: 'middle', dominantBaseline: 'middle', fill: a.textColor, fontSize: a.overlapSize, fontWeight: 600, fontFamily: 'inherit', opacity: 0.85 }, a.overlapAC),
97 el('text', { key: 'oABC', x: pABC.x, y: pABC.y, textAnchor: 'middle', dominantBaseline: 'middle', fill: a.textColor, fontSize: a.overlapSize + 1, fontWeight: 700, fontFamily: 'inherit' }, a.overlapABC),
98 ],
99 );
100 }
101
102 // ── Circle items legend ───────────────────────────────────────────
103 function renderItems(a) {
104 const cols = a.mode === 'three' ? [a.circleA, a.circleB, a.circleC] : [a.circleA, a.circleB];
105 return el('div', { className: 'bkbg-venn-items', style: { display: 'flex', gap: '24px', flexWrap: 'wrap', justifyContent: 'center', marginTop: '24px' } },
106 cols.map((c, i) =>
107 el('div', { key: i, style: { minWidth: '140px', flex: '1' } },
108 el('div', { style: { fontWeight: 700, fontSize: a.labelSize + 'px', color: c.color, marginBottom: '8px', display: 'flex', alignItems: 'center', gap: '6px' } },
109 el('span', { style: { display: 'inline-block', width: '10px', height: '10px', borderRadius: '50%', background: c.color } }),
110 c.label
111 ),
112 (c.items || []).map((item, j) =>
113 el('div', { key: j, style: { fontSize: a.fontSize + 'px', color: a.subtitleColor, marginBottom: '4px', paddingLeft: '16px' } }, '· ' + item)
114 )
115 )
116 )
117 );
118 }
119
120 function wrapStyle(a) {
121 return { background: a.bgColor, borderRadius: a.borderRadius + 'px', paddingTop: a.paddingTop + 'px', paddingBottom: a.paddingBottom + 'px', paddingLeft: '32px', paddingRight: '32px' };
122 }
123
124 // ── Circle editor panel ───────────────────────────────────────────
125 function circlePanel(label, circle, onChange, __, el, TextControl, TextareaControl, PanelBody) {
126 return el(PanelBody, { title: label, initialOpen: false },
127 el(TextControl, { label: __('Label'), value: circle.label, onChange: v => onChange({ ...circle, label: v }) }),
128 el('div', { style: { marginBottom: '8px' } },
129 el('label', { style: { display: 'block', marginBottom: '6px', fontSize: '11px', fontWeight: '600', textTransform: 'uppercase' } }, __('Circle Color')),
130 el('input', { type: 'color', value: circle.color, style: { width: '100%', height: '36px', border: '1px solid #ddd', borderRadius: '4px', cursor: 'pointer' }, onChange: e => onChange({ ...circle, color: e.target.value }) })
131 ),
132 el(TextareaControl, { label: __('Items (one per line)'), value: (circle.items || []).join('\n'), rows: 4, onChange: v => onChange({ ...circle, items: v.split('\n').filter(s => s.trim()) }) }),
133 );
134 }
135
136 registerBlockType('blockenberg/venn-diagram', {
137 edit: function ({ attributes: a, setAttributes }) {
138 const blockProps = useBlockProps((function () {
139 var s = wrapStyle(a);
140 Object.assign(s, getTypoCssVars(a));
141 return { style: s };
142 })());
143 const is3 = a.mode === 'three';
144 return el('div', blockProps,
145 el(InspectorControls, {},
146 el(PanelBody, { title: __('Content'), initialOpen: true },
147 el(TextControl, { label: __('Title'), value: a.title, onChange: v => setAttributes({ title: v }) }),
148 el(ToggleControl, { label: __('Show title'), checked: a.showTitle, onChange: v => setAttributes({ showTitle: v }) }),
149 el(TextControl, { label: __('Subtitle'), value: a.subtitle, onChange: v => setAttributes({ subtitle: v }) }),
150 el(ToggleControl, { label: __('Show subtitle'), checked: a.showSubtitle, onChange: v => setAttributes({ showSubtitle: v }) }),
151 el(SelectControl, { label: __('Mode'), value: a.mode, options: [{ value: 'two', label: 'Two circles' }, { value: 'three', label: 'Three circles' }], onChange: v => setAttributes({ mode: v }) }),
152 el(ToggleControl, { label: __('Show circle labels'), checked: a.showCircleLabels, onChange: v => setAttributes({ showCircleLabels: v }) }),
153 el(ToggleControl, { label: __('Show overlap text'), checked: a.showOverlapText, onChange: v => setAttributes({ showOverlapText: v }) }),
154 el(ToggleControl, { label: __('Show item lists'), checked: a.showCircleItems, onChange: v => setAttributes({ showCircleItems: v }) }),
155 ),
156 el(PanelBody, { title: __('Overlap Text'), initialOpen: false },
157 el(TextControl, { label: is3 ? __('A ∩ B') : __('Overlap label'), value: a.overlapAB, onChange: v => setAttributes({ overlapAB: v }) }),
158 is3 && el(TextControl, { label: __('B ∩ C'), value: a.overlapBC, onChange: v => setAttributes({ overlapBC: v }) }),
159 is3 && el(TextControl, { label: __('A ∩ C'), value: a.overlapAC, onChange: v => setAttributes({ overlapAC: v }) }),
160 is3 && el(TextControl, { label: __('A ∩ B ∩ C (centre)'), value: a.overlapABC, onChange: v => setAttributes({ overlapABC: v }) }),
161 ),
162 circlePanel(__('Circle A'), a.circleA, v => setAttributes({ circleA: v }), __, el, TextControl, TextareaControl, PanelBody),
163 circlePanel(__('Circle B'), a.circleB, v => setAttributes({ circleB: v }), __, el, TextControl, TextareaControl, PanelBody),
164 is3 && circlePanel(__('Circle C'), a.circleC, v => setAttributes({ circleC: v }), __, el, TextControl, TextareaControl, PanelBody),
165 el(PanelBody, { title: __('Appearance'), initialOpen: false },
166 el(RangeControl, { label: __('Diagram size'), value: a.svgSize, min: 240, max: 600, onChange: v => setAttributes({ svgSize: v }) }),
167 el(RangeControl, { label: __('Circle opacity'), value: Math.round(a.circleOpacity * 100), min: 5, max: 60, onChange: v => setAttributes({ circleOpacity: v / 100 }) }),
168 el(RangeControl, { label: __('Border radius'), value: a.borderRadius, min: 0, max: 32, onChange: v => setAttributes({ borderRadius: v }) }),
169 el(RangeControl, { label: __('Padding top'), value: a.paddingTop, min: 0, max: 120, onChange: v => setAttributes({ paddingTop: v }) }),
170 el(RangeControl, { label: __('Padding bottom'), value: a.paddingBottom, min: 0, max: 120, onChange: v => setAttributes({ paddingBottom: v }) }),
171 ),
172
173 el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
174 getTypoControl(__('Title', 'blockenberg'), 'titleTypo', a, setAttributes),
175 getTypoControl(__('Subtitle', 'blockenberg'), 'subtitleTypo', a, setAttributes),
176 el(RangeControl, { label: __('Label font size'), value: a.labelSize, min: 10, max: 28, onChange: v => setAttributes({ labelSize: v }) }),
177 el(RangeControl, { label: __('Overlap font size'), value: a.overlapSize, min: 8, max: 22, onChange: v => setAttributes({ overlapSize: v }) }),
178 el(RangeControl, { label: __('Item font size'), value: a.fontSize, min: 10, max: 20, onChange: v => setAttributes({ fontSize: v }) })
179 ),
180 el(PanelColorSettings, {
181 title: __('Colors'), initialOpen: false,
182 colorSettings: [
183 { label: __('Background'), value: a.bgColor, onChange: v => setAttributes({ bgColor: v || '#ffffff' }) },
184 { label: __('Title'), value: a.titleColor, onChange: v => setAttributes({ titleColor: v || '#0f172a' }) },
185 { label: __('Subtitle'), value: a.subtitleColor, onChange: v => setAttributes({ subtitleColor: v || '#64748b' }) },
186 { label: __('Text / overlaps'), value: a.textColor, onChange: v => setAttributes({ textColor: v || '#1e293b' }) },
187 ]
188 }),
189 ),
190
191 a.showTitle && el('h3', { className: 'bkbg-venn-title', style: { color: a.titleColor, textAlign: 'center', margin: '0 0 8px' } }, a.title),
192 a.showSubtitle && el('p', { className: 'bkbg-venn-subtitle', style: { color: a.subtitleColor, textAlign: 'center', margin: '0 0 20px' } }, a.subtitle),
193 is3 ? renderVenn3(a) : renderVenn2(a),
194 a.showCircleItems && renderItems(a),
195 );
196 },
197
198 save: function ({ attributes: a }) {
199 const is3 = a.mode === 'three';
200 var _saveStyle = wrapStyle(a);
201 Object.assign(_saveStyle, getTypoCssVars(a));
202 return el('div', { className: 'bkbg-venn-wrap', style: _saveStyle },
203 a.showTitle && el('h3', { className: 'bkbg-venn-title', style: { color: a.titleColor, textAlign: 'center', margin: '0 0 8px' } }, a.title),
204 a.showSubtitle && el('p', { className: 'bkbg-venn-subtitle', style: { color: a.subtitleColor, textAlign: 'center', margin: '0 0 20px' } }, a.subtitle),
205 is3 ? renderVenn3(a) : renderVenn2(a),
206 a.showCircleItems && renderItems(a),
207 );
208 }
209 });
210 }() );
211