loading-spinner.tsx 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  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. // Ensure that spinner is displayed immediately if delay is 0
  26. if (delay === 0) {
  27. setShow(true)
  28. return
  29. }
  30. const timer = setTimeout(() => {
  31. setShow(true)
  32. }, delay)
  33. return () => {
  34. window.clearTimeout(timer)
  35. }
  36. }, [delay])
  37. if (!show) {
  38. return null
  39. }
  40. const extraClasses = isBootstrap5()
  41. ? [align === 'left' ? 'align-items-start' : 'align-items-center']
  42. : null
  43. return (
  44. <div className={classNames('loading', className, extraClasses)}>
  45. <OLSpinner size={size} />
  46. &nbsp;
  47. {loadingText || `${t('loading')}…`}
  48. </div>
  49. )
  50. }
  51. export default LoadingSpinner
  52. export function FullSizeLoadingSpinner({
  53. delay = 0,
  54. minHeight,
  55. loadingText,
  56. size = 'sm',
  57. className,
  58. }: {
  59. delay?: 0 | 500
  60. minHeight?: string
  61. loadingText?: string
  62. size?: OLSpinnerSize
  63. className?: string
  64. }) {
  65. return (
  66. <div
  67. className={classNames('full-size-loading-spinner-container', className)}
  68. style={{ minHeight }}
  69. >
  70. <LoadingSpinner size={size} loadingText={loadingText} delay={delay} />
  71. </div>
  72. )
  73. }