393 lines
12 KiB
JavaScript
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));
|