loading-spinner.tsx 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import { useTranslation } from 'react-i18next'
  2. import { useEffect, useState } from 'react'
  3. import OLSpinner, {
  4. OLSpinnerSize,
  5. } from '@/features/ui/components/ol/ol-spinner'
  6. import { isBootstrap5 } from '@/features/utils/bootstrap-5'
  7. import { setTimeout } from '@/utils/window'
  8. import classNames from 'classnames'
  9. function LoadingSpinner({
  10. align,
  11. delay = 0,
  12. loadingText,
  13. size = 'sm',
  14. className,
  15. }: {
  16. align?: 'left' | 'center'
  17. delay?: 0 | 500 // 500 is our standard delay
  18. loadingText?: string
  19. size?: OLSpinnerSize
  20. className?: string
  21. }) {
  22. const { t } = useTranslation()
  23. const [show, setShow] = useState(false)
  24. useEffect(() => {
  25. const timer = setTimeout(() => {
  26. setShow(true)
  27. }, delay)
  28. return () => {
  29. window.clearTimeout(timer)
  30. }
  31. }, [delay])
  32. if (!show) {
  33. return null
  34. }
  35. const extraClasses = isBootstrap5()
  36. ? [
  37. 'd-inline-flex',
  38. align === 'left' ? 'align-items-start' : 'align-items-center',
  39. ]
  40. : null
  41. return (
  42. <div className={classNames('loading', className, extraClasses)}>
  43. <OLSpinner size={size} />
  44. &nbsp;
  45. {loadingText || t('loading')}…
  46. </div>
  47. )
  48. }
  49. export default LoadingSpinner
  50. export function FullSizeLoadingSpinner({
  51. delay = 0,
  52. minHeight,
  53. loadingText,
  54. size = 'sm',
  55. }: {
  56. delay?: 0 | 500
  57. minHeight?: string
  58. loadingText?: string
  59. size?: OLSpinnerSize
  60. }) {
  61. return (
  62. <div className="full-size-loading-spinner-container" style={{ minHeight }}>
  63. <LoadingSpinner size={size} loadingText={loadingText} delay={delay} />
  64. </div>
  65. )
  66. }