import PropTypes from 'prop-types'
import {useState, useEffect} from 'react'

import LoadingSpinner from '../LoadingSpinner'
import Typography from '../Typography'
import StyledLoadMask, {StyledLoadingIconAndTest} from './StyledLoadMask'

/**
 * A loadmask that can hide elements as long as promises are not resolved
 */
const LoadMask = ({promises, required, children, loadingText, className}) => {
  const [isLoaded, setIsLoaded] = useState(false)
  const [isMounted, setIsMounted] = useState(true)

  const setIsLoadedSafe = isLoaded => {
    if (isMounted) {
      setIsLoaded(isLoaded)
    }
  }

  // only on mount
  useEffect(() => {
    if (promises) {
      Promise.all(promises).then(() => {
        setIsLoadedSafe(true)
      })
    }
    return () => {
      setIsMounted(false)
    }
  }, []) // eslint-disable-line react-hooks/exhaustive-deps

  useEffect(() => {
    if (required && Array.isArray(required)) {
      setIsLoaded(!required.some(r => !r))
    }
  }, [required])

  return (
    <StyledLoadMask className={className}>
      {isLoaded ? (
        children
      ) : (
        <StyledLoadingIconAndTest>
          <LoadingSpinner key="loading-spinner" size="30px" />
          {loadingText && <Typography.Span key="loadingText">{loadingText}</Typography.Span>}
        </StyledLoadingIconAndTest>
      )}
    </StyledLoadMask>
  )
}

LoadMask.propTypes = {
  /**
   * Optional className for being able to overwrite styles.
   */
  className: PropTypes.string,
  /**
   * Optional text to be shown below spinner
   */
  loadingText: PropTypes.string,
  /**
   * As soon as all elements of the array are truthy, children will be displayed.
   */
  required: PropTypes.arrayOf(PropTypes.any),
  /**
   * An array of promises as alternative to required.
   */
  promises: PropTypes.array,
  /**
   * Will be shown once promises are resolved
   */
  children: PropTypes.node
}

export default LoadMask

import PropTypes from 'prop-types'
import {useState, useEffect} from 'react'

import LoadingSpinner from '../LoadingSpinner'
import Typography from '../Typography'
import StyledLoadMask, {StyledLoadingIconAndTest} from './StyledLoadMask'

/**
 * A loadmask that can hide elements as long as promises are not resolved
 */
const LoadMask = ({promises, required, children, loadingText, className}) => {
  const [isPromiseLoaded, setIsPromiseLoaded] = useState(false)
  const [isMounted, setIsMounted] = useState(true)

  const setIsLoadedSafe = isLoaded => {
    if (isMounted) {
      setIsPromiseLoaded(isLoaded)
    }
  }

  // only on mount
  useEffect(() => {
    if (promises) {
      Promise.all(promises).then(() => {
        setIsLoadedSafe(true)
      })
    }
    return () => {
      setIsMounted(false)
    }
  }, []) // eslint-disable-line react-hooks/exhaustive-deps

  const getIsLoaded = () => {
    if (required && Array.isArray(required)) {
      return !required.some(r => !r)
    }

    if (promises) {
      return isPromiseLoaded
    }

    // show infinite loading mask when no required and no promises are provided
    return false
  }

  const isLoaded = getIsLoaded()

  return (
    <StyledLoadMask className={className}>
      {isLoaded ? (
        children
      ) : (
        <StyledLoadingIconAndTest>
          <LoadingSpinner key="loading-spinner" size="30px" />
          {loadingText && <Typography.Span key="loadingText">{loadingText}</Typography.Span>}
        </StyledLoadingIconAndTest>
      )}
    </StyledLoadMask>
  )
}

LoadMask.propTypes = {
  /**
   * Optional className for being able to overwrite styles.
   */
  className: PropTypes.string,
  /**
   * Optional text to be shown below spinner
   */
  loadingText: PropTypes.string,
  /**
   * As soon as all elements of the array are truthy, children will be displayed.
   */
  required: PropTypes.arrayOf(PropTypes.any),
  /**
   * An array of promises as alternative to required.
   */
  promises: PropTypes.array,
  /**
   * Will be shown once promises are resolved
   */
  children: PropTypes.node
}

export default LoadMask

fix load mask required calculation