185 lines
23 KiB
JavaScript
185 lines
23 KiB
JavaScript
|
|
const el = wp.element.createElement;
|
||
|
|
const { registerBlockType } = wp.blocks;
|
||
|
|
const { RichText, InnerBlocks, MediaUpload, InspectorControls, URLInput } = wp.blockEditor;
|
||
|
|
const { Button, PanelBody, ToggleControl, TextControl, ButtonGroup } = wp.components;
|
||
|
|
const { useSelect, useDispatch } = wp.data;
|
||
|
|
|
||
|
|
const moveItem = (list, fromIndex, toIndex) => {
|
||
|
|
const result = Array.from(list);
|
||
|
|
const [removed] = result.splice(fromIndex, 1);
|
||
|
|
result.splice(toIndex, 0, removed);
|
||
|
|
return result;
|
||
|
|
};
|
||
|
|
|
||
|
|
registerBlockType('cv/company', {
|
||
|
|
title: 'Company (CV)', icon: 'building', category: 'layout',
|
||
|
|
attributes: { name: { type: 'string', source: 'html', selector: '.cv-company-name' }, dates: { type: 'string', source: 'html', selector: '.cv-company-dates' } },
|
||
|
|
edit: ({ attributes, setAttributes }) => el('div', { className: 'cv-company' }, el(RichText, { tagName: 'div', className: 'cv-company-name', placeholder: 'Company Name', value: attributes.name, onChange: val => setAttributes({ name: val }) }), el(RichText, { tagName: 'div', className: 'cv-company-dates', placeholder: 'Years', value: attributes.dates, onChange: val => setAttributes({ dates: val }) }), el(InnerBlocks, { allowedBlocks: ['cv/position'], template: [['cv/position']] })),
|
||
|
|
save: ({ attributes }) => el('div', { className: 'cv-company' }, el(RichText.Content, { tagName: 'div', className: 'cv-company-name', value: attributes.name }), el(RichText.Content, { tagName: 'div', className: 'cv-company-dates', value: attributes.dates }), el(InnerBlocks.Content, null))
|
||
|
|
});
|
||
|
|
|
||
|
|
registerBlockType('cv/position', {
|
||
|
|
title: 'Position (CV)', icon: 'id', parent: ['cv/company'], category: 'layout',
|
||
|
|
attributes: { title: { type: 'string', source: 'html', selector: '.cv-position-title' }, department: { type: 'string', source: 'html', selector: '.cv-position-department' }, dates: { type: 'string', source: 'html', selector: '.cv-position-dates' } },
|
||
|
|
edit: ({ attributes, setAttributes }) => el('div', { className: 'cv-position' }, el(RichText, { tagName: 'div', className: 'cv-position-title', placeholder: 'Job Title', value: attributes.title, onChange: val => setAttributes({ title: val }) }), el(RichText, { tagName: 'div', className: 'cv-position-department', placeholder: 'Department / Unit', value: attributes.department, onChange: val => setAttributes({ department: val }) }), el(RichText, { tagName: 'div', className: 'cv-position-dates', placeholder: 'Period', value: attributes.dates, onChange: val => setAttributes({ dates: val }) }), el(InnerBlocks, { allowedBlocks: ['core/list'], template: [['core/list']] })),
|
||
|
|
save: ({ attributes }) => el('div', { className: 'cv-position' }, el(RichText.Content, { tagName: 'div', className: 'cv-position-title', value: attributes.title }), el(RichText.Content, { tagName: 'div', className: 'cv-position-department', value: attributes.department }), el(RichText.Content, { tagName: 'div', className: 'cv-position-dates', value: attributes.dates }), el(InnerBlocks.Content, null))
|
||
|
|
});
|
||
|
|
|
||
|
|
registerBlockType('cv/education', {
|
||
|
|
title: 'Education (CV)', icon: 'welcome-learn-more', category: 'layout',
|
||
|
|
attributes: { degree: { type: 'string', source: 'html', selector: '.cv-education-degree' }, institution: { type: 'string', source: 'html', selector: '.cv-education-institution' }, dates: { type: 'string', source: 'html', selector: '.cv-education-dates' } },
|
||
|
|
edit: ({ attributes, setAttributes }) => el('div', { className: 'cv-education' }, el(RichText, { tagName: 'div', className: 'cv-education-degree', placeholder: 'Degree / Qualification', value: attributes.degree, onChange: val => setAttributes({ degree: val }) }), el(RichText, { tagName: 'div', className: 'cv-education-institution', placeholder: 'University or School', value: attributes.institution, onChange: val => setAttributes({ institution: val }) }), el(RichText, { tagName: 'div', className: 'cv-education-dates', placeholder: 'Years', value: attributes.dates, onChange: val => setAttributes({ dates: val }) })),
|
||
|
|
save: ({ attributes }) => el('div', { className: 'cv-education' }, el(RichText.Content, { tagName: 'div', className: 'cv-education-degree', value: attributes.degree }), el(RichText.Content, { tagName: 'div', className: 'cv-education-institution', value: attributes.institution }), el(RichText.Content, { tagName: 'div', className: 'cv-education-dates', value: attributes.dates }))
|
||
|
|
});
|
||
|
|
|
||
|
|
registerBlockType('cv/profileheader', {
|
||
|
|
title: 'Profile Header (CV)', icon: 'id-alt', category: 'layout',
|
||
|
|
supports: { align: ['wide', 'full'] },
|
||
|
|
attributes: { headerImage: { type: 'string', default: '' }, profileImage: { type: 'string', default: '' }, name: { type: 'string', source: 'html', selector: '.cv-profileheader-name' }, title: { type: 'string', source: 'html', selector: '.cv-profileheader-title' }, company: { type: 'string', source: 'html', selector: '.cv-profileheader-company' }, showMenu: { type: 'boolean', default: false }, menuItems: { type: 'array', default: [] } },
|
||
|
|
edit: ({ attributes, setAttributes }) => {
|
||
|
|
const updateMenuItem = (index, key, value) => { const newItems = [...attributes.menuItems]; newItems[index] = { ...newItems[index], [key]: value }; setAttributes({ menuItems: newItems }); };
|
||
|
|
const addMenuItem = () => setAttributes({ menuItems: [...attributes.menuItems, { label: '', url: '' }] });
|
||
|
|
const removeMenuItem = (index) => { const newItems = attributes.menuItems.filter((_, i) => i !== index); setAttributes({ menuItems: newItems }); };
|
||
|
|
const moveMenuItemAt = (index, direction) => { const newPos = index + direction; if (newPos >= 0 && newPos < attributes.menuItems.length) setAttributes({ menuItems: moveItem(attributes.menuItems, index, newPos) }); };
|
||
|
|
return [
|
||
|
|
el(InspectorControls, {}, el(PanelBody, { title: 'Navigation Menu', initialOpen: true }, el(ToggleControl, { label: 'Enable Navigation Menu', checked: attributes.showMenu, onChange: (val) => setAttributes({ showMenu: val }) }))),
|
||
|
|
el('div', { className: 'cv-profileheader' },
|
||
|
|
el('div', { className: 'cv-profileheader-cover', style: { backgroundImage: attributes.headerImage ? `url(${attributes.headerImage})` : 'none' } }, el(MediaUpload, { onSelect: media => setAttributes({ headerImage: media.url }), type: 'image', render: ({ open }) => el(Button, { onClick: open, className: 'button', style: { position: 'absolute', top: '10px', right: '10px', backgroundColor: 'rgba(255,255,255,0.9)' } }, attributes.headerImage ? 'Change Header' : 'Add Header Image') })),
|
||
|
|
el('div', { className: 'cv-profileheader-avatar-container' }, el(MediaUpload, { onSelect: media => setAttributes({ profileImage: media.url }), type: 'image', render: ({ open }) => el('div', { onClick: open, style: { cursor: 'pointer' }, title: 'Click to set profile picture' }, attributes.profileImage ? el('img', { src: attributes.profileImage, className: 'cv-profileheader-avatar' }) : el('div', { className: 'cv-profileheader-avatar placeholder' }, 'Add Photo')) })),
|
||
|
|
el('div', { className: 'cv-profileheader-info' }, el(RichText, { tagName: 'div', className: 'cv-profileheader-name', placeholder: 'Full Name', value: attributes.name, onChange: val => setAttributes({ name: val }) }), el(RichText, { tagName: 'div', className: 'cv-profileheader-title', placeholder: 'Current Job Title', value: attributes.title, onChange: val => setAttributes({ title: val }) }), el(RichText, { tagName: 'div', className: 'cv-profileheader-company', placeholder: 'Company or Organization', value: attributes.company, onChange: val => setAttributes({ company: val }) })),
|
||
|
|
attributes.showMenu && el('div', { className: 'cv-profileheader-nav-editor' }, attributes.menuItems.map((item, index) => el('div', { className: 'cv-menu-item-edit', key: index }, el('div', { className: 'cv-menu-item-fields' }, el(TextControl, { placeholder: 'Label', value: item.label, onChange: val => updateMenuItem(index, 'label', val) }), el(URLInput, { className: 'cv-url-input', value: item.url, onChange: val => updateMenuItem(index, 'url', val), disableSuggestions: false, isFullWidth: true, placeholder: 'Link or Search Page...' })), el(ButtonGroup, {}, el(Button, { icon: 'arrow-up-alt2', onClick: () => moveMenuItemAt(index, -1), disabled: index === 0 }), el(Button, { icon: 'arrow-down-alt2', onClick: () => moveMenuItemAt(index, 1), disabled: index === attributes.menuItems.length - 1 }), el(Button, { isDestructive: true, onClick: () => removeMenuItem(index) }, 'Remove')))), el(Button, { isPrimary: true, onClick: addMenuItem }, 'Add Menu Item'))
|
||
|
|
)
|
||
|
|
];
|
||
|
|
},
|
||
|
|
save: ({ attributes }) => el('div', { className: 'cv-profileheader' }, el('div', { className: 'cv-profileheader-cover', style: { backgroundImage: attributes.headerImage ? `url(${attributes.headerImage})` : 'none' } }), el('div', { className: 'cv-profileheader-avatar-container' }, attributes.profileImage ? el('img', { src: attributes.profileImage, className: 'cv-profileheader-avatar', alt: '' }) : null), el('div', { className: 'cv-profileheader-info' }, el(RichText.Content, { tagName: 'div', className: 'cv-profileheader-name', value: attributes.name }), el(RichText.Content, { tagName: 'div', className: 'cv-profileheader-title', value: attributes.title }), el(RichText.Content, { tagName: 'div', className: 'cv-profileheader-company', value: attributes.company })), attributes.showMenu && attributes.menuItems.length > 0 && el('nav', { className: 'cv-profileheader-nav' }, el('ul', {}, attributes.menuItems.map((item, index) => el('li', { key: index }, el('a', { href: item.url }, item.label))))))
|
||
|
|
});
|
||
|
|
|
||
|
|
registerBlockType('cv/contentblock', {
|
||
|
|
title: 'Content Block (CV)', icon: 'layout', category: 'layout',
|
||
|
|
attributes: { heading: { type: 'string', source: 'html', selector: '.cv-contentblock-heading' }, includeInToc: { type: 'boolean', default: true } },
|
||
|
|
edit: ({ attributes, setAttributes }) => {
|
||
|
|
return [
|
||
|
|
el(InspectorControls, {}, el(PanelBody, { title: 'Table of Contents', initialOpen: true }, el(ToggleControl, { label: 'Include in Table of Contents', checked: attributes.includeInToc, onChange: (val) => setAttributes({ includeInToc: val }) }))),
|
||
|
|
el('div', { className: 'cv-contentblock' }, el(RichText, { tagName: 'h2', className: 'cv-contentblock-heading', placeholder: 'Section Heading', value: attributes.heading, onChange: val => setAttributes({ heading: val }) }), el('div', { className: 'cv-contentblock-inner' }, el(InnerBlocks, {})))
|
||
|
|
];
|
||
|
|
},
|
||
|
|
save: ({ attributes }) => el('div', { className: 'cv-contentblock', 'data-include-toc': attributes.includeInToc }, el(RichText.Content, { tagName: 'h2', className: 'cv-contentblock-heading', value: attributes.heading }), el('div', { className: 'cv-contentblock-inner' }, el(InnerBlocks.Content, null)))
|
||
|
|
});
|
||
|
|
|
||
|
|
registerBlockType('cv/container', {
|
||
|
|
title: 'Container (CV)', icon: 'editor-expand', category: 'layout',
|
||
|
|
edit: () => el('div', { className: 'cv-container' }, el('div', { className: 'cv-container-inner' }, el(InnerBlocks, {}))),
|
||
|
|
save: () => el('div', { className: 'cv-container' }, el('div', { className: 'cv-container-inner' }, el(InnerBlocks.Content, null)))
|
||
|
|
});
|
||
|
|
|
||
|
|
registerBlockType('cv/contactform', {
|
||
|
|
title: 'Contact Form (CV)', icon: 'email', category: 'layout',
|
||
|
|
attributes: { nameLabel: { type: 'string', default: 'Name' }, emailLabel: { type: 'string', default: 'Email' }, subjectLabel: { type: 'string', default: 'Subject' }, messageLabel: { type: 'string', default: 'Message' }, buttonLabel: { type: 'string', default: 'Send Message' }, receiverEmail: { type: 'string', default: '' }, successMessage: { type: 'string', default: 'The message has been sent!' }, enableControlField: { type: 'boolean', default: false }, controlQuestion: { type: 'string', default: 'What is 2+2?' }, controlAnswer: { type: 'string', default: '4' } },
|
||
|
|
edit: ({ attributes, setAttributes }) => {
|
||
|
|
return [
|
||
|
|
el(InspectorControls, {}, el(PanelBody, { title: 'Contact Form Settings', initialOpen: true }, el(TextControl, { label: 'Receiver Email Address', placeholder: 'your@email.com', value: attributes.receiverEmail, onChange: val => setAttributes({ receiverEmail: val }) }), el(TextControl, { label: 'Success Message', value: attributes.successMessage, onChange: val => setAttributes({ successMessage: val }) }), el(ToggleControl, { label: 'Enable Control Question (Anti-spam)', checked: attributes.enableControlField, onChange: val => setAttributes({ enableControlField: val }) }), attributes.enableControlField && el(TextControl, { label: 'Control Question', value: attributes.controlQuestion, onChange: val => setAttributes({ controlQuestion: val }) }), attributes.enableControlField && el(TextControl, { label: 'Expected Answer', value: attributes.controlAnswer, onChange: val => setAttributes({ controlAnswer: val }) }))),
|
||
|
|
el('div', { className: 'cv-contactform' }, el('div', { className: 'cv-form-group' }, el(RichText, { tagName: 'label', value: attributes.nameLabel, onChange: (val) => setAttributes({ nameLabel: val }) }), el('input', { type: 'text', disabled: true })), el('div', { className: 'cv-form-group' }, el(RichText, { tagName: 'label', value: attributes.emailLabel, onChange: (val) => setAttributes({ emailLabel: val }) }), el('input', { type: 'email', disabled: true })), el('div', { className: 'cv-form-group' }, el(RichText, { tagName: 'label', value: attributes.subjectLabel, onChange: (val) => setAttributes({ subjectLabel: val }) }), el('input', { type: 'text', disabled: true })), el('div', { className: 'cv-form-group' }, el(RichText, { tagName: 'label', value: attributes.messageLabel, onChange: (val) => setAttributes({ messageLabel: val }) }), el('textarea', { disabled: true, rows: 10 })), attributes.enableControlField && el('div', { className: 'cv-form-group' }, el('label', {}, attributes.controlQuestion), el('input', { type: 'text', disabled: true })), el('div', { className: 'cv-form-group' }, el(RichText, { tagName: 'button', className: 'cv-contactform-button', value: attributes.buttonLabel, onChange: (val) => setAttributes({ buttonLabel: val }) })))
|
||
|
|
];
|
||
|
|
},
|
||
|
|
save: ({ attributes }) => {
|
||
|
|
return el('div', { className: 'cv-contactform' }, el('form', { action: '#', method: 'post', 'data-receiver': attributes.receiverEmail, 'data-success': attributes.successMessage, 'data-control-answer': attributes.enableControlField ? attributes.controlAnswer : '' }, el('div', { className: 'cv-form-group' }, el('label', {}, attributes.nameLabel), el('input', { type: 'text', name: 'cv-name', required: true })), el('div', { className: 'cv-form-group' }, el('label', {}, attributes.emailLabel), el('input', { type: 'email', name: 'cv-email', required: true })), el('div', { className: 'cv-form-group' }, el('label', {}, attributes.subjectLabel), el('input', { type: 'text', name: 'cv-subject' })), el('div', { className: 'cv-form-group' }, el('label', {}, attributes.messageLabel), el('textarea', { name: 'cv-message', rows: 10, required: true })), attributes.enableControlField && el('div', { className: 'cv-form-group' }, el('label', {}, attributes.controlQuestion), el('input', { type: 'text', name: 'cv-control', required: true })), el('button', { type: 'submit', className: 'cv-contactform-button' }, attributes.buttonLabel)), el('div', { className: 'cv-contactform-feedback', style: { display: 'none' } }));
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
registerBlockType('cv/toc', {
|
||
|
|
title: 'Table of Contents (CV)', icon: 'list-view', category: 'layout',
|
||
|
|
attributes: {
|
||
|
|
heading: { type: 'string', source: 'html', selector: '.cv-toc-heading', default: 'Table of Content' }
|
||
|
|
},
|
||
|
|
edit: ({ attributes, setAttributes }) => {
|
||
|
|
const headings = useSelect(select => {
|
||
|
|
const blocks = select('core/block-editor').getBlocks();
|
||
|
|
const findHeadings = (blocksList) => {
|
||
|
|
let result = [];
|
||
|
|
blocksList.forEach(block => {
|
||
|
|
if (block.name === 'cv/contentblock' && block.attributes.includeInToc !== false && block.attributes.heading) result.push(block.attributes.heading.replace(/<[^>]+>/g, ''));
|
||
|
|
if (block.innerBlocks) result = result.concat(findHeadings(block.innerBlocks));
|
||
|
|
});
|
||
|
|
return result;
|
||
|
|
};
|
||
|
|
return findHeadings(blocks);
|
||
|
|
}, []);
|
||
|
|
return el('div', { className: 'cv-toc cv-contentblock' },
|
||
|
|
el(RichText, { tagName: 'h2', className: 'cv-toc-heading cv-contentblock-heading', value: attributes.heading, onChange: val => setAttributes({ heading: val }), placeholder: 'Table of Content' }),
|
||
|
|
el('div', { className: 'cv-toc-editor-preview' },
|
||
|
|
headings.length > 0 ? el('ul', { className: 'cv-toc-list' }, headings.map((h, i) => el('li', { key: i }, el('a', { href: '#' }, h)))) : el('p', { style: { color: '#666', fontStyle: 'italic', margin: 0, fontSize: '0.9rem' } }, 'Add Content Blocks to see headings.')
|
||
|
|
)
|
||
|
|
);
|
||
|
|
},
|
||
|
|
save: ({ attributes }) => el('div', { className: 'cv-toc cv-contentblock' },
|
||
|
|
el(RichText.Content, { tagName: 'h2', className: 'cv-toc-heading cv-contentblock-heading', value: attributes.heading })
|
||
|
|
)
|
||
|
|
});
|
||
|
|
|
||
|
|
registerBlockType('cv/profile', {
|
||
|
|
title: 'Profile (CV)', icon: 'admin-users', category: 'layout',
|
||
|
|
attributes: { profileImage: { type: 'string', default: '' }, name: { type: 'string', source: 'html', selector: '.cv-profile-name' }, titles: { type: 'string', source: 'html', selector: '.cv-profile-titles' }, showSocial: { type: 'boolean', default: false } },
|
||
|
|
edit: ({ attributes, setAttributes }) => {
|
||
|
|
return [
|
||
|
|
el(InspectorControls, {}, el(PanelBody, { title: 'Profile Settings', initialOpen: true }, el(ToggleControl, { label: 'Enable Social Icons', checked: attributes.showSocial, onChange: (val) => setAttributes({ showSocial: val }) }))),
|
||
|
|
el('div', { className: 'cv-profile' },
|
||
|
|
el('div', { className: 'cv-profile-avatar-container' }, el(MediaUpload, { onSelect: media => setAttributes({ profileImage: media.url }), type: 'image', render: ({ open }) => el('div', { onClick: open, style: { cursor: 'pointer' } }, attributes.profileImage ? el('img', { src: attributes.profileImage, className: 'cv-profile-avatar' }) : el('div', { className: 'cv-profile-avatar placeholder' }, 'Add Photo')) })),
|
||
|
|
el(RichText, { tagName: 'div', className: 'cv-profile-name', placeholder: 'Full Name', value: attributes.name, onChange: val => setAttributes({ name: val }) }),
|
||
|
|
attributes.showSocial && el('div', { className: 'cv-profile-social-container' }, el(InnerBlocks, { allowedBlocks: ['core/social-links'], template: [['core/social-links']] })),
|
||
|
|
el(RichText, { tagName: 'div', className: 'cv-profile-titles', placeholder: 'Titles (Press Enter for new line)', value: attributes.titles, onChange: val => setAttributes({ titles: val }) })
|
||
|
|
)
|
||
|
|
];
|
||
|
|
},
|
||
|
|
save: ({ attributes }) => el('div', { className: 'cv-profile' }, el('div', { className: 'cv-profile-avatar-container' }, attributes.profileImage ? el('img', { src: attributes.profileImage, className: 'cv-profile-avatar', alt: '' }) : null), el(RichText.Content, { tagName: 'div', className: 'cv-profile-name', value: attributes.name }), attributes.showSocial && el('div', { className: 'cv-profile-social-container' }, el(InnerBlocks.Content, null)), el(RichText.Content, { tagName: 'div', className: 'cv-profile-titles', value: attributes.titles }))
|
||
|
|
});
|
||
|
|
|
||
|
|
registerBlockType('cv/topnav', {
|
||
|
|
title: 'Top Navigation (CV)', icon: 'menu', category: 'layout',
|
||
|
|
supports: { align: ['wide', 'full'] },
|
||
|
|
attributes: {
|
||
|
|
siteName: { type: 'string', source: 'html', selector: '.cv-topnav-name', default: '' },
|
||
|
|
menuItems: { type: 'array', default: [] }
|
||
|
|
},
|
||
|
|
edit: ({ attributes, setAttributes }) => {
|
||
|
|
const updateMenuItem = (index, key, value) => { const newItems = [...attributes.menuItems]; newItems[index] = { ...newItems[index], [key]: value }; setAttributes({ menuItems: newItems }); };
|
||
|
|
const addMenuItem = () => setAttributes({ menuItems: [...attributes.menuItems, { label: '', url: '' }] });
|
||
|
|
const removeMenuItem = (index) => { const newItems = attributes.menuItems.filter((_, i) => i !== index); setAttributes({ menuItems: newItems }); };
|
||
|
|
const moveMenuItemAt = (index, direction) => { const newPos = index + direction; if (newPos >= 0 && newPos < attributes.menuItems.length) setAttributes({ menuItems: moveItem(attributes.menuItems, index, newPos) }); };
|
||
|
|
const siteTitle = useSelect(select => select('core').getSite()?.title);
|
||
|
|
wp.element.useEffect(() => { if (!attributes.siteName && siteTitle) setAttributes({ siteName: siteTitle }); }, [siteTitle]);
|
||
|
|
|
||
|
|
return el('div', { className: 'cv-topnav' },
|
||
|
|
el('div', { className: 'cv-topnav-link-wrapper' },
|
||
|
|
el(RichText, { tagName: 'h1', className: 'cv-topnav-name', placeholder: 'Site Name', value: attributes.siteName, onChange: val => setAttributes({ siteName: val }) })
|
||
|
|
),
|
||
|
|
el('div', { className: 'cv-topnav-menu-editor' },
|
||
|
|
attributes.menuItems.map((item, index) => el('div', { className: 'cv-menu-item-edit', key: index }, el('div', { className: 'cv-menu-item-fields' }, el(TextControl, { placeholder: 'Label', value: item.label, onChange: val => updateMenuItem(index, 'label', val) }), el(URLInput, { className: 'cv-url-input', value: item.url, onChange: val => updateMenuItem(index, 'url', val), disableSuggestions: false, isFullWidth: true, placeholder: 'Link or Search Page...' })), el(ButtonGroup, {}, el(Button, { icon: 'arrow-up-alt2', onClick: () => moveMenuItemAt(index, -1), disabled: index === 0 }), el(Button, { icon: 'arrow-down-alt2', onClick: () => moveMenuItemAt(index, 1), disabled: index === attributes.menuItems.length - 1 }), el(Button, { isDestructive: true, onClick: () => removeMenuItem(index) }, 'Remove')))),
|
||
|
|
el(Button, { isPrimary: true, onClick: addMenuItem, style: {marginTop: '10px'} }, 'Add Menu Link')
|
||
|
|
),
|
||
|
|
el('div', { className: 'cv-topnav-line' })
|
||
|
|
);
|
||
|
|
},
|
||
|
|
save: ({ attributes }) => el('header', { className: 'cv-topnav' },
|
||
|
|
el('a', { href: '/', className: 'cv-topnav-home-link' }, el(RichText.Content, { tagName: 'h1', className: 'cv-topnav-name', value: attributes.siteName })),
|
||
|
|
attributes.menuItems.length > 0 && el('nav', { className: 'cv-topnav-nav' }, el('ul', {}, attributes.menuItems.map((item, index) => el('li', { key: index }, el('a', { href: item.url }, item.label))))),
|
||
|
|
el('div', { className: 'cv-topnav-line' })
|
||
|
|
)
|
||
|
|
});
|
||
|
|
|
||
|
|
if (wp.plugins && wp.editPost) {
|
||
|
|
const { registerPlugin } = wp.plugins;
|
||
|
|
const { PluginDocumentSettingPanel } = wp.editPost;
|
||
|
|
const PageSettingsPanel = () => {
|
||
|
|
const postType = useSelect(select => select('core/editor').getCurrentPostType(), []);
|
||
|
|
if (postType !== 'page') return null;
|
||
|
|
const meta = useSelect(select => select('core/editor').getEditedPostAttribute('meta'), []);
|
||
|
|
const { editPost } = useDispatch('core/editor');
|
||
|
|
if (!meta) return null;
|
||
|
|
return el(PluginDocumentSettingPanel, { name: 'ansico-cv-page-settings', title: 'CV Page Settings', icon: 'layout' },
|
||
|
|
el(ToggleControl, { label: 'Hide Page Title (H1)', checked: meta.ansico_cv_hide_title || false, onChange: (val) => editPost({ meta: { ...meta, ansico_cv_hide_title: val } }) }),
|
||
|
|
el(ToggleControl, { label: 'Enable Frame Design', help: 'Wraps the page content in a CV-styled box.', checked: meta.ansico_cv_frame_design || false, onChange: (val) => editPost({ meta: { ...meta, ansico_cv_frame_design: val } }) })
|
||
|
|
);
|
||
|
|
};
|
||
|
|
registerPlugin('ansico-cv-page-settings-plugin', { render: PageSettingsPanel });
|
||
|
|
}
|