<commit_before>import { Box, ChevronIcon, Flex } from "@artsy/palette"
import { Options as FlickityOptions } from "flickity"
import React, { ReactNode, useRef, useState } from "react"
import styled from "styled-components"
import { left, LeftProps, right, RightProps } from "styled-system"
import { useDidMount } from "Utils/hooks/useDidMount"
import { Media } from "Utils/Responsive"

type Arrow = (
  props: {
    Arrow: React.ReactType
    getFlickity: any
  } & Props
) => React.ReactNode

interface Props {
  height?: number
  data: object[] // This is designed to handle any shape of data passed, as long as its an array
  render: (slide) => ReactNode
  renderLeftArrow?: Arrow
  renderRightArrow?: Arrow
  onArrowClick?: () => void
  options?: FlickityOptions
}

const isClient = typeof window !== "undefined"

export class Carousel extends React.Component<Props> {
  static defaultProps = {
    height: 300,
  }

  render() {
    return (
      <>
        {isClient && (
          <Box key={Math.random()}>
            <Media at="xs">
              <SmallCarousel {...this.props} />
            </Media>
            <Media greaterThan="xs">
              <LargeCarousel {...this.props} />
            </Media>
          </Box>
        )}
        {!isClient && (
          <Box key={Math.random()}>
            <CarouselServer {...this.props} />
          </Box>
        )}
      </>
    )
  }
}

const renderSlides = props => {
  return props.data.map((slide, index) => {
    return <Box key={index}>{props.render(slide)}</Box>
  })
}

const CarouselServer = (props: Props) => {
  return (
    <Flex
      flexDirection="row"
      position="relative"
      justifyContent="space-around"
      alignItems="center"
      height={props.height}
    >
      <CarouselContainer height={props.height}>
        <Flex>{renderSlides(props)}</Flex>
      </CarouselContainer>
    </Flex>
  )
}

/*
 * Returns null if no window for SSR
 */
const Flickity = isClient ? require("react-flickity-component") : () => null

export const LargeCarousel = (props: Props) => {
  const [currentSlideIndex, setSlideIndex] = useState(0)
  const [lastItemVisible, setLastItemVisible] = useState(false)
  const flicktyRef = useRef(null)

  const isMounted = useDidMount()

  let flickity = null

  const checkLastItemVisible = () => {
    if (!flickity.slides.length) {
      return
    }
    const isLastItemVisible = flickity.selectedElements.includes(
      flickity.getLastCell().element
    )
    setLastItemVisible(isLastItemVisible)
  }

  if (isMounted) {
    if (flicktyRef.current !== null) {
      flickity = flicktyRef.current.flkty
    }

    flickity.on("select", index => {
      setSlideIndex(index)
      checkLastItemVisible()
    })
  }

  const options = {
    draggable: false,
    freeScroll: false,
    wrapAround: false,
    cellAlign: "left",
    pageDots: false,
    prevNextButtons: false,
    groupCells: true,
    contain: true,
    ...props.options,
  }

  const LeftArrow = () => {
    return (
      <ArrowButton
        onClick={() => {
          if (flickity) {
            flickity.previous()
          }
        }}
      >
        <ChevronIcon direction="left" fill="black100" width={30} height={30} />
      </ArrowButton>
    )
  }

  const RightArrow = () => {
    return (
      <ArrowButton
        onClick={() => {
          if (flickity) {
            flickity.next()
          }
        }}
      >
        <ChevronIcon direction="right" fill="black100" width={30} height={30} />
      </ArrowButton>
    )
  }

  const showLeftArrow = currentSlideIndex !== 0 || options.wrapAround === true
  const showRightArrow = !lastItemVisible || options.wrapAround === true

  return (
    <Flex
      flexDirection="row"
      position="relative"
      justifyContent="space-around"
      alignItems="center"
      height={props.height}
    >
      {showLeftArrow && (
        <ArrowWrapper left={-38}>
          {props.renderLeftArrow ? (
            props.renderLeftArrow({
              Arrow: LeftArrow,
              getFlickity: flickity,
              ...props,
            })
          ) : (
            <LeftArrow />
          )}
        </ArrowWrapper>
      )}

      <CarouselContainer height={props.height}>
        <Flickity options={options} ref={flicktyRef}>
          {renderSlides(props)}
        </Flickity>
      </CarouselContainer>

      {showRightArrow && (
        <ArrowWrapper right={-38}>
          {props.renderRightArrow ? (
            props.renderRightArrow({
              Arrow: RightArrow,
              getFlickity: flickity,
              ...props,
            })
          ) : (
            <RightArrow />
          )}
        </ArrowWrapper>
      )}
    </Flex>
  )
}

export const SmallCarousel = (props: Props) => {
  const options = {
    draggable: true,
    freeScroll: false,
    wrapAround: false,
    cellAlign: "left",
    pageDots: false,
    prevNextButtons: false,
    ...props.options,
  }

  return (
    <Flex justifyContent="space-around" alignItems="center"><commit_msg>Uses space instead of hardcoded pixels for arrow offset<commit_after>import { Box, ChevronIcon, Flex, space } from "@artsy/palette"
import { Options as FlickityOptions } from "flickity"
import React, { ReactNode, useRef, useState } from "react"
import styled from "styled-components"
import { left, LeftProps, right, RightProps } from "styled-system"
import { useDidMount } from "Utils/hooks/useDidMount"
import { Media } from "Utils/Responsive"

type Arrow = (
  props: {
    Arrow: React.ReactType
    getFlickity: any
  } & Props
) => React.ReactNode

interface Props {
  height?: number
  data: object[] // This is designed to handle any shape of data passed, as long as its an array
  render: (slide) => ReactNode
  renderLeftArrow?: Arrow
  renderRightArrow?: Arrow
  onArrowClick?: () => void
  options?: FlickityOptions
}

const isClient = typeof window !== "undefined"

export class Carousel extends React.Component<Props> {
  static defaultProps = {
    height: 300,
  }

  render() {
    return (
      <>
        {isClient && (
          <Box key={Math.random()}>
            <Media at="xs">
              <SmallCarousel {...this.props} />
            </Media>
            <Media greaterThan="xs">
              <LargeCarousel {...this.props} />
            </Media>
          </Box>
        )}
        {!isClient && (
          <Box key={Math.random()}>
            <CarouselServer {...this.props} />
          </Box>
        )}
      </>
    )
  }
}

const renderSlides = props => {
  return props.data.map((slide, index) => {
    return <Box key={index}>{props.render(slide)}</Box>
  })
}

const CarouselServer = (props: Props) => {
  return (
    <Flex
      flexDirection="row"
      position="relative"
      justifyContent="space-around"
      alignItems="center"
      height={props.height}
    >
      <CarouselContainer height={props.height}>
        <Flex>{renderSlides(props)}</Flex>
      </CarouselContainer>
    </Flex>
  )
}

/*
 * Returns null if no window for SSR
 */
const Flickity = isClient ? require("react-flickity-component") : () => null

export const LargeCarousel = (props: Props) => {
  const [currentSlideIndex, setSlideIndex] = useState(0)
  const [lastItemVisible, setLastItemVisible] = useState(false)
  const flicktyRef = useRef(null)

  const isMounted = useDidMount()

  let flickity = null

  const checkLastItemVisible = () => {
    if (!flickity.slides.length) {
      return
    }
    const isLastItemVisible = flickity.selectedElements.includes(
      flickity.getLastCell().element
    )
    setLastItemVisible(isLastItemVisible)
  }

  if (isMounted) {
    if (flicktyRef.current !== null) {
      flickity = flicktyRef.current.flkty
    }

    flickity.on("select", index => {
      setSlideIndex(index)
      checkLastItemVisible()
    })
  }

  const options = {
    draggable: false,
    freeScroll: false,
    wrapAround: false,
    cellAlign: "left",
    pageDots: false,
    prevNextButtons: false,
    groupCells: true,
    contain: true,
    ...props.options,
  }

  const LeftArrow = () => {
    return (
      <ArrowButton
        onClick={() => {
          if (flickity) {
            flickity.previous()
          }
        }}
      >
        <ChevronIcon direction="left" fill="black100" width={30} height={30} />
      </ArrowButton>
    )
  }

  const RightArrow = () => {
    return (
      <ArrowButton
        onClick={() => {
          if (flickity) {
            flickity.next()
          }
        }}
      >
        <ChevronIcon direction="right" fill="black100" width={30} height={30} />
      </ArrowButton>
    )
  }

  const showLeftArrow = currentSlideIndex !== 0 || options.wrapAround === true
  const showRightArrow = !lastItemVisible || options.wrapAround === true

  return (
    <Flex
      flexDirection="row"
      position="relative"
      justifyContent="space-around"
      alignItems="center"
      height={props.height}
    >
      {showLeftArrow && (
        <ArrowWrapper left={-space(4)}>
          {props.renderLeftArrow ? (
            props.renderLeftArrow({
              Arrow: LeftArrow,
              getFlickity: flickity,
              ...props,
            })
          ) : (
            <LeftArrow />
          )}
        </ArrowWrapper>
      )}

      <CarouselContainer height={props.height}>
        <Flickity options={options} ref={flicktyRef}>
          {renderSlides(props)}
        </Flickity>
      </CarouselContainer>

      {showRightArrow && (
        <ArrowWrapper right={-space(4)}>
          {props.renderRightArrow ? (
            props.renderRightArrow({
              Arrow: RightArrow,
              getFlickity: flickity,
              ...props,
            })
          ) : (
            <RightArrow />
          )}
        </ArrowWrapper>
      )}
    </Flex>
  )
}

export const SmallCarousel = (props: Props) => {
  const options = {
    draggable: true,
    freeScroll: false,
    wrapAround: false,
    cellAlign: "left",
    pageDots: false,
    prevNextButtons: false,
    ...props.options,
  }

  return (
    <Flex justifyContent="space-around" alignItems="center">
{'fraction_non_alphanumeric': 0.13215728786833547, 'fraction_numerical': 0.004336257021779836, 'mean_word_length': 2.1811912225705328, 'pattern_counts': {'":': 0, '<': 85, '<?xml version=': 0, '>': 115, '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': '1189134', 'n_tokens_mistral': 3143, 'n_tokens_neox': 3127, 'n_words': 644}