/** * External dependencies */ import { ActorRefFrom, sendTo, setup, fromCallback } from 'xstate5'; import React from 'react'; import classnames from 'classnames'; import { getQuery } from '@woocommerce/navigation'; /** * Internal dependencies */ import { LaunchYourStoreHubSidebar } from './components/launch-store-hub'; import type { LaunchYourStoreComponentProps } from '..'; import type { mainContentMachine } from '../main-content/xstate'; import { updateQueryParams, createQueryParamsListener } from '../common'; export type SidebarMachineContext = { externalUrl: string | null; mainContentMachineRef: ActorRefFrom< typeof mainContentMachine >; }; export type SidebarComponentProps = LaunchYourStoreComponentProps & { context: SidebarMachineContext; }; export type SidebarMachineEvents = | { type: 'EXTERNAL_URL_UPDATE' } | { type: 'OPEN_EXTERNAL_URL'; url: string } | { type: 'OPEN_WC_ADMIN_URL'; url: string } | { type: 'OPEN_WC_ADMIN_URL_IN_CONTENT_AREA'; url: string } | { type: 'LAUNCH_STORE' } | { type: 'LAUNCH_STORE_SUCCESS' }; const sidebarQueryParamListener = fromCallback( ( { sendBack } ) => { return createQueryParamsListener( 'sidebar', sendBack ); } ); export const sidebarMachine = setup( { types: {} as { context: SidebarMachineContext; events: SidebarMachineEvents; input: { mainContentMachineRef: ActorRefFrom< typeof mainContentMachine >; }; }, actions: { openExternalUrl: ( { event } ) => { if ( event.type === 'OPEN_EXTERNAL_URL' ) { window.open( event.url, '_self' ); } }, showLaunchStoreSuccessPage: sendTo( ( { context } ) => context.mainContentMachineRef, { type: 'SHOW_LAUNCH_STORE_SUCCESS' } ), showLoadingPage: sendTo( ( { context } ) => context.mainContentMachineRef, { type: 'SHOW_LOADING' } ), updateQueryParams: ( _, params: { sidebar?: string; content?: string } ) => { updateQueryParams( params ); }, }, guards: { hasSidebarLocation: ( _, { sidebarLocation }: { sidebarLocation: string } ) => { const { sidebar } = getQuery() as { sidebar?: string }; return !! sidebar && sidebar === sidebarLocation; }, }, actors: { sidebarQueryParamListener, }, } ).createMachine( { id: 'sidebar', initial: 'navigate', context: ( { input } ) => ( { externalUrl: null, mainContentMachineRef: input.mainContentMachineRef, } ), invoke: { id: 'sidebarQueryParamListener', src: 'sidebarQueryParamListener', }, states: { navigate: { always: [ { guard: { type: 'hasSidebarLocation', params: { sidebarLocation: 'hub' }, }, target: 'launchYourStoreHub', }, { guard: { type: 'hasSidebarLocation', params: { sidebarLocation: 'launch-success' }, }, target: 'storeLaunchSuccessful', }, { target: 'launchYourStoreHub', }, ], }, launchYourStoreHub: { initial: 'preLaunchYourStoreHub', states: { preLaunchYourStoreHub: { always: 'launchYourStoreHub', // do async stuff here such as retrieving task statuses }, launchYourStoreHub: { tags: 'sidebar-visible', meta: { component: LaunchYourStoreHubSidebar, }, on: { LAUNCH_STORE: { target: '#storeLaunching', }, }, }, }, }, storeLaunching: { id: 'storeLaunching', initial: 'launching', states: { launching: { tags: 'fullscreen', entry: { type: 'showLoadingPage' }, on: { LAUNCH_STORE_SUCCESS: { target: '#storeLaunchSuccessful', }, }, }, }, }, storeLaunchSuccessful: { id: 'storeLaunchSuccessful', tags: 'fullscreen', entry: [ { type: 'updateQueryParams', params: { sidebar: 'launch-success', content: 'launch-store-success', }, }, { type: 'showLaunchStoreSuccessPage' }, ], }, openExternalUrl: { id: 'openExternalUrl', tags: 'sidebar-visible', // unintuitive but it prevents a layout shift just before leaving entry: [ 'openExternalUrl' ], }, }, on: { EXTERNAL_URL_UPDATE: { target: '.navigate', }, OPEN_EXTERNAL_URL: { target: '#openExternalUrl', }, OPEN_WC_ADMIN_URL: {}, OPEN_WC_ADMIN_URL_IN_CONTENT_AREA: {}, }, } ); export const SidebarContainer = ( { children, className, }: { children: React.ReactNode; className?: string; } ) => { return (