woocommerce/plugins/woocommerce-admin/client/customize-store/assembler-hub/toolbar/toolbar.tsx

248 lines
6.7 KiB
TypeScript
Raw Normal View History

/* eslint-disable @woocommerce/dependency-group */
/**
* External dependencies
*/
import { BlockInstance } from '@wordpress/blocks';
import {
ToolbarGroup,
Toolbar as WPToolbar,
Popover,
} from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import {
useContext,
useEffect,
useMemo,
useRef,
useState,
} from '@wordpress/element';
import {
BlockMover,
store as blockEditorStore,
// @ts-expect-error missing type
} from '@wordpress/block-editor';
/**
* Internal dependencies
*/
import { useQuery } from '@woocommerce/navigation';
import Shuffle from './shuffle';
import Delete from './delete';
import './style.scss';
import { useIsNoBlocksPlaceholderPresent } from '../hooks/block-placeholder/use-is-no-blocks-placeholder-present';
import { SelectedBlockContext } from '../context/selected-block-ref-context';
CYS: Add Zoomed Out feature (#50070) * useZoomOut hook * Update iframe with logic with zoomed out feature * Add back in styling code for margins * Spaces to tabs * Device size toolbar * Move zoom out state to context * Rename variable * Fork iframe component from Gutenberg * Add getCompatibilityStyles needed for forked iframe * Update usePopoverHandler iframe selector * Remove zoom out context as its not needed * Revert "Remove zoom out context as its not needed" This reverts commit b29780d805a38f719ca7317e47d9c4bc0fca2c47. * Add Zoom Out toggle to icons WIP * Fix icon fill * Update selectors to fix toolbar and sidebar pattern bugs * Add comment to get getCompatibilityStyles file * Update iframe comment * Move device toolbar into its own component * Resize and device changes * Add prop to disable the resize handler * Update toolbar to work with Zoom Out * Hide changes behind feature gate so they dont impact design with AI flow * Toolbar account for top device bar * Add body class for with/without AI flow * Adds changelog * Fix typo * Change TS comment to expect error * Cleanup iframe with unneeded code * Remove getcompatibilitystyles * Remove device code from resizable frame * Add ? operator * Remove keydown code from iframe * Fix toolbar scroll * Pass deviceType as a prop to resizable frame * Disable devicetoolbar whilst editor is loading * Disable focus state * Remove comment * not disabled selector for button hover states * Fix linting * Remove unused fn * Focus specific styles
2024-08-06 13:29:21 +00:00
import { isFullComposabilityFeatureAndAPIAvailable } from '../utils/is-full-composability-enabled';
const isHomepageUrl = ( path: string ) => {
return path.includes( '/customize-store/assembler-hub/homepage' );
};
export const Toolbar = () => {
const [ isHomepageSidebarOpen, setIsHomepageSidebarOpen ] =
useState( false );
const {
currentBlock,
nextBlock,
previousBlock,
allBlocks,
}: {
currentBlock: BlockInstance | undefined;
nextBlock: BlockInstance | undefined;
previousBlock: BlockInstance | undefined;
allBlocks: BlockInstance[];
} = useSelect( ( select ) => {
const selectedBlockId =
// @ts-expect-error missing type
select( blockEditorStore ).getSelectedBlockClientId();
const nextBlockClientId =
// @ts-expect-error missing type
select( blockEditorStore ).getNextBlockClientId();
const previousBlockClientId =
// @ts-expect-error missing type
select( blockEditorStore ).getPreviousBlockClientId();
// @ts-expect-error missing type
const [ current ] = select( blockEditorStore ).getBlocksByClientId( [
selectedBlockId,
] );
// @ts-expect-error missing type
const [ next ] = select( blockEditorStore ).getBlocksByClientId( [
nextBlockClientId,
] );
const [ previous ] = select(
blockEditorStore
// @ts-expect-error missing type
).getBlocksByClientId( [ previousBlockClientId ] );
const blocks = select(
blockEditorStore
// @ts-expect-error missing type
).getBlocks();
return {
currentBlock: current,
nextBlock: next,
previousBlock: previous,
allBlocks: blocks,
};
}, [] );
const query = useQuery();
useEffect( () => {
const path = query.path;
if ( ! path ) {
return;
}
setIsHomepageSidebarOpen( isHomepageUrl( path ) );
}, [ query ] );
const selectedBlockClientId = currentBlock?.clientId ?? null;
const { isBlockMoverUpButtonDisabled, isBlockMoverDownButtonDisabled } =
useMemo( () => {
const isPreviousBlockTemplatePart =
previousBlock?.name === 'core/template-part';
const isNextBlockTemplatePart =
nextBlock?.name === 'core/template-part';
return {
isBlockMoverUpButtonDisabled:
isPreviousBlockTemplatePart ||
// The first block is the header, which is not movable.
allBlocks[ 1 ]?.clientId === selectedBlockClientId,
isBlockMoverDownButtonDisabled:
isNextBlockTemplatePart ||
// The last block is the footer, which is not movable.
allBlocks[ allBlocks.length - 2 ]?.clientId ===
selectedBlockClientId,
};
}, [
allBlocks,
nextBlock?.name,
previousBlock?.name,
selectedBlockClientId,
] );
const isNoBlocksPlaceholderPresent =
useIsNoBlocksPlaceholderPresent( allBlocks );
const isHeaderOrFooter = useMemo( () => {
const selectedBlock = allBlocks.find( ( { clientId } ) => {
return clientId === selectedBlockClientId;
} );
return selectedBlock?.name === 'core/template-part';
}, [ allBlocks, selectedBlockClientId ] );
const { selectedBlockRef } = useContext( SelectedBlockContext );
const blockPopoverRef = useRef< HTMLDivElement | null >( null );
CYS: Add Zoomed Out feature (#50070) * useZoomOut hook * Update iframe with logic with zoomed out feature * Add back in styling code for margins * Spaces to tabs * Device size toolbar * Move zoom out state to context * Rename variable * Fork iframe component from Gutenberg * Add getCompatibilityStyles needed for forked iframe * Update usePopoverHandler iframe selector * Remove zoom out context as its not needed * Revert "Remove zoom out context as its not needed" This reverts commit b29780d805a38f719ca7317e47d9c4bc0fca2c47. * Add Zoom Out toggle to icons WIP * Fix icon fill * Update selectors to fix toolbar and sidebar pattern bugs * Add comment to get getCompatibilityStyles file * Update iframe comment * Move device toolbar into its own component * Resize and device changes * Add prop to disable the resize handler * Update toolbar to work with Zoom Out * Hide changes behind feature gate so they dont impact design with AI flow * Toolbar account for top device bar * Add body class for with/without AI flow * Adds changelog * Fix typo * Change TS comment to expect error * Cleanup iframe with unneeded code * Remove getcompatibilitystyles * Remove device code from resizable frame * Add ? operator * Remove keydown code from iframe * Fix toolbar scroll * Pass deviceType as a prop to resizable frame * Disable devicetoolbar whilst editor is loading * Disable focus state * Remove comment * not disabled selector for button hover states * Fix linting * Remove unused fn * Focus specific styles
2024-08-06 13:29:21 +00:00
// Note: This feature is only available when the full composability feature flag is enabled.
const isEligibleForZoomOutFeature =
isFullComposabilityFeatureAndAPIAvailable();
const popoverAnchor = useMemo( () => {
if ( ! selectedBlockRef || ! selectedBlockClientId ) {
return undefined;
}
return {
getBoundingClientRect() {
const { top, width, height } =
selectedBlockRef.getBoundingClientRect();
CYS: Add Zoomed Out feature (#50070) * useZoomOut hook * Update iframe with logic with zoomed out feature * Add back in styling code for margins * Spaces to tabs * Device size toolbar * Move zoom out state to context * Rename variable * Fork iframe component from Gutenberg * Add getCompatibilityStyles needed for forked iframe * Update usePopoverHandler iframe selector * Remove zoom out context as its not needed * Revert "Remove zoom out context as its not needed" This reverts commit b29780d805a38f719ca7317e47d9c4bc0fca2c47. * Add Zoom Out toggle to icons WIP * Fix icon fill * Update selectors to fix toolbar and sidebar pattern bugs * Add comment to get getCompatibilityStyles file * Update iframe comment * Move device toolbar into its own component * Resize and device changes * Add prop to disable the resize handler * Update toolbar to work with Zoom Out * Hide changes behind feature gate so they dont impact design with AI flow * Toolbar account for top device bar * Add body class for with/without AI flow * Adds changelog * Fix typo * Change TS comment to expect error * Cleanup iframe with unneeded code * Remove getcompatibilitystyles * Remove device code from resizable frame * Add ? operator * Remove keydown code from iframe * Fix toolbar scroll * Pass deviceType as a prop to resizable frame * Disable devicetoolbar whilst editor is loading * Disable focus state * Remove comment * not disabled selector for button hover states * Fix linting * Remove unused fn * Focus specific styles
2024-08-06 13:29:21 +00:00
const iframe = window.document.querySelector(
'.woocommerce-customize-store-assembler > .block-editor-iframe__container iframe[name="editor-canvas"]'
);
const iframeHtmlElement =
// @ts-expect-error missing type
iframe?.contentDocument?.documentElement;
const iframeRect = iframe?.getBoundingClientRect();
const iframeHtmlElementRect =
iframeHtmlElement?.getBoundingClientRect();
const isZoomedOut =
isEligibleForZoomOutFeature &&
iframeHtmlElement?.classList.contains( 'is-zoomed-out' );
if ( ! iframeRect ) {
return new window.DOMRect( 0, 0, 0, 0 );
}
CYS: Add Zoomed Out feature (#50070) * useZoomOut hook * Update iframe with logic with zoomed out feature * Add back in styling code for margins * Spaces to tabs * Device size toolbar * Move zoom out state to context * Rename variable * Fork iframe component from Gutenberg * Add getCompatibilityStyles needed for forked iframe * Update usePopoverHandler iframe selector * Remove zoom out context as its not needed * Revert "Remove zoom out context as its not needed" This reverts commit b29780d805a38f719ca7317e47d9c4bc0fca2c47. * Add Zoom Out toggle to icons WIP * Fix icon fill * Update selectors to fix toolbar and sidebar pattern bugs * Add comment to get getCompatibilityStyles file * Update iframe comment * Move device toolbar into its own component * Resize and device changes * Add prop to disable the resize handler * Update toolbar to work with Zoom Out * Hide changes behind feature gate so they dont impact design with AI flow * Toolbar account for top device bar * Add body class for with/without AI flow * Adds changelog * Fix typo * Change TS comment to expect error * Cleanup iframe with unneeded code * Remove getcompatibilitystyles * Remove device code from resizable frame * Add ? operator * Remove keydown code from iframe * Fix toolbar scroll * Pass deviceType as a prop to resizable frame * Disable devicetoolbar whilst editor is loading * Disable focus state * Remove comment * not disabled selector for button hover states * Fix linting * Remove unused fn * Focus specific styles
2024-08-06 13:29:21 +00:00
// Here we need to account for when the iframe is zoomed out as the width changes.
const rectLeft =
isZoomedOut && iframeHtmlElementRect
? iframeRect?.left + iframeHtmlElementRect.left + 60
: iframeRect?.left + 10;
// Here we need to account for when the zoom out feature is eligible because a toolbar is added to the top of the iframe.
const rectTop = isEligibleForZoomOutFeature
? Math.max( top + 70 + iframeRect.top, iframeRect.top + 60 )
: Math.max(
top + 70 + iframeRect.top,
iframeRect.top + 60
);
return new window.DOMRect( rectLeft, rectTop, width, height );
},
};
}, [ selectedBlockRef, selectedBlockClientId ] );
if (
! isHomepageSidebarOpen ||
! selectedBlockClientId ||
isNoBlocksPlaceholderPresent ||
isHeaderOrFooter ||
! popoverAnchor
) {
return null;
}
return (
<Popover
as="div"
animate={ false }
className="components-tooltip woocommerce-customize-store_block-toolbar-popover"
// @ts-expect-error missing type
variant="unstyled"
resize={ false }
flip={ false }
shift={ true }
anchor={ popoverAnchor }
placement="top-start"
ref={ blockPopoverRef }
>
<div className="woocommerce-customize-store-block-toolbar">
<WPToolbar label="Options">
<>
<ToolbarGroup>
<BlockMover
clientIds={ [ selectedBlockClientId ] }
isBlockMoverUpButtonDisabled={
isBlockMoverUpButtonDisabled
}
isBlockMoverDownButtonDisabled={
isBlockMoverDownButtonDisabled
}
/>
</ToolbarGroup>
<Shuffle clientId={ selectedBlockClientId } />
<Delete
clientId={ selectedBlockClientId }
currentBlockName={ currentBlock?.name }
nextBlockClientId={ nextBlock?.clientId }
/>
</>
</WPToolbar>
</div>
</Popover>
);
};