diff --git a/Gruntfile.js b/Gruntfile.js
index cf9b2285a..6236889cc 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -28,7 +28,8 @@ module.exports = function( grunt) {
// one to one
front: {
files: {
- '<%= dirs.css %>/frontend-forms.css': '<%= dirs.less %>/frontend-forms.less'
+ '<%= dirs.css %>/frontend-forms.css': '<%= dirs.less %>/frontend-forms.less',
+ '<%= dirs.css %>/elementor-frontend-forms.css': '<%= dirs.less %>/elementor-frontend-forms.less'
}
},
diff --git a/assets/css/elementor-frontend-forms.css b/assets/css/elementor-frontend-forms.css
new file mode 100644
index 000000000..c46f8e910
--- /dev/null
+++ b/assets/css/elementor-frontend-forms.css
@@ -0,0 +1,197 @@
+/**
+ * DESCRIPTION: Elementor-specific WPUF frontend form styles
+ *
+ * This file contains form styles scoped to the Elementor widget wrapper
+ * to avoid conflicts with the theme and provide better Elementor integration.
+ *
+ * @package WPUF\Elementor
+ */
+.wpuf-elementor-widget-wrapper {
+ --wpuf-border-color: #dadbdd;
+ --wpuf-border-radius: 7px;
+ --wpuf-text-color: #606266;
+ --wpuf-primary-color: #1a7efb;
+ --wpuf-danger-color: #F56C6C;
+}
+.wpuf-elementor-widget-wrapper .wpuf-fields input[type="text"],
+.wpuf-elementor-widget-wrapper .wpuf-fields input[type="email"],
+.wpuf-elementor-widget-wrapper .wpuf-fields input[type="url"],
+.wpuf-elementor-widget-wrapper .wpuf-fields input[type="password"],
+.wpuf-elementor-widget-wrapper .wpuf-fields input[type="number"],
+.wpuf-elementor-widget-wrapper .wpuf-fields input[type="tel"],
+.wpuf-elementor-widget-wrapper .wpuf-fields textarea,
+.wpuf-elementor-widget-wrapper .wpuf-fields select {
+ padding: 12px 15px;
+ color: var(--wpuf-text-color);
+ border: 1px solid var(--wpuf-border-color);
+ border-radius: var(--wpuf-border-radius);
+ transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+ margin-bottom: 0;
+ width: 100%;
+}
+.wpuf-elementor-widget-wrapper .wpuf-fields input[type="text"]:focus,
+.wpuf-elementor-widget-wrapper .wpuf-fields input[type="email"]:focus,
+.wpuf-elementor-widget-wrapper .wpuf-fields input[type="url"]:focus,
+.wpuf-elementor-widget-wrapper .wpuf-fields input[type="password"]:focus,
+.wpuf-elementor-widget-wrapper .wpuf-fields input[type="number"]:focus,
+.wpuf-elementor-widget-wrapper .wpuf-fields input[type="tel"]:focus,
+.wpuf-elementor-widget-wrapper .wpuf-fields textarea:focus,
+.wpuf-elementor-widget-wrapper .wpuf-fields select:focus {
+ color: var(--wpuf-text-color);
+ background-color: #fff;
+ border-color: var(--wpuf-primary-color);
+ outline: none;
+ box-shadow: 0 0 0 2px rgba(26, 126, 251, 0.1);
+}
+.wpuf-elementor-widget-wrapper .wpuf-fields .wpuf-radio-block,
+.wpuf-elementor-widget-wrapper .wpuf-fields .wpuf-checkbox-block {
+ display: flex;
+ align-items: center;
+ margin-bottom: 6px;
+}
+.wpuf-elementor-widget-wrapper ul.wpuf-form {
+ list-style: none;
+}
+.wpuf-elementor-widget-wrapper ul.wpuf-form li:not(:first-child) {
+ margin-top: 2rem;
+}
+.wpuf-elementor-widget-wrapper ul.wpuf-form li.wpuf-el .wpuf-label {
+ margin-bottom: 1rem;
+}
+.wpuf-elementor-widget-wrapper[data-align="left"] {
+ margin: 0 auto 0 0;
+}
+.wpuf-elementor-widget-wrapper[data-align="center"] {
+ margin: 0 auto;
+}
+.wpuf-elementor-widget-wrapper[data-align="right"] {
+ margin: 0 0 0 auto;
+}
+.wpuf-elementor-widget-wrapper.wpuf-elementor-submit-full .wpuf-submit .wpuf-submit-button {
+ width: 100%;
+ display: block;
+}
+.wpuf-elementor-widget-wrapper.wpuf-elementor-upload-full .wpuf-attachment-upload-filelist .file-selector {
+ width: 100%;
+ display: block;
+}
+.wpuf-elementor-widget-wrapper.wpuf-elementor-hide-labels .wpuf-label {
+ display: none !important;
+}
+.wpuf-elementor-widget-wrapper.wpuf-elementor-hide-errors .wpuf-error,
+.wpuf-elementor-widget-wrapper.wpuf-elementor-hide-errors .error {
+ display: none;
+}
+.wpuf-elementor-widget-wrapper.wpuf-elementor-hide-placeholder input::-webkit-input-placeholder,
+.wpuf-elementor-widget-wrapper.wpuf-elementor-hide-placeholder textarea::-webkit-input-placeholder {
+ opacity: 0;
+ visibility: hidden;
+}
+.wpuf-elementor-widget-wrapper.wpuf-elementor-hide-placeholder input::-moz-placeholder,
+.wpuf-elementor-widget-wrapper.wpuf-elementor-hide-placeholder textarea::-moz-placeholder {
+ opacity: 0;
+ visibility: hidden;
+}
+.wpuf-elementor-widget-wrapper.wpuf-elementor-hide-placeholder input:-moz-placeholder,
+.wpuf-elementor-widget-wrapper.wpuf-elementor-hide-placeholder textarea:-moz-placeholder {
+ opacity: 0;
+ visibility: hidden;
+}
+.wpuf-elementor-widget-wrapper.wpuf-elementor-hide-placeholder input:-ms-input-placeholder,
+.wpuf-elementor-widget-wrapper.wpuf-elementor-hide-placeholder textarea:-ms-input-placeholder {
+ opacity: 0;
+ visibility: hidden;
+}
+.wpuf-elementor-widget-wrapper.wpuf-elementor-hide-placeholder input::-ms-input-placeholder,
+.wpuf-elementor-widget-wrapper.wpuf-elementor-hide-placeholder textarea::-ms-input-placeholder {
+ opacity: 0;
+ visibility: hidden;
+}
+.wpuf-elementor-widget-wrapper.wpuf-elementor-custom-radio-checkbox input[type="checkbox"],
+.wpuf-elementor-widget-wrapper.wpuf-elementor-custom-radio-checkbox input[type="radio"] {
+ outline: none;
+ min-width: 1px;
+ width: 15px;
+ height: 15px;
+ background: #ddd;
+ padding: 3px;
+}
+.wpuf-elementor-widget-wrapper.wpuf-elementor-custom-radio-checkbox input[type="radio"] {
+ border-radius: 50%;
+}
+.wpuf-elementor-widget-wrapper.wpuf-elementor-submit-center .wpuf-submit {
+ text-align: center;
+}
+.wpuf-elementor-widget-wrapper.wpuf-elementor-submit-center .wpuf-submit .wpuf-submit-button {
+ margin: 0 auto;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+}
+.wpuf-elementor-widget-wrapper.wpuf-elementor-submit-right .wpuf-submit {
+ text-align: right;
+}
+.wpuf-elementor-widget-wrapper.wpuf-elementor-submit-left .wpuf-submit {
+ text-align: left;
+}
+.wpuf-elementor-widget-wrapper .wpuf-math-captcha .captcha {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ flex-wrap: wrap;
+}
+.wpuf-elementor-widget-wrapper .wpuf-math-captcha .captcha .refresh {
+ cursor: pointer;
+ transition: opacity 0.2s ease;
+}
+.wpuf-elementor-widget-wrapper .wpuf-math-captcha .captcha .refresh:hover {
+ opacity: 0.7;
+}
+.wpuf-elementor-widget-wrapper .wpuf-math-captcha .captcha .refresh svg {
+ display: block;
+}
+.wpuf-elementor-widget-wrapper .wpuf-math-captcha .captcha .captcha-number-area .captcha-number {
+ display: flex;
+ align-items: center;
+ gap: 5px;
+ margin: 0;
+ font-size: 16px;
+ font-weight: 500;
+ color: var(--wpuf-text-color);
+}
+.wpuf-elementor-widget-wrapper .wpuf-math-captcha .captcha .captcha-equal {
+ font-size: 18px;
+ font-weight: 600;
+ color: var(--wpuf-text-color);
+}
+.wpuf-elementor-widget-wrapper .wpuf-math-captcha .captcha .wpuf-captcha-input-wrapper {
+ flex: 1;
+ min-width: 80px;
+ position: relative;
+}
+.wpuf-elementor-widget-wrapper .wpuf-math-captcha .captcha .wpuf-captcha-input-wrapper .wpuf-captcha-input {
+ padding: 11px 15px;
+ color: var(--wpuf-text-color);
+ border: 1px solid var(--wpuf-border-color);
+ border-radius: var(--wpuf-border-radius);
+ transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+ margin-bottom: 0;
+ width: 100%;
+ font-family: -apple-system, system-ui, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
+}
+.wpuf-elementor-widget-wrapper .wpuf-math-captcha .captcha .wpuf-captcha-input-wrapper .wpuf-captcha-input:focus {
+ color: var(--wpuf-text-color);
+ background-color: #fff;
+ border-color: var(--wpuf-primary-color);
+ outline: none;
+ box-shadow: 0 0 0 2px rgba(26, 126, 251, 0.1);
+}
+.wpuf-elementor-widget-wrapper .wpuf-math-captcha .captcha .wpuf-captcha-input-wrapper .wpuf-captcha-error {
+ display: block;
+ margin-top: 5px;
+ font-size: 13px;
+ color: var(--wpuf-danger-color);
+}
+.lity {
+ z-index: 9999 !important;
+}
diff --git a/assets/less/elementor-frontend-forms.less b/assets/less/elementor-frontend-forms.less
new file mode 100644
index 000000000..553e0973c
--- /dev/null
+++ b/assets/less/elementor-frontend-forms.less
@@ -0,0 +1,254 @@
+/**
+ * DESCRIPTION: Elementor-specific WPUF frontend form styles
+ *
+ * This file contains form styles scoped to the Elementor widget wrapper
+ * to avoid conflicts with the theme and provide better Elementor integration.
+ *
+ * @package WPUF\Elementor
+ */
+
+// ============================================
+// CSS Custom Properties (Variables)
+// ============================================
+
+.wpuf-elementor-widget-wrapper {
+ --wpuf-border-color: #dadbdd;
+ --wpuf-border-radius: 7px;
+ --wpuf-text-color: #606266;
+ --wpuf-primary-color: #1a7efb;
+ --wpuf-danger-color: #F56C6C;
+
+ // ============================================
+ // Base Input Styles
+ // ============================================
+
+ .wpuf-fields input[type="text"],
+ .wpuf-fields input[type="email"],
+ .wpuf-fields input[type="url"],
+ .wpuf-fields input[type="password"],
+ .wpuf-fields input[type="number"],
+ .wpuf-fields input[type="tel"],
+ .wpuf-fields textarea,
+ .wpuf-fields select {
+ padding: 12px 15px;
+ color: var(--wpuf-text-color);
+ border: 1px solid var(--wpuf-border-color);
+ border-radius: var(--wpuf-border-radius);
+ transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+ margin-bottom: 0;
+ width: 100%;
+
+ &:focus {
+ color: var(--wpuf-text-color);
+ background-color: #fff;
+ border-color: var(--wpuf-primary-color);
+ outline: none;
+ box-shadow: 0 0 0 2px rgba(26, 126, 251, 0.1);
+ }
+ }
+
+ .wpuf-fields .wpuf-radio-block,
+ .wpuf-fields .wpuf-checkbox-block {
+ display: flex;
+ align-items: center;
+ margin-bottom: 6px;
+ }
+
+ ul.wpuf-form {
+ list-style: none;
+
+ li:not(:first-child) {
+ margin-top: 2rem;
+ }
+
+ li.wpuf-el {
+ .wpuf-label {
+ margin-bottom: 1rem;
+ }
+
+ }
+ }
+
+ // Container alignment based on data-align attribute
+ &[data-align="left"] {
+ margin: 0 auto 0 0;
+ }
+
+ &[data-align="center"] {
+ margin: 0 auto;
+ }
+
+ &[data-align="right"] {
+ margin: 0 0 0 auto;
+ }
+
+ // Full width submit button
+ &.wpuf-elementor-submit-full .wpuf-submit .wpuf-submit-button {
+ width: 100%;
+ display: block;
+ }
+
+ // Full width upload button
+ &.wpuf-elementor-upload-full .wpuf-attachment-upload-filelist .file-selector {
+ width: 100%;
+ display: block;
+ }
+
+ // Hide labels option
+ &.wpuf-elementor-hide-labels .wpuf-label {
+ display: none !important;
+ }
+
+ // Hide error messages option
+ &.wpuf-elementor-hide-errors .wpuf-error,
+ &.wpuf-elementor-hide-errors .error {
+ display: none;
+ }
+
+ // Hide placeholder option
+ &.wpuf-elementor-hide-placeholder input::-webkit-input-placeholder,
+ &.wpuf-elementor-hide-placeholder textarea::-webkit-input-placeholder {
+ opacity: 0;
+ visibility: hidden;
+ }
+
+ &.wpuf-elementor-hide-placeholder input::-moz-placeholder,
+ &.wpuf-elementor-hide-placeholder textarea::-moz-placeholder {
+ opacity: 0;
+ visibility: hidden;
+ }
+
+ &.wpuf-elementor-hide-placeholder input:-moz-placeholder,
+ &.wpuf-elementor-hide-placeholder textarea:-moz-placeholder {
+ opacity: 0;
+ visibility: hidden;
+ }
+
+ &.wpuf-elementor-hide-placeholder input:-ms-input-placeholder,
+ &.wpuf-elementor-hide-placeholder textarea:-ms-input-placeholder {
+ opacity: 0;
+ visibility: hidden;
+ }
+
+ &.wpuf-elementor-hide-placeholder input::-ms-input-placeholder,
+ &.wpuf-elementor-hide-placeholder textarea::-ms-input-placeholder {
+ opacity: 0;
+ visibility: hidden;
+ }
+
+ // Custom radio/checkbox styling
+ &.wpuf-elementor-custom-radio-checkbox input[type="checkbox"],
+ &.wpuf-elementor-custom-radio-checkbox input[type="radio"] {
+ outline: none;
+ min-width: 1px;
+ width: 15px;
+ height: 15px;
+ background: #ddd;
+ padding: 3px;
+ }
+
+ &.wpuf-elementor-custom-radio-checkbox input[type="radio"] {
+ border-radius: 50%;
+ }
+
+ // Submit button alignment
+ &.wpuf-elementor-submit-center .wpuf-submit {
+ text-align: center;
+
+ .wpuf-submit-button {
+ margin: 0 auto;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ }
+ }
+
+ &.wpuf-elementor-submit-right .wpuf-submit {
+ text-align: right;
+ }
+
+ &.wpuf-elementor-submit-left .wpuf-submit {
+ text-align: left;
+ }
+
+ // ============================================
+ // Math Captcha Styles
+ // ============================================
+
+ .wpuf-math-captcha {
+ .captcha {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ flex-wrap: wrap;
+
+ .refresh {
+ cursor: pointer;
+ transition: opacity 0.2s ease;
+
+ &:hover {
+ opacity: 0.7;
+ }
+
+ svg {
+ display: block;
+ }
+ }
+
+ .captcha-number-area {
+ .captcha-number {
+ display: flex;
+ align-items: center;
+ gap: 5px;
+ margin: 0;
+ font-size: 16px;
+ font-weight: 500;
+ color: var(--wpuf-text-color);
+ }
+ }
+
+ .captcha-equal {
+ font-size: 18px;
+ font-weight: 600;
+ color: var(--wpuf-text-color);
+ }
+
+ .wpuf-captcha-input-wrapper {
+ flex: 1;
+ min-width: 80px;
+ position: relative;
+
+ .wpuf-captcha-input {
+ padding: 11px 15px;
+ color: var(--wpuf-text-color);
+ border: 1px solid var(--wpuf-border-color);
+ border-radius: var(--wpuf-border-radius);
+ transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+ margin-bottom: 0;
+ width: 100%;
+ font-family: -apple-system, system-ui, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
+
+ &:focus {
+ color: var(--wpuf-text-color);
+ background-color: #fff;
+ border-color: var(--wpuf-primary-color);
+ outline: none;
+ box-shadow: 0 0 0 2px rgba(26, 126, 251, 0.1);
+ }
+ }
+
+ .wpuf-captcha-error {
+ display: block;
+ margin-top: 5px;
+ font-size: 13px;
+ color: var(--wpuf-danger-color);
+ }
+ }
+ }
+ }
+}
+
+// Ensure lity popup appears above Elementor popup
+.lity {
+ z-index: 9999 !important;
+}
\ No newline at end of file
diff --git a/includes/Admin/template-parts/modal-v4.2.php b/includes/Admin/template-parts/modal-v4.2.php
index 94e668198..dab721df6 100644
--- a/includes/Admin/template-parts/modal-v4.2.php
+++ b/includes/Admin/template-parts/modal-v4.2.php
@@ -454,8 +454,6 @@ class="wpuf-btn-secondary wpuf-w-max wpuf-absolute wpuf-top-[50%] wpuf-left-[50%
$( '.wpuf-ai-forms-template a' ).on( 'click', $.proxy( this.handleAIFormsClick, this ) );
$( '#ai-config-cancel' ).on( 'click', $.proxy( this.closeAIConfigModal, this ) );
$( '#ai-config-settings' ).on( 'click', $.proxy( this.goToSettings, this ) );
- } else {
- console.log('NOT attaching AI click handler - AI is configured or template not found');
}
},
diff --git a/includes/Assets.php b/includes/Assets.php
index aa9a20372..af17e35fb 100644
--- a/includes/Assets.php
+++ b/includes/Assets.php
@@ -109,6 +109,9 @@ public function get_styles() {
'frontend-forms' => [
'src' => WPUF_ASSET_URI . '/css/frontend-forms.css',
],
+ 'elementor-frontend-forms' => [
+ 'src' => WPUF_ASSET_URI . '/css/elementor-frontend-forms.css',
+ ],
'frontend-subscriptions' => [
'src' => WPUF_ASSET_URI . '/css/frontend-subscriptions.min.css',
],
diff --git a/includes/Fields/Field_Contract.php b/includes/Fields/Field_Contract.php
index 007de51df..f3b3bbb10 100755
--- a/includes/Fields/Field_Contract.php
+++ b/includes/Fields/Field_Contract.php
@@ -763,6 +763,33 @@ public function get_default_textarea_option_settings() {
];
}
+ /**
+ * Check if we should render admin-style markup
+ *
+ * Returns true for admin dashboard, but false for Elementor editor
+ * since Elementor editor needs frontend-style markup for proper preview.
+ *
+ * @since WPUF_SINCE
+ *
+ * @return bool
+ */
+ protected function use_admin_markup() {
+ if ( ! is_admin() ) {
+ return false;
+ }
+
+ // Check if we're in Elementor editor mode
+ // Elementor editor needs frontend markup for proper preview
+ if ( class_exists( '\Elementor\Plugin' ) ) {
+ $elementor = \Elementor\Plugin::$instance;
+ if ( $elementor && $elementor->editor && $elementor->editor->is_edit_mode() ) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
/**
* Prints form input label for admin
*
@@ -770,7 +797,7 @@ public function get_default_textarea_option_settings() {
* @param int $form_id
*/
public function field_print_label( $field, $form_id = 0 ) {
- if ( is_admin() ) { ?>
+ if ( $this->use_admin_markup() ) { ?>
print_list_attributes( $field ); ?>> | required_mark( $field ) ); ?> |
@@ -782,7 +809,7 @@ public function field_print_label( $field, $form_id = 0 ) {
}
public function after_field_print_label() {
- if ( is_admin() ) {
+ if ( $this->use_admin_markup() ) {
?>
|
diff --git a/includes/Fields/Form_Field_Post_Excerpt.php b/includes/Fields/Form_Field_Post_Excerpt.php
index b3d8c9aae..636853bc9 100755
--- a/includes/Fields/Form_Field_Post_Excerpt.php
+++ b/includes/Fields/Form_Field_Post_Excerpt.php
@@ -56,6 +56,7 @@ public function render( $field_settings, $form_id, $type = 'post', $post_id = nu
];
$editor_settings = apply_filters( 'wpuf_textarea_editor_args', $editor_settings );
+
wp_editor( $value, $textarea_id, $editor_settings );
} elseif ( ! empty( $field_settings['rich'] ) && $field_settings['rich'] == 'teeny' ) {
$editor_settings = [
@@ -68,6 +69,7 @@ public function render( $field_settings, $form_id, $type = 'post', $post_id = nu
];
$editor_settings = apply_filters( 'wpuf_textarea_editor_args', $editor_settings );
+
wp_editor( $value, $textarea_id, $editor_settings );
} else {
?>
diff --git a/includes/Integrations.php b/includes/Integrations.php
index 99bb8ea77..eca318303 100644
--- a/includes/Integrations.php
+++ b/includes/Integrations.php
@@ -45,6 +45,10 @@ public function __construct() {
}
}
}
+
+ add_action('elementor/init', function() {
+ $this->container['elementor'] = new Integrations\Elementor\Elementor();
+ });
}
/**
diff --git a/includes/Integrations/Elementor/Elementor.php b/includes/Integrations/Elementor/Elementor.php
new file mode 100644
index 000000000..2bd0045da
--- /dev/null
+++ b/includes/Integrations/Elementor/Elementor.php
@@ -0,0 +1,259 @@
+enqueue_wpuf_form_assets();
+
+ // Ensure editor scripts are loaded for TinyMCE in Elementor preview
+ if ( function_exists( 'wp_enqueue_editor' ) ) {
+ wp_enqueue_editor();
+
+ // Also explicitly enqueue TinyMCE scripts if available
+ if ( function_exists( 'wp_enqueue_script' ) ) {
+ // Check if these scripts exist and enqueue them
+ global $wp_scripts;
+ if ( isset( $wp_scripts->registered['tinymce'] ) ) {
+ wp_enqueue_script( 'tinymce' );
+ }
+ if ( isset( $wp_scripts->registered['wp-tinymce'] ) ) {
+ wp_enqueue_script( 'wp-tinymce' );
+ }
+ }
+ }
+
+ /**
+ * Fires after WPUF has enqueued its scripts in Elementor context.
+ *
+ * @since WPUF_SINCE
+ */
+ do_action( 'wpuf_elementor_after_enqueue_scripts' );
+ }
+
+ /**
+ * Enqueue all required WPUF form assets for Elementor
+ *
+ * Ensures all necessary styles and scripts are loaded for WPUF forms
+ * to render properly in Elementor preview and frontend.
+ *
+ * @since WPUF_SINCE
+ *
+ * @return void
+ */
+ private function enqueue_wpuf_form_assets() {
+ // Core styles (already handled by enqueue_styles, but ensure they're available)
+ wp_enqueue_style( 'wpuf-sweetalert2' );
+ wp_enqueue_style( 'wpuf-jquery-ui' );
+
+ // Core scripts required for all WPUF forms
+ wp_enqueue_script( 'suggest' );
+ wp_enqueue_script( 'wpuf-billing-address' );
+ wp_enqueue_script( 'wpuf-upload' );
+ wp_enqueue_script( 'wpuf-frontend-form' );
+ wp_enqueue_script( 'wpuf-sweetalert2' );
+ wp_enqueue_script( 'wpuf-subscriptions' );
+
+ // Localize wpuf-upload script
+ wp_localize_script(
+ 'wpuf-upload',
+ 'wpuf_upload',
+ [
+ 'confirmMsg' => __( 'Are you sure?', 'wp-user-frontend' ),
+ 'delete_it' => __( 'Yes, delete it', 'wp-user-frontend' ),
+ 'cancel_it' => __( 'No, cancel it', 'wp-user-frontend' ),
+ 'ajaxurl' => admin_url( 'admin-ajax.php' ),
+ 'nonce' => wp_create_nonce( 'wpuf_nonce' ),
+ 'plupload' => [
+ 'url' => admin_url( 'admin-ajax.php' ) . '?nonce=' . wp_create_nonce( 'wpuf-upload-nonce' ),
+ 'flash_swf_url' => includes_url( 'js/plupload/plupload.flash.swf' ),
+ 'filters' => [
+ [
+ 'title' => __( 'Allowed Files', 'wp-user-frontend' ),
+ 'extensions' => '*',
+ ],
+ ],
+ 'multipart' => true,
+ 'urlstream_upload' => true,
+ 'warning' => __( 'Maximum number of files reached!', 'wp-user-frontend' ),
+ 'size_error' => __( 'The file you have uploaded exceeds the file size limit. Please try again.', 'wp-user-frontend' ),
+ 'type_error' => __( 'You have uploaded an incorrect file type. Please try again.', 'wp-user-frontend' ),
+ ],
+ ]
+ );
+
+ // Localize wpuf-frontend-form script
+ wp_localize_script(
+ 'wpuf-frontend-form',
+ 'wpuf_frontend',
+ apply_filters(
+ 'wpuf_frontend_object',
+ [
+ 'asset_url' => WPUF_ASSET_URI,
+ 'ajaxurl' => admin_url( 'admin-ajax.php' ),
+ 'error_message' => __( 'Please fix the errors to proceed', 'wp-user-frontend' ),
+ 'nonce' => wp_create_nonce( 'wpuf_nonce' ),
+ 'word_limit' => __( 'Word limit reached', 'wp-user-frontend' ),
+ 'cancelSubMsg' => __( 'Are you sure you want to cancel your current subscription ?', 'wp-user-frontend' ),
+ 'delete_it' => __( 'Yes', 'wp-user-frontend' ),
+ 'cancel_it' => __( 'No', 'wp-user-frontend' ),
+ 'word_max_title' => __( 'Maximum word limit reached. Please shorten your texts.', 'wp-user-frontend' ),
+ 'word_max_details' => __( 'This field supports a maximum of %number% words, and the limit is reached. Remove a few words to reach the acceptable limit of the field.', 'wp-user-frontend' ),
+ 'word_min_title' => __( 'Minimum word required.', 'wp-user-frontend' ),
+ 'word_min_details' => __( 'This field requires minimum %number% words. Please add some more text.', 'wp-user-frontend' ),
+ 'char_max_title' => __( 'Maximum character limit reached. Please shorten your texts.', 'wp-user-frontend' ),
+ 'char_max_details' => __( 'This field supports a maximum of %number% characters, and the limit is reached. Remove a few characters to reach the acceptable limit of the field.', 'wp-user-frontend' ),
+ 'char_min_title' => __( 'Minimum character required.', 'wp-user-frontend' ),
+ 'char_min_details' => __( 'This field requires minimum %number% characters. Please add some more character.', 'wp-user-frontend' ),
+ 'protected_shortcodes' => wpuf_get_protected_shortcodes(),
+ 'protected_shortcodes_message' => __( 'Using %shortcode% is restricted', 'wp-user-frontend' ),
+ 'password_warning_weak' => __( 'Your password should be at least weak in strength', 'wp-user-frontend' ),
+ 'password_warning_medium' => __( 'Your password needs to be medium strength for better protection', 'wp-user-frontend' ),
+ 'password_warning_strong' => __( 'Create a strong password for maximum security', 'wp-user-frontend' ),
+ ]
+ )
+ );
+
+ wp_localize_script(
+ 'wpuf-frontend-form',
+ 'error_str_obj',
+ [
+ 'required' => __( 'is required', 'wp-user-frontend' ),
+ 'mismatch' => __( 'does not match', 'wp-user-frontend' ),
+ 'validation' => __( 'is not valid', 'wp-user-frontend' ),
+ ]
+ );
+
+ // Localize subscription script
+ wp_localize_script(
+ 'wpuf-subscriptions',
+ 'wpuf_subscription',
+ apply_filters(
+ 'wpuf_subscription_js_data',
+ [
+ 'pack_notice' => __( 'Please Cancel Your Currently Active Pack first!', 'wp-user-frontend' ),
+ ]
+ )
+ );
+
+ // Localize billing address script
+ wp_localize_script(
+ 'wpuf-billing-address',
+ 'ajax_object',
+ [
+ 'ajaxurl' => admin_url( 'admin-ajax.php' ),
+ 'fill_notice' => __( 'Some Required Fields are not filled!', 'wp-user-frontend' ),
+ ]
+ );
+
+ // Conditionally enqueue Google Maps if API key is configured
+ $api_key = wpuf_get_option( 'gmap_api_key', 'wpuf_general' );
+ if ( ! empty( $api_key ) ) {
+ $scheme = is_ssl() ? 'https' : 'http';
+ wp_enqueue_script( 'wpuf-google-maps', $scheme . '://maps.google.com/maps/api/js?libraries=places&key=' . $api_key, [], null, true );
+ }
+ }
+
+ /**
+ * Register Elementor Widget Category
+ *
+ * @param \Elementor\Elements_Manager $elements_manager
+ *
+ * @return void
+ */
+ public function register_category( $elements_manager ) {
+ $elements_manager->add_category(
+ 'user-frontend',
+ [
+ 'title' => __( 'User Frontend', 'wp-user-frontend' ),
+ 'icon' => 'eicon-form-horizontal',
+ ]
+ );
+ }
+
+ /**
+ * Register Elementor Widgets
+ *
+ * @param \Elementor\Widgets_Manager $widgets_manager
+ *
+ * @return void
+ */
+ public function register_widgets( $widgets_manager ) {
+ require_once __DIR__ . '/Widget.php';
+
+ $widgets_manager->register( new Widget() );
+ }
+}
diff --git a/includes/Integrations/Elementor/Widget.php b/includes/Integrations/Elementor/Widget.php
new file mode 100644
index 000000000..78b9c42ee
--- /dev/null
+++ b/includes/Integrations/Elementor/Widget.php
@@ -0,0 +1,1570 @@
+start_controls_section(
+ 'section_content',
+ [
+ 'label' => __( 'Content', 'wp-user-frontend' ),
+ ]
+ );
+
+ $this->add_control(
+ 'form_id',
+ [
+ 'label' => __( 'Select Form', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::SELECT,
+ 'default' => '',
+ 'options' => $this->get_wpuf_forms(),
+ ]
+ );
+
+ $this->end_controls_section();
+
+ // Style Tab
+ $this->register_label_style_controls();
+ $this->register_help_text_style_controls();
+ $this->register_input_style_controls();
+ $this->register_placeholder_style_controls();
+ $this->register_richtext_style_controls();
+ $this->register_section_break_style_controls();
+ $this->register_radio_checkbox_style_controls();
+ $this->register_upload_button_style_controls();
+ $this->register_submit_button_style_controls();
+
+ /**
+ * Fires after the widget has registered its style controls.
+ *
+ * Use this to add additional style sections (e.g. for Pro features like multistep).
+ *
+ * @since WPUF_SINCE
+ *
+ * @param \Elementor\Widget_Base $this The widget instance.
+ */
+ do_action( 'wpuf_elementor_widget_register_style_controls', $this );
+ }
+
+ /**
+ * Retrieve all published WPUF forms
+ *
+ * @since WPUF_SINCE
+ *
+ * @return array Array of forms formatted as select options
+ */
+ protected function get_wpuf_forms() {
+ $forms = get_posts( [
+ 'post_type' => 'wpuf_forms',
+ 'posts_per_page' => -1,
+ 'post_status' => 'publish',
+ ] );
+
+ $options = [ '' => __( 'Select a Form', 'wp-user-frontend' ) ];
+
+ if ( ! empty( $forms ) ) {
+ foreach ( $forms as $form ) {
+ $options[ $form->ID ] = $form->post_title;
+ }
+ }
+
+ /**
+ * Filters the form options shown in the widget's form dropdown.
+ *
+ * @since WPUF_SINCE
+ *
+ * @param array $options Associative array of form_id => form_title.
+ * @param \Elementor\Widget_Base $this The widget instance.
+ */
+ return apply_filters( 'wpuf_elementor_form_options', $options, $this );
+ }
+
+ /**
+ * Register label style controls
+ *
+ * @since WPUF_SINCE
+ *
+ * @return void
+ */
+ protected function register_label_style_controls() {
+ $this->start_controls_section(
+ 'section_label_style',
+ [
+ 'label' => __( 'Labels', 'wp-user-frontend' ),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'label_color',
+ [
+ 'label' => __( 'Text Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'selectors' => [
+ '{{WRAPPER}} .wpuf-form .wpuf-label, {{WRAPPER}} .wpuf-form .wpuf-form-sub-label, {{WRAPPER}} .wpuf-form .wpuf-repeat-container > p' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Typography::get_type(),
+ [
+ 'name' => 'label_typography',
+ 'selector' => '{{WRAPPER}} .wpuf-form .wpuf-label, {{WRAPPER}} .wpuf-form .wpuf-form-sub-label, {{WRAPPER}} .wpuf-form .wpuf-repeat-container > p',
+ ]
+ );
+
+ $this->add_control(
+ 'label_asterisk_color',
+ [
+ 'label' => __( 'Asterisk Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'selectors' => [
+ '{{WRAPPER}} .wpuf-form .wpuf-label .required, {{WRAPPER}} .wpuf-form .wpuf-form-sub-label .required' => 'color: {{VALUE}};',
+ ],
+ 'separator' => 'before',
+ ]
+ );
+
+ $this->add_control(
+ 'label_asterisk_size',
+ [
+ 'label' => __( 'Asterisk Size', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::SLIDER,
+ 'size_units' => [ 'px', 'em', '%' ],
+ 'range' => [
+ 'px' => [ 'min' => 0, 'max' => 30, 'step' => 1 ],
+ '%' => [ 'min' => 0, 'max' => 30, 'step' => 1 ],
+ ],
+ 'selectors' => [
+ '{{WRAPPER}} .wpuf-form .wpuf-label .required, {{WRAPPER}} .wpuf-form .wpuf-form-sub-label .required' => 'font-size: {{SIZE}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->end_controls_section();
+ }
+
+ /**
+ * Register help text style controls
+ *
+ * @since WPUF_SINCE
+ *
+ * @return void
+ */
+ protected function register_help_text_style_controls() {
+ $this->start_controls_section(
+ 'section_help_text_style',
+ [
+ 'label' => __( 'Help Text', 'wp-user-frontend' ),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'help_text_color',
+ [
+ 'label' => __( 'Text Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'selectors' => [
+ '{{WRAPPER}} .wpuf-form .wpuf-help' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Typography::get_type(),
+ [
+ 'name' => 'help_text_typography',
+ 'selector' => '{{WRAPPER}} .wpuf-form .wpuf-help',
+ ]
+ );
+
+ $this->end_controls_section();
+ }
+
+ /**
+ * Register input field style controls
+ *
+ * @since WPUF_SINCE
+ *
+ * @return void
+ */
+ protected function register_input_style_controls() {
+ $input_selector = '{{WRAPPER}} .wpuf-form input[type="text"], {{WRAPPER}} .wpuf-form input[type="email"], {{WRAPPER}} .wpuf-form input[type="url"], {{WRAPPER}} .wpuf-form input[type="password"], {{WRAPPER}} .wpuf-form input[type="number"], {{WRAPPER}} .wpuf-form textarea, {{WRAPPER}} .wpuf-form select';
+
+ $this->start_controls_section(
+ 'section_input_style',
+ [
+ 'label' => __( 'Input & Textarea', 'wp-user-frontend' ),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'input_alignment',
+ [
+ 'label' => __( 'Alignment', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::CHOOSE,
+ 'options' => [
+ 'left' => [ 'title' => __( 'Left', 'wp-user-frontend' ), 'icon' => 'eicon-text-align-left' ],
+ 'center' => [ 'title' => __( 'Center', 'wp-user-frontend' ), 'icon' => 'eicon-text-align-center' ],
+ 'right' => [ 'title' => __( 'Right', 'wp-user-frontend' ), 'icon' => 'eicon-text-align-right' ],
+ ],
+ 'selectors' => [ $input_selector => 'text-align: {{VALUE}};' ],
+ ]
+ );
+
+ $this->start_controls_tabs( 'tabs_input_style' );
+
+ $this->start_controls_tab( 'tab_input_normal', [ 'label' => __( 'Normal', 'wp-user-frontend' ) ] );
+
+ $this->add_control(
+ 'input_bg_color',
+ [
+ 'label' => __( 'Background Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'selectors' => [ $input_selector => 'background-color: {{VALUE}};' ],
+ ]
+ );
+
+ $this->add_control(
+ 'input_text_color',
+ [
+ 'label' => __( 'Text Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'selectors' => [ $input_selector => 'color: {{VALUE}};' ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Typography::get_type(),
+ [ 'name' => 'input_typography', 'selector' => $input_selector ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Border::get_type(),
+ [ 'name' => 'input_border', 'selector' => $input_selector ]
+ );
+
+ $this->add_control(
+ 'input_border_radius',
+ [
+ 'label' => __( 'Border Radius', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => [ 'px', '%' ],
+ 'selectors' => [ $input_selector => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'input_padding',
+ [
+ 'label' => __( 'Padding', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => [ 'px', 'em', '%' ],
+ 'selectors' => [ $input_selector => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Box_Shadow::get_type(),
+ [
+ 'name' => 'input_box_shadow',
+ 'selector' => $input_selector,
+ 'separator' => 'before',
+ ]
+ );
+
+ $this->end_controls_tab();
+
+ $this->start_controls_tab( 'tab_input_focus', [ 'label' => __( 'Focus', 'wp-user-frontend' ) ] );
+
+ $this->add_control(
+ 'input_focus_bg_color',
+ [
+ 'label' => __( 'Background Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'selectors' => [
+ '{{WRAPPER}} .wpuf-form input[type="text"]:focus, {{WRAPPER}} .wpuf-form input[type="email"]:focus, {{WRAPPER}} .wpuf-form input[type="url"]:focus, {{WRAPPER}} .wpuf-form input[type="password"]:focus, {{WRAPPER}} .wpuf-form input[type="number"]:focus, {{WRAPPER}} .wpuf-form textarea:focus, {{WRAPPER}} .wpuf-form select:focus' => 'background-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Border::get_type(),
+ [
+ 'name' => 'input_focus_border',
+ 'selector' => '{{WRAPPER}} .wpuf-form input[type="text"]:focus, {{WRAPPER}} .wpuf-form input[type="email"]:focus, {{WRAPPER}} .wpuf-form input[type="url"]:focus, {{WRAPPER}} .wpuf-form input[type="password"]:focus, {{WRAPPER}} .wpuf-form input[type="number"]:focus, {{WRAPPER}} .wpuf-form textarea:focus, {{WRAPPER}} .wpuf-form select:focus',
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Box_Shadow::get_type(),
+ [
+ 'name' => 'input_focus_box_shadow',
+ 'selector' => '{{WRAPPER}} .wpuf-form input[type="text"]:focus, {{WRAPPER}} .wpuf-form input[type="email"]:focus, {{WRAPPER}} .wpuf-form input[type="url"]:focus, {{WRAPPER}} .wpuf-form input[type="password"]:focus, {{WRAPPER}} .wpuf-form input[type="number"]:focus, {{WRAPPER}} .wpuf-form textarea:focus, {{WRAPPER}} .wpuf-form select:focus',
+ ]
+ );
+
+ $this->end_controls_tab();
+
+ $this->end_controls_tabs();
+
+ $this->end_controls_section();
+ }
+
+ /**
+ * Register placeholder style controls.
+ *
+ * @since WPUF_SINCE
+ *
+ * @return void
+ */
+ protected function register_placeholder_style_controls() {
+ $this->start_controls_section(
+ 'section_placeholder_style',
+ [
+ 'label' => __( 'Placeholder', 'wp-user-frontend' ),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $placeholder_selector = '{{WRAPPER}} .wpuf-form input::placeholder, {{WRAPPER}} .wpuf-form textarea::placeholder, {{WRAPPER}} .wpuf-form input::-webkit-input-placeholder, {{WRAPPER}} .wpuf-form textarea::-webkit-input-placeholder, {{WRAPPER}} .wpuf-form input::-moz-placeholder, {{WRAPPER}} .wpuf-form textarea::-moz-placeholder, {{WRAPPER}} .wpuf-form input:-ms-input-placeholder, {{WRAPPER}} .wpuf-form textarea:-ms-input-placeholder';
+
+ $this->add_control(
+ 'placeholder_color',
+ [
+ 'label' => __( 'Text Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'selectors' => [ $placeholder_selector => 'color: {{VALUE}};' ],
+ ]
+ );
+
+ $this->end_controls_section();
+ }
+
+ /**
+ * Register rich text editor style controls
+ *
+ * @since WPUF_SINCE
+ *
+ * @return void
+ */
+ protected function register_richtext_style_controls() {
+ $toolbar_selector = '{{WRAPPER}} .wpuf-form .mce-toolbar-grp';
+ $insert_image_btn = '{{WRAPPER}} .wpuf-form .wpuf-insert-image';
+
+ $this->start_controls_section(
+ 'section_richtext_style',
+ [
+ 'label' => __( 'Rich Text Editor', 'wp-user-frontend' ),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Border::get_type(),
+ [
+ 'name' => 'richtext_border',
+ 'label' => __( 'Border', 'wp-user-frontend' ),
+ 'selector' => '{{WRAPPER}} .wpuf-form .mce-tinymce',
+ ]
+ );
+
+ $this->add_control(
+ 'richtext_border_radius',
+ [
+ 'label' => __( 'Border Radius', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => [ 'px', '%' ],
+ 'selectors' => [
+ '{{WRAPPER}} .wpuf-form .mce-tinymce' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'richtext_toolbar_heading',
+ [
+ 'label' => __( 'Toolbar', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::HEADING,
+ 'separator' => 'before',
+ ]
+ );
+
+ $this->add_control(
+ 'richtext_toolbar_text_color',
+ [
+ 'label' => __( 'Text Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'selectors' => [
+ $toolbar_selector . ' .mce-btn button' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'richtext_toolbar_icon_color',
+ [
+ 'label' => __( 'Icon Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'selectors' => [
+ $toolbar_selector . ' .mce-ico' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'richtext_toolbar_bg_color',
+ [
+ 'label' => __( 'Background Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'selectors' => [
+ $toolbar_selector => 'background-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'richtext_insert_image_heading',
+ [
+ 'label' => __( 'Insert Photo Button', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::HEADING,
+ 'separator' => 'before',
+ ]
+ );
+
+ $this->start_controls_tabs( 'tabs_insert_image_style' );
+
+ $this->start_controls_tab( 'tab_insert_image_normal', [ 'label' => __( 'Normal', 'wp-user-frontend' ) ] );
+
+ $this->add_control(
+ 'richtext_insert_image_color',
+ [
+ 'label' => __( 'Text Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'selectors' => [
+ $insert_image_btn => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'richtext_insert_image_bg_color',
+ [
+ 'label' => __( 'Background Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'selectors' => [
+ $insert_image_btn => 'background-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Border::get_type(),
+ [
+ 'name' => 'richtext_insert_image_border',
+ 'selector' => $insert_image_btn,
+ ]
+ );
+
+ $this->add_control(
+ 'richtext_insert_image_border_radius',
+ [
+ 'label' => __( 'Border Radius', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => [ 'px', '%' ],
+ 'selectors' => [
+ $insert_image_btn => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'richtext_insert_image_padding',
+ [
+ 'label' => __( 'Padding', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => [ 'px', 'em', '%' ],
+ 'selectors' => [
+ $insert_image_btn => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'richtext_insert_image_margin',
+ [
+ 'label' => __( 'Margin', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => [ 'px', 'em', '%' ],
+ 'selectors' => [
+ '{{WRAPPER}} .wpuf-form #wpuf-insert-image-container' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->end_controls_tab();
+
+ $this->start_controls_tab( 'tab_insert_image_hover', [ 'label' => __( 'Hover', 'wp-user-frontend' ) ] );
+
+ $this->add_control(
+ 'richtext_insert_image_hover_color',
+ [
+ 'label' => __( 'Text Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'selectors' => [
+ $insert_image_btn . ':hover' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'richtext_insert_image_hover_bg_color',
+ [
+ 'label' => __( 'Background Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'selectors' => [
+ $insert_image_btn . ':hover' => 'background-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'richtext_insert_image_hover_border_color',
+ [
+ 'label' => __( 'Border Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'selectors' => [
+ $insert_image_btn . ':hover' => 'border-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->end_controls_tab();
+
+ $this->end_controls_tabs();
+
+ $this->end_controls_section();
+ }
+
+ /**
+ * Register section break style controls
+ *
+ * @since WPUF_SINCE
+ *
+ * @return void
+ */
+ protected function register_section_break_style_controls() {
+ $section_wrap = '{{WRAPPER}} .wpuf-form .wpuf-section-wrap';
+ $section_title = '{{WRAPPER}} .wpuf-form .wpuf-section-title';
+ $section_desc = '{{WRAPPER}} .wpuf-form .wpuf-section-details';
+
+ $this->start_controls_section(
+ 'section_break_style',
+ [
+ 'label' => __( 'Section Break', 'wp-user-frontend' ),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'section_break_bg_color',
+ [
+ 'label' => __( 'Background Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'selectors' => [
+ $section_wrap => 'background-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'section_break_padding',
+ [
+ 'label' => __( 'Padding', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => [ 'px', 'em', '%' ],
+ 'selectors' => [
+ $section_wrap => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'section_break_margin',
+ [
+ 'label' => __( 'Margin', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => [ 'px', 'em', '%' ],
+ 'selectors' => [
+ $section_wrap => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Border::get_type(),
+ [
+ 'name' => 'section_break_border',
+ 'selector' => $section_wrap,
+ ]
+ );
+
+ $this->add_control(
+ 'section_break_border_radius',
+ [
+ 'label' => __( 'Border Radius', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => [ 'px', '%' ],
+ 'selectors' => [
+ $section_wrap => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'section_break_title_heading',
+ [
+ 'label' => __( 'Title', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::HEADING,
+ 'separator' => 'before',
+ ]
+ );
+
+ $this->add_control(
+ 'section_break_title_color',
+ [
+ 'label' => __( 'Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'selectors' => [
+ $section_title => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Typography::get_type(),
+ [
+ 'name' => 'section_break_title_typography',
+ 'selector' => $section_title,
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'section_break_title_alignment',
+ [
+ 'label' => __( 'Alignment', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::CHOOSE,
+ 'options' => [
+ 'left' => [ 'title' => __( 'Left', 'wp-user-frontend' ), 'icon' => 'eicon-text-align-left' ],
+ 'center' => [ 'title' => __( 'Center', 'wp-user-frontend' ), 'icon' => 'eicon-text-align-center' ],
+ 'right' => [ 'title' => __( 'Right', 'wp-user-frontend' ), 'icon' => 'eicon-text-align-right' ],
+ ],
+ 'selectors' => [ $section_title => 'text-align: {{VALUE}};' ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'section_break_title_margin',
+ [
+ 'label' => __( 'Margin', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => [ 'px', 'em', '%' ],
+ 'selectors' => [
+ $section_title => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'section_break_desc_heading',
+ [
+ 'label' => __( 'Description', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::HEADING,
+ 'separator' => 'before',
+ ]
+ );
+
+ $this->add_control(
+ 'section_break_desc_color',
+ [
+ 'label' => __( 'Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'selectors' => [
+ $section_desc => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Typography::get_type(),
+ [
+ 'name' => 'section_break_desc_typography',
+ 'selector' => $section_desc,
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'section_break_desc_alignment',
+ [
+ 'label' => __( 'Alignment', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::CHOOSE,
+ 'options' => [
+ 'left' => [ 'title' => __( 'Left', 'wp-user-frontend' ), 'icon' => 'eicon-text-align-left' ],
+ 'center' => [ 'title' => __( 'Center', 'wp-user-frontend' ), 'icon' => 'eicon-text-align-center' ],
+ 'right' => [ 'title' => __( 'Right', 'wp-user-frontend' ), 'icon' => 'eicon-text-align-right' ],
+ ],
+ 'selectors' => [ $section_desc => 'text-align: {{VALUE}};' ],
+ ]
+ );
+
+ $this->end_controls_section();
+ }
+
+ /**
+ * Register radio and checkbox style controls.
+ *
+ * @since WPUF_SINCE
+ *
+ * @return void
+ */
+ protected function register_radio_checkbox_style_controls() {
+ $this->start_controls_section(
+ 'section_radio_checkbox_style',
+ [
+ 'label' => __( 'Radio & Checkbox', 'wp-user-frontend' ),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'radio_checkbox_size',
+ [
+ 'label' => __( 'Size', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::SLIDER,
+ 'size_units' => [ 'px' ],
+ 'range' => [ 'px' => [ 'min' => 0, 'max' => 80, 'step' => 1 ] ],
+ 'default' => [ 'size' => 18, 'unit' => 'px' ],
+ 'selectors' => [
+ '{{WRAPPER}} .wpuf-form input[type="radio"], {{WRAPPER}} .wpuf-form input[type="checkbox"]' => 'width: {{SIZE}}{{UNIT}}; height: {{SIZE}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'radio_checkbox_spacing',
+ [
+ 'label' => __( 'Spacing', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::SLIDER,
+ 'size_units' => [ 'px', 'em' ],
+ 'range' => [ 'px' => [ 'min' => 0, 'max' => 30, 'step' => 1 ] ],
+ 'selectors' => [
+ '{{WRAPPER}} .wpuf-form input[type="radio"], {{WRAPPER}} .wpuf-form input[type="checkbox"]' => 'margin-right: {{SIZE}}{{UNIT}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'radio_checkbox_selector_color',
+ [
+ 'label' => __( 'Selector Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'selectors' => [
+ '{{WRAPPER}} .wpuf-form input[type="radio"], {{WRAPPER}} .wpuf-form input[type="checkbox"]' => 'accent-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'radio_checkbox_options_text_color',
+ [
+ 'label' => __( 'Options Text Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'selectors' => [
+ '{{WRAPPER}} .wpuf-form .wpuf-radio-block, {{WRAPPER}} .wpuf-form .wpuf-checkbox-block, {{WRAPPER}} .wpuf-form .wpuf-radio-inline, {{WRAPPER}} .wpuf-form .wpuf-checkbox-inline, {{WRAPPER}} .wpuf-form .wpuf-price-label, {{WRAPPER}} .wpuf-form .wpuf-fields[data-type="radio"] > label' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->end_controls_section();
+ }
+
+ /**
+ * Register upload button style controls
+ *
+ * Styles the file/image upload buttons (e.g. "Select File", "Select Image") within WPUF forms.
+ *
+ * @since WPUF_SINCE
+ *
+ * @return void
+ */
+ protected function register_upload_button_style_controls() {
+ $btn_selector = '{{WRAPPER}} .wpuf-form .file-selector';
+ $align_selector = '{{WRAPPER}} .wpuf-form .wpuf-attachment-upload-filelist';
+
+ $this->start_controls_section(
+ 'section_upload_button_style',
+ [
+ 'label' => __( 'Upload Button', 'wp-user-frontend' ),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'upload_button_width_type',
+ [
+ 'label' => __( 'Width', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::SELECT,
+ 'default' => 'custom',
+ 'options' => [
+ 'full-width' => __( 'Full Width', 'wp-user-frontend' ),
+ 'custom' => __( 'Custom', 'wp-user-frontend' ),
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'upload_button_align',
+ [
+ 'label' => __( 'Alignment', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::CHOOSE,
+ 'default' => 'left',
+ 'options' => [
+ 'left' => [ 'title' => __( 'Left', 'wp-user-frontend' ), 'icon' => 'eicon-h-align-left' ],
+ 'center' => [ 'title' => __( 'Center', 'wp-user-frontend' ), 'icon' => 'eicon-h-align-center' ],
+ 'right' => [ 'title' => __( 'Right', 'wp-user-frontend' ), 'icon' => 'eicon-h-align-right' ],
+ ],
+ 'selectors' => [ $align_selector => 'text-align: {{VALUE}};' ],
+ 'condition' => [ 'upload_button_width_type' => 'custom' ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'upload_button_width',
+ [
+ 'label' => __( 'Width', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::SLIDER,
+ 'size_units' => [ 'px', '%' ],
+ 'range' => [ 'px' => [ 'min' => 0, 'max' => 1200, 'step' => 1 ] ],
+ 'selectors' => [ $btn_selector => 'width: {{SIZE}}{{UNIT}};' ],
+ 'condition' => [ 'upload_button_width_type' => 'custom' ],
+ ]
+ );
+
+ $this->start_controls_tabs( 'tabs_upload_button_style' );
+
+ $this->start_controls_tab( 'tab_upload_button_normal', [ 'label' => __( 'Normal', 'wp-user-frontend' ) ] );
+
+ $this->add_control(
+ 'upload_button_bg_color',
+ [
+ 'label' => __( 'Background Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#6b7280',
+ 'selectors' => [ $btn_selector => 'background-color: {{VALUE}};' ],
+ ]
+ );
+
+ $this->add_control(
+ 'upload_button_text_color',
+ [
+ 'label' => __( 'Text Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#ffffff',
+ 'selectors' => [ $btn_selector => 'color: {{VALUE}};' ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Typography::get_type(),
+ [
+ 'name' => 'upload_button_typography',
+ 'selector' => $btn_selector,
+ 'fields_options' => [
+ 'font_weight' => [
+ 'default' => '500',
+ ],
+ 'font_size' => [
+ 'default' => [
+ 'unit' => 'px',
+ 'size' => '16',
+ ],
+ ],
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Border::get_type(),
+ [
+ 'name' => 'upload_button_border',
+ 'selector' => $btn_selector,
+ 'fields_options' => [
+ 'border' => [
+ 'default' => 'solid',
+ ],
+ 'width' => [
+ 'default' => [
+ 'top' => '0',
+ 'right' => '0',
+ 'bottom' => '0',
+ 'left' => '0',
+ ],
+ ],
+ 'color' => [
+ 'default' => 'transparent',
+ ],
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'upload_button_border_radius',
+ [
+ 'label' => __( 'Border Radius', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => [ 'px', '%' ],
+ 'default' => [
+ 'top' => '6',
+ 'right' => '6',
+ 'bottom' => '6',
+ 'left' => '6',
+ 'unit' => 'px',
+ ],
+ 'selectors' => [ $btn_selector => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'upload_button_padding',
+ [
+ 'label' => __( 'Padding', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => [ 'px', 'em', '%' ],
+ 'default' => [
+ 'top' => '12',
+ 'right' => '24',
+ 'bottom' => '12',
+ 'left' => '24',
+ 'unit' => 'px',
+ ],
+ 'selectors' => [ $btn_selector => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Box_Shadow::get_type(),
+ [
+ 'name' => 'upload_button_box_shadow',
+ 'selector' => $btn_selector,
+ 'separator' => 'before',
+ 'fields_options' => [
+ 'box_shadow_type' => [
+ 'default' => 'yes',
+ ],
+ 'box_shadow' => [
+ 'default' => [
+ 'horizontal' => 0,
+ 'vertical' => 1,
+ 'blur' => 3,
+ 'spread' => 0,
+ 'color' => 'rgba(0, 0, 0, 0.1)',
+ ],
+ ],
+ ],
+ ]
+ );
+
+ $this->end_controls_tab();
+
+ $this->start_controls_tab( 'tab_upload_button_hover', [ 'label' => __( 'Hover', 'wp-user-frontend' ) ] );
+
+ $this->add_control(
+ 'upload_button_hover_bg_color',
+ [
+ 'label' => __( 'Background Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#4b5563',
+ 'selectors' => [ $btn_selector . ':hover' => 'background-color: {{VALUE}};' ],
+ ]
+ );
+
+ $this->add_control(
+ 'upload_button_hover_text_color',
+ [
+ 'label' => __( 'Text Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#ffffff',
+ 'selectors' => [ $btn_selector . ':hover' => 'color: {{VALUE}};' ],
+ ]
+ );
+
+ $this->add_control(
+ 'upload_button_hover_border_color',
+ [
+ 'label' => __( 'Border Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'selectors' => [ $btn_selector . ':hover' => 'border-color: {{VALUE}};' ],
+ ]
+ );
+
+ $this->end_controls_tab();
+
+ $this->end_controls_tabs();
+
+ $this->end_controls_section();
+ }
+
+ /**
+ * Register submit button style controls
+ *
+ * @since WPUF_SINCE
+ *
+ * @return void
+ */
+ protected function register_submit_button_style_controls() {
+ $btn_selector = '{{WRAPPER}} .wpuf-form .wpuf-submit-button';
+
+ $this->start_controls_section(
+ 'section_submit_button_style',
+ [
+ 'label' => __( 'Submit Button', 'wp-user-frontend' ),
+ 'tab' => Controls_Manager::TAB_STYLE,
+ ]
+ );
+
+ $this->add_control(
+ 'submit_button_width_type',
+ [
+ 'label' => __( 'Width', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::SELECT,
+ 'default' => 'custom',
+ 'options' => [
+ 'full-width' => __( 'Full Width', 'wp-user-frontend' ),
+ 'custom' => __( 'Custom', 'wp-user-frontend' ),
+ ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'submit_button_align',
+ [
+ 'label' => __( 'Alignment', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::CHOOSE,
+ 'default' => 'left',
+ 'options' => [
+ 'left' => [ 'title' => __( 'Left', 'wp-user-frontend' ), 'icon' => 'eicon-h-align-left' ],
+ 'center' => [ 'title' => __( 'Center', 'wp-user-frontend' ), 'icon' => 'eicon-h-align-center' ],
+ 'right' => [ 'title' => __( 'Right', 'wp-user-frontend' ), 'icon' => 'eicon-h-align-right' ],
+ ],
+ 'selectors' => [ '{{WRAPPER}} .wpuf-form .wpuf-submit' => 'text-align: {{VALUE}};' ],
+ 'condition' => [ 'submit_button_width_type' => 'custom' ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'submit_button_width',
+ [
+ 'label' => __( 'Width', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::SLIDER,
+ 'size_units' => [ 'px', '%' ],
+ 'range' => [ 'px' => [ 'min' => 0, 'max' => 1200, 'step' => 1 ] ],
+ 'selectors' => [ $btn_selector => 'width: {{SIZE}}{{UNIT}};' ],
+ 'condition' => [ 'submit_button_width_type' => 'custom' ],
+ ]
+ );
+
+ $this->start_controls_tabs( 'tabs_submit_button_style' );
+
+ $this->start_controls_tab( 'tab_submit_button_normal', [ 'label' => __( 'Normal', 'wp-user-frontend' ) ] );
+
+ $this->add_control(
+ 'submit_button_bg_color',
+ [
+ 'label' => __( 'Background Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#6b7280',
+ 'selectors' => [ $btn_selector => 'background-color: {{VALUE}};' ],
+ ]
+ );
+
+ $this->add_control(
+ 'submit_button_text_color',
+ [
+ 'label' => __( 'Text Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#ffffff',
+ 'selectors' => [ $btn_selector => 'color: {{VALUE}};' ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Typography::get_type(),
+ [
+ 'name' => 'submit_button_typography',
+ 'selector' => $btn_selector,
+ 'fields_options' => [
+ 'font_weight' => [
+ 'default' => '500',
+ ],
+ 'font_size' => [
+ 'default' => [
+ 'unit' => 'px',
+ 'size' => '16',
+ ],
+ ],
+ ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Border::get_type(),
+ [
+ 'name' => 'submit_button_border',
+ 'selector' => $btn_selector,
+ 'fields_options' => [
+ 'border' => [
+ 'default' => 'solid',
+ ],
+ 'width' => [
+ 'default' => [
+ 'top' => '0',
+ 'right' => '0',
+ 'bottom' => '0',
+ 'left' => '0',
+ ],
+ ],
+ 'color' => [
+ 'default' => 'transparent',
+ ],
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'submit_button_border_radius',
+ [
+ 'label' => __( 'Border Radius', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => [ 'px', '%' ],
+ 'default' => [
+ 'top' => '6',
+ 'right' => '6',
+ 'bottom' => '6',
+ 'left' => '6',
+ 'unit' => 'px',
+ ],
+ 'selectors' => [ $btn_selector => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ],
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'submit_button_padding',
+ [
+ 'label' => __( 'Padding', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::DIMENSIONS,
+ 'size_units' => [ 'px', 'em', '%' ],
+ 'default' => [
+ 'top' => '12',
+ 'right' => '24',
+ 'bottom' => '12',
+ 'left' => '24',
+ 'unit' => 'px',
+ ],
+ 'selectors' => [ $btn_selector => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ],
+ ]
+ );
+
+ $this->add_group_control(
+ Group_Control_Box_Shadow::get_type(),
+ [
+ 'name' => 'submit_button_box_shadow',
+ 'selector' => $btn_selector,
+ 'separator' => 'before',
+ 'fields_options' => [
+ 'box_shadow_type' => [
+ 'default' => 'yes',
+ ],
+ 'box_shadow' => [
+ 'default' => [
+ 'horizontal' => 0,
+ 'vertical' => 1,
+ 'blur' => 3,
+ 'spread' => 0,
+ 'color' => 'rgba(0, 0, 0, 0.1)',
+ ],
+ ],
+ ],
+ ]
+ );
+
+ $this->end_controls_tab();
+
+ $this->start_controls_tab( 'tab_submit_button_hover', [ 'label' => __( 'Hover', 'wp-user-frontend' ) ] );
+
+ $this->add_control(
+ 'submit_button_hover_bg_color',
+ [
+ 'label' => __( 'Background Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#4b5563',
+ 'selectors' => [ $btn_selector . ':hover' => 'background-color: {{VALUE}};' ],
+ ]
+ );
+
+ $this->add_control(
+ 'submit_button_hover_text_color',
+ [
+ 'label' => __( 'Text Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#ffffff',
+ 'selectors' => [ $btn_selector . ':hover' => 'color: {{VALUE}};' ],
+ ]
+ );
+
+ $this->add_control(
+ 'submit_button_hover_border_color',
+ [
+ 'label' => __( 'Border Color', 'wp-user-frontend' ),
+ 'type' => Controls_Manager::COLOR,
+ 'selectors' => [ $btn_selector . ':hover' => 'border-color: {{VALUE}};' ],
+ ]
+ );
+
+ $this->end_controls_tab();
+
+ $this->end_controls_tabs();
+
+ $this->end_controls_section();
+ }
+
+ /**
+ * Render the widget output on the frontend
+ *
+ * @since WPUF_SINCE
+ *
+ * @return void
+ */
+ protected function render() {
+ $settings = $this->get_settings_for_display();
+ $form_id = isset( $settings['form_id'] ) ? $settings['form_id'] : null;
+
+ if ( empty( $form_id ) ) {
+ return;
+ }
+
+ $wrapper_classes = [ 'wpuf-elementor-widget-wrapper' ];
+
+ if ( ! empty( $settings['submit_button_width_type'] ) && 'full-width' === $settings['submit_button_width_type'] ) {
+ $wrapper_classes[] = 'wpuf-elementor-submit-full';
+ }
+
+ if ( ! empty( $settings['upload_button_width_type'] ) && 'full-width' === $settings['upload_button_width_type'] ) {
+ $wrapper_classes[] = 'wpuf-elementor-upload-full';
+ }
+
+ /**
+ * Filters the CSS classes applied to the widget wrapper.
+ *
+ * @since WPUF_SINCE
+ *
+ * @param string[] $wrapper_classes Array of class names.
+ * @param array $settings Widget settings.
+ * @param int|null $form_id Selected form ID.
+ */
+ $wrapper_classes = apply_filters( 'wpuf_elementor_widget_wrapper_classes', $wrapper_classes, $settings, $form_id );
+
+ $this->add_render_attribute( 'wrapper', 'class', $wrapper_classes );
+
+
+ $wrapper_attributes = apply_filters( 'wpuf_elementor_widget_wrapper_attributes', [], $settings, $form_id );
+ foreach ( $wrapper_attributes as $attr_key => $attr_value ) {
+ if ( is_string( $attr_key ) && is_string( $attr_value ) ) {
+ $this->add_render_attribute( 'wrapper', $attr_key, $attr_value );
+ }
+ }
+
+ $shortcode_str = '[wpuf_form id="' . $form_id . '"]';
+ $output = do_shortcode( $shortcode_str );
+
+ $is_elementor = class_exists( '\Elementor\Plugin' ) && (
+ ( isset( \Elementor\Plugin::$instance->editor ) && \Elementor\Plugin::$instance->editor->is_edit_mode() )
+ || ( isset( \Elementor\Plugin::$instance->preview ) && \Elementor\Plugin::$instance->preview->is_preview_mode() )
+ );
+
+ echo 'get_render_attribute_string( 'wrapper' ) ) . '>';
+ echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- shortcode output
+
+ // Initialize TinyMCE in Elementor preview
+ if ( $is_elementor ) {
+ ?>
+
+ ';
+
+ /**
+ * Fires after the widget has rendered its output.
+ *
+ * @since WPUF_SINCE
+ *
+ * @param \Elementor\Widget_Base $this The widget instance.
+ */
+ do_action( 'wpuf_elementor_widget_after_render', $this );
+ }
+
+ /**
+ * Render the widget output in the editor.
+ *
+ * When empty, Elementor will fall back to using the render() method for
+ * both frontend and editor preview.
+ *
+ * @since WPUF_SINCE
+ *
+ * @access protected
+ */
+ protected function content_template() {}
+}
diff --git a/package-lock.json b/package-lock.json
index 1a60a824c..037148b94 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -929,7 +929,6 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.80.tgz",
"integrity": "sha512-kEWeMwMeIvxYkeg1gTc01awpwLbfMRZXdIhwRcakd/KlK53jmRC26LqcbIt7fnAQTu5GzlnWmzA3H6+l1u6xxQ==",
"dev": true,
- "peer": true,
"dependencies": {
"undici-types": "~5.26.4"
}
@@ -1899,7 +1898,6 @@
"url": "https://github.com/sponsors/ai"
}
],
- "peer": true,
"dependencies": {
"caniuse-lite": "^1.0.30001646",
"electron-to-chromium": "^1.5.4",
@@ -4617,7 +4615,6 @@
"resolved": "https://registry.npmjs.org/grunt/-/grunt-1.5.3.tgz",
"integrity": "sha512-mKwmo4X2d8/4c/BmcOETHek675uOqw0RuA/zy12jaspWqvTp4+ZeQF1W+OTpcbncnaBsfbQJ6l0l4j+Sn/GmaQ==",
"dev": true,
- "peer": true,
"dependencies": {
"dateformat": "~3.0.3",
"eventemitter2": "~0.4.13",
@@ -8786,7 +8783,6 @@
"url": "https://github.com/sponsors/ai"
}
],
- "peer": true,
"dependencies": {
"nanoid": "^3.3.7",
"picocolors": "^1.0.1",
@@ -8947,7 +8943,6 @@
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
"integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
"dev": true,
- "peer": true,
"bin": {
"prettier": "bin/prettier.cjs"
},
@@ -10487,7 +10482,6 @@
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.11.tgz",
"integrity": "sha512-qhEuBcLemjSJk5ajccN9xJFtM/h0AVCPaA6C92jNP+M2J8kX+eMJHI7R2HFKUvvAsMpcfLILMCFYSeDwpMmlUg==",
"dev": true,
- "peer": true,
"dependencies": {
"@alloc/quick-lru": "^5.2.0",
"arg": "^5.0.2",
@@ -11356,7 +11350,6 @@
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.4.tgz",
"integrity": "sha512-RHFCkULitycHVTtelJ6jQLd+KSAAzOgEYorV32R2q++M6COBjKJR6BxqClwp5sf0XaBDjVMuJ9wnNfyAJwjMkA==",
"dev": true,
- "peer": true,
"dependencies": {
"esbuild": "^0.21.3",
"postcss": "^8.4.43",
@@ -11415,7 +11408,6 @@
"version": "3.5.4",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.4.tgz",
"integrity": "sha512-3yAj2gkmiY+i7+22A1PWM+kjOVXjU74UPINcTiN7grIVPyFFI0lpGwHlV/4xydDmobaBn7/xmi+YG8HeSlCTcg==",
- "peer": true,
"dependencies": {
"@vue/compiler-dom": "3.5.4",
"@vue/compiler-sfc": "3.5.4",
diff --git a/wpuf-functions.php b/wpuf-functions.php
index 1ac383782..c0d6e9644 100644
--- a/wpuf-functions.php
+++ b/wpuf-functions.php
@@ -1492,6 +1492,11 @@ function wpuf_shortcode_map( $location, $post_id = null, $args = [], $meta_key =