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

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

376 lines 29.8 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 useState = wp.element.useState;
5 var __ = wp.i18n.__;
6 var registerBlockType = wp.blocks.registerBlockType;
7 var InspectorControls = wp.blockEditor.InspectorControls;
8 var RichText = wp.blockEditor.RichText;
9 var useBlockProps = wp.blockEditor.useBlockProps;
10 var MediaUpload = wp.blockEditor.MediaUpload;
11 var MediaUploadCheck = wp.blockEditor.MediaUploadCheck;
12 var PanelBody = wp.components.PanelBody;
13 var Button = wp.components.Button;
14 var ToggleControl = wp.components.ToggleControl;
15 var RangeControl = wp.components.RangeControl;
16 var SelectControl = wp.components.SelectControl;
17 var TextControl = wp.components.TextControl;
18 var ColorPicker = wp.components.ColorPicker;
19 var Popover = wp.components.Popover;
20
21 var TAB_STYLE_OPTIONS = [
22 { label: __('Pill', 'blockenberg'), value: 'pill' },
23 { label: __('Underline', 'blockenberg'), value: 'underline' },
24 { label: __('Flat', 'blockenberg'), value: 'flat' },
25 ];
26 var SESSION_STYLE_OPTIONS = [
27 { label: __('Cards', 'blockenberg'), value: 'card' },
28 { label: __('List', 'blockenberg'), value: 'list' },
29 ];
30 var TIME_FORMAT_OPTIONS = [
31 { label: __('12-hour (9:00 AM)', 'blockenberg'), value: '12h' },
32 { label: __('24-hour (09:00)', 'blockenberg'), value: '24h' },
33 ];
34 var SESSION_TYPE_ICONS = { keynote: '🎤', talk: '💬', workshop: '🛠', break: '' };
35
36 var _eaTC, _eaTV;
37 function _tc() { return _eaTC || (_eaTC = window.bkbgTypographyControl); }
38 function _tv(t, p) { return (_eaTV || (_eaTV = window.bkbgTypoCssVars)) ? _eaTV(t, p) : {}; }
39
40 function makeId() { return 'ea' + Math.random().toString(36).substr(2, 5); }
41
42 function buildWrapStyle(a) {
43 return Object.assign({
44 '--bkbg-ea-accent': a.accentColor,
45 '--bkbg-ea-active-tab-bg': a.activeTabBg,
46 '--bkbg-ea-active-tab-color': a.activeTabColor,
47 '--bkbg-ea-inactive-tab-bg': a.inactiveTabBg,
48 '--bkbg-ea-inactive-tab-color': a.inactiveTabColor,
49 '--bkbg-ea-session-title': a.sessionTitleColor,
50 '--bkbg-ea-speaker-name': a.speakerNameColor,
51 '--bkbg-ea-meta': a.metaColor,
52 '--bkbg-ea-time-color': a.timeColor,
53 '--bkbg-ea-card-bg': a.cardBg,
54 '--bkbg-ea-card-border': a.cardBorderColor,
55 '--bkbg-ea-break-card-bg': a.breakCardBg,
56 '--bkbg-ea-timeline-bar': a.timelineBarColor,
57 '--bkbg-ea-time-sz': a.timeLabelSize + 'px',
58 '--bkbg-ea-session-title-sz': a.sessionTitleSize + 'px',
59 '--bkbg-ea-speaker-sz': a.speakerNameSize + 'px',
60 '--bkbg-ea-meta-sz': a.metaSize + 'px',
61 '--bkbg-ea-tag-sz': a.tagSize + 'px',
62 '--bkbg-ea-tab-sz': a.tabSize + 'px',
63 '--bkbg-ea-avatar-sz': a.avatarSize + 'px',
64 '--bkbg-ea-tag-r': a.tagRadius + 'px',
65 '--bkbg-ea-card-r': a.cardRadius + 'px',
66 '--bkbg-ea-card-pad': a.cardPadding + 'px',
67 paddingTop: a.paddingTop + 'px',
68 paddingBottom: a.paddingBottom + 'px',
69 backgroundColor: a.bgColor || undefined,
70 },
71 _tv(a.typoSessionTitle || {}, '--bkbg-ea-st-'),
72 _tv(a.typoSpeaker || {}, '--bkbg-ea-sp-'),
73 _tv(a.typoMeta || {}, '--bkbg-ea-mt-'),
74 _tv(a.typoTab || {}, '--bkbg-ea-tb-')
75 );
76 }
77
78 function renderColorControl(key, label, value, onChange, openKey, setOpenKey) {
79 var isOpen = openKey === key;
80 return el('div', { key: key, style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '4px 0', gap: '8px' } },
81 el('span', { style: { fontSize: '12px', color: '#1e1e1e', flex: 1, lineHeight: 1.4 } }, label),
82 el('div', { style: { position: 'relative', flexShrink: 0 } },
83 el('button', { type: 'button', onClick: function () { setOpenKey(isOpen ? null : key); }, style: { width: '28px', height: '28px', borderRadius: '4px', border: isOpen ? '2px solid #007cba' : '2px solid #ddd', cursor: 'pointer', padding: 0, background: value || '#ccc' } }),
84 isOpen && el(Popover, { position: 'bottom left', onClose: function () { setOpenKey(null); } },
85 el('div', { style: { padding: '8px' } },
86 el(ColorPicker, { color: value, enableAlpha: true, onChange: onChange })
87 )
88 )
89 )
90 );
91 }
92
93 /* ── Get color for session type ────────────────────────────────── */
94 function getSessionTypeColor(sessionTypes, type) {
95 var found = (sessionTypes || []).filter(function (t) { return t.type === type; })[0];
96 return found ? found.color : '#9ca3af';
97 }
98 function getSessionTypeLabel(sessionTypes, type) {
99 var found = (sessionTypes || []).filter(function (t) { return t.type === type; })[0];
100 return found ? found.label : type;
101 }
102
103 /* ── Session card ───────────────────────────────────────────────── */
104 function SessionCard(props) {
105 var s = props.session;
106 var a = props.a;
107 var typeColor = getSessionTypeColor(a.sessionTypes, s.type);
108 var typeLabel = getSessionTypeLabel(a.sessionTypes, s.type);
109 var isBreak = s.type === 'break';
110 var cardBg = isBreak ? a.breakCardBg : a.cardBg;
111
112 var cardStyle = {
113 background: cardBg,
114 borderRadius: a.cardRadius + 'px',
115 padding: a.cardPadding + 'px',
116 border: '1px solid ' + a.cardBorderColor,
117 position: 'relative',
118 flex: 1,
119 boxSizing: 'border-box',
120 };
121 if (a.timelineBar) {
122 cardStyle.borderLeft = '4px solid ' + typeColor;
123 }
124
125 return el('div', { className: 'bkbg-ea-session bkbg-ea-session--' + s.type, style: { display: 'flex', gap: '16px', alignItems: 'flex-start', marginBottom: '12px' } },
126 /* Time column */
127 el('div', { className: 'bkbg-ea-time-col', style: { minWidth: '72px', flexShrink: 0, paddingTop: '4px', textAlign: 'right' } },
128 el('span', { className: 'bkbg-ea-time-label', style: { color: a.timeColor, display: 'block' } }, s.time),
129 a.showDuration && s.duration && el('span', { className: 'bkbg-ea-duration', style: { color: a.metaColor, display: 'block' } }, s.duration)
130 ),
131 /* Card */
132 el('div', { className: 'bkbg-ea-session-card', style: cardStyle },
133 el('div', { className: 'bkbg-ea-session-header', style: { display: 'flex', alignItems: 'flex-start', gap: '10px', marginBottom: s.speaker ? '10px' : '0' } },
134 /* Avatar */
135 a.showSpeakerAvatar && !isBreak && el('div', { className: 'bkbg-ea-avatar', style: { width: a.avatarSize + 'px', height: a.avatarSize + 'px', borderRadius: '50%', background: typeColor + '22', flexShrink: 0, overflow: 'hidden', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: a.avatarSize * 0.44 + 'px' } },
136 s.avatarUrl ? el('img', { src: s.avatarUrl, alt: s.speaker, style: { width: '100%', height: '100%', objectFit: 'cover' } }) : el('span', null, SESSION_TYPE_ICONS[s.type] || '👤')
137 ),
138 el('div', { style: { flex: 1, minWidth: 0 } },
139 el('div', { className: 'bkbg-ea-session-meta-row', style: { display: 'flex', alignItems: 'center', gap: '8px', flexWrap: 'wrap', marginBottom: '4px' } },
140 el('span', { className: 'bkbg-ea-type-badge', style: { display: 'inline-block', padding: '2px 9px', borderRadius: '99px', background: typeColor + '18', color: typeColor } }, SESSION_TYPE_ICONS[s.type] + ' ' + typeLabel),
141 a.showRoom && s.room && el('span', { className: 'bkbg-ea-room', style: { color: a.metaColor } }, '📍 ' + s.room)
142 ),
143 el('div', { className: 'bkbg-ea-session-title', style: { color: a.sessionTitleColor } }, s.title),
144 s.speaker && el('div', { className: 'bkbg-ea-speaker-info', style: { marginTop: '6px', display: 'flex', flexWrap: 'wrap', gap: '4px', alignItems: 'center' } },
145 el('span', { className: 'bkbg-ea-speaker-name', style: { color: a.speakerNameColor } }, s.speaker),
146 a.showSpeakerRole && s.role && el('span', { className: 'bkbg-ea-speaker-role', style: { color: a.metaColor } }, s.role),
147 a.showSpeakerCompany && s.company && el('span', { className: 'bkbg-ea-speaker-company', style: { color: a.metaColor } }, '@ ' + s.company)
148 ),
149 a.showTags && s.tags && s.tags.length > 0 && el('div', { className: 'bkbg-ea-tags', style: { marginTop: '8px', display: 'flex', flexWrap: 'wrap', gap: '5px' } },
150 s.tags.map(function (tag, ti) {
151 return el('span', { key: ti, className: 'bkbg-ea-tag', style: { display: 'inline-block', padding: '2px 8px', borderRadius: a.tagRadius + 'px', background: '#f3f4f6', color: '#374151' } }, tag);
152 })
153 )
154 )
155 )
156 )
157 );
158 }
159
160 registerBlockType('blockenberg/event-agenda', {
161 title: __('Event Agenda', 'blockenberg'),
162 icon: 'calendar-alt',
163 category: 'bkbg-business',
164
165 edit: function (props) {
166 var a = props.attributes;
167 var setAttributes = props.setAttributes;
168
169 var openColorKeyState = useState(null);
170 var openColorKey = openColorKeyState[0];
171 var setOpenColorKey = openColorKeyState[1];
172
173 var activeDayState = useState(0);
174 var activeDay = activeDayState[0];
175 var setActiveDay = activeDayState[1];
176
177 var blockProps = useBlockProps({ style: buildWrapStyle(a) });
178
179 function cc(key, label, attrKey) {
180 return renderColorControl(key, label, a[attrKey], function (val) {
181 var upd = {}; upd[attrKey] = val; setAttributes(upd);
182 }, openColorKey, setOpenColorKey);
183 }
184
185 function updateDay(dayId, key, val) {
186 setAttributes({ days: a.days.map(function (d) {
187 if (d.id !== dayId) return d;
188 var u = Object.assign({}, d); u[key] = val; return u;
189 }) });
190 }
191
192 function updateSession(dayId, sessionId, key, val) {
193 setAttributes({ days: a.days.map(function (d) {
194 if (d.id !== dayId) return d;
195 return Object.assign({}, d, { sessions: d.sessions.map(function (s) {
196 if (s.id !== sessionId) return s;
197 var u = Object.assign({}, s); u[key] = val; return u;
198 }) });
199 }) });
200 }
201
202 function addSession(dayId) {
203 setAttributes({ days: a.days.map(function (d) {
204 if (d.id !== dayId) return d;
205 return Object.assign({}, d, { sessions: d.sessions.concat([{ id: makeId(), time: '10:00 AM', duration: '30 min', type: 'talk', title: __('Session title', 'blockenberg'), speaker: __('Speaker Name', 'blockenberg'), role: '', company: '', avatarUrl: '', avatarId: 0, room: '', tags: [] }]) });
206 }) });
207 }
208
209 var safeDay = Math.min(activeDay, a.days.length - 1);
210 var currentDay = a.days[safeDay];
211
212 /* Tab bar */
213 var tabBar = a.showDayTabs && el('div', { className: 'bkbg-ea-tab-bar', style: { display: 'flex', gap: '6px', flexWrap: 'wrap', marginBottom: '28px' } },
214 a.days.map(function (day, di) {
215 var isActive = di === safeDay;
216 return el('button', { key: day.id, type: 'button', onClick: function () { setActiveDay(di); }, className: 'bkbg-ea-tab-btn' + (isActive ? ' is-active' : ''), style: { padding: '9px 20px', borderRadius: a.tabStyle === 'pill' ? '99px' : '8px', border: a.tabStyle === 'underline' ? ('none') : 'none', borderBottom: a.tabStyle === 'underline' ? (isActive ? '3px solid ' + a.accentColor : '3px solid transparent') : undefined, fontFamily: 'inherit', cursor: 'pointer', background: a.tabStyle === 'underline' ? 'transparent' : (isActive ? a.activeTabBg : a.inactiveTabBg), color: isActive ? a.activeTabColor : a.inactiveTabColor, transition: 'all 0.2s' } },
217 day.label
218 );
219 })
220 );
221
222 return el(Fragment, null,
223 el(InspectorControls, null,
224 el(PanelBody, { title: __('Display', 'blockenberg'), initialOpen: true },
225 el(ToggleControl, { label: __('Show day tabs', 'blockenberg'), checked: a.showDayTabs, onChange: function (v) { setAttributes({ showDayTabs: v }); }, __nextHasNoMarginBottom: true }),
226 el(ToggleControl, { label: __('Speaker avatar', 'blockenberg'), checked: a.showSpeakerAvatar, onChange: function (v) { setAttributes({ showSpeakerAvatar: v }); }, __nextHasNoMarginBottom: true }),
227 el(ToggleControl, { label: __('Speaker role', 'blockenberg'), checked: a.showSpeakerRole, onChange: function (v) { setAttributes({ showSpeakerRole: v }); }, __nextHasNoMarginBottom: true }),
228 el(ToggleControl, { label: __('Speaker company', 'blockenberg'), checked: a.showSpeakerCompany, onChange: function (v) { setAttributes({ showSpeakerCompany: v }); }, __nextHasNoMarginBottom: true }),
229 el(ToggleControl, { label: __('Room', 'blockenberg'), checked: a.showRoom, onChange: function (v) { setAttributes({ showRoom: v }); }, __nextHasNoMarginBottom: true }),
230 el(ToggleControl, { label: __('Duration', 'blockenberg'), checked: a.showDuration, onChange: function (v) { setAttributes({ showDuration: v }); }, __nextHasNoMarginBottom: true }),
231 el(ToggleControl, { label: __('Tags', 'blockenberg'), checked: a.showTags, onChange: function (v) { setAttributes({ showTags: v }); }, __nextHasNoMarginBottom: true }),
232 el(ToggleControl, { label: __('Timeline bar', 'blockenberg'), checked: a.timelineBar, onChange: function (v) { setAttributes({ timelineBar: v }); }, __nextHasNoMarginBottom: true })
233 ),
234 el(PanelBody, { title: __('Style', 'blockenberg'), initialOpen: false },
235 el(SelectControl, { label: __('Session style', 'blockenberg'), value: a.sessionStyle, options: SESSION_STYLE_OPTIONS, onChange: function (v) { setAttributes({ sessionStyle: v }); } }),
236 el(SelectControl, { label: __('Tab style', 'blockenberg'), value: a.tabStyle, options: TAB_STYLE_OPTIONS, onChange: function (v) { setAttributes({ tabStyle: v }); } }),
237 el(SelectControl, { label: __('Time format', 'blockenberg'), value: a.timeFormat, options: TIME_FORMAT_OPTIONS, onChange: function (v) { setAttributes({ timeFormat: v }); } })
238 ),
239 el(PanelBody, { title: __('Session Types', 'blockenberg'), initialOpen: false },
240 a.sessionTypes.map(function (st) {
241 return el('div', { key: st.type, style: { marginBottom: '8px' } },
242 el('div', { style: { display: 'flex', alignItems: 'center', gap: '8px' } },
243 el('span', { style: { fontSize: '14px' } }, SESSION_TYPE_ICONS[st.type]),
244 el(TextControl, { label: __('Label', 'blockenberg'), value: st.label, style: { flex: 1 }, onChange: function (v) { setAttributes({ sessionTypes: a.sessionTypes.map(function (t) { if (t.type !== st.type) return t; return Object.assign({}, t, { label: v }); }) }); } }),
245 renderColorControl('stype-' + st.type, __('Color', 'blockenberg'), st.color, function (val) {
246 setAttributes({ sessionTypes: a.sessionTypes.map(function (t) { if (t.type !== st.type) return t; return Object.assign({}, t, { color: val }); }) });
247 }, openColorKey, setOpenColorKey)
248 )
249 );
250 })
251 ),
252 el(PanelBody, { title: __('Card & Sizes', 'blockenberg'), initialOpen: false },
253 el(RangeControl, { label: __('Card radius (px)', 'blockenberg'), value: a.cardRadius, min: 0, max: 24, onChange: function (v) { setAttributes({ cardRadius: v }); } }),
254 el(RangeControl, { label: __('Card padding (px)', 'blockenberg'), value: a.cardPadding, min: 8, max: 40, onChange: function (v) { setAttributes({ cardPadding: v }); } }),
255 el(RangeControl, { label: __('Avatar size (px)', 'blockenberg'), value: a.avatarSize, min: 28, max: 72, onChange: function (v) { setAttributes({ avatarSize: v }); } }),
256 el(RangeControl, { label: __('Tag radius (px)', 'blockenberg'), value: a.tagRadius, min: 0, max: 12, onChange: function (v) { setAttributes({ tagRadius: v }); } })
257 ),
258 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
259 _tc() && el(_tc(), { label: __('Session Title', 'blockenberg'), typo: a.typoSessionTitle || {}, onChange: function (v) { setAttributes({ typoSessionTitle: v }); } }),
260 _tc() && el(_tc(), { label: __('Speaker Name', 'blockenberg'), typo: a.typoSpeaker || {}, onChange: function (v) { setAttributes({ typoSpeaker: v }); } }),
261 _tc() && el(_tc(), { label: __('Meta / Time / Tags', 'blockenberg'), typo: a.typoMeta || {}, onChange: function (v) { setAttributes({ typoMeta: v }); } }),
262 _tc() && el(_tc(), { label: __('Tab Label', 'blockenberg'), typo: a.typoTab || {}, onChange: function (v) { setAttributes({ typoTab: v }); } })
263 ),
264 el(PanelBody, { title: __('Colors', 'blockenberg'), initialOpen: false },
265 cc('accentColor', __('Accent', 'blockenberg'), 'accentColor'),
266 cc('activeTabBg', __('Active tab bg', 'blockenberg'), 'activeTabBg'),
267 cc('activeTabColor', __('Active tab text', 'blockenberg'), 'activeTabColor'),
268 cc('inactiveTabBg', __('Inactive tab bg', 'blockenberg'), 'inactiveTabBg'),
269 cc('inactiveTabColor', __('Inactive tab text', 'blockenberg'), 'inactiveTabColor'),
270 cc('timeColor', __('Time label', 'blockenberg'), 'timeColor'),
271 cc('sessionTitleColor', __('Session title', 'blockenberg'), 'sessionTitleColor'),
272 cc('speakerNameColor', __('Speaker name', 'blockenberg'), 'speakerNameColor'),
273 cc('metaColor', __('Meta / room / role', 'blockenberg'), 'metaColor'),
274 cc('cardBg', __('Card background', 'blockenberg'), 'cardBg'),
275 cc('cardBorderColor', __('Card border', 'blockenberg'), 'cardBorderColor'),
276 cc('breakCardBg', __('Break card background', 'blockenberg'), 'breakCardBg'),
277 cc('timelineBarColor', __('Timeline bar (idle)', 'blockenberg'), 'timelineBarColor'),
278 cc('bgColor', __('Section background', 'blockenberg'), 'bgColor')
279 ),
280 el(PanelBody, { title: __('Spacing', 'blockenberg'), initialOpen: false },
281 el(RangeControl, { label: __('Padding top (px)', 'blockenberg'), value: a.paddingTop, min: 0, max: 200, onChange: function (v) { setAttributes({ paddingTop: v }); } }),
282 el(RangeControl, { label: __('Padding bottom (px)', 'blockenberg'), value: a.paddingBottom, min: 0, max: 200, onChange: function (v) { setAttributes({ paddingBottom: v }); } })
283 ),
284 el(PanelBody, { title: __('Agenda Days & Sessions', 'blockenberg'), initialOpen: false },
285 a.days.map(function (day, di) {
286 return el(PanelBody, { key: day.id, title: day.label || 'Day ' + (di + 1), initialOpen: false },
287 el(TextControl, { label: __('Day label', 'blockenberg'), value: day.label, onChange: function (v) { updateDay(day.id, 'label', v); } }),
288 el('p', { style: { fontSize: '12px', fontWeight: 600, margin: '6px 0 4px' } }, __('Sessions', 'blockenberg')),
289 day.sessions.map(function (s, si) {
290 return el(PanelBody, { key: s.id, title: (s.time || '') + ' ' + (s.title ? s.title.substring(0,20) : 'Session ' + (si+1)), initialOpen: false },
291 el(TextControl, { label: __('Time', 'blockenberg'), value: s.time, onChange: function (v) { updateSession(day.id, s.id, 'time', v); } }),
292 el(TextControl, { label: __('Duration', 'blockenberg'), value: s.duration, onChange: function (v) { updateSession(day.id, s.id, 'duration', v); } }),
293 el(SelectControl, { label: __('Type', 'blockenberg'), value: s.type, options: [{ label: 'Keynote', value: 'keynote' }, { label: 'Talk', value: 'talk' }, { label: 'Workshop', value: 'workshop' }, { label: 'Break', value: 'break' }], onChange: function (v) { updateSession(day.id, s.id, 'type', v); } }),
294 el(TextControl, { label: __('Title', 'blockenberg'), value: s.title, onChange: function (v) { updateSession(day.id, s.id, 'title', v); } }),
295 el(TextControl, { label: __('Speaker', 'blockenberg'), value: s.speaker, onChange: function (v) { updateSession(day.id, s.id, 'speaker', v); } }),
296 el(TextControl, { label: __('Role', 'blockenberg'), value: s.role, onChange: function (v) { updateSession(day.id, s.id, 'role', v); } }),
297 el(TextControl, { label: __('Company', 'blockenberg'), value: s.company, onChange: function (v) { updateSession(day.id, s.id, 'company', v); } }),
298 el(TextControl, { label: __('Room', 'blockenberg'), value: s.room, onChange: function (v) { updateSession(day.id, s.id, 'room', v); } }),
299 el(TextControl, { label: __('Tags (comma-separated)', 'blockenberg'), value: (s.tags || []).join(', '), onChange: function (v) { updateSession(day.id, s.id, 'tags', v.split(',').map(function (t) { return t.trim(); }).filter(Boolean)); } }),
300 el(MediaUploadCheck, null,
301 el(MediaUpload, { onSelect: function (m) { updateSession(day.id, s.id, 'avatarUrl', m.url); updateSession(day.id, s.id, 'avatarId', m.id); }, allowedTypes: ['image'], value: s.avatarId, render: function (rp) {
302 return el(Button, { variant: 'secondary', size: 'compact', onClick: rp.open, style: { marginTop: '4px' } }, s.avatarUrl ? __('Change avatar', 'blockenberg') : __('Upload avatar', 'blockenberg'));
303 } })
304 ),
305 el(Button, { onClick: function () { updateDay(day.id, 'sessions', day.sessions.filter(function (se) { return se.id !== s.id; })); }, isDestructive: true, variant: 'tertiary', size: 'compact', style: { marginTop: '6px' } }, __('Remove session', 'blockenberg'))
306 );
307 }),
308 el(Button, { variant: 'secondary', size: 'compact', onClick: function () { addSession(day.id); }, style: { marginTop: '4px' } }, __('+ Add Session', 'blockenberg')),
309 el(Button, { onClick: function () { setAttributes({ days: a.days.filter(function (d) { return d.id !== day.id; }) }); setActiveDay(Math.max(0, safeDay - 1)); }, isDestructive: true, variant: 'tertiary', size: 'compact', style: { marginTop: '6px', display: 'block' } }, __('Remove day', 'blockenberg'))
310 );
311 }),
312 el(Button, { variant: 'primary', onClick: function () { setAttributes({ days: a.days.concat([{ id: makeId(), label: __('New Day', 'blockenberg'), sessions: [] }]) }); }, style: { marginTop: '8px' } }, __('+ Add Day', 'blockenberg'))
313 )
314 ),
315
316 el('div', blockProps,
317 tabBar,
318 currentDay && el('div', { className: 'bkbg-ea-sessions', 'data-day': currentDay.id },
319 currentDay.sessions.map(function (s) {
320 return el(SessionCard, { key: s.id, session: s, a: a });
321 }),
322 currentDay.sessions.length === 0 && el('p', { style: { textAlign: 'center', color: '#9ca3af', padding: '32px' } }, __('No sessions yet. Add sessions in the panel →', 'blockenberg'))
323 )
324 )
325 );
326 },
327
328 save: function (props) {
329 var a = props.attributes;
330 return el('div', wp.blockEditor.useBlockProps.save({ className: 'bkbg-ea-wrapper bkbg-ea-session-style--' + a.sessionStyle, style: buildWrapStyle(a) }),
331 a.showDayTabs && el('nav', { className: 'bkbg-ea-tab-bar bkbg-ea-tab-bar--' + a.tabStyle, role: 'tablist' },
332 a.days.map(function (day, di) {
333 return el('button', { key: day.id, type: 'button', role: 'tab', className: 'bkbg-ea-tab-btn' + (di === 0 ? ' is-active' : ''), 'data-day': day.id, 'aria-selected': di === 0 ? 'true' : 'false' }, day.label);
334 })
335 ),
336 el('div', { className: 'bkbg-ea-body' },
337 a.days.map(function (day, di) {
338 return el('div', { key: day.id, className: 'bkbg-ea-day-panel' + (di === 0 ? ' is-active' : ''), 'data-day': day.id, role: 'tabpanel', 'aria-hidden': di === 0 ? 'false' : 'true', style: { display: di === 0 ? 'block' : 'none' } },
339 el('div', { className: 'bkbg-ea-sessions' },
340 day.sessions.map(function (s) {
341 return el('div', { key: s.id, className: 'bkbg-ea-session bkbg-ea-session--' + s.type, 'data-type': s.type },
342 el('div', { className: 'bkbg-ea-time-col' },
343 el('span', { className: 'bkbg-ea-time-label' }, s.time),
344 a.showDuration && s.duration && el('span', { className: 'bkbg-ea-duration' }, s.duration)
345 ),
346 el('div', { className: 'bkbg-ea-session-card' },
347 a.showSpeakerAvatar && el('div', { className: 'bkbg-ea-avatar' },
348 s.avatarUrl ? el('img', { src: s.avatarUrl, alt: s.speaker || '', loading: 'lazy' }) : el('span', { 'aria-hidden': 'true' }, SESSION_TYPE_ICONS[s.type] || '👤')
349 ),
350 el('div', { className: 'bkbg-ea-session-info' },
351 el('div', { className: 'bkbg-ea-session-meta-row' },
352 el('span', { className: 'bkbg-ea-type-badge' }, SESSION_TYPE_ICONS[s.type] + ' ' + getSessionTypeLabel(a.sessionTypes, s.type)),
353 a.showRoom && s.room && el('span', { className: 'bkbg-ea-room' }, '📍 ' + s.room)
354 ),
355 el('div', { className: 'bkbg-ea-session-title' }, s.title),
356 s.speaker && el('div', { className: 'bkbg-ea-speaker-info' },
357 el('span', { className: 'bkbg-ea-speaker-name' }, s.speaker),
358 a.showSpeakerRole && s.role && el('span', { className: 'bkbg-ea-speaker-role' }, s.role),
359 a.showSpeakerCompany && s.company && el('span', { className: 'bkbg-ea-speaker-company' }, '@ ' + s.company)
360 ),
361 a.showTags && s.tags && s.tags.length > 0 && el('div', { className: 'bkbg-ea-tags' },
362 s.tags.map(function (tag, ti) { return el('span', { key: ti, className: 'bkbg-ea-tag' }, tag); })
363 )
364 )
365 )
366 );
367 })
368 )
369 );
370 })
371 )
372 );
373 }
374 });
375 }() );
376