loading-spinner.tsx 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  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. ? [align === 'left' ? 'align-items-start' : 'align-items-center']
  37. : null
  38. return (
  39. <div className={classNames('loading', className, extraClasses)}>
  40. <OLSpinner size={size} />
  41. &nbsp;
  42. {loadingText || `${t('loading')}…`}
  43. </div>
  44. )
  45. }
  46. export default LoadingSpinner
  47. export function FullSizeLoadingSpinner({
  48. delay = 0,
  49. minHeight,
  50. loadingText,
  51. size = 'sm',
  52. className,
  53. }: {
  54. delay?: 0 | 500
  55. minHeight?: string
  56. loadingText?: string
  57. size?: OLSpinnerSize
  58. className?: string
  59. }) {
  60. return (
  61. <div
  62. className={classNames('full-size-loading-spinner-container', className)}
  63. style={{ minHeight }}
  64. >
  65. <LoadingSpinner size={size} loadingText={loadingText} delay={delay} />
  66. </div>
  67. )
  68. }