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

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

374 lines 30.5 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 Fragment = wp.element.Fragment;
4 var __ = wp.i18n.__;
5 var registerBlockType = wp.blocks.registerBlockType;
6 var InspectorControls = wp.blockEditor.InspectorControls;
7 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
8 var useBlockProps = wp.blockEditor.useBlockProps;
9 var PanelBody = wp.components.PanelBody;
10 var RangeControl = wp.components.RangeControl;
11 var ToggleControl = wp.components.ToggleControl;
12 var TextControl = wp.components.TextControl;
13 var SelectControl = wp.components.SelectControl;
14 var Button = wp.components.Button;
15
16 var _tc; function getTC() { return _tc || (_tc = window.bkbgTypographyControl); }
17 var _tv; function getTV() { return _tv || (_tv = window.bkbgTypoCssVars); }
18
19 function buildTypoVars(a) {
20 var fn = getTV(); if (!fn) return {};
21 return Object.assign({},
22 fn(a.titleTypo || {}, '--bksk-tt-'),
23 fn(a.categoryTypo || {}, '--bksk-ct-'),
24 fn(a.skillTypo || {}, '--bksk-sn-'),
25 fn(a.levelTypo || {}, '--bksk-lv-')
26 );
27 }
28
29 var DISPLAY_OPTIONS = [
30 { label: __('Bars', 'blockenberg'), value: 'bars' },
31 { label: __('Dots', 'blockenberg'), value: 'dots' },
32 { label: __('Tags', 'blockenberg'), value: 'tags' },
33 { label: __('Circles', 'blockenberg'), value: 'circles' },
34 ];
35
36 function makeId() { return 'sk' + Math.random().toString(36).substr(2, 6); }
37
38 /* ── Render a single skill item ─────────────────────────── */
39 function SkillItem(props) {
40 var skill = props.skill;
41 var a = props.a;
42 var levelLabel = a.levelLabels[skill.level - 1] || '';
43
44 if (a.displayStyle === 'dots') {
45 return el('div', { className: 'bkbg-skills-item bkbg-skills-item--dots', style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: '10px' } },
46 el('span', { className: 'bkbg-skills-name', style: { color: a.skillNameColor } }, skill.name),
47 el('div', { style: { display: 'flex', gap: a.dotGap + 'px' } },
48 Array.from({ length: a.maxLevel }).map(function (_, i) {
49 return el('div', { key: i, style: { width: a.dotSize + 'px', height: a.dotSize + 'px', borderRadius: '50%', background: i < skill.level ? a.accentColor : a.trackColor } });
50 })
51 )
52 );
53 }
54
55 if (a.displayStyle === 'tags') {
56 return el('span', { className: 'bkbg-skills-tag', style: { display: 'inline-block', background: a.accentColor + '16', color: a.accentColor, borderRadius: '99px', padding: '4px 14px' } }, skill.name);
57 }
58
59 if (a.displayStyle === 'circles') {
60 var pct = Math.round((skill.level / a.maxLevel) * 100);
61 var r = (a.circleSize / 2) - a.circleThickness;
62 var circ = 2 * Math.PI * r;
63 var dash = (pct / 100) * circ;
64 return el('div', { className: 'bkbg-skills-item bkbg-skills-item--circle', style: { display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '8px' } },
65 el('svg', { width: a.circleSize, height: a.circleSize, viewBox: '0 0 ' + a.circleSize + ' ' + a.circleSize, style: { transform: 'rotate(-90deg)' } },
66 el('circle', { cx: a.circleSize / 2, cy: a.circleSize / 2, r: r, fill: 'none', stroke: a.trackColor, strokeWidth: a.circleThickness }),
67 el('circle', { className: 'bkbg-skills-arc', cx: a.circleSize / 2, cy: a.circleSize / 2, r: r, fill: 'none', stroke: a.accentColor, strokeWidth: a.circleThickness, strokeLinecap: 'round', strokeDasharray: circ, strokeDashoffset: circ - dash, 'data-pct': pct })
68 ),
69 el('span', { className: 'bkbg-skills-name', style: { color: a.skillNameColor, textAlign: 'center' } }, skill.name),
70 a.showLevels && el('span', { className: 'bkbg-skills-level', style: { color: a.levelColor } }, pct + '%')
71 );
72 }
73
74 /* Default: bars */
75 var pctBar = Math.round((skill.level / a.maxLevel) * 100);
76 return el('div', { className: 'bkbg-skills-item bkbg-skills-item--bar' },
77 el('div', { style: { display: 'flex', justifyContent: 'space-between', marginBottom: '6px' } },
78 el('span', { className: 'bkbg-skills-name', style: { color: a.skillNameColor } }, skill.name),
79 a.showLevels && el('span', { className: 'bkbg-skills-level', style: { color: a.levelColor } }, levelLabel)
80 ),
81 el('div', { style: { height: a.barHeight + 'px', background: a.trackColor, borderRadius: a.barRadius + 'px', overflow: 'hidden' } },
82 el('div', { className: 'bkbg-skills-fill', 'data-pct': pctBar, style: { height: '100%', width: pctBar + '%', background: a.accentColor, borderRadius: a.barRadius + 'px', transition: 'width 0.9s ease' } })
83 )
84 );
85 }
86
87 /* ── Render all categories ──────────────────────────────── */
88 function SkillsPreview(props) {
89 var a = props.a;
90 var isCircles = a.displayStyle === 'circles';
91 var isTags = a.displayStyle === 'tags';
92
93 var gridStyle = {
94 display: 'grid',
95 gridTemplateColumns: 'repeat(' + a.columns + ', 1fr)',
96 gap: a.gap + 'px',
97 };
98
99 return el('div', { className: 'bkbg-skills bkbg-skills--' + a.displayStyle },
100 a.showTitle && a.title && el('h2', { className: 'bkbg-skills-title', style: { color: a.titleColor, margin: '0 0 24px' } }, a.title),
101 el('div', { style: gridStyle },
102 a.categories.map(function (cat) {
103 var itemsWrap = isTags
104 ? { display: 'flex', flexWrap: 'wrap', gap: '8px' }
105 : isCircles
106 ? { display: 'flex', flexWrap: 'wrap', gap: a.dotGap + 'px' }
107 : { display: 'flex', flexDirection: 'column', gap: a.itemGap + 'px' };
108 return el('div', { key: cat.id, className: 'bkbg-skills-cat' },
109 a.showCategories && el('p', { className: 'bkbg-skills-cat-label', style: { color: a.categoryColor, margin: '0 0 14px' } }, cat.label),
110 el('div', { style: itemsWrap },
111 cat.items.map(function (skill) {
112 return el(SkillItem, { key: skill.id, skill: skill, a: a });
113 })
114 )
115 );
116 })
117 )
118 );
119 }
120
121 registerBlockType('blockenberg/skills', {
122 edit: function (props) {
123 var a = props.attributes;
124 var setAttributes = props.setAttributes;
125 var blockProps = useBlockProps((function () {
126 var s = { paddingTop: a.paddingTop + 'px', paddingBottom: a.paddingBottom + 'px', backgroundColor: a.bgColor || undefined };
127 Object.assign(s, buildTypoVars(a));
128 return { style: s };
129 })());
130
131 function setCat(id, patch) {
132 setAttributes({ categories: a.categories.map(function (c) { return c.id === id ? Object.assign({}, c, patch) : c; }) });
133 }
134 function addCat() {
135 setAttributes({ categories: a.categories.concat([{ id: makeId(), label: 'New Category', items: [{ id: makeId(), name: 'New Skill', level: 3 }] }]) });
136 }
137 function removeCat(id) {
138 if (a.categories.length <= 1) return;
139 setAttributes({ categories: a.categories.filter(function (c) { return c.id !== id; }) });
140 }
141 function addSkill(catId) {
142 setCat(catId, { items: a.categories.find(function (c) { return c.id === catId; }).items.concat([{ id: makeId(), name: 'New Skill', level: 3 }]) });
143 }
144 function removeSkill(catId, skillId) {
145 var cat = a.categories.find(function (c) { return c.id === catId; });
146 setCat(catId, { items: cat.items.filter(function (s) { return s.id !== skillId; }) });
147 }
148 function setSkill(catId, skillId, patch) {
149 var cat = a.categories.find(function (c) { return c.id === catId; });
150 setCat(catId, { items: cat.items.map(function (s) { return s.id === skillId ? Object.assign({}, s, patch) : s; }) });
151 }
152
153 return el(Fragment, null,
154 el(InspectorControls, null,
155 el(PanelBody, { title: __('Display', 'blockenberg'), initialOpen: true },
156 el(SelectControl, { label: __('Display style', 'blockenberg'), value: a.displayStyle, options: DISPLAY_OPTIONS, onChange: function (v) { setAttributes({ displayStyle: v }); } }),
157 el(RangeControl, { label: __('Columns', 'blockenberg'), value: a.columns, min: 1, max: 4, onChange: function (v) { setAttributes({ columns: v }); } }),
158 el(ToggleControl, { label: __('Show categories', 'blockenberg'), checked: a.showCategories, onChange: function (v) { setAttributes({ showCategories: v }); }, __nextHasNoMarginBottom: true }),
159 el(ToggleControl, { label: __('Show proficiency labels', 'blockenberg'), checked: a.showLevels, onChange: function (v) { setAttributes({ showLevels: v }); }, __nextHasNoMarginBottom: true }),
160 el(ToggleControl, { label: __('Animate on scroll', 'blockenberg'), checked: a.animateOnScroll, onChange: function (v) { setAttributes({ animateOnScroll: v }); }, __nextHasNoMarginBottom: true }),
161 el(ToggleControl, { label: __('Show title', 'blockenberg'), checked: a.showTitle, onChange: function (v) { setAttributes({ showTitle: v }); }, __nextHasNoMarginBottom: true }),
162 a.showTitle && el(TextControl, { label: __('Title', 'blockenberg'), value: a.title, onChange: function (v) { setAttributes({ title: v }); } })
163 ),
164 a.displayStyle === 'bars' && el(PanelBody, { title: __('Bar Settings', 'blockenberg'), initialOpen: false },
165 el(RangeControl, { label: __('Bar height (px)', 'blockenberg'), value: a.barHeight, min: 4, max: 24, onChange: function (v) { setAttributes({ barHeight: v }); } }),
166 el(RangeControl, { label: __('Bar radius (px)', 'blockenberg'), value: a.barRadius, min: 0, max: 99, onChange: function (v) { setAttributes({ barRadius: v }); } })
167 ),
168 a.displayStyle === 'dots' && el(PanelBody, { title: __('Dot Settings', 'blockenberg'), initialOpen: false },
169 el(RangeControl, { label: __('Dot size (px)', 'blockenberg'), value: a.dotSize, min: 8, max: 24, onChange: function (v) { setAttributes({ dotSize: v }); } }),
170 el(RangeControl, { label: __('Dot gap (px)', 'blockenberg'), value: a.dotGap, min: 2, max: 12, onChange: function (v) { setAttributes({ dotGap: v }); } })
171 ),
172 a.displayStyle === 'circles' && el(PanelBody, { title: __('Circle Settings', 'blockenberg'), initialOpen: false },
173 el(RangeControl, { label: __('Circle size (px)', 'blockenberg'), value: a.circleSize, min: 48, max: 160, onChange: function (v) { setAttributes({ circleSize: v }); } }),
174 el(RangeControl, { label: __('Stroke thickness (px)', 'blockenberg'), value: a.circleThickness, min: 2, max: 20, onChange: function (v) { setAttributes({ circleThickness: v }); } })
175 ),
176 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
177 el(getTC(), { label: __('Title', 'blockenberg'), value: a.titleTypo || {}, onChange: function (v) { setAttributes({ titleTypo: v }); } }),
178 el(getTC(), { label: __('Category Label', 'blockenberg'), value: a.categoryTypo || {}, onChange: function (v) { setAttributes({ categoryTypo: v }); } }),
179 el(getTC(), { label: __('Skill Name', 'blockenberg'), value: a.skillTypo || {}, onChange: function (v) { setAttributes({ skillTypo: v }); } }),
180 el(getTC(), { label: __('Level Label', 'blockenberg'), value: a.levelTypo || {}, onChange: function (v) { setAttributes({ levelTypo: v }); } })
181 ),
182 el(PanelBody, { title: __('Spacing', 'blockenberg'), initialOpen: false },
183 el(RangeControl, { label: __('Column gap (px)', 'blockenberg'), value: a.gap, min: 8, max: 80, onChange: function (v) { setAttributes({ gap: v }); } }),
184 el(RangeControl, { label: __('Item gap (px)', 'blockenberg'), value: a.itemGap, min: 4, max: 40, onChange: function (v) { setAttributes({ itemGap: v }); } }),
185 el(RangeControl, { label: __('Padding top (px)', 'blockenberg'), value: a.paddingTop, min: 0, max: 200, onChange: function (v) { setAttributes({ paddingTop: v }); } }),
186 el(RangeControl, { label: __('Padding bottom (px)', 'blockenberg'), value: a.paddingBottom, min: 0, max: 200, onChange: function (v) { setAttributes({ paddingBottom: v }); } })
187 ),
188 el(PanelColorSettings, {
189 title: __('Colors', 'blockenberg'), initialOpen: false,
190 colorSettings: [
191 { value: a.accentColor, onChange: function (v) { setAttributes({ accentColor: v || '' }); }, label: __('Accent / fill', 'blockenberg') },
192 { value: a.trackColor, onChange: function (v) { setAttributes({ trackColor: v || '' }); }, label: __('Track', 'blockenberg') },
193 { value: a.titleColor, onChange: function (v) { setAttributes({ titleColor: v || '' }); }, label: __('Title', 'blockenberg') },
194 { value: a.categoryColor, onChange: function (v) { setAttributes({ categoryColor: v || '' }); }, label: __('Category label', 'blockenberg') },
195 { value: a.skillNameColor, onChange: function (v) { setAttributes({ skillNameColor: v || '' }); }, label: __('Skill name', 'blockenberg') },
196 { value: a.levelColor, onChange: function (v) { setAttributes({ levelColor: v || '' }); }, label: __('Level label', 'blockenberg') },
197 { value: a.bgColor, onChange: function (v) { setAttributes({ bgColor: v || '' }); }, label: __('Section background', 'blockenberg') },
198 ]
199 }),
200 el(PanelBody, { title: __('Categories & Skills', 'blockenberg'), initialOpen: false },
201 a.categories.map(function (cat) {
202 return el(PanelBody, { key: cat.id, title: cat.label || __('Category', 'blockenberg'), initialOpen: false },
203 el(TextControl, { label: __('Category name', 'blockenberg'), value: cat.label, onChange: function (v) { setCat(cat.id, { label: v }); } }),
204 cat.items.map(function (skill) {
205 return el('div', { key: skill.id, style: { padding: '10px', background: '#f9fafb', borderRadius: '8px', marginBottom: '8px' } },
206 el(TextControl, { label: __('Skill name', 'blockenberg'), value: skill.name, onChange: function (v) { setSkill(cat.id, skill.id, { name: v }); } }),
207 el(RangeControl, { label: __('Level (1–' + a.maxLevel + ')', 'blockenberg'), value: skill.level, min: 1, max: a.maxLevel, onChange: function (v) { setSkill(cat.id, skill.id, { level: v }); } }),
208 cat.items.length > 1 && el(Button, { onClick: function () { removeSkill(cat.id, skill.id); }, variant: 'tertiary', isDestructive: true, size: 'compact' }, __('Remove skill', 'blockenberg'))
209 );
210 }),
211 el(Button, { onClick: function () { addSkill(cat.id); }, variant: 'secondary', size: 'compact', style: { marginBottom: '8px' } }, __('+ Add Skill', 'blockenberg')),
212 a.categories.length > 1 && el(Button, { onClick: function () { removeCat(cat.id); }, variant: 'tertiary', isDestructive: true, size: 'compact' }, __('Remove category', 'blockenberg'))
213 );
214 }),
215 el(Button, { onClick: addCat, variant: 'primary', style: { marginTop: '8px' } }, __('+ Add Category', 'blockenberg'))
216 )
217 ),
218
219 el('div', blockProps, el(SkillsPreview, { a: a }))
220 );
221 },
222
223 deprecated: [{
224 attributes: Object.assign({},
225 wp.blocks.getBlockType('blockenberg/skills') && wp.blocks.getBlockType('blockenberg/skills').attributes || {},
226 { titleTypo: { type: 'object', default: {} }, categoryTypo: { type: 'object', default: {} }, skillTypo: { type: 'object', default: {} }, levelTypo: { type: 'object', default: {} } }
227 ),
228 migrate: function (a) {
229 return Object.assign({}, a, {
230 titleTypo: { sizeDesktop: a.titleSize || 22, weight: String(a.titleFontWeight || 700) },
231 categoryTypo: { sizeDesktop: a.categorySize || 13 },
232 skillTypo: { sizeDesktop: a.skillNameSize || 14, weight: String(a.skillNameFontWeight || 500) },
233 levelTypo: { sizeDesktop: a.levelSize || 12 }
234 });
235 },
236 save: function (props) {
237 var a = props.attributes;
238 var blockProps = wp.blockEditor.useBlockProps.save({ className: 'bkbg-skills-wrap' });
239 var isCircles = a.displayStyle === 'circles';
240 var isTags = a.displayStyle === 'tags';
241
242 return el('div', Object.assign({}, blockProps, { style: { paddingTop: a.paddingTop + 'px', paddingBottom: a.paddingBottom + 'px', backgroundColor: a.bgColor || undefined } }),
243 el('div', { className: 'bkbg-skills bkbg-skills--' + a.displayStyle, 'data-animate': a.animateOnScroll ? '1' : '0' },
244 a.showTitle && a.title && el('h2', { style: { fontSize: a.titleSize + 'px', color: a.titleColor, margin: '0 0 24px' } }, a.title),
245 el('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(' + a.columns + ', 1fr)', gap: a.gap + 'px' } },
246 a.categories.map(function (cat) {
247 var itemsWrap = isTags ? { display: 'flex', flexWrap: 'wrap', gap: '8px' }
248 : isCircles ? { display: 'flex', flexWrap: 'wrap', gap: a.dotGap + 'px' }
249 : { display: 'flex', flexDirection: 'column', gap: a.itemGap + 'px' };
250 return el('div', { key: cat.id, className: 'bkbg-skills-cat' },
251 a.showCategories && el('p', { style: { fontSize: a.categorySize + 'px', color: a.categoryColor, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.08em', margin: '0 0 14px' } }, cat.label),
252 el('div', { style: itemsWrap },
253 cat.items.map(function (skill) {
254 var levelLabel = a.levelLabels[skill.level - 1] || '';
255 var pct = Math.round((skill.level / a.maxLevel) * 100);
256
257 if (a.displayStyle === 'dots') {
258 return el('div', { key: skill.id, className: 'bkbg-skills-item bkbg-skills-item--dots', style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: '10px' } },
259 el('span', { style: { fontSize: a.skillNameSize + 'px', color: a.skillNameColor, fontWeight: 500 } }, skill.name),
260 el('div', { style: { display: 'flex', gap: a.dotGap + 'px' } },
261 Array.from({ length: a.maxLevel }).map(function (_, i) {
262 return el('div', { key: i, style: { width: a.dotSize + 'px', height: a.dotSize + 'px', borderRadius: '50%', background: i < skill.level ? a.accentColor : a.trackColor } });
263 })
264 )
265 );
266 }
267 if (a.displayStyle === 'tags') {
268 return el('span', { key: skill.id, className: 'bkbg-skills-tag', style: { display: 'inline-block', background: a.accentColor + '16', color: a.accentColor, borderRadius: '99px', padding: '4px 14px', fontSize: a.skillNameSize + 'px', fontWeight: 600 } }, skill.name);
269 }
270 if (a.displayStyle === 'circles') {
271 var r = (a.circleSize / 2) - a.circleThickness;
272 var circ = 2 * Math.PI * r;
273 var dash = (pct / 100) * circ;
274 return el('div', { key: skill.id, className: 'bkbg-skills-item bkbg-skills-item--circle', style: { display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '8px' } },
275 el('svg', { width: a.circleSize, height: a.circleSize, viewBox: '0 0 ' + a.circleSize + ' ' + a.circleSize, style: { transform: 'rotate(-90deg)' } },
276 el('circle', { cx: a.circleSize / 2, cy: a.circleSize / 2, r: r, fill: 'none', stroke: a.trackColor, strokeWidth: a.circleThickness }),
277 el('circle', { className: 'bkbg-skills-arc', cx: a.circleSize / 2, cy: a.circleSize / 2, r: r, fill: 'none', stroke: a.accentColor, strokeWidth: a.circleThickness, strokeLinecap: 'round', strokeDasharray: circ, strokeDashoffset: circ - dash, 'data-pct': pct, 'data-circ': circ })
278 ),
279 el('span', { style: { fontSize: a.skillNameSize + 'px', color: a.skillNameColor, fontWeight: 600, textAlign: 'center' } }, skill.name),
280 a.showLevels && el('span', { style: { fontSize: a.levelSize + 'px', color: a.levelColor } }, pct + '%')
281 );
282 }
283 /* bars */
284 return el('div', { key: skill.id, className: 'bkbg-skills-item bkbg-skills-item--bar' },
285 el('div', { style: { display: 'flex', justifyContent: 'space-between', marginBottom: '6px' } },
286 el('span', { style: { fontSize: a.skillNameSize + 'px', color: a.skillNameColor, fontWeight: 500 } }, skill.name),
287 a.showLevels && el('span', { style: { fontSize: a.levelSize + 'px', color: a.levelColor } }, levelLabel)
288 ),
289 el('div', { style: { height: a.barHeight + 'px', background: a.trackColor, borderRadius: a.barRadius + 'px', overflow: 'hidden' } },
290 el('div', { className: 'bkbg-skills-fill', 'data-pct': pct, style: { height: '100%', width: '0%', background: a.accentColor, borderRadius: a.barRadius + 'px' } })
291 )
292 );
293 })
294 )
295 );
296 })
297 )
298 )
299 );
300 }
301 }],
302
303 save: function (props) {
304 var a = props.attributes;
305 var bp = wp.blockEditor.useBlockProps.save((function () {
306 var s = { paddingTop: a.paddingTop + 'px', paddingBottom: a.paddingBottom + 'px', backgroundColor: a.bgColor || undefined };
307 Object.assign(s, buildTypoVars(a));
308 return { className: 'bkbg-skills-wrap', style: s };
309 })());
310 var isCircles = a.displayStyle === 'circles';
311 var isTags = a.displayStyle === 'tags';
312
313 return el('div', bp,
314 el('div', { className: 'bkbg-skills bkbg-skills--' + a.displayStyle, 'data-animate': a.animateOnScroll ? '1' : '0' },
315 a.showTitle && a.title && el('h2', { className: 'bkbg-skills-title', style: { color: a.titleColor, margin: '0 0 24px' } }, a.title),
316 el('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(' + a.columns + ', 1fr)', gap: a.gap + 'px' } },
317 a.categories.map(function (cat) {
318 var itemsWrap = isTags ? { display: 'flex', flexWrap: 'wrap', gap: '8px' }
319 : isCircles ? { display: 'flex', flexWrap: 'wrap', gap: a.dotGap + 'px' }
320 : { display: 'flex', flexDirection: 'column', gap: a.itemGap + 'px' };
321 return el('div', { key: cat.id, className: 'bkbg-skills-cat' },
322 a.showCategories && el('p', { className: 'bkbg-skills-cat-label', style: { color: a.categoryColor, margin: '0 0 14px' } }, cat.label),
323 el('div', { style: itemsWrap },
324 cat.items.map(function (skill) {
325 var levelLabel = a.levelLabels[skill.level - 1] || '';
326 var pct = Math.round((skill.level / a.maxLevel) * 100);
327
328 if (a.displayStyle === 'dots') {
329 return el('div', { key: skill.id, className: 'bkbg-skills-item bkbg-skills-item--dots', style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: '10px' } },
330 el('span', { className: 'bkbg-skills-name', style: { color: a.skillNameColor } }, skill.name),
331 el('div', { style: { display: 'flex', gap: a.dotGap + 'px' } },
332 Array.from({ length: a.maxLevel }).map(function (_, i) {
333 return el('div', { key: i, style: { width: a.dotSize + 'px', height: a.dotSize + 'px', borderRadius: '50%', background: i < skill.level ? a.accentColor : a.trackColor } });
334 })
335 )
336 );
337 }
338 if (a.displayStyle === 'tags') {
339 return el('span', { key: skill.id, className: 'bkbg-skills-tag', style: { display: 'inline-block', background: a.accentColor + '16', color: a.accentColor, borderRadius: '99px', padding: '4px 14px' } }, skill.name);
340 }
341 if (a.displayStyle === 'circles') {
342 var r = (a.circleSize / 2) - a.circleThickness;
343 var circ = 2 * Math.PI * r;
344 var dash = (pct / 100) * circ;
345 return el('div', { key: skill.id, className: 'bkbg-skills-item bkbg-skills-item--circle', style: { display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '8px' } },
346 el('svg', { width: a.circleSize, height: a.circleSize, viewBox: '0 0 ' + a.circleSize + ' ' + a.circleSize, style: { transform: 'rotate(-90deg)' } },
347 el('circle', { cx: a.circleSize / 2, cy: a.circleSize / 2, r: r, fill: 'none', stroke: a.trackColor, strokeWidth: a.circleThickness }),
348 el('circle', { className: 'bkbg-skills-arc', cx: a.circleSize / 2, cy: a.circleSize / 2, r: r, fill: 'none', stroke: a.accentColor, strokeWidth: a.circleThickness, strokeLinecap: 'round', strokeDasharray: circ, strokeDashoffset: circ - dash, 'data-pct': pct, 'data-circ': circ })
349 ),
350 el('span', { className: 'bkbg-skills-name', style: { color: a.skillNameColor, textAlign: 'center' } }, skill.name),
351 a.showLevels && el('span', { className: 'bkbg-skills-level', style: { color: a.levelColor } }, pct + '%')
352 );
353 }
354 /* bars */
355 return el('div', { key: skill.id, className: 'bkbg-skills-item bkbg-skills-item--bar' },
356 el('div', { style: { display: 'flex', justifyContent: 'space-between', marginBottom: '6px' } },
357 el('span', { className: 'bkbg-skills-name', style: { color: a.skillNameColor } }, skill.name),
358 a.showLevels && el('span', { className: 'bkbg-skills-level', style: { color: a.levelColor } }, levelLabel)
359 ),
360 el('div', { style: { height: a.barHeight + 'px', background: a.trackColor, borderRadius: a.barRadius + 'px', overflow: 'hidden' } },
361 el('div', { className: 'bkbg-skills-fill', 'data-pct': pct, style: { height: '100%', width: '0%', background: a.accentColor, borderRadius: a.barRadius + 'px' } })
362 )
363 );
364 })
365 )
366 );
367 })
368 )
369 )
370 );
371 }
372 });
373 }() );
374