import * as R from 'ramda';
import React, {useReducer, useEffect} from 'react';
import PropTypes from 'prop-types';
const RouteContext = React.createContext(null);
const ActionDispatcherContext = React.createContext(null);
function RouteProvider({children, actionDispatcher, _window}) {
const [route, updateRoute] = useReducer((state, action) =>
R.omit(['type'], R.assoc('routeName', action.type, action))
, {});
useEffect(() => {
return actionDispatcher.addActionListener(action => updateRoute(action));
});
useEffect(() => {
actionDispatcher.receiveLocation(_window.location);
});
return (
{children}
);
}
RouteProvider.defaultProps = {
_window: window ? window : null
};
RouteProvider.propTypes = {
_window: PropTypes.object,
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
]),
actionDispatcher: PropTypes.object
};
function getDisplayName(WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || 'Component';
}
function withRoute(Component) {
const routeAdded = ({children, ...restProps}) => {
return (
{route =>
{children}
}
)
};
routeAdded.displayName = `withRoute(${getDisplayName(Component)})`
routeAdded.propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
])
};
return routeAdded;
}
function RouteLink({route, params, children, ...props}) {
const action = {
type: route, ...params
};
return {
dispatcher => {
const url = dispatcher.pathForAction(action);
return {
ev.preventDefault();
dispatcher.receiveAction(action, true);
}}
href={url} {...props}>{children}
}
}
;
}
RouteLink.propTypes = {
route: PropTypes.string,
params: PropTypes.object,
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
]),
};
export {RouteProvider, withRoute, RouteLink};