Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
919f3c9
initial commit
Liviu-p Nov 12, 2025
ff6a5a5
code cleanup, add default values dynamically to web components, impro…
Liviu-p Jan 6, 2026
68f7296
master conflicts fix
Liviu-p Jan 6, 2026
1aab5d9
eslint fixes, add extra checks for empty or null values in typography…
Liviu-p Jan 9, 2026
bb34d15
master conflict fixes
Liviu-p Jan 9, 2026
1950156
eslint fixes
Liviu-p Jan 12, 2026
20a4d31
make private few properties from web component classes, code cleanup
Liviu-p Jan 14, 2026
6c0baea
Merge branch 'master' into feature/make-style-elements-accesible-as-w…
Liviu-p Jan 14, 2026
bd33d21
Merge branch 'master' into feature/make-style-elements-accesible-as-w…
Crabcyborg Jan 21, 2026
7858bfb
eslint fixes, slider steps update
Liviu-p Jan 21, 2026
c108430
Merge branch 'feature/make-style-elements-accesible-as-web-components…
Liviu-p Jan 21, 2026
943842e
QA fixes and revisions
Liviu-p Feb 2, 2026
f9a1576
fix master merge conflicts
Liviu-p Feb 2, 2026
d78aff3
fix js deepsource reported issues and phpstan
Liviu-p Feb 4, 2026
98b8161
phpstan fix
Liviu-p Feb 4, 2026
ce798e3
deepscan js fixes
Liviu-p Feb 5, 2026
11fa250
make more functions static in frmSliderComponent
Liviu-p Feb 5, 2026
b3c34ee
rever changes to classes/controllers/FrmAppController from commit ce7…
Liviu-p Feb 5, 2026
506c697
Merge branch 'master' into feature/make-style-elements-accesible-as-w…
Crabcyborg Feb 9, 2026
6678674
add pro version that includes pro web components, fix typography bord…
Liviu-p Feb 10, 2026
d66b178
accessibility improvement under frm web components
Liviu-p Feb 10, 2026
b92c60c
extra check if pro installed when getting the js dependencies
Liviu-p Feb 10, 2026
4fc9444
phpcs fix and js lint fix
Liviu-p Feb 10, 2026
72c0950
Run npm build
Crabcyborg Feb 11, 2026
95e7eb1
Merge branch 'master' into feature/make-style-elements-accesible-as-w…
Crabcyborg Feb 11, 2026
d9397cf
build js
Liviu-p Feb 11, 2026
a3cde3d
merge conflcits
Liviu-p Feb 11, 2026
d0a90c2
FrmCssScopeHelper - support the direct-scoped selectors
Liviu-p Feb 12, 2026
671e0be
fix failing analysis
Liviu-p Feb 12, 2026
975cec6
phpcs fix
Liviu-p Feb 12, 2026
450787c
phpcs
Liviu-p Feb 12, 2026
86d8c06
border radius web component - strip possible unit string from input v…
Liviu-p Feb 12, 2026
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
25 changes: 20 additions & 5 deletions classes/controllers/FrmAppController.php
Original file line number Diff line number Diff line change
Expand Up @@ -691,11 +691,12 @@ private static function trigger_page_load_hooks() {
* @return void
*/
public static function admin_js() {
$plugin_url = FrmAppHelper::plugin_url();
$version = FrmAppHelper::plugin_version();
$plugin_url = FrmAppHelper::plugin_url();
$version = FrmAppHelper::plugin_version();
$is_pro_min_v6_28 = FrmAppHelper::pro_is_installed() && FrmAppHelper::meets_min_pro_version( '6.28' );
$frm_components_dependencies = $is_pro_min_v6_28 ? array( 'formidable_admin', 'formidable-pro-web-components' ) : array( 'formidable_admin' );

Comment thread
Liviu-p marked this conversation as resolved.
FrmAppHelper::load_admin_wide_js();

// Register component assets early to ensure they can be enqueued later in controllers.
wp_register_style( 'formidable-animations', $plugin_url . '/css/admin/animations.css', array(), $version );

Expand All @@ -721,8 +722,7 @@ public static function admin_js() {
);
wp_register_script( 'formidable_settings', $plugin_url . '/js/admin/settings.js', array(), $version, true );
wp_localize_script( 'formidable_settings', 'frmSettings', $settings_js_vars );

wp_register_script( 'formidable-web-components', $plugin_url . '/js/formidable-web-components.js', array( 'formidable_admin' ), $version, true );
wp_register_script( 'formidable-web-components', $plugin_url . '/js/formidable-web-components.js', $frm_components_dependencies, $version, true );
Comment thread
Liviu-p marked this conversation as resolved.

if ( self::should_show_floating_links() ) {
self::enqueue_floating_links( $plugin_url, $version );
Expand Down Expand Up @@ -1688,4 +1688,19 @@ public static function small_screen_proceed() {
update_user_option( get_current_user_id(), 'frm_ignore_small_screen_warning', true );
wp_send_json_success();
}

/**
* Enqueue the components scripts.
*
* @since x.x
*
* @return void
*/
public static function enqueue_components_scripts() {
if ( is_callable( array( 'FrmProFormsController', 'enqueue_pro_web_components_script' ) ) ) {
FrmProFormsController::enqueue_pro_web_components_script();
}
Comment thread
Liviu-p marked this conversation as resolved.

wp_enqueue_script( 'formidable-web-components' );
}
Comment thread
Liviu-p marked this conversation as resolved.
}
140 changes: 119 additions & 21 deletions classes/helpers/FrmCssScopeHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public function nest( $css, $class_name ) {
if ( false === $brace_pos ) {
$buffer .= $char;
++$i;

continue;
}

Expand All @@ -51,6 +52,7 @@ public function nest( $css, $class_name ) {

$i = $closing_brace + 1;
$buffer = '';

continue;
}//end if

Expand All @@ -63,15 +65,7 @@ public function nest( $css, $class_name ) {
$declarations = $this->preserve_declaration_formatting( $declarations );

if ( '' !== $selector && '' !== trim( $declarations ) ) {
// Handle multiple selectors
$selectors = array_map( 'trim', explode( ',', $selector ) );
$prefixed_selectors = array();

foreach ( $selectors as $single_selector ) {
if ( '' !== $single_selector ) {
$prefixed_selectors[] = '.' . $class_name . ' ' . $single_selector;
}
}
$prefixed_selectors = $this->prefix_selectors( $selector, $class_name );

if ( $prefixed_selectors ) {
$output[] = "\n" . implode( ',' . "\n", $prefixed_selectors ) . ' {' . $declarations . '}' . "\n";
Expand All @@ -80,6 +74,7 @@ public function nest( $css, $class_name ) {

$i = $closing_brace + 1;
$buffer = '';

continue;
}//end if

Expand Down Expand Up @@ -134,6 +129,7 @@ public function unnest( $css, $class_name ) {

$i = $closing_brace + 1;
$buffer = '';

continue;
}//end if

Expand All @@ -146,18 +142,7 @@ public function unnest( $css, $class_name ) {
$declarations = $this->preserve_declaration_formatting( $declarations );

if ( '' !== $selector && '' !== trim( $declarations ) ) {
// Handle multiple selectors
$selectors = array_filter(
array_map( 'trim', explode( ',', $selector ) ),
function ( $s ) {
return '' !== $s;
}
);
$unprefixed_selectors = array();

foreach ( $selectors as $single_selector ) {
$unprefixed_selectors[] = str_starts_with( $single_selector, $prefix ) ? trim( substr( $single_selector, $prefix_length ) ) : $single_selector;
}
$unprefixed_selectors = $this->unprefix_selectors( $selector, $class_name, $prefix, $prefix_length );

if ( $unprefixed_selectors ) {
$output[] = "\n" . implode( ',' . "\n", $unprefixed_selectors ) . ' {' . $declarations . '}' . "\n";
Expand All @@ -166,12 +151,14 @@ function ( $s ) {

$i = $closing_brace + 1;
$buffer = '';

continue;
}//end if

$buffer .= $char;
++$i;
}//end while

return implode( '', $output );
}

Expand Down Expand Up @@ -211,6 +198,116 @@ private function preserve_declaration_formatting( $declarations ) {
return ' ' . $declarations . ' ';
}

/**
* Build the list of prefixed selectors for a given selector string.
* Generates both descendant (.scope selector) and direct (selector.scope) forms.
*
* @param string $selector The comma-separated selector string.
* @param string $class_name The scope class name.
*
* @return array The list of prefixed selectors.
*/
private function prefix_selectors( $selector, $class_name ) {
$selectors = array_map( 'trim', explode( ',', $selector ) );
$prefixed_selectors = array();

foreach ( $selectors as $single_selector ) {
if ( '' === $single_selector ) {
continue;
}

$prefixed_selectors[] = '.' . $class_name . ' ' . $single_selector;
$direct = $this->add_direct_scope( $single_selector, $class_name );

if ( null !== $direct ) {
$prefixed_selectors[] = $direct;
}
}

return $prefixed_selectors;
}

/**
* Build the list of unprefixed selectors for a given selector string.
* Handles both descendant (.scope selector) and direct (selector.scope) forms.
*
* @param string $selector The comma-separated selector string.
* @param string $class_name The scope class name.
* @param string $prefix The descendant prefix string (.class_name followed by space).
* @param int $prefix_length The length of the descendant prefix.
*
* @return array The list of unprefixed selectors (deduplicated).
*/
private function unprefix_selectors( $selector, $class_name, $prefix, $prefix_length ) {
$selectors = array_filter(
array_map( 'trim', explode( ',', $selector ) ),
function ( $s ) {
return '' !== $s;
}
);
$unprefixed_selectors = array();

foreach ( $selectors as $single_selector ) {
if ( str_starts_with( $single_selector, $prefix ) ) {
$unprefixed_selectors[] = trim( substr( $single_selector, $prefix_length ) );
} else {
$unprefixed_selectors[] = $this->remove_direct_scope( $single_selector, $class_name ) ?? $single_selector;
}
}

return array_values( array_unique( $unprefixed_selectors ) );
}

/**
* Add the scope class directly to the first segment of a selector.
* For example, "h2" becomes "h2.scope" and ".foo .bar" becomes ".foo.scope .bar".
*
* @param string $selector The CSS selector.
* @param string $class_name The scope class name.
*
* @return string|null The direct-scoped selector, or null if not applicable.
*/
private function add_direct_scope( $selector, $class_name ) {
$parts = preg_split( '/(\s+)/', $selector, 2, PREG_SPLIT_DELIM_CAPTURE );
$first = $parts[0];

// Don't add direct scope to selectors starting with combinators or universal selector.
if ( preg_match( '/^[>+~*]/', $first ) ) {
return null;
}

$rest = '';

if ( count( $parts ) > 1 ) {
$rest = $parts[1] . $parts[2];
}

return $first . '.' . $class_name . $rest;
}

/**
* Remove the scope class from the first segment of a direct-scoped selector.
* For example, "h2.scope" becomes "h2" and ".foo.scope .bar" becomes ".foo .bar".
*
* @param string $selector The CSS selector.
* @param string $class_name The scope class name.
*
* @return string|null The unscoped selector, or null if the scope was not found.
*/
private function remove_direct_scope( $selector, $class_name ) {
$scope_pattern = '/\.' . preg_quote( $class_name, '/' ) . '(?![a-zA-Z0-9_-])/';
$parts = preg_split( '/(\s+)/', $selector, 2, PREG_SPLIT_DELIM_CAPTURE );

if ( false === $parts || ! preg_match( $scope_pattern, $parts[0] ) ) {
return null;
}

$parts[0] = preg_replace( $scope_pattern, '', $parts[0], 1 );
$result = trim( implode( '', $parts ) );

return '' !== $result ? $result : null;
}

/**
* Find the matching brace in the CSS.
*
Expand All @@ -236,6 +333,7 @@ private function find_matching_brace( $css, $open_pos ) {
} elseif ( $char === $string_char ) {
$in_string = false;
}

continue;
}

Expand Down
2 changes: 1 addition & 1 deletion classes/views/styles/components/templates/colorpicker.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
?>
<span class="frm-style-component frm-colorpicker" tabindex="0">
<input type="text" <?php echo esc_attr( $field_name ); ?> id="<?php echo esc_attr( $component['id'] ); ?>" class="hex" value="<?php echo esc_attr( $field_value ); ?>" <?php do_action( 'frm_style_settings_input_atts', $component['action_slug'] ); ?>/>
</span>
</span>
Loading
Loading