import PropTypes from 'prop-types';
import classnames from 'classnames';
import useResizeObserver from "../../../hooks/useResizeObserver/index.js";
import ContainerBreakpointContext from './context';
import { breakpoints } from './breakpoints';
import classes from './styles.module.scss';

/**
 * A container that provides a container-based breakpoint value. It provides
 * a React context that contains the breakpoint name and it also renders a CSS
 * class that powers the container breakpoint SCSS mixins like
 * `container-at-least("md")` and such. One of these containers is also
 * required to make container breakpoint hooks work, like
 * `useContainerResponsiveValues()`.
 *
 * Note that you should generally _not_ nest container breakpoints or you may
 * end up with unintended behaviors. The JavaScript functionality should still
 * work as expected, but the CSS mixins may break.
 *
 * Also note that this Storybook includes a `ContainerBreakpoint` wrapper as
 * a global decorator.
 */
const ContainerBreakpoint = function ContainerBreakpoint(props) {
  const {
    as: Tag,
    className,
    forwardProps,
    children
  } = props;
  const [ref, [width]] = useResizeObserver();
  const [breakpoint] = breakpoints.find((b, i, bs) => {
    const nextBreakpoint = bs[i + 1];
    return !width || !nextBreakpoint || width < nextBreakpoint[1];
  });
  return <ContainerBreakpointContext.Provider value={breakpoint}>
      <Tag ref={ref} className={classnames(classes.container, `int-container-${breakpoint}`, className)} {...forwardProps}>
        {children}
      </Tag>
    </ContainerBreakpointContext.Provider>;
};
ContainerBreakpoint.defaultProps = {
  as: 'div',
  className: undefined,
  children: undefined,
  forwardProps: {}
};
ContainerBreakpoint.propTypes = {
  /**
   * Render the container as a custom tag type. Note that if this is a custom
   * element type it needs to support both the `ref` and `className` props as
   * well as `children`.
   */
  as: PropTypes.elementType,
  /**
   * A custom CSS class to apply to the container.
   */
  className: PropTypes.string,
  /**
   * Custom props to forward to the wrapping element.
   */
  forwardProps: PropTypes.shape({}),
  /**
   * Children to render inside the container.
   */
  children: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)])
};
export default ContainerBreakpoint;