| 1 |
( function () { |
| 2 |
var el = wp.element.createElement; |
| 3 |
var Fragment = wp.element.Fragment; |
| 4 |
var PanelColorSettings = wp.blockEditor.PanelColorSettings; |
| 5 |
var useBlockProps = wp.blockEditor.useBlockProps; |
| 6 |
var InspectorControls = wp.blockEditor.InspectorControls; |
| 7 |
var TextControl = wp.components.TextControl; |
| 8 |
var TextareaControl = wp.components.TextareaControl; |
| 9 |
var ToggleControl = wp.components.ToggleControl; |
| 10 |
var RangeControl = wp.components.RangeControl; |
| 11 |
var SelectControl = wp.components.SelectControl; |
| 12 |
var PanelBody = wp.components.PanelBody; |
| 13 |
var Button = wp.components.Button; |
| 14 |
var __ = wp.i18n.__; |
| 15 |
|
| 16 |
var _tc, _tv; |
| 17 |
function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); } |
| 18 |
function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); } |
| 19 |
|
| 20 |
var typeOptions = [ |
| 21 |
{ label: '📖 Lesson', value: 'lesson' }, |
| 22 |
{ label: '🔨 Project', value: 'project' }, |
| 23 |
{ label: '✏️ Quiz', value: 'quiz' }, |
| 24 |
{ label: '📄 Reading', value: 'reading' }, |
| 25 |
{ label: '🎬 Video', value: 'video' } |
| 26 |
]; |
| 27 |
var difficultyOptions = [ |
| 28 |
{ label: 'Beginner', value: 'beginner' }, |
| 29 |
{ label: 'Intermediate', value: 'intermediate' }, |
| 30 |
{ label: 'Advanced', value: 'advanced' } |
| 31 |
]; |
| 32 |
var typeIcons = { lesson: '📖', project: '🔨', quiz: '✏️', reading: '📄', video: '🎬' }; |
| 33 |
|
| 34 |
function upd(arr, idx, field, val) { |
| 35 |
return arr.map(function (e, i) { |
| 36 |
if (i !== idx) return e; |
| 37 |
var u = {}; u[field] = val; |
| 38 |
return Object.assign({}, e, u); |
| 39 |
}); |
| 40 |
} |
| 41 |
|
| 42 |
function typeColor(t, a) { |
| 43 |
var map = { lesson: a.lessonColor, project: a.projectColor, quiz: a.quizColor, reading: a.readingColor, video: a.videoColor }; |
| 44 |
return map[t] || a.lessonColor; |
| 45 |
} |
| 46 |
|
| 47 |
function renderStep(step, idx, total, a) { |
| 48 |
var tc = typeColor(step.type, a); |
| 49 |
return el('div', { className: 'bkbg-lp-step', key: idx }, |
| 50 |
el('div', { className: 'bkbg-lp-step-left' }, |
| 51 |
a.showStepNumbers && el('div', { className: 'bkbg-lp-step-num', style: { background: a.stepNumBg, color: a.stepNumColor } }, idx + 1), |
| 52 |
idx < total - 1 && el('div', { className: 'bkbg-lp-connector', style: { background: a.connectorColor } }) |
| 53 |
), |
| 54 |
el('div', { className: 'bkbg-lp-step-card', style: { background: a.stepBg, border: '1px solid ' + a.stepBorderColor } }, |
| 55 |
el('div', { className: 'bkbg-lp-step-header' }, |
| 56 |
el('div', { className: 'bkbg-lp-step-title-row' }, |
| 57 |
el('span', { className: 'bkbg-lp-type-icon', style: { color: tc } }, typeIcons[step.type] || '📖'), |
| 58 |
el('span', { className: 'bkbg-lp-step-title', style: { color: a.stepTitleColor } }, step.title) |
| 59 |
), |
| 60 |
a.showDuration && step.duration && el('span', { className: 'bkbg-lp-duration', style: { color: a.durationColor } }, '⏱ ' + step.duration) |
| 61 |
), |
| 62 |
step.description && el('p', { className: 'bkbg-lp-step-desc', style: { color: a.stepDescColor } }, step.description), |
| 63 |
a.showSkills && step.skills && step.skills.length > 0 && |
| 64 |
el('div', { className: 'bkbg-lp-skills' }, |
| 65 |
step.skills.map(function (s, j) { |
| 66 |
return el('span', { key: j, className: 'bkbg-lp-skill-tag', style: { background: a.skillBg, color: a.skillColor } }, s); |
| 67 |
}) |
| 68 |
) |
| 69 |
) |
| 70 |
); |
| 71 |
} |
| 72 |
|
| 73 |
wp.blocks.registerBlockType('blockenberg/learning-path', { |
| 74 |
edit: function (props) { |
| 75 |
var a = props.attributes; |
| 76 |
var setAttr = props.setAttributes; |
| 77 |
var lh = (a.lineHeight / 100).toFixed(2); |
| 78 |
|
| 79 |
var difficultyLabels = { beginner: 'Beginner', intermediate: 'Intermediate', advanced: 'Advanced' }; |
| 80 |
|
| 81 |
var blockProps = useBlockProps((function () { |
| 82 |
var _tvFn = getTypoCssVars(); |
| 83 |
var s = { background: a.bgColor, borderRadius: a.borderRadius + 'px', border: '1px solid ' + a.borderColor, overflow: 'hidden', fontSize: a.fontSize + 'px', lineHeight: lh }; |
| 84 |
if (_tvFn) { |
| 85 |
Object.assign(s, _tvFn(a.titleTypo, '--bkbg-lp-tt-')); |
| 86 |
Object.assign(s, _tvFn(a.descTypo, '--bkbg-lp-d-')); |
| 87 |
Object.assign(s, _tvFn(a.stepTitleTypo, '--bkbg-lp-st-')); |
| 88 |
} |
| 89 |
return { className: 'bkbg-lp-wrap', style: s }; |
| 90 |
})()); |
| 91 |
|
| 92 |
return el(Fragment, null, |
| 93 |
el(InspectorControls, null, |
| 94 |
el(PanelBody, { title: __('Path Settings'), initialOpen: true }, |
| 95 |
el(TextControl, { label: __('Path Title'), value: a.pathTitle, onChange: function (v) { setAttr({ pathTitle: v }); }, __nextHasNoMarginBottom: true }), |
| 96 |
el(TextareaControl, { label: __('Description'), value: a.description, onChange: function (v) { setAttr({ description: v }); }, __nextHasNoMarginBottom: true }), |
| 97 |
el(ToggleControl, { label: __('Show Description'), checked: a.showDescription, onChange: function (v) { setAttr({ showDescription: v }); }, __nextHasNoMarginBottom: true }), |
| 98 |
el(TextControl, { label: __('Total Duration'), value: a.totalDuration, onChange: function (v) { setAttr({ totalDuration: v }); }, __nextHasNoMarginBottom: true }), |
| 99 |
el(SelectControl, { label: __('Difficulty'), value: a.difficulty, options: difficultyOptions, onChange: function (v) { setAttr({ difficulty: v }); }, __nextHasNoMarginBottom: true }), |
| 100 |
el(ToggleControl, { label: __('Show Skills'), checked: a.showSkills, onChange: function (v) { setAttr({ showSkills: v }); }, __nextHasNoMarginBottom: true }), |
| 101 |
el(ToggleControl, { label: __('Show Duration'), checked: a.showDuration, onChange: function (v) { setAttr({ showDuration: v }); }, __nextHasNoMarginBottom: true }), |
| 102 |
el(ToggleControl, { label: __('Show Step Numbers'), checked: a.showStepNumbers, onChange: function (v) { setAttr({ showStepNumbers: v }); }, __nextHasNoMarginBottom: true }) |
| 103 |
), |
| 104 |
el(PanelBody, { title: __('Steps'), initialOpen: false }, |
| 105 |
a.steps.map(function (step, i) { |
| 106 |
return el('div', { key: i, style: { border: '1px solid #e2e8f0', borderRadius: 8, padding: 12, marginBottom: 12, background: '#fafafa' } }, |
| 107 |
el('strong', { style: { display: 'block', marginBottom: 6 } }, (typeIcons[step.type] || '📖') + ' ' + (step.title || 'Step ' + (i + 1))), |
| 108 |
el(TextControl, { label: __('Title'), value: step.title, onChange: function (v) { setAttr({ steps: upd(a.steps, i, 'title', v) }); }, __nextHasNoMarginBottom: true }), |
| 109 |
el(TextareaControl, { label: __('Description'), value: step.description, onChange: function (v) { setAttr({ steps: upd(a.steps, i, 'description', v) }); }, __nextHasNoMarginBottom: true }), |
| 110 |
el(SelectControl, { label: __('Type'), value: step.type, options: typeOptions, onChange: function (v) { setAttr({ steps: upd(a.steps, i, 'type', v) }); }, __nextHasNoMarginBottom: true }), |
| 111 |
el(TextControl, { label: __('Duration'), value: step.duration, onChange: function (v) { setAttr({ steps: upd(a.steps, i, 'duration', v) }); }, __nextHasNoMarginBottom: true }), |
| 112 |
el(TextControl, { label: __('Skills (comma-separated)'), value: (step.skills || []).join(', '), onChange: function (v) { setAttr({ steps: upd(a.steps, i, 'skills', v.split(',').map(function (s) { return s.trim(); }).filter(Boolean)) }); }, __nextHasNoMarginBottom: true }), |
| 113 |
el(Button, { isDestructive: true, variant: 'secondary', onClick: function () { setAttr({ steps: a.steps.filter(function (_, j) { return j !== i; }) }); } }, __('Remove')) |
| 114 |
); |
| 115 |
}), |
| 116 |
el(Button, { variant: 'primary', onClick: function () { setAttr({ steps: a.steps.concat([{ title: 'New Step', description: '', duration: '1 week', type: 'lesson', skills: [], completed: false }]) }); } }, __('+ Add Step')) |
| 117 |
), |
| 118 |
el(PanelBody, { title: __('Typography'), initialOpen: false }, |
| 119 |
getTypoControl() && el(getTypoControl(), { label: __('Title'), value: a.titleTypo || {}, onChange: function (v) { setAttr({ titleTypo: v }); } }), |
| 120 |
getTypoControl() && el(getTypoControl(), { label: __('Description'), value: a.descTypo || {}, onChange: function (v) { setAttr({ descTypo: v }); } }), |
| 121 |
getTypoControl() && el(getTypoControl(), { label: __('Step Title'), value: a.stepTitleTypo || {}, onChange: function (v) { setAttr({ stepTitleTypo: v }); } }), |
| 122 |
el(RangeControl, { label: __('Base Font Size'), value: a.fontSize, min: 10, max: 22, onChange: function (v) { setAttr({ fontSize: v }); }, __nextHasNoMarginBottom: true }), |
| 123 |
el(RangeControl, { label: __('Line Height (%)'), value: a.lineHeight, min: 120, max: 220, onChange: function (v) { setAttr({ lineHeight: v }); }, __nextHasNoMarginBottom: true }), |
| 124 |
el(RangeControl, { label: __('Border Radius'), value: a.borderRadius, min: 0, max: 32, onChange: function (v) { setAttr({ borderRadius: v }); }, __nextHasNoMarginBottom: true }) |
| 125 |
), |
| 126 |
el(PanelColorSettings, { |
| 127 |
title: __('Layout Colors'), |
| 128 |
initialOpen: false, |
| 129 |
colorSettings: [ |
| 130 |
{ label: __('Background'), value: a.bgColor, onChange: function (v) { setAttr({ bgColor: v || '#ffffff' }); } }, |
| 131 |
{ label: __('Border'), value: a.borderColor, onChange: function (v) { setAttr({ borderColor: v || '#e5e7eb' }); } }, |
| 132 |
{ label: __('Title'), value: a.titleColor, onChange: function (v) { setAttr({ titleColor: v || '#111827' }); } }, |
| 133 |
{ label: __('Description'), value: a.descColor, onChange: function (v) { setAttr({ descColor: v || '#6b7280' }); } }, |
| 134 |
{ label: __('Meta Bar BG'), value: a.metaBg, onChange: function (v) { setAttr({ metaBg: v || '#f8fafc' }); } }, |
| 135 |
{ label: __('Meta Bar Border'), value: a.metaBorderColor, onChange: function (v) { setAttr({ metaBorderColor: v || '#e2e8f0' }); } }, |
| 136 |
{ label: __('Difficulty BG'), value: a.difficultyBg, onChange: function (v) { setAttr({ difficultyBg: v || '#ede9fe' }); } }, |
| 137 |
{ label: __('Difficulty Text'), value: a.difficultyColor, onChange: function (v) { setAttr({ difficultyColor: v || '#5b21b6' }); } }, |
| 138 |
{ label: __('Step Card BG'), value: a.stepBg, onChange: function (v) { setAttr({ stepBg: v || '#ffffff' }); } }, |
| 139 |
{ label: __('Step Card Border'), value: a.stepBorderColor, onChange: function (v) { setAttr({ stepBorderColor: v || '#e5e7eb' }); } }, |
| 140 |
{ label: __('Step Title'), value: a.stepTitleColor, onChange: function (v) { setAttr({ stepTitleColor: v || '#1f2937' }); } }, |
| 141 |
{ label: __('Step Description'), value: a.stepDescColor, onChange: function (v) { setAttr({ stepDescColor: v || '#6b7280' }); } }, |
| 142 |
{ label: __('Step Number BG'), value: a.stepNumBg, onChange: function (v) { setAttr({ stepNumBg: v || '#0f172a' }); } }, |
| 143 |
{ label: __('Step Number Text'), value: a.stepNumColor, onChange: function (v) { setAttr({ stepNumColor: v || '#ffffff' }); } }, |
| 144 |
{ label: __('Connector Line'), value: a.connectorColor, onChange: function (v) { setAttr({ connectorColor: v || '#e5e7eb' }); } }, |
| 145 |
{ label: __('Duration Text'), value: a.durationColor, onChange: function (v) { setAttr({ durationColor: v || '#6b7280' }); } }, |
| 146 |
{ label: __('Skill Tag BG'), value: a.skillBg, onChange: function (v) { setAttr({ skillBg: v || '#f1f5f9' }); } }, |
| 147 |
{ label: __('Skill Tag Text'), value: a.skillColor, onChange: function (v) { setAttr({ skillColor: v || '#475569' }); } } |
| 148 |
] |
| 149 |
}), |
| 150 |
el(PanelColorSettings, { |
| 151 |
title: __('Step Type Colors'), |
| 152 |
initialOpen: false, |
| 153 |
colorSettings: [ |
| 154 |
{ label: __('📖 Lesson'), value: a.lessonColor, onChange: function (v) { setAttr({ lessonColor: v || '#2563eb' }); } }, |
| 155 |
{ label: __('🔨 Project'), value: a.projectColor, onChange: function (v) { setAttr({ projectColor: v || '#d97706' }); } }, |
| 156 |
{ label: __('✏️ Quiz'), value: a.quizColor, onChange: function (v) { setAttr({ quizColor: v || '#7c3aed' }); } }, |
| 157 |
{ label: __('📄 Reading'), value: a.readingColor, onChange: function (v) { setAttr({ readingColor: v || '#059669' }); } }, |
| 158 |
{ label: __('🎬 Video'), value: a.videoColor, onChange: function (v) { setAttr({ videoColor: v || '#dc2626' }); } } |
| 159 |
] |
| 160 |
}) |
| 161 |
), |
| 162 |
el('div', blockProps, |
| 163 |
el('div', { className: 'bkbg-lp-header', style: { borderBottom: '1px solid ' + a.borderColor } }, |
| 164 |
el('h2', { className: 'bkbg-lp-title', style: { color: a.titleColor } }, a.pathTitle), |
| 165 |
a.showDescription && el('p', { className: 'bkbg-lp-desc', style: { color: a.descColor } }, a.description) |
| 166 |
), |
| 167 |
el('div', { className: 'bkbg-lp-meta', style: { background: a.metaBg, borderBottom: '1px solid ' + a.metaBorderColor } }, |
| 168 |
el('span', { className: 'bkbg-lp-meta-item' }, '⏱ ' + a.totalDuration), |
| 169 |
el('span', { className: 'bkbg-lp-meta-item' }, '📚 ' + a.steps.length + ' steps'), |
| 170 |
el('span', { className: 'bkbg-lp-difficulty', style: { background: a.difficultyBg, color: a.difficultyColor } }, { beginner: 'Beginner', intermediate: 'Intermediate', advanced: 'Advanced' }[a.difficulty] || a.difficulty) |
| 171 |
), |
| 172 |
el('div', { className: 'bkbg-lp-steps' }, |
| 173 |
a.steps.map(function (step, i) { return renderStep(step, i, a.steps.length, a); }) |
| 174 |
) |
| 175 |
) |
| 176 |
); |
| 177 |
}, |
| 178 |
save: function (props) { |
| 179 |
var useBlockProps = wp.blockEditor.useBlockProps; |
| 180 |
return el('div', useBlockProps.save(), |
| 181 |
el('div', { className: 'bkbg-learning-path-app', 'data-opts': JSON.stringify(props.attributes) }) |
| 182 |
); |
| 183 |
} |
| 184 |
}); |
| 185 |
}() ); |
| 186 |
|