(function (blocks, blockEditor, components, element, i18n) { const registerBlockType = blocks.registerBlockType; const InspectorControls = blockEditor.InspectorControls; const MediaUpload = blockEditor.MediaUpload; const MediaUploadCheck = blockEditor.MediaUploadCheck; const useBlockProps = blockEditor.useBlockProps; const Button = components.Button; const PanelBody = components.PanelBody; const Placeholder = components.Placeholder; const RangeControl = components.RangeControl; const SelectControl = components.SelectControl; const TextControl = components.TextControl; const ToggleControl = components.ToggleControl; const Fragment = element.Fragment; const el = element.createElement; const __ = i18n.__; function updateLogoAtIndex(logos, index, nextLogo) { return logos.map(function (logo, logoIndex) { return logoIndex === index ? nextLogo : logo; }); } registerBlockType('logo-soup/showcase', { edit: function (props) { const attributes = props.attributes; const setAttributes = props.setAttributes; const logos = attributes.logos || []; const layout = attributes.layout || 'carousel'; const grayscale = typeof attributes.grayscale === 'boolean' ? attributes.grayscale : true; const speed = attributes.speed || 22; const baseSize = attributes.baseSize || 48; const scaleFactor = typeof attributes.scaleFactor === 'number' ? attributes.scaleFactor : 0.5; const densityAware = typeof attributes.densityAware === 'boolean' ? attributes.densityAware : true; const densityFactor = typeof attributes.densityFactor === 'number' ? attributes.densityFactor : 0.5; const cropToContent = typeof attributes.cropToContent === 'boolean' ? attributes.cropToContent : false; const alignBy = attributes.alignBy || 'bounds'; const pauseOnHover = typeof attributes.pauseOnHover === 'boolean' ? attributes.pauseOnHover : true; const blockProps = useBlockProps({ className: 'logo-soup-editor' }); function addLogo(media) { if (!media || !media.url) { return; } setAttributes({ logos: logos.concat({ id: media.id || 0, url: media.url, alt: media.alt || media.title || '', link: '', }), }); } function removeLogo(index) { setAttributes({ logos: logos.filter(function (_, logoIndex) { return logoIndex !== index; }), }); } function moveLogo(index, direction) { const nextIndex = index + direction; const nextLogos = logos.slice(); const currentLogo = nextLogos[index]; if (nextIndex < 0 || nextIndex >= logos.length) { return; } nextLogos[index] = nextLogos[nextIndex]; nextLogos[nextIndex] = currentLogo; setAttributes({ logos: nextLogos }); } function renderMediaButton(label) { return el(MediaUploadCheck, null, el(MediaUpload, { onSelect: addLogo, allowedTypes: ['image'], render: function (mediaProps) { return el( Button, { variant: 'primary', onClick: mediaProps.open, }, label ); }, })); } function renderLogoCard(logo, index) { const cardKey = String(logo.id || 'logo') + '-' + String(index); return el( 'div', { className: 'logo-soup-editor__card', key: cardKey, }, [ el( 'div', { className: 'logo-soup-editor__thumb', key: 'thumb', }, el('img', { src: logo.url, alt: logo.alt || '', }) ), el(TextControl, { key: 'alt', label: __('Alt text', 'logo-soup'), value: logo.alt || '', onChange: function (value) { setAttributes({ logos: updateLogoAtIndex(logos, index, { id: logo.id, url: logo.url, alt: value, link: logo.link, }), }); }, }), el(TextControl, { key: 'link', label: __('Link URL', 'logo-soup'), value: logo.link || '', placeholder: 'https://example.com', onChange: function (value) { setAttributes({ logos: updateLogoAtIndex(logos, index, { id: logo.id, url: logo.url, alt: logo.alt, link: value, }), }); }, }), el( 'div', { className: 'logo-soup-editor__actions', key: 'actions', }, [ el( Button, { key: 'up', disabled: index === 0, onClick: function () { moveLogo(index, -1); }, }, __('Move Up', 'logo-soup') ), el( Button, { key: 'down', disabled: index === logos.length - 1, onClick: function () { moveLogo(index, 1); }, }, __('Move Down', 'logo-soup') ), el( Button, { key: 'remove', isDestructive: true, onClick: function () { removeLogo(index); }, }, __('Remove', 'logo-soup') ), ] ), ] ); } return el(Fragment, null, [ el( InspectorControls, { key: 'controls', }, el( PanelBody, { title: __('Display', 'logo-soup'), }, [ el(SelectControl, { key: 'layout', label: __('Layout', 'logo-soup'), value: layout, options: [ { label: __('Carousel', 'logo-soup'), value: 'carousel' }, { label: __('Grid', 'logo-soup'), value: 'grid' }, ], onChange: function (value) { setAttributes({ layout: value }); }, }), el(ToggleControl, { key: 'grayscale', label: __('Use grayscale styling', 'logo-soup'), checked: grayscale, onChange: function (value) { setAttributes({ grayscale: value }); }, }), el(ToggleControl, { key: 'pauseOnHover', label: __('Pause carousel on hover', 'logo-soup'), checked: pauseOnHover, help: __('Applies to carousel layout only.', 'logo-soup'), onChange: function (value) { setAttributes({ pauseOnHover: value }); }, }), el(RangeControl, { key: 'speed', label: __('Carousel speed (seconds)', 'logo-soup'), value: speed, min: 8, max: 80, onChange: function (value) { setAttributes({ speed: value }); }, }), el(RangeControl, { key: 'baseSize', label: __('Base size', 'logo-soup'), value: baseSize, min: 16, max: 160, onChange: function (value) { setAttributes({ baseSize: value }); }, }), el(RangeControl, { key: 'scaleFactor', label: __('Scale factor', 'logo-soup'), value: scaleFactor, min: 0.1, max: 2, step: 0.1, onChange: function (value) { setAttributes({ scaleFactor: value }); }, }), el(ToggleControl, { key: 'densityAware', label: __('Density aware', 'logo-soup'), checked: densityAware, onChange: function (value) { setAttributes({ densityAware: value }); }, }), el(RangeControl, { key: 'densityFactor', label: __('Density factor', 'logo-soup'), value: densityFactor, min: 0, max: 1, step: 0.1, onChange: function (value) { setAttributes({ densityFactor: value }); }, }), el(ToggleControl, { key: 'cropToContent', label: __('Crop to content', 'logo-soup'), checked: cropToContent, onChange: function (value) { setAttributes({ cropToContent: value }); }, }), el(SelectControl, { key: 'alignBy', label: __('Align by', 'logo-soup'), value: alignBy, options: [ { label: __('Bounds', 'logo-soup'), value: 'bounds' }, { label: __('Visual center', 'logo-soup'), value: 'visual-center', }, { label: __('Visual center X', 'logo-soup'), value: 'visual-center-x', }, { label: __('Visual center Y', 'logo-soup'), value: 'visual-center-y', }, ], onChange: function (value) { setAttributes({ alignBy: value }); }, }), ] ) ), el( 'div', blockProps, logos.length === 0 ? el( Placeholder, { label: __('Logo Soup', 'logo-soup'), instructions: __( 'Upload a set of logos and optional links.', 'logo-soup' ), }, renderMediaButton(__('Add Logo', 'logo-soup')) ) : el( 'div', { className: 'logo-soup-editor__preview layout-' + layout + (grayscale ? ' is-grayscale' : '') + (cropToContent ? ' crop-to-content' : '') + (densityAware ? ' is-density-aware' : '') + ' align-by-' + alignBy, style: { '--logo-soup-base-size': String(baseSize) + 'px', '--logo-soup-scale-factor': String(scaleFactor), '--logo-soup-density-factor': String(densityFactor), }, }, [ el( 'div', { className: 'logo-soup-editor__toolbar', key: 'toolbar', }, renderMediaButton(__('Add Another Logo', 'logo-soup')) ), el( 'div', { className: 'logo-soup-editor__list', key: 'list', }, logos.map(renderLogoCard) ), ] ) ), ]); }, save: function () { return null; }, }); }(window.wp.blocks, window.wp.blockEditor, window.wp.components, window.wp.element, window.wp.i18n));