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
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