Skip to content
Open
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
9 changes: 4 additions & 5 deletions interactions.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,12 @@ function interact_on_activation() {
require_once( plugin_dir_path( __FILE__ ) . 'src/editor/editor.php' );
} else {
add_action( 'after_setup_theme', function() {
if (
( function_exists( 'bricks_is_builder_main' ) && bricks_is_builder_main() ) ||
( function_exists( 'bricks_is_builder' ) && bricks_is_builder() )
) {
if ( function_exists( 'et_core_is_fb_enabled' ) ||
function_exists( 'bricks_is_builder_main' ) ||
function_exists( 'bricks_is_builder' ) ) {
require_once( plugin_dir_path( __FILE__ ) . 'src/editor/editor.php' );
}
} );
}, 20 );
}

/**
Expand Down
41 changes: 41 additions & 0 deletions src/editor/app.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import ElementSVG from './assets/element.svg'
import PageSVG from './assets/page.svg'
import LibrarySVG from './assets/library.svg'
import {
AddInteractionButton,
InteractionButton,
Expand All @@ -8,6 +9,10 @@ import {
} from './components'
import { createNewInteraction, createNewAction } from './util'
import { useInteractions } from './hooks'
import {
getCurrentSelectedTarget,
isBuilderEditor,
} from './editors'
import { interactions as interactionsConfig, manageInteractionsUrl } from 'interactions'

import { __ } from '@wordpress/i18n'
Expand Down Expand Up @@ -74,6 +79,7 @@ const InteractionsApp = ( {
// Interaction library open modal and set target function.
const {
setMode: setInteractionLibraryMode,
setTarget: setInteractionLibraryTarget,
} = useDispatch( 'interact/interaction-library-modal' )

const [ selectedInteraction, setSelectedInteraction ] = useState( null )
Expand Down Expand Up @@ -208,6 +214,18 @@ const InteractionsApp = ( {
setImportExportModalProps( null )
}

const onOpenInteractionLibraryHandler = () => {
const selectedTarget = getCurrentSelectedTarget()

if ( ! selectedTarget ) {
alert( __( 'Select an element in the editor first before opening the Interaction Library.', 'interactions' ) ) // eslint-disable-line no-alert
return
}

setInteractionLibraryTarget( selectedTarget )
setInteractionLibraryMode( 'apply' )
}

return <>
{ selectedInteraction === null && loadingError && isShowingError &&
<PanelBody>
Expand Down Expand Up @@ -236,6 +254,29 @@ const InteractionsApp = ( {
</Notice>
</PanelBody>
}
{ isBuilderEditor() && selectedInteraction === null &&
<PanelBody>
<BaseControl
className="interact-list-control"
label={ __( 'Interaction Library', 'interactions' ) }
>
<div className="interact-panel-side-buttons">
<Button
icon={ <LibrarySVG width="20" height="20" /> }
onClick={ onOpenInteractionLibraryHandler }
>
{ __( 'Apply', 'interactions' ) }
</Button>
<Button
icon={ <LibrarySVG width="20" height="20" /> }
disabled
>
{ __( 'Insert', 'interactions' ) }
</Button>
</div>
</BaseControl>
</PanelBody>
}
{ allInteractions.length > 0 && selectedInteraction === null &&
<PanelBody>
{ interactions.length > 0 && <p className="interact-editor-footer">{ __( 'These interactions are on this page because of their location rules.', 'interactions' ) }</p> }
Expand Down
13 changes: 8 additions & 5 deletions src/editor/components/interaction-panel/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
useLayoutEffect,
} from '@wordpress/element'
import { Icon, download } from '@wordpress/icons'
import { saveCurrentEditor } from '~interact/editor/editors'
import TargetSelector from '../target-selector'
import { getInteractionWarning } from './util'

Expand Down Expand Up @@ -225,11 +226,13 @@ const InteractionPanel = props => {
setStatus( 'publishing' )
// TODO: if publishing and then we are missing a target, we should show a notice.
onChange( editedInteraction ).then( () => {
setStatus( 'idle' )
setIsDirty( false )
if ( callback ) {
setTimeout( callback, 1 ) // Need a timeout here because re-publishing may be too fast.
}
return Promise.resolve( saveCurrentEditor() ).finally( () => {
setStatus( 'idle' )
setIsDirty( false )
if ( callback ) {
setTimeout( callback, 1 ) // Need a timeout here because re-publishing may be too fast.
}
} )
} )
}, [ editedInteraction, onChange ] )

Expand Down
16 changes: 13 additions & 3 deletions src/editor/components/target-selector/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { GridLayout, FlexLayout } from '~interact/editor/components'
import {
getSelectedBlockAnchor,
isBricksEditor,
isDiviEditor,
isElementorEditor,
startEditorElementPicker,
} from '~interact/editor/editors'
Expand Down Expand Up @@ -43,7 +44,7 @@ const TargetSelector = props => {
noArrow = false,
} = props

const isBuilder = isBricksEditor() || isElementorEditor()
const isBuilder = isBricksEditor() || isElementorEditor() || isDiviEditor()
const isElementor = isElementorEditor()
const hasBlockEditor = !! select( 'core/block-editor' )?.getSelectedBlockClientId
const [ isPopoverOpen, setIsPopoverOpen ] = useState( false )
Expand All @@ -59,6 +60,8 @@ const TargetSelector = props => {
const displayType = isElementor && elementorUiType === 'elementor-element'
? 'elementor-element'
: value.type
// Remove the picker button for Divi when the target type is class, since Divi doesn't support it.
const isDiviManualClassInput = isDiviEditor() && displayType === 'class'

const targetButton = (
<>
Expand Down Expand Up @@ -219,6 +222,13 @@ const TargetSelector = props => {
targetOptions = targetOptions.filter( target => bricksTargetTypes.includes( target.value ) )
}

if ( isDiviEditor() ) {
const diviTargetOrder = [ 'selector', 'class', 'trigger', 'window' ]
targetOptions = diviTargetOrder
.map( targetValue => targetOptions.find( target => target.value === targetValue ) )
.filter( Boolean )
}

useEffect( () => {
return () => {
elementPickerStopRef.current?.()
Expand Down Expand Up @@ -313,7 +323,7 @@ const TargetSelector = props => {
) }
{ displayType === 'class' && (
<FlexLayout justifyContent="start">
{ isHorizontal && targetButton }
{ isHorizontal && ! isDiviManualClassInput && targetButton }
<TextControl
label={ __( 'CSS Class', 'interactions' ) }
value={ value.value }
Expand All @@ -331,7 +341,7 @@ const TargetSelector = props => {
}
} }
/>
{ ! isHorizontal && targetButton }
{ ! isHorizontal && ! isDiviManualClassInput && targetButton }
</FlexLayout>
) }
{ displayType === 'block-name' && (
Expand Down
29 changes: 29 additions & 0 deletions src/editor/editor.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ function __construct() {
}
add_action( 'elementor/editor/after_enqueue_scripts', array( $this, 'enqueue_elementor_editor' ) );

// Only register the Divi builder enqueue callback when Divi is
// present on the request.
if ( function_exists( 'et_core_is_fb_enabled' ) ) {
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_divi_editor' ) );
}

// Only register the Bricks builder enqueue callback when Bricks is
// present on the request.
if ( function_exists( 'bricks_is_builder_main' ) || function_exists( 'bricks_is_builder' ) ) {
Expand Down Expand Up @@ -70,6 +76,29 @@ public function enqueue_bricks_editor() {
$this->enqueue_editor( 'bricks' );
}

/**
* Loads the editor script inside Divi's Visual Builder top window.
*
* @return void
*/
public function enqueue_divi_editor() {
$is_divi_builder = function_exists( 'et_core_is_fb_enabled' ) &&
et_core_is_fb_enabled() &&
( ! isset( $_GET['app_window'] ) || '1' !== $_GET['app_window'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended

if ( ! $is_divi_builder ) {
return;
}

// Defense-in-depth: only load the builder editor for users who can
// edit content, even if the request matches Divi's builder URL.
if ( ! current_user_can( 'edit_posts' ) ) {
return;
}

$this->enqueue_editor( 'divi' );
}

/**
* Loads the editor script.
*
Expand Down
11 changes: 9 additions & 2 deletions src/editor/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@
/* Interaction Elementor Editor Panel Styles */

.interact-elementor-launcher,
.interact-bricks-launcher {
.interact-bricks-launcher,
.interact-divi-launcher {
display: inline-flex;
align-items: center;
justify-content: flex-start;
Expand Down Expand Up @@ -181,7 +182,8 @@
}

.interact-elementor-launcher.is-hidden,
.interact-bricks-launcher.is-hidden {
.interact-bricks-launcher.is-hidden,
.interact-divi-launcher.is-hidden {
opacity: 0;
pointer-events: none;
}
Expand Down Expand Up @@ -230,6 +232,11 @@
}
}

.interact-divi-panel {
top: 0;
height: 100vh;
}

.interact-pagebuilder-panel.is-open {
transform: translateX(0);
}
Expand Down
30 changes: 29 additions & 1 deletion src/editor/editors/abstract.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
pluginVersion,
srcUrl,
} from 'interactions'
import { applyTargetMappings } from '../interaction-library/util'
import { select } from '@wordpress/data'

const NOOP = () => {}
Expand Down Expand Up @@ -36,12 +37,16 @@ class InteractionsEditorAbstract {
return this.getEditorMode() === 'bricks'
}

isDivi() {
return this.getEditorMode() === 'divi'
}

isGutenberg() {
return this.getEditorMode() === 'gutenberg'
}

isBuilder() {
return this.isElementor() || this.isBricks()
return this.isElementor() || this.isBricks() || this.isDivi()
}

ensureBuilderEditorStyles() {
Expand Down Expand Up @@ -111,6 +116,29 @@ class InteractionsEditorAbstract {
return NOOP
}

// Persist the parent editor when the interaction data should also be saved.
saveEditor() {
return Promise.resolve()
}

// Insert a library preset into the current editor and return the inserted
// content descriptor so target mappings can be resolved afterward.
insertLibraryPreset() {
return null
}

// Resolve a preset's target mappings against either inserted editor content
// or a selected target object, depending on the current library mode.
resolveLibraryPresetTargets( interactionSetup, selectedPreset = {}, insertionContext = null ) {
applyTargetMappings(
interactionSetup,
selectedPreset.targetMappings,
insertionContext
)

return interactionSetup
}

// Start an editor-specific target picker.
startElementPicker( args = {} ) {
const {
Expand Down
2 changes: 2 additions & 0 deletions src/editor/editors/bricks.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import IconSVG from '../assets/icon.svg'
import InteractionsApp from '../app'
import InteractionsEditorAbstract from './abstract'
import { InteractionLibraryRoot } from '../interaction-library'

import { __ } from '@wordpress/i18n'
import { Button } from '@wordpress/components'
Expand Down Expand Up @@ -90,6 +91,7 @@ class BricksInteractionsEditor extends InteractionsEditorAbstract {
</div>
</div>
</div>
<InteractionLibraryRoot />
</>
)
}
Expand Down
Loading
Loading