Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
99 changes: 68 additions & 31 deletions my-scroll-block.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,59 +99,96 @@ function my_scroll_block_register_assets() {
return $block_content;
}
$attrs = $block['attrs'];
if ( isset( $attrs['animationType'] ) && 'none' !== $attrs['animationType'] ) {

$has_animation = isset( $attrs['animationType'] ) && 'none' !== $attrs['animationType'];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 This condition is crucial for determining whether to apply scroll animation or parallax effects. A brief comment explaining its purpose would enhance code clarity.

$parallax_enabled = isset( $attrs['parallaxEnabled'] ) && $attrs['parallaxEnabled'];

if ( $has_animation || $parallax_enabled ) {
if ( wp_style_is( 'my-scroll-block-style', 'registered' ) ) {
wp_enqueue_style( 'my-scroll-block-style' );
}
// No view script on frontend when relying on CSS scroll timelines.

// Also ensure outer wrapper receives classes and attributes if missing (covers dynamic blocks).
if ( is_string( $block_content ) && $block_content !== '' && strpos( $block_content, 'scroll-anim-block' ) === false ) {
$animation_type = sanitize_key( (string) $attrs['animationType'] );
$animation_range = isset( $attrs['animationRange'] ) ? sanitize_key( (string) $attrs['animationRange'] ) : 'default';

$add_classes = sprintf( 'scroll-anim-block scroll-anim-%s', strtolower( str_replace( ' ', '-', $animation_type ) ) );

// Build data attributes
$data_attrs = ' data-scroll-anim="1" data-anim-range="' . esc_attr( $animation_range ) . '"';

// Add custom range values if using custom range
if ( $animation_range === 'custom' ) {
if ( isset( $attrs['animationEntryStart'] ) ) {
$data_attrs .= ' data-entry-start="' . absint( $attrs['animationEntryStart'] ) . '"';
}
if ( isset( $attrs['animationEntryEnd'] ) ) {
$data_attrs .= ' data-entry-end="' . absint( $attrs['animationEntryEnd'] ) . '"';
}
// Add exit range for in-out animations
if ( strpos( $animation_type, 'in-out' ) !== false ) {
if ( isset( $attrs['animationExitStart'] ) ) {
$data_attrs .= ' data-exit-start="' . absint( $attrs['animationExitStart'] ) . '"';
$needs_injection = is_string( $block_content ) && $block_content !== '';
$missing_anim = $has_animation && strpos( $block_content, 'scroll-anim-block' ) === false;
$missing_parallax = $parallax_enabled && strpos( $block_content, 'data-parallax' ) === false;

if ( $needs_injection && ( $missing_anim || $missing_parallax ) ) {
$add_classes = '';
$data_attrs = '';
$style_attr = '';

// Handle animation classes and data attributes
if ( $has_animation && $missing_anim ) {
$animation_type = sanitize_key( (string) $attrs['animationType'] );
$animation_range = isset( $attrs['animationRange'] ) ? sanitize_key( (string) $attrs['animationRange'] ) : 'default';

$add_classes = sprintf( 'scroll-anim-block scroll-anim-%s', strtolower( str_replace( ' ', '-', $animation_type ) ) );

// Build data attributes
$data_attrs = ' data-scroll-anim="1" data-anim-range="' . esc_attr( $animation_range ) . '"';

// Add custom range values if using custom range
if ( $animation_range === 'custom' ) {
if ( isset( $attrs['animationEntryStart'] ) ) {
$data_attrs .= ' data-entry-start="' . absint( $attrs['animationEntryStart'] ) . '"';
}
if ( isset( $attrs['animationEntryEnd'] ) ) {
$data_attrs .= ' data-entry-end="' . absint( $attrs['animationEntryEnd'] ) . '"';
}
if ( isset( $attrs['animationExitEnd'] ) ) {
$data_attrs .= ' data-exit-end="' . absint( $attrs['animationExitEnd'] ) . '"';
// Add exit range for in-out animations
if ( strpos( $animation_type, 'in-out' ) !== false ) {
if ( isset( $attrs['animationExitStart'] ) ) {
$data_attrs .= ' data-exit-start="' . absint( $attrs['animationExitStart'] ) . '"';
}
if ( isset( $attrs['animationExitEnd'] ) ) {
$data_attrs .= ' data-exit-end="' . absint( $attrs['animationExitEnd'] ) . '"';
}
}
}
}

// Handle parallax data attributes and styles
if ( $parallax_enabled && $missing_parallax ) {
$parallax_strength = isset( $attrs['parallaxStrength'] ) ? absint( $attrs['parallaxStrength'] ) : 50;
$data_attrs .= ' data-parallax="1" data-parallax-strength="' . $parallax_strength . '"';
$style_attr = '--parallax-strength: ' . $parallax_strength . 'px;';
}

// Inject into first element tag.
if ( preg_match( '/^\s*<([a-zA-Z0-9:-]+)([^>]*)>/', $block_content, $m, PREG_OFFSET_CAPTURE ) ) {
$full = $m[0][0];
$attrsStr = $m[2][0];
$updated = $attrsStr;

if ( preg_match( '/\sclass\s*=\s*"([^"]*)"/i', $attrsStr, $cm ) ) {
$newClass = trim( $cm[1] . ' ' . $add_classes );
$updated = preg_replace( '/\sclass\s*=\s*"([^"]*)"/i', ' class="' . esc_attr( $newClass ) . '"', $updated, 1 );
} else {
$updated .= ' class="' . esc_attr( $add_classes ) . '"';
// Add or merge classes
if ( $add_classes ) {
if ( preg_match( '/\sclass\s*=\s*"([^"]*)"/i', $attrsStr, $cm ) ) {
$newClass = trim( $cm[1] . ' ' . $add_classes );
$updated = preg_replace( '/\sclass\s*=\s*"([^"]*)"/i', ' class="' . esc_attr( $newClass ) . '"', $updated, 1 );
} else {
$updated .= ' class="' . esc_attr( $add_classes ) . '"';
}
}

if ( strpos( $updated, 'data-scroll-anim' ) === false ) {
// Add data attributes
if ( $data_attrs && strpos( $updated, 'data-scroll-anim' ) === false && strpos( $updated, 'data-parallax' ) === false ) {
$updated .= $data_attrs;
}

$newOpen = '<' . $m[1][0] . $updated . '>';
// Add or merge style attribute for parallax
if ( $style_attr ) {
if ( preg_match( '/\sstyle\s*=\s*"([^"]*)"/i', $attrsStr, $sm ) ) {
$existing_style = rtrim( $sm[1], '; ' );
$new_style = $existing_style . '; ' . $style_attr;
$updated = preg_replace( '/\sstyle\s*=\s*"([^"]*)"/i', ' style="' . esc_attr( $new_style ) . '"', $updated, 1 );
} else {
$updated .= ' style="' . esc_attr( $style_attr ) . '"';
}
}

$newOpen = '<' . $m[1][0] . $updated . '>';
$block_content = substr_replace( $block_content, $newOpen, $m[0][1], strlen( $full ) );
}
}
Expand Down
76 changes: 38 additions & 38 deletions playwright.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,54 +4,54 @@ import { defineConfig, devices } from '@playwright/test';
* @see https://playwright.dev/docs/test-configuration
*/
export default defineConfig({
testDir: './tests',
testDir: './tests',

/* Global setup to start WordPress Playground */
globalSetup: './tests/global-setup.ts',
globalTeardown: './tests/global-teardown.ts',
/* Global setup to start WordPress Playground */
globalSetup: './tests/global-setup.ts',
globalTeardown: './tests/global-teardown.ts',

/* Run tests in files in parallel */
fullyParallel: true,
/* Run tests in files in parallel */
fullyParallel: true,

/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,

/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,

/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,

/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',

/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: 'http://127.0.0.1:9400',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: 'http://127.0.0.1:9400',

/* Maximum time for each action (e.g. click, fill, etc.) */
actionTimeout: 5000,
/* Maximum time for each action (e.g. click, fill, etc.) */
actionTimeout: 5000,

/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
},
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
},

/* Maximum time one test can run for */
timeout: 30000,
/* Maximum time one test can run for */
timeout: 30000,

/* Configure projects for Chromium only */
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],
/* Configure projects for Chromium only */
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],

/* Run your local dev server before starting the tests */
// webServer: {
// command: 'npm run start',
// url: 'http://127.0.0.1:9400',
// reuseExistingServer: !process.env.CI,
// },
/* Run your local dev server before starting the tests */
// webServer: {
// command: 'npm run start',
// url: 'http://127.0.0.1:9400',
// reuseExistingServer: !process.env.CI,
// },
});
48 changes: 24 additions & 24 deletions src/editor.css
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
/* Animation indicator icon */
.scroll-anim-indicator-wrapper {
position: relative;
position: relative;

.scroll-anim-indicator {
position: absolute;
top: 0;
left: 0;
background: #ff69b4;
border-radius: 100%;
aspect-ratio: 1;
width: 24px;
padding: 5px;
display: flex;
justify-content: center;
align-items: center;
transform: translate(-50%, -50%);
opacity: 0.3;
transition: opacity 0.2s ease;
.scroll-anim-indicator {
position: absolute;
top: 0;
left: 0;
background: #ff69b4;
border-radius: 100%;
aspect-ratio: 1;
width: 24px;
padding: 5px;
display: flex;
justify-content: center;
align-items: center;
transform: translate(-50%, -50%);
opacity: 0.3;
transition: opacity 0.2s ease;

&:hover {
opacity: 1;
}
&:hover {
opacity: 1;
}

svg {
width: 12px;
height: 12px;
}
}
svg {
width: 12px;
height: 12px;
}
}
}
Loading
Loading