فهرست منبع

Integrate Gliderjs

Francesco Baccetti 4 سال پیش
والد
کامیت
b49b57b696

+ 2 - 0
package.json

@@ -80,6 +80,7 @@
     "eslint-plugin-react-hooks": "^4.0.4",
     "faker": "^5.1.0",
     "fluent-ffmpeg": "^2.1.2",
+    "glider": "^0.1.0",
     "graphql": "^15.3.0",
     "graphql-tag": "^2.11.0",
     "graphql-tools": "^6.2.4",
@@ -93,6 +94,7 @@
     "react-app-rewired": "^2.1.6",
     "react-docgen-typescript-loader": "^3.7.1",
     "react-dom": "^16.13.1",
+    "react-glider": "^2.0.2",
     "react-player": "^2.2.0",
     "react-scripts": "3.4.1",
     "react-spring": "^8.0.27",

+ 4 - 1
src/components/ChannelGallery.tsx

@@ -3,6 +3,7 @@ import styled from '@emotion/styled'
 
 import { ChannelPreviewBase, Gallery } from '@/shared/components'
 import ChannelPreview from './ChannelPreviewWithNavigation'
+import { spacing } from '@/shared/theme'
 import { ChannelFields } from '@/api/queries/__generated__/ChannelFields'
 
 type ChannelGalleryProps = {
@@ -14,11 +15,13 @@ type ChannelGalleryProps = {
 
 const PLACEHOLDERS_COUNT = 12
 
+const trackPadding = `${spacing.xs} 0 0 ${spacing.xs}`
+
 const ChannelGallery: React.FC<ChannelGalleryProps> = ({ title, action, channels, loading }) => {
   const displayPlaceholders = loading || !channels
 
   return (
-    <Gallery title={title} action={action} disableControls={displayPlaceholders}>
+    <Gallery title={title} action={action} trackPadding={trackPadding}>
       {displayPlaceholders
         ? Array.from({ length: PLACEHOLDERS_COUNT }).map((_, idx) => (
             <StyledChannelPreviewBase key={`channel-placeholder-${idx}`} />

+ 7 - 31
src/components/VideoGallery.tsx

@@ -1,11 +1,12 @@
-import React, { useCallback, useMemo, useState } from 'react'
-import { css, SerializedStyles } from '@emotion/core'
+import React from 'react'
+
 import styled from '@emotion/styled'
 
 import { Gallery, MAX_VIDEO_PREVIEW_WIDTH, VideoPreviewBase } from '@/shared/components'
 import VideoPreview from './VideoPreviewWithNavigation'
 import { VideoFields } from '@/api/queries/__generated__/VideoFields'
-import { CAROUSEL_CONTROL_SIZE } from '@/shared/components/Carousel'
+
+import { spacing } from '@/shared/theme'
 
 type VideoGalleryProps = {
   title: string
@@ -16,37 +17,13 @@ type VideoGalleryProps = {
 
 const PLACEHOLDERS_COUNT = 12
 
-const VideoGallery: React.FC<VideoGalleryProps> = ({ title, action, videos, loading }) => {
-  const [posterSize, setPosterSize] = useState(0)
-  const [galleryControlCss, setGalleryControlCss] = useState<SerializedStyles>(css``)
-
-  useMemo(() => {
-    if (!posterSize) {
-      return
-    }
-
-    const topPx = posterSize / 2 - CAROUSEL_CONTROL_SIZE / 2
-    setGalleryControlCss(css`
-      top: ${topPx}px;
-    `)
-  }, [posterSize])
+const trackPadding = `${spacing.xs} 0 0 ${spacing.xs}`
 
+const VideoGallery: React.FC<VideoGalleryProps> = ({ title, action, videos, loading }) => {
   const displayPlaceholders = loading || !videos
 
-  const imgRef = useCallback((node: HTMLImageElement) => {
-    if (node != null) {
-      setPosterSize(node.clientHeight)
-    }
-  }, [])
-
   return (
-    <Gallery
-      title={title}
-      action={action}
-      leftControlCss={galleryControlCss}
-      rightControlCss={galleryControlCss}
-      disableControls={displayPlaceholders}
-    >
+    <Gallery title={title} action={action} trackPadding={trackPadding}>
       {displayPlaceholders
         ? Array.from({ length: PLACEHOLDERS_COUNT }).map((_, idx) => (
             <StyledVideoPreviewBase key={`video-placeholder-${idx}`} />
@@ -62,7 +39,6 @@ const VideoGallery: React.FC<VideoGalleryProps> = ({ title, action, videos, load
               createdAt={video.publishedOnJoystreamAt}
               duration={video.duration}
               posterURL={video.thumbnailURL}
-              imgRef={idx === 0 ? imgRef : null}
               key={video.id}
             />
           ))}

+ 0 - 49
src/shared/components/Carousel/Carousel.style.ts

@@ -1,49 +0,0 @@
-import { makeStyles, StyleFn } from '../../utils'
-import { spacing } from '../../theme'
-import theme from '@/shared/theme'
-
-export type CarouselStyleProps = Record<string, unknown>
-
-export const CAROUSEL_CONTROL_SIZE = theme.sizes.b12
-
-const container: StyleFn = () => ({
-  position: 'relative',
-  display: 'flex',
-})
-const outerItemsContainer: StyleFn = () => ({
-  overflow: 'hidden',
-  padding: `${spacing.xs} 0 0 ${spacing.xs}`,
-  margin: `-${spacing.xs} 0 0 -${spacing.xs}`,
-})
-
-const innerItemsContainer: StyleFn = () => ({
-  display: 'flex',
-})
-
-const navBase: StyleFn = () => ({
-  minWidth: `${CAROUSEL_CONTROL_SIZE}px`,
-  minHeight: `${CAROUSEL_CONTROL_SIZE}px`,
-  width: `${CAROUSEL_CONTROL_SIZE}px`,
-  height: `${CAROUSEL_CONTROL_SIZE}px`,
-  position: 'absolute',
-})
-
-const navLeft: StyleFn = (styles) => ({
-  ...styles,
-  left: 0,
-  top: `calc(50% - ${Math.round((CAROUSEL_CONTROL_SIZE + 1) / 2)}px)`,
-})
-
-const navRight: StyleFn = (styles) => ({
-  ...styles,
-  right: 0,
-  top: `calc(50% - ${Math.round((CAROUSEL_CONTROL_SIZE + 1) / 2)}px)`,
-})
-
-export const useCSS = (props: CarouselStyleProps) => ({
-  container: makeStyles([container])(props),
-  outerItemsContainer: makeStyles([outerItemsContainer])(props),
-  innerItemsContainer: makeStyles([innerItemsContainer])(props),
-  navLeft: makeStyles([navBase, navLeft])(props),
-  navRight: makeStyles([navBase, navRight])(props),
-})

+ 43 - 85
src/shared/components/Carousel/Carousel.tsx

@@ -1,94 +1,52 @@
-import React, { useState } from 'react'
-import { SerializedStyles } from '@emotion/core'
-import { animated, useSpring } from 'react-spring'
-import useResizeObserver from 'use-resize-observer'
-import { CarouselStyleProps, useCSS } from './Carousel.style'
-import NavButton from '../NavButton'
+import React from 'react'
+import styled from '@emotion/styled'
+import Glider, { GliderProps, BreakPoint } from 'react-glider'
+import 'glider-js/glider.min.css'
 
-export type CarouselProps = {
-  containerCss?: SerializedStyles
-  leftControlCss?: SerializedStyles
-  rightControlCss?: SerializedStyles
-  disableControls?: boolean
-  onScroll?: (direction: 'left' | 'right') => void
-} & CarouselStyleProps
+import Icon from '../Icon'
 
+export type CarouselProps = {
+  trackPadding?: string
+} & GliderProps
+
+const Track: React.FC<any> = ({ className = '', ...props }) => (
+  <div className={`glider-track ${className}`} {...props} />
+)
+
+const defaultBreakpoints: BreakPoint[] = [
+  {
+    breakpoint: 400,
+    settings: {
+      slidesToShow: 1,
+      slidesToScroll: 1,
+      duration: 0.25,
+    },
+  },
+  {
+    breakpoint: 775,
+    settings: {
+      slidesToShow: 4,
+      slidesToScroll: 'auto',
+      duration: 0.25,
+    },
+  },
+] as BreakPoint[]
+
+const StyledTrack = styled(Track)<{ padding: string }>`
+  padding: ${(props) => props.padding};
+`
+const LeftIcon = <Icon name="chevron-left" />
+const RightIcon = <Icon name="chevron-right" />
 const Carousel: React.FC<CarouselProps> = ({
   children,
-  containerCss,
-  leftControlCss,
-  rightControlCss,
-  disableControls = false,
-  onScroll = () => {},
+  trackPadding = '0',
+  responsive = defaultBreakpoints,
+  ...gliderProps
 }) => {
-  const [scroll, setScroll] = useSpring(() => ({
-    transform: `translateX(0px)`,
-  }))
-  const [carouselOffset, setCarouselOffset] = useState(0)
-  const { width: containerWidth = 0, ref: containerRef } = useResizeObserver<HTMLDivElement>()
-  const { width: childrenWidth = 0, ref: childrenContainerRef } = useResizeObserver<HTMLDivElement>()
-
-  const styles = useCSS({})
-
-  const maxScrollOffset = childrenWidth - containerWidth
-
-  const showLeftControl = !disableControls && carouselOffset > 0
-  const showRightControl = !disableControls && carouselOffset < maxScrollOffset
-
-  const handleScroll = (direction: 'left' | 'right') => {
-    if (containerWidth == null) {
-      return
-    }
-    let scrollAmount
-    switch (direction) {
-      case 'left': {
-        // Prevent overscroll on the left
-        const newOffset = carouselOffset - containerWidth
-        scrollAmount = newOffset < 0 ? 0 : newOffset
-        onScroll('left')
-        break
-      }
-      case 'right': {
-        // Prevent overscroll on the right
-        const newOffset = carouselOffset + containerWidth
-        scrollAmount = newOffset > maxScrollOffset ? maxScrollOffset : newOffset
-        onScroll('right')
-        break
-      }
-    }
-    setCarouselOffset(scrollAmount)
-    setScroll({
-      transform: `translateX(-${scrollAmount}px)`,
-    })
-  }
-
-  if (!Array.isArray(children)) {
-    return <>{children}</>
-  }
-
   return (
-    <div css={[styles.container, containerCss]}>
-      <div css={styles.outerItemsContainer} ref={containerRef}>
-        <animated.div css={styles.innerItemsContainer} style={scroll}>
-          <div css={styles.innerItemsContainer} ref={childrenContainerRef}>
-            {children.map((element, idx) => (
-              <React.Fragment key={`Carousel-${idx}`}>{element}</React.Fragment>
-            ))}
-          </div>
-        </animated.div>
-      </div>
-      {showLeftControl && (
-        <NavButton outerCss={[styles.navLeft, leftControlCss]} direction="left" onClick={() => handleScroll('left')} />
-      )}
-      {showRightControl && (
-        <NavButton
-          outerCss={[styles.navRight, rightControlCss]}
-          direction="right"
-          onClick={() => handleScroll('right')}
-        />
-      )}
-    </div>
+    <Glider skipTrack hasArrows iconLeft={LeftIcon} iconRight={RightIcon} responsive={responsive} {...gliderProps}>
+      <StyledTrack padding={trackPadding}>{children}</StyledTrack>
+    </Glider>
   )
 }
-
 export default Carousel

+ 3 - 3
src/shared/components/Carousel/index.ts

@@ -1,5 +1,5 @@
-import Carousel, { CarouselProps } from './Carousel'
-import { CAROUSEL_CONTROL_SIZE } from './Carousel.style'
+import type { CarouselProps } from './Carousel'
+import Carousel from './Carousel'
 
-export { Carousel as default, CAROUSEL_CONTROL_SIZE }
+export default Carousel
 export type { CarouselProps }

+ 1 - 0
src/shared/components/ChannelPreview/ChannelPreviewBase.style.tsx

@@ -5,6 +5,7 @@ import { colors, sizes, spacing } from '../../theme'
 const imageTopOverflow = '2rem'
 
 export const OuterContainer = styled.article`
+  max-width: 200px;
   width: 200px;
   height: ${`calc(166px + ${imageTopOverflow})`};
   padding-top: ${imageTopOverflow};

+ 5 - 8
src/shared/stories/12-Carousel.stories.tsx

@@ -21,13 +21,10 @@ export const Default = () => (
   </Carousel>
 )
 
-export const LongerScroll = () => (
-  <Carousel scrollAmount={500}>
-    <CarouselItem>CarouselItem 1</CarouselItem>
-    <CarouselItem>CarouselItem 2</CarouselItem>
-    <CarouselItem>CarouselItem 3</CarouselItem>
-    <CarouselItem>CarouselItem 4</CarouselItem>
-    <CarouselItem>CarouselItem 5</CarouselItem>
-    <CarouselItem>CarouselItem 6</CarouselItem>
+export const Draggable = () => (
+  <Carousel draggable>
+    {Array.from({ length: 10 }, (_, i) => (
+      <CarouselItem> Carousel Item {i}</CarouselItem>
+    ))}
   </Carousel>
 )

+ 112 - 2
yarn.lock

@@ -5118,6 +5118,11 @@ buffer-indexof@^1.0.0:
   resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c"
   integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==
 
+buffer-writer@1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-1.0.1.tgz#22a936901e3029afcd7547eb4487ceb697a3bf08"
+  integrity sha1-Iqk2kB4wKa/NdUfrRIfOtpejvwg=
+
 buffer-xor@^1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
@@ -8303,6 +8308,11 @@ generic-names@^2.0.1:
   dependencies:
     loader-utils "^1.1.0"
 
+generic-pool@2.4.2:
+  version "2.4.2"
+  resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-2.4.2.tgz#886bc5bf0beb7db96e81bcbba078818de5a62683"
+  integrity sha1-iGvFvwvrfblugby7oHiBjeWmJoM=
+
 gensync@^1.0.0-beta.1:
   version "1.0.0-beta.1"
   resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269"
@@ -8393,6 +8403,18 @@ github-slugger@^1.0.0:
   dependencies:
     emoji-regex ">=6.0.0 <=6.1.1"
 
+glider-js@1.7.1:
+  version "1.7.1"
+  resolved "https://registry.yarnpkg.com/glider-js/-/glider-js-1.7.1.tgz#ffa4ae6775b0c005e2eeca72e586acd1f64774e9"
+  integrity sha512-kry/GVCmo/MFUtMTgZONTjXorcvzKskt4VklSQD8kVDJbVfT3arV4Xf7o/ZwMZkDhLKlWX9bpV30fsp7vLHuUA==
+
+glider@^0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/glider/-/glider-0.1.0.tgz#5049570c6f5f8673abb183e9b4b4d7b7dc6c6f3d"
+  integrity sha1-UElXDG9fhnOrsYPptLTXt9xsbz0=
+  dependencies:
+    pg "^4.5.1"
+
 glob-base@^0.3.0:
   version "0.3.0"
   resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"
@@ -10345,7 +10367,7 @@ js-beautify@^1.8.8:
     mkdirp "^1.0.4"
     nopt "^5.0.0"
 
-js-string-escape@^1.0.1:
+js-string-escape@1.0.1, js-string-escape@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef"
   integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8=
@@ -12329,6 +12351,11 @@ p-try@^2.0.0:
   resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
   integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
 
+packet-reader@0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-0.2.0.tgz#819df4d010b82d5ea5671f8a1a3acf039bcd7700"
+  integrity sha1-gZ300BC4LV6lZx+KGjrPA5vNdwA=
+
 pako@~1.0.5:
   version "1.0.11"
   resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
@@ -12584,6 +12611,48 @@ performance-now@^2.1.0:
   resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
   integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
 
+pg-connection-string@0.1.3:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7"
+  integrity sha1-2hhHsglA5C7hSSvq9l1J2RskXfc=
+
+pg-int8@1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c"
+  integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==
+
+pg-types@1.*:
+  version "1.13.0"
+  resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-1.13.0.tgz#75f490b8a8abf75f1386ef5ec4455ecf6b345c63"
+  integrity sha512-lfKli0Gkl/+za/+b6lzENajczwZHc7D5kiUCZfgm914jipD2kIOIvEkAhZ8GrW3/TUoP9w8FHjwpPObBye5KQQ==
+  dependencies:
+    pg-int8 "1.0.1"
+    postgres-array "~1.0.0"
+    postgres-bytea "~1.0.0"
+    postgres-date "~1.0.0"
+    postgres-interval "^1.1.0"
+
+pg@^4.5.1:
+  version "4.5.7"
+  resolved "https://registry.yarnpkg.com/pg/-/pg-4.5.7.tgz#45ae16b23706a6345a03279decc6af795c16d29b"
+  integrity sha1-Ra4WsjcGpjRaAyed7MaveVwW0ps=
+  dependencies:
+    buffer-writer "1.0.1"
+    generic-pool "2.4.2"
+    js-string-escape "1.0.1"
+    packet-reader "0.2.0"
+    pg-connection-string "0.1.3"
+    pg-types "1.*"
+    pgpass "0.0.3"
+    semver "^4.1.0"
+
+pgpass@0.0.3:
+  version "0.0.3"
+  resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-0.0.3.tgz#12e67e343b3189c2f31206ebc9cc0befffcf9140"
+  integrity sha1-EuZ+NDsxicLzEgbrycwL7//PkUA=
+  dependencies:
+    split "~0.3"
+
 picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1:
   version "2.2.2"
   resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
@@ -13408,6 +13477,28 @@ postcss@^7, postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, po
     source-map "^0.6.1"
     supports-color "^6.1.0"
 
+postgres-array@~1.0.0:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-1.0.3.tgz#c561fc3b266b21451fc6555384f4986d78ec80f5"
+  integrity sha512-5wClXrAP0+78mcsNX3/ithQ5exKvCyK5lr5NEEEeGwwM6NJdQgzIJBVxLvRW+huFpX92F2QnZ5CcokH0VhK2qQ==
+
+postgres-bytea@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35"
+  integrity sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=
+
+postgres-date@~1.0.0:
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.7.tgz#51bc086006005e5061c591cee727f2531bf641a8"
+  integrity sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==
+
+postgres-interval@^1.1.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695"
+  integrity sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==
+  dependencies:
+    xtend "^4.0.0"
+
 prelude-ls@~1.1.2:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
@@ -14063,6 +14154,13 @@ react-focus-lock@^2.1.0:
     use-callback-ref "^1.2.1"
     use-sidecar "^1.0.1"
 
+react-glider@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/react-glider/-/react-glider-2.0.2.tgz#d8d098f341b4776c6cafda160dfd275ba23b3194"
+  integrity sha512-ONDO+e5gFTp+R0bVGvEh+NWGSHVaTdPrQxNYQWz3u8Oybkr48DWmqOxLpdEH48kd09Q12TI3kd13EgOO8Xen/A==
+  dependencies:
+    glider-js "1.7.1"
+
 react-helmet-async@^1.0.2:
   version "1.0.7"
   resolved "https://registry.yarnpkg.com/react-helmet-async/-/react-helmet-async-1.0.7.tgz#b988fbc3abdc4b704982bb74b9cb4a08fcf062c1"
@@ -15058,6 +15156,11 @@ semver@7.0.0:
   resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
   integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
 
+semver@^4.1.0:
+  version "4.3.6"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da"
+  integrity sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=
+
 semver@^7.3.2:
   version "7.3.2"
   resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"
@@ -15522,6 +15625,13 @@ split-string@^3.0.1, split-string@^3.0.2:
   dependencies:
     extend-shallow "^3.0.0"
 
+split@~0.3:
+  version "0.3.3"
+  resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f"
+  integrity sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=
+  dependencies:
+    through "2"
+
 sprintf-js@~1.0.2:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
@@ -16115,7 +16225,7 @@ through2@^2.0.0:
     readable-stream "~2.3.6"
     xtend "~4.0.1"
 
-through@^2.3.6, through@^2.3.8:
+through@2, through@^2.3.6, through@^2.3.8:
   version "2.3.8"
   resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
   integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=