Files
Logo-Soup/blocks/logo-soup/build/index.js
T
2026-04-13 20:06:32 -05:00

393 lines
12 KiB
JavaScript

(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));