Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
596 changes: 38 additions & 558 deletions assets/admin/settings.css

Large diffs are not rendered by default.

309 changes: 288 additions & 21 deletions assets/carousel/frontblocks-advanced-option.js

Large diffs are not rendered by default.

532 changes: 394 additions & 138 deletions assets/carousel/frontblocks-advanced-option.jsx

Large diffs are not rendered by default.

28 changes: 28 additions & 0 deletions assets/carousel/frontblocks-carousel-editor.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* Editor-only carousel preview styles */

/* Hide the native scrollbar on the carousel grid element */
.frbl-carousel-noscrollbar {
scrollbar-width: none;
-ms-overflow-style: none;
}
.frbl-carousel-noscrollbar::-webkit-scrollbar {
display: none;
}

/* Navigation arrows – rendered in the outer document body as position:fixed */
.frbl-editor-arrow {
width: 32px;
height: 32px;
border-radius: 50%;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
padding: 0;
transition: opacity 0.2s;
}

.frbl-editor-arrow:hover {
opacity: 0.8;
}
56 changes: 32 additions & 24 deletions assets/carousel/frontblocks-carousel.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
width: 100%;
max-width: 100%;
box-sizing: border-box;
overflow: hidden;
overflow: visible;
margin: 0;
padding: 0;
}
Expand Down Expand Up @@ -123,45 +123,41 @@
}

.frontblocks .glide__bullets {
position: absolute;
z-index: 2;
bottom: -1em;
left: 50%;
display: inline-flex;
display: flex;
justify-content: center;
list-style: none;
transform: translateX(-50%);
gap: 2px;
margin: 0.75em 0 0;
padding: 0;
}

.frontblocks .glide__bullet {
background-color: rgba(255, 255, 255, 0.5);
width: 14px;
height: 14px;
padding: 10px;
box-sizing: content-box;
width: 10px;
height: 10px;
padding: 0;
border-radius: 50%;
border: 2px solid transparent;
background-clip: content-box;
transition: all 300ms ease-in-out;
border: none;
background-color: var(--frbl-bullet-bg, rgba(0, 0, 0, 0.25));
cursor: pointer;
line-height: 0;
margin: 0;
transition: background-color 300ms ease-in-out, transform 300ms ease-in-out;
margin: 0 2px;
flex-shrink: 0;
}

.frontblocks .glide__bullet:focus {
outline: 2px solid white;
outline: 2px solid var(--frbl-bullet-color, rgba(0, 0, 0, 0.8));
outline-offset: 2px;
}

.frontblocks .glide__bullet:hover,
.frontblocks .glide__bullet:focus {
border: 2px solid white;
background-color: rgba(255, 255, 255, 0.5);
background-clip: content-box;
.frontblocks .glide__bullet:hover {
background-color: var(--frbl-bullet-color, rgba(0, 0, 0, 0.8));
transform: scale(1.2);
}

.frontblocks .glide__bullet--active {
background-color: white;
background-clip: content-box;
background-color: var(--frbl-bullet-color, rgba(0, 0, 0, 0.8));
transform: scale(1.2);
}

.frontblocks.glide--swipeable {
Expand Down Expand Up @@ -262,3 +258,15 @@
min-width: 0;
flex-shrink: 0;
}

/**
* GenerateBlocks (and any other plugin) may inject column-gap via generated
* utility classes on the carousel slides container. Glide manages its own
* spacing through margin-right on each slide, so any external column-gap
* breaks the width calculation and must be zeroed out.
*/
.frontblocks-carousel,
.frontblocks .glide__slides {
column-gap: 0 !important;
gap: 0 !important;
}
17 changes: 8 additions & 9 deletions assets/carousel/frontblocks-carousel.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,20 +72,19 @@ window.addEventListener('load', function (event) {
bullet.classList.add('glide__bullet');
bullet.setAttribute('data-glide-dir', '=' + i);
bullet.setAttribute('aria-label', 'Go to slide ' + (i + 1));
bullet.style.backgroundColor = carouselbuttonsBackgroundColor;
bullets.appendChild(bullet);
}

wrapperParent.appendChild(bullets);

// Add custom CSS for active bullet color
const style = document.createElement('style');
style.textContent = `
.frontblocks .glide__bullet.glide__bullet--active {
background-color: ${carouselbuttonsColor};
}
`;
document.head.appendChild(style);
// Set bullet colors via CSS custom properties on the wrapper.
// This avoids specificity conflicts with the stylesheet.
if (carouselbuttonsColor) {
wrapperParent.style.setProperty('--frbl-bullet-color', carouselbuttonsColor);
}
if (carouselbuttonsBackgroundColor && carouselbuttonsBackgroundColor !== 'transparent') {
wrapperParent.style.setProperty('--frbl-bullet-bg', carouselbuttonsBackgroundColor);
}
}

if (carouselbuttons == 'arrows') {
Expand Down
123 changes: 22 additions & 101 deletions assets/shape-animations/frontblocks-shape-animation-option.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
var _wp$components = wp.components,
PanelBody = _wp$components.PanelBody,
ToggleControl = _wp$components.ToggleControl,
TextareaControl = _wp$components.TextareaControl,
Button = _wp$components.Button,
Notice = _wp$components.Notice,
FormFileUpload = _wp$components.FormFileUpload;
Notice = _wp$components.Notice;

/**
* Add custom SVG animation controls to GenerateBlocks Shape block.
Expand All @@ -45,14 +45,6 @@ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
_useState4 = _slicedToArray(_useState3, 2),
jsonPreview = _useState4[0],
setJsonPreview = _useState4[1];
var _useState5 = useState(''),
_useState6 = _slicedToArray(_useState5, 2),
fileName = _useState6[0],
setFileName = _useState6[1];
var _useState7 = useState(0),
_useState8 = _slicedToArray(_useState7, 2),
fileInputKey = _useState8[0],
setFileInputKey = _useState8[1];

// Detect if JSON is Lottie format.
var isLottieJson = function isLottieJson(parsed) {
Expand Down Expand Up @@ -100,46 +92,19 @@ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
}
};

// Handle file upload.
var handleFileUpload = function handleFileUpload(event) {
var file = event.target.files[0];
if (!file) {
return;
}

// Check if it's a JSON file.
if (!file.name.endsWith('.json')) {
setJsonError(__('Please select a JSON file', 'frontblocks'));
setFileInputKey(function(prev) { return prev + 1; });
return;
// Handle JSON change.
var handleJsonChange = function handleJsonChange(value) {
setAttributes({
frblCustomSvgAnimationJson: value
});
if (value.trim()) {
validateJson(value);
} else {
setJsonError('');
setJsonPreview(null);
}

setFileName(file.name);

// Read file content.
var reader = new FileReader();
reader.onload = function(e) {
var content = e.target.result;
setAttributes({ frblCustomSvgAnimationJson: content });
validateJson(content);
setFileInputKey(function(prev) { return prev + 1; });
};
reader.onerror = function() {
setJsonError(__('Error reading file', 'frontblocks'));
setFileInputKey(function(prev) { return prev + 1; });
};
reader.readAsText(file);
};

// Clear imported JSON.
var handleClear = function handleClear() {
setAttributes({ frblCustomSvgAnimationJson: '' });
setJsonError('');
setJsonPreview(null);
setFileName('');
setFileInputKey(function(prev) { return prev + 1; });
};

// Example JSON template.
var exampleJson = JSON.stringify({
"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" width=\"48\" height=\"48\" fill=\"currentColor\"><path d=\"M12 2L2 7v10c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V7l-10-5z\"/></svg>",
Expand All @@ -152,20 +117,6 @@ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
"trigger": "load"
}
}, null, 2);

// Download example JSON.
var handleDownloadExample = function handleDownloadExample() {
var blob = new Blob([exampleJson], { type: 'application/json' });
var url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = url;
a.download = 'example-animation.json';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
};

return wp.element.createElement(Fragment, {}, wp.element.createElement(BlockEdit, props), wp.element.createElement(InspectorControls, {}, wp.element.createElement(PanelBody, {
title: __('FrontBlocks Custom SVG Animation', 'frontblocks'),
initialOpen: false
Expand All @@ -181,36 +132,16 @@ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
}), frblCustomSvgAnimationEnabled && wp.element.createElement(Fragment, {}, wp.element.createElement('p', {
style: {
fontSize: '12px',
marginBottom: '12px',
marginBottom: '8px',
color: '#757575'
}
}, __('Import a JSON file with your animation configuration:', 'frontblocks')), wp.element.createElement(FormFileUpload, {
key: fileInputKey,
accept: '.json',
onChange: handleFileUpload,
render: function(ref) {
return wp.element.createElement(Button, {
isSecondary: true,
onClick: ref.openFileDialog,
style: { marginBottom: '8px', width: '100%' }
}, fileName ? __('Change JSON file', 'frontblocks') : __('Import JSON file', 'frontblocks'));
}
}), fileName && wp.element.createElement('div', {
style: {
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: '12px',
padding: '8px',
background: '#f6f7f7',
borderRadius: '4px',
fontSize: '12px'
}
}, wp.element.createElement('span', {}, '📄 ' + fileName), wp.element.createElement(Button, {
isSmall: true,
isDestructive: true,
onClick: handleClear
}, __('Clear', 'frontblocks'))), jsonError && wp.element.createElement(Notice, {
}, __('Paste your JSON configuration below:', 'frontblocks')), wp.element.createElement(TextareaControl, {
label: __('JSON Configuration', 'frontblocks'),
value: frblCustomSvgAnimationJson,
onChange: handleJsonChange,
rows: 10,
help: __('JSON with svg and animation properties', 'frontblocks')
}), jsonError && wp.element.createElement(Notice, {
status: 'error',
isDismissible: false
}, jsonError), jsonPreview && wp.element.createElement(Notice, {
Expand All @@ -227,7 +158,7 @@ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
fontWeight: '600',
marginBottom: '8px'
}
}, __('📋 Download example JSON', 'frontblocks')), wp.element.createElement('pre', {
}, __('📋 Show example JSON', 'frontblocks')), wp.element.createElement('pre', {
style: {
background: '#f6f7f7',
padding: '12px',
Expand All @@ -237,23 +168,13 @@ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
maxHeight: '300px'
}
}, exampleJson), wp.element.createElement(Button, {
isSecondary: true,
isSmall: true,
onClick: handleDownloadExample,
style: {
marginTop: '8px',
marginRight: '8px'
}
}, __('Download example', 'frontblocks')), wp.element.createElement(Button, {
isSecondary: true,
isSmall: true,
onClick: function onClick() {
setAttributes({
frblCustomSvgAnimationJson: exampleJson
});
setFileName('example-animation.json');
validateJson(exampleJson);
setFileInputKey(function(prev) { return prev + 1; });
},
style: {
marginTop: '8px'
Expand Down
18 changes: 18 additions & 0 deletions includes/Frontend/Carousel.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,30 @@ public function __construct() {
*/
private function init_hooks() {
add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_block_editor_assets' ) );
add_action( 'enqueue_block_assets', array( $this, 'enqueue_block_canvas_assets' ) );
add_filter( 'render_block_generateblocks/grid', array( $this, 'add_custom_attributes_to_grid_block' ), 10, 2 );
add_filter( 'render_block_generateblocks/element', array( $this, 'add_custom_attributes_to_element_block' ), 10, 2 );
add_filter( 'render_block_core/group', array( $this, 'add_custom_attributes_to_core_group_block' ), 10, 2 );
add_action( 'init', array( $this, 'register_custom_attributes' ), 5 );
}

/**
* Enqueue carousel CSS in the editor canvas (iframe).
*
* @return void
*/
public function enqueue_block_canvas_assets() {
if ( ! is_admin() ) {
return;
}
wp_enqueue_style(
'frontblocks-carousel-editor',
FRBL_PLUGIN_URL . 'assets/carousel/frontblocks-carousel-editor.css',
array(),
FRBL_VERSION
);
}

/**
* Enqueue block editor assets.
*
Expand Down