Skip to content
2 changes: 1 addition & 1 deletion src/components/base-control2/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export const BaseControl = props => {
{ props.after }
</div>
</div>
<div className="stk-control-content">
<div className="stk-control-content" data-attribute={ props.attribute }>
{ props.children }
</div>
</VisualGuide>
Expand Down
14 changes: 11 additions & 3 deletions src/components/block-styles-control/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@ export const BlockStylesControl = props => {
} else {
setOpenProNotice( value => ! value )
}

setOpenPopover( false )
}

const SaveUpdateModal = applyFilters( 'stackable.global-settings.global-block-styles.save-update-modal', Fragment )
Expand All @@ -233,11 +235,13 @@ export const BlockStylesControl = props => {
>
<Button
variant="tertiary"
className="ugb-block-styles-controls__block-style-button"
className={ classnames( 'ugb-block-styles-controls__block-style-button', {
'is-opened': openPopover,
} ) }
size="small"
icon="edit"
iconSize={ 12 }
onMouseDown={ () => setOpenPopover( isOpen => ! isOpen ) }
onClick={ () => setOpenPopover( isOpen => ! isOpen ) }
ref={ buttonRef }
>
{ `${ __( 'Block Style', i18n ) }:` } <wbr /> { blockStyleLabel }{ isModified && inBlockStyleOptions ? <span className="stk-panel-modified-indicator stk--visible"></span> : '' }
Expand Down Expand Up @@ -267,7 +271,6 @@ export const BlockStylesControl = props => {
className="ugb-button-icon-control__popover ugb-block-styles-controls__popover"
anchor={ buttonRef.current }
onEscape={ () => setOpenPopover( false ) }
onClose={ () => setOpenPopover( false ) }
focusOnMount={ false }
placement="left-start"
resize={ false }
Expand Down Expand Up @@ -297,6 +300,8 @@ export const BlockStylesControl = props => {
onClick={ () => onSelectBlockStyle( option.slug, index + 1 ) }
className={ blockStyle === option.slug ? 'ugb-block-styles-controls__selected' : '' }
tabIndex={ 0 }
data-slug={ option.slug }
data-name={ option.name }
>
{ blockStyle === option.slug && <span className="ugb-block-styles-controls__selected-icon"> <Dashicon icon="saved" /> </span> }
<span className="ugb-block-styles-controls__label">
Expand All @@ -313,6 +318,7 @@ export const BlockStylesControl = props => {
blockStyle={ blockStyle }
inOptions={ inBlockStyleOptions }
isModified={ isModified }
buttonClassName={ `${ openSaveModal ? 'is-opened' : '' }` }
setOpenSaveModal={ setOpenSaveModal }
onAddBlockStyle={ onAddBlockStyle }
/>
Expand Down Expand Up @@ -347,6 +353,8 @@ const SaveUpdateButtons = props => {
variant="primary"
onClick={ () => onAddBlockStyle() }
size="small"
data-action="save-style"
className={ props.buttonClassName }
>
{ __( 'Save New Block Style', i18n ) }
{ ! isPro && <span className="stk-pulsating-circle" role="presentation" /> }
Expand Down
1 change: 1 addition & 0 deletions src/components/color-palette-control/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ const ColorPaletteControl = memo( props => {
{ ...controlProps }
className={ classnames( [ className, 'editor-color-palette-control', 'stk-color-palette-control' ] ) }
label={ label }
data-attribute={ props.attribute }
>
{ props.isExpanded && colorPalette }
{ ! props.isExpanded && (
Expand Down
3 changes: 2 additions & 1 deletion src/components/guided-modal-tour/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@
}
}
}
&.ugb-tour-modal--left-top {
&.ugb-tour-modal--left-top,
&.ugb-tour-modal--right-top {
.components-modal__content {
&::after {
top: 30px;
Expand Down
4 changes: 3 additions & 1 deletion src/components/guided-modal-tour/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { models } from '@wordpress/api'
import {
useEffect, useState, lazy, Suspense, memo,
} from '@wordpress/element'
import { applyFilters } from '@wordpress/hooks'

// The main tour component.
const GuidedModalTour = memo( props => {
Expand Down Expand Up @@ -59,7 +60,8 @@ const GuidedModalTour = memo( props => {
// condition can be true, false, or null. true will show the tour (even if
// it's already done), false will not show the tour, null will show the tour
// only once (normal behavior).
const condition = TOUR_CONDITIONS[ tourId ]
const conditions = applyFilters( 'stackable.guided-tour.conditions', TOUR_CONDITIONS )
const condition = conditions[ tourId ]
const conditionResult = condition ? condition() : null
if ( conditionResult === false ) {
return null
Expand Down
20 changes: 20 additions & 0 deletions src/components/guided-modal-tour/tour-conditions.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,24 @@ export const TOUR_CONDITIONS = {
// Force show the tour if there is a GET parameter tour=site-kit
return window?.location?.search?.includes( 'tour=site-kit' ) ? true : null
},
'block-backgrounds': () => {
// Force show the tour if there is a GET parameter tour=block-backgrounds
return window?.location?.search?.includes( 'tour=block-backgrounds' ) ? true : null
},
'responsive-controls': () => {
// Force show the tour if there is a GET parameter tour=responsive-controls
return window?.location?.search?.includes( 'tour=responsive-controls' ) ? true : null
},
'hover-states': () => {
// Force show the tour if there is a GET parameter tour=hover-states
return window?.location?.search?.includes( 'tour=hover-states' ) ? true : null
},
'advanced-hover-states': () => {
// Force show the tour if there is a GET parameter tour=advanced-hover-states
return window?.location?.search?.includes( 'tour=advanced-hover-states' ) ? true : null
},
'global-color-schemes': () => {
// Force show the tour if there is a GET parameter tour=global-color-schemes
return window?.location?.search?.includes( 'tour=global-color-schemes' ) ? true : null
},
}
1 change: 1 addition & 0 deletions src/components/sortable-picker/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ const LabeledItemIndicator = props => {
}
} }
isPressed={ isOpen }
data-item-key={ item.key || item.slug || item.name }
>
<HStack justify="flex-start">
<ItemPreview item={ item } />
Expand Down
80 changes: 57 additions & 23 deletions src/lazy-components/modal-tour/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,17 @@ const ModalTour = memo( props => {
// eslint-disable-next-line no-unused-vars
postStep = NOOP, // If provided, this is a function to run after the step is shown.
skipIf = NOOP, // If provided, this is a function to check if the step should be skipped.
modalDelay = 200, // If provided, this is the delay in milliseconds to show the modal.
anchorInIframe = false,
glowTargetInIframe = false,
} = steps[ currentStep ]

useEffect( () => {
setTimeout( () => {
initialize()
if ( currentStep === 0 && preStep ) {
preStep( currentStep )
}
}, 50 )
}, [ initialize ] )

Expand Down Expand Up @@ -146,7 +152,7 @@ const ModalTour = memo( props => {
setIsVisibleDelayed( true )
setIsTransitioning( false )
}, 150 )
}, 200 )
}, modalDelay )
}, 100 )

setTimeout( () => {
Expand Down Expand Up @@ -285,47 +291,60 @@ const ModalTour = memo( props => {

// Based on the anchor and position, calculate the X and Y offsets of the modal relative to the anchor.
// We have the modalRef.current which we can use to get the modal's bounding client rect.
const anchorRect = document.querySelector( anchor )?.getBoundingClientRect()
let anchorRect = null

let iframeRect = null
if ( anchorInIframe ) {
const iframe = document.querySelector( 'iframe[name="editor-canvas"]' )
iframeRect = iframe?.getBoundingClientRect()
anchorRect = iframe?.contentDocument?.querySelector( anchor )?.getBoundingClientRect()
} else {
anchorRect = document.querySelector( anchor )?.getBoundingClientRect()
}

if ( ! anchorRect ) {
return defaultOffset
}

const offsetCoord = ( x, y ) => {
if ( anchorInIframe && iframeRect ) {
return [ `${ x + iframeRect.left }px`, `${ y + iframeRect.top }px` ]
}
return [ `${ x }px`, `${ y }px` ]
}

switch ( position ) {
case 'left':
// Left, middle
return [ `${ anchorRect.left - modalRect.width - 16 }px`, `${ anchorRect.top + ( anchorRect.height / 2 ) - ( modalRect.height / 2 ) }px` ]
return offsetCoord( anchorRect.left - modalRect.width - 16, anchorRect.top + ( anchorRect.height / 2 ) - ( modalRect.height / 2 ) )
case 'left-top':
return [ `${ anchorRect.left - modalRect.width - 16 }px`, `${ anchorRect.top + 16 }px` ]
return offsetCoord( anchorRect.left - modalRect.width - 16, anchorRect.top + 16 )
case 'left-bottom':
return [ `${ anchorRect.left - modalRect.width - 16 }px`, `${ anchorRect.bottom - modalRect.height - 16 }px` ]
return offsetCoord( anchorRect.left - modalRect.width - 16, anchorRect.bottom - modalRect.height - 16 )
case 'right':
// Right, middle
return [ `${ anchorRect.right + 16 }px`, `${ anchorRect.top + ( anchorRect.height / 2 ) - ( modalRect.height / 2 ) }px` ]
return offsetCoord( anchorRect.right + 16, anchorRect.top + ( anchorRect.height / 2 ) - ( modalRect.height / 2 ) )
case 'right-top':
return [ `${ anchorRect.right + 16 }px`, `${ anchorRect.top + 16 }px` ]
return offsetCoord( anchorRect.right + 16, anchorRect.top + 16 )
case 'right-bottom':
return [ `${ anchorRect.right + 16 }px`, `${ anchorRect.bottom - modalRect.height - 16 }px` ]
return offsetCoord( anchorRect.right + 16, anchorRect.bottom - modalRect.height - 16 )
case 'top':
// Center, top
return [ `${ anchorRect.left + ( anchorRect.width / 2 ) - ( modalRect.width / 2 ) }px`, `${ anchorRect.top - modalRect.height - 16 }px` ]
return offsetCoord( anchorRect.left + ( anchorRect.width / 2 ) - ( modalRect.width / 2 ), anchorRect.top - modalRect.height - 16 )
case 'top-left':
return [ `${ anchorRect.left + 16 }px`, `${ anchorRect.top - modalRect.height - 16 }px` ]
return offsetCoord( anchorRect.left + 16, anchorRect.top - modalRect.height - 16 )
case 'top-right':
return [ `${ anchorRect.right - modalRect.width - 16 }px`, `${ anchorRect.top - modalRect.height - 16 }px` ]
return offsetCoord( anchorRect.right - modalRect.width - 16, anchorRect.top - modalRect.height - 16 )
case 'bottom':
// Center, bottom
return [ `${ anchorRect.left + ( anchorRect.width / 2 ) - ( modalRect.width / 2 ) }px`, `${ anchorRect.bottom + 16 }px` ]
return offsetCoord( anchorRect.left + ( anchorRect.width / 2 ) - ( modalRect.width / 2 ), anchorRect.bottom + 16 )
case 'bottom-left':
return [ `${ anchorRect.left + 16 }px`, `${ anchorRect.bottom + 16 }px` ]
return offsetCoord( anchorRect.left + 16, anchorRect.bottom + 16 )
case 'bottom-right':
return [ `${ anchorRect.right - modalRect.width - 16 }px`, `${ anchorRect.bottom + 16 }px` ]
return offsetCoord( anchorRect.right - modalRect.width - 16, anchorRect.bottom + 16 )
case 'center':
return [ `${ anchorRect.left + ( anchorRect.width / 2 ) - ( modalRect.width / 2 ) }px`, `${ anchorRect.top + ( anchorRect.height / 2 ) - ( modalRect.height / 2 ) }px` ]
return offsetCoord( anchorRect.left + ( anchorRect.width / 2 ) - ( modalRect.width / 2 ), anchorRect.top + ( anchorRect.height / 2 ) - ( modalRect.height / 2 ) )
case 'center-top':
return [ `${ anchorRect.left + ( anchorRect.width / 2 ) - ( modalRect.width / 2 ) }px`, `${ anchorRect.top + 16 }px` ]
return offsetCoord( anchorRect.left + ( anchorRect.width / 2 ) - ( modalRect.width / 2 ), anchorRect.top + 16 )
case 'center-bottom':
return [ `${ anchorRect.left + ( anchorRect.width / 2 ) - ( modalRect.width / 2 ) }px`, `${ anchorRect.bottom - modalRect.height - 16 }px` ]
return offsetCoord( anchorRect.left + ( anchorRect.width / 2 ) - ( modalRect.width / 2 ), anchorRect.bottom - modalRect.height - 16 )
default:
return defaultOffset
}
Expand All @@ -335,7 +354,12 @@ const ModalTour = memo( props => {
useEffect( () => {
if ( glowTarget && isVisibleDelayed ) {
// Get the top, left, width, and height of the target.
const target = document.querySelector( glowTarget )
let target = null
if ( glowTargetInIframe ) {
target = document.querySelector( 'iframe[name="editor-canvas"]' )?.contentDocument?.querySelector( glowTarget )
} else {
target = document.querySelector( glowTarget )
}
if ( target ) {
const targetRect = target.getBoundingClientRect()

Expand All @@ -347,8 +371,18 @@ const ModalTour = memo( props => {
// Create the element.
if ( glowElementRef.current ) {
glowElementRef.current.className = `ugb-tour-modal__glow ugb-tour-modal__glow--${ glowTargetSize }`
glowElementRef.current.style.top = `${ targetRect.top - 8 }px`
glowElementRef.current.style.left = `${ targetRect.left - 8 }px`
let top = targetRect.top - 8
let left = targetRect.left - 8
if ( glowTargetInIframe ) {
const iframe = document.querySelector( 'iframe[name="editor-canvas"]' )
if ( iframe ) {
const iframeRect = iframe.getBoundingClientRect()
left += iframeRect.left
top += iframeRect.top
}
}
glowElementRef.current.style.top = `${ top }px`
glowElementRef.current.style.left = `${ left }px`
glowElementRef.current.style.width = `${ targetRect.width + 16 }px`
glowElementRef.current.style.height = `${ targetRect.height + 16 }px`
}
Expand Down
Loading
Loading