<commit_before>import React, { useRef, useState, useEffect } from 'react'
import PropTypes from 'prop-types'
import throttle from 'lodash.throttle'
import classNames from 'classnames'
import { noop } from '../../utilities/other'
import { AvatarRowUI, CounterAvatarUI } from './AvatarRow.css'
import Avatar from '../Avatar'
import Tooltip from '../Tooltip'
import { config } from '../Avatar/Avatar.css'
import { setupObserver, splitAvatarsArray } from './AvatarRow.utils'

const { size: avatarConfigSizes } = config

function AvatarRow({
  adaptable = true,
  avatars = [],
  className,
  'data-cy': dataCy = 'AvatarRow',
  extraTooltipProps = {},
  gap = 2,
  ieCompatible = false,
  throttleOnResize = true,
  throttleWait = 200,
  ...avatarProps
}) {
  const { size: avatarSize, fontSize: avatarFontSize } = avatarConfigSizes[
    avatarProps.size || 'md'
  ]
  const avatarRowRef = useRef(null)
  const numberOfAvatars = avatars.length
  const [numberOfItemsOnDisplay, setNumberOfItemsOnDisplay] = useState(
    numberOfAvatars
  )

  const throttledOnResize = !ieCompatible
    ? throttle(onResize, throttleWait)
    : noop
  const throttledHandleWindowResize = ieCompatible
    ? throttle(handleWindowResize, throttleWait)
    : noop

  useEffect(() => {
    if (!adaptable || ieCompatible || avatarRowRef.current == null) return

    const avatarRowEl = avatarRowRef.current
    const resizeObserver = setupObserver(
      throttleOnResize ? throttledOnResize : onResize
    )

    resizeObserver.observe(avatarRowEl)

    return () => {
      if (!adaptable || ieCompatible || avatarRowEl == null) return

      resizeObserver.unobserve(avatarRowEl)
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [numberOfAvatars])

  useEffect(() => {
    if (ieCompatible && adaptable) {
      window.addEventListener(
        'resize',
        throttleOnResize ? throttledHandleWindowResize : handleWindowResize
      )

      const measures = avatarRowRef.current.getBoundingClientRect()
      onResize(measures)
    }

    return () => {
      ieCompatible &&
        adaptable &&
        window.addEventListener(
          'resize',
          throttleOnResize ? throttledHandleWindowResize : handleWindowResize
        )
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [numberOfAvatars])

  function handleWindowResize() {
    if (avatarRowRef.current != null) {
      const measures = avatarRowRef.current.getBoundingClientRect()

      onResize(measures)
    }
  }

  function onResize({ width: containerWidth }) {
    /** Only act if we have more than 1 avatar */
    if (!containerWidth || numberOfAvatars <= 1) {
      return
    }

    /** The total space for the avatars is comprised of:
     * Avatar space: Number of avatars * the size of the avatar
     * +
     * Margin space: gap between avatars * the number of gaps. For example, for 3 avatars, there are 2 gaps => [AV]gap[AV]gap[AV]
     */
    const spaceForAllAvatars =
      avatarSize * numberOfAvatars + (numberOfAvatars - 1) * gap

    if (containerWidth >= spaceForAllAvatars) {<commit_msg>avoid duplicated observers and events<commit_after>import React, { useRef, useState, useEffect, useCallback } from 'react'
import PropTypes from 'prop-types'
import throttle from 'lodash.throttle'
import classNames from 'classnames'
import { noop } from '../../utilities/other'
import { AvatarRowUI, CounterAvatarUI } from './AvatarRow.css'
import Avatar from '../Avatar'
import Tooltip from '../Tooltip'
import { config } from '../Avatar/Avatar.css'
import { setupObserver, splitAvatarsArray } from './AvatarRow.utils'

const { size: avatarConfigSizes } = config

function AvatarRow({
  adaptable = true,
  avatars = [],
  className,
  'data-cy': dataCy = 'AvatarRow',
  extraTooltipProps = {},
  gap = 2,
  ieCompatible = false,
  throttleOnResize = true,
  throttleWait = 200,
  ...avatarProps
}) {
  const { size: avatarSize, fontSize: avatarFontSize } = avatarConfigSizes[
    avatarProps.size || 'md'
  ]
  const avatarRowRef = useRef(null)
  const observerRef = useRef(null)
  const windowResizeRef = useRef(null)
  const numberOfAvatars = avatars.length
  const [numberOfItemsOnDisplay, setNumberOfItemsOnDisplay] = useState(
    numberOfAvatars
  )

  const throttledOnResize = !ieCompatible
    ? throttle(onResize, throttleWait)
    : noop
  const throttledHandleWindowResize = ieCompatible
    ? throttle(handleWindowResize, throttleWait)
    : noop

  useEffect(() => {
    if (!adaptable || ieCompatible || avatarRowRef.current == null) return

    // Avoid adding multiple observers
    if (observerRef.current instanceof ResizeObserver) {
      observerRef.current.disconnect()
    }

    const avatarRowEl = avatarRowRef.current
    const resizeObserver = setupObserver(
      throttleOnResize ? throttledOnResize : onResize
    )

    observerRef.current = resizeObserver

    resizeObserver.observe(avatarRowEl)

    return () => {
      if (!adaptable || ieCompatible || avatarRowEl == null) return

      resizeObserver.unobserve(avatarRowEl)
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [numberOfAvatars])

  useEffect(() => {
    if (ieCompatible && adaptable) {
      // Avoid adding multiple resize events
      if (typeof windowResizeRef.current === 'function') {
        console.log(
          '🚀 ~ file: AvatarRow.jsx ~ line 73 ~ windowResizeRef.current',
          windowResizeRef.current
        )
        window.removeEventListener('resize', windowResizeRef.current)
      }

      const handler = throttleOnResize
        ? throttledHandleWindowResize
        : handleWindowResize
      windowResizeRef.current = handler

      window.addEventListener('resize', handler)

      const measures = avatarRowRef.current.getBoundingClientRect()
      onResize(measures)
    }

    return () => {
      if (ieCompatible && adaptable) {
        const handler = throttleOnResize
          ? throttledHandleWindowResize
          : handleWindowResize

        window.removeEventListener('resize', handler)
      }
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [numberOfAvatars])

  function handleWindowResize() {
    if (avatarRowRef.current != null) {
      const measures = avatarRowRef.current.getBoundingClientRect()

      onResize(measures)
    }
  }

  function onResize({ width: containerWidth }) {
    /** Only act if we have more than 1 avatar */
    if (!containerWidth || numberOfAvatars <= 1) {
      return
    }

    /** The total space for the avatars is comprised of:
     * Avatar space: Number of avatars * the size of the avatar
     * +
     * Margin space: gap between avatars * the number of gaps. For example, for 3 avatars, there are 2 gaps => [AV]gap[AV]gap[AV]
     */
    const spaceForAllAvatars =
      avatarSize * numberOfAvatars + (numberOfAvatars - 1) * gap

    if (containerWidth >= spaceForAllAvatars) {
{'fraction_non_alphanumeric': 0.10388672157202716, 'fraction_numerical': 0.002889755815633579, 'mean_word_length': 3.251842751842752, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1674178', 'n_tokens_mistral': 2174, 'n_tokens_neox': 2089, 'n_words': 500}