Browse Source

Remove React-Glider and Refactor Carousel

Francesco Baccetti 4 years ago
parent
commit
7335724df7

+ 2 - 1
package.json

@@ -55,6 +55,7 @@
     "@storybook/theming": "^5.3.19",
     "@types/enzyme": "^3.10.5",
     "@types/faker": "^5.1.0",
+    "@types/glider-js": "^1.7.3",
     "@types/jest": "^24.0.0",
     "@types/lodash": "^4.14.157",
     "@types/node": "^12.0.0",
@@ -80,6 +81,7 @@
     "eslint-plugin-react-hooks": "^4.0.4",
     "faker": "^5.1.0",
     "fluent-ffmpeg": "^2.1.2",
+    "glider-js": "^1.7.3",
     "graphql": "^15.3.0",
     "graphql-tag": "^2.11.0",
     "graphql-tools": "^6.2.4",
@@ -93,7 +95,6 @@
     "react-app-rewired": "^2.1.6",
     "react-docgen-typescript-loader": "^3.7.1",
     "react-dom": "^16.13.1",
-    "react-glider": "^2.0.2",
     "react-error-boundary": "^3.0.2",
     "react-player": "^2.2.0",
     "react-scripts": "3.4.1",

+ 1 - 2
src/components/VideoGallery.tsx

@@ -1,5 +1,4 @@
 import React from 'react'
-import { BreakPoint } from 'react-glider'
 
 import styled from '@emotion/styled'
 
@@ -31,7 +30,7 @@ const breakpoints = breakpointsOfGrid({
   settings: {
     slidesToShow: idx + 1,
   },
-})) as BreakPoint[]
+}))
 
 const VideoGallery: React.FC<VideoGalleryProps> = ({ title, videos, loading }) => {
   const displayPlaceholders = loading || !videos

+ 25 - 16
src/shared/components/Button/Button.tsx

@@ -4,24 +4,28 @@ import { ButtonStyleProps, StyledButton, StyledIcon } from './Button.style'
 import type { IconType } from '../Icon'
 
 export type ButtonProps = {
-  icon: IconType
-  disabled: boolean
-  containerCss: SerializedStyles
-  className: string
-  onClick: (e: React.MouseEvent<HTMLButtonElement>) => void
+  children?: React.ReactNode
+  icon?: IconType
+  disabled?: boolean
+  containerCss?: SerializedStyles
+  className?: string
+  onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void
 } & Omit<ButtonStyleProps, 'clickable' | 'hasText'>
 
-const Button: React.FC<Partial<ButtonProps>> = ({
-  children,
-  icon,
-  variant = 'primary',
-  disabled = false,
-  full = false,
-  size = 'regular',
-  containerCss,
-  className,
-  onClick,
-}) => {
+const ButtonComponent: React.ForwardRefRenderFunction<HTMLButtonElement, ButtonProps> = (
+  {
+    children,
+    icon,
+    variant = 'primary',
+    disabled = false,
+    full = false,
+    size = 'regular',
+    containerCss,
+    className,
+    onClick,
+  },
+  ref
+) => {
   const clickable = !!onClick
   const hasText = !!children
   const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
@@ -40,6 +44,7 @@ const Button: React.FC<Partial<ButtonProps>> = ({
       hasText={hasText}
       full={full}
       size={size}
+      ref={ref}
     >
       {icon && <StyledIcon name={icon} />}
       {children && <span>{children}</span>}
@@ -47,4 +52,8 @@ const Button: React.FC<Partial<ButtonProps>> = ({
   )
 }
 
+const Button = React.forwardRef(ButtonComponent)
+
+Button.displayName = 'Button'
+
 export default Button

+ 33 - 33
src/shared/components/Carousel/Carousel.style.ts

@@ -1,48 +1,48 @@
 import styled from '@emotion/styled'
-import Glider from 'react-glider'
+import Button from '../Button'
 
-import Icon from '../Icon'
-import { colors } from '../../theme'
+export const FADE_COLOR = 'black'
+export const Container = styled.div`
+  --prev-arrow-color: transparent;
+  --next-arrow-color: ${FADE_COLOR};
+  position: relative;
 
-export const Container = styled.div<{ trackPadding: string }>`
-  .glider-prev,
-  .glider-next {
+  ::after {
+    content: '';
     position: absolute;
-
-    display: grid;
-    place-items: center;
-    color: ${colors.white};
-    background-color: ${colors.blue[500]};
-    border: unset;
-    width: 48px;
-    height: 48px;
-    transition: none;
-    :hover {
-      color: ${colors.white};
-      background-color: ${colors.blue[700]};
-    }
-    :active {
-      background-color: ${colors.blue[900]};
-    }
+    top: 0;
+    left: calc(-1 * var(--global-horizontal-padding));
+    bottom: 0;
+    right: calc(-1 * var(--global-horizontal-padding));
+    background-image: linear-gradient(90deg, transparent 75%, var(--next-arrow-color)),
+      linear-gradient(270deg, transparent 75%, var(--prev-arrow-color));
+    pointer-events: none;
+    transition: background-image 0.2s;
   }
-  .glider-prev.disabled,
-  .glider-next.disabled {
+`
+
+export const Arrow = styled(Button)`
+  position: absolute;
+  width: 48px;
+  height: 48px;
+  transition: none;
+
+  &.disabled {
     opacity: 0;
   }
-  .glider-prev {
+
+  &.glider-prev {
     left: 0;
   }
-  .glider-next {
+  &.glider-next {
     right: 0;
   }
-
-  .glider-track {
-    padding: ${(props) => props.trackPadding};
-    align-items: start;
-  }
 `
 
-export const StyledGlider = styled(Glider)`
+export const GliderContainer = styled.div`
   scrollbar-width: none;
 `
-export const Arrow = styled(Icon)``
+export const Track = styled.div<{ trackPadding: string }>`
+  align-items: flex-start;
+  padding: ${(props) => props.trackPadding};
+`

+ 132 - 48
src/shared/components/Carousel/Carousel.tsx

@@ -1,75 +1,159 @@
-import React, { useLayoutEffect, useRef, useState } from 'react'
-import { GliderMethods, GliderProps } from 'react-glider'
+import React, { useEffect, useRef, useLayoutEffect } from 'react'
 
-import { Arrow, Container, StyledGlider } from './Carousel.style'
+import { Container, GliderContainer, Arrow, Track, FADE_COLOR } from './Carousel.style'
 
+import Glider, { Options, GliderEventMap, GliderEvent } from 'glider-js'
 import 'glider-js/glider.min.css'
 
+type GliderEventHandlers = {
+  onAdd?: (event: GliderEvent<GliderEventMap['glider-add']>) => void
+  onAnimated?: (event: GliderEvent<GliderEventMap['glider-animated']>) => void
+  onDestroy?: (args: GliderEvent<GliderEventMap['glider-destroy']>) => void
+  onLoaded?: (args: GliderEvent<GliderEventMap['glider-loaded']>) => void
+  onRefresh?: (args: GliderEvent<GliderEventMap['glider-refresh']>) => void
+  onRemove?: (args: GliderEvent<GliderEventMap['glider-remove']>) => void
+  onSlideHidden?: (args: GliderEvent<GliderEventMap['glider-slide-hidden']>) => void
+  onSlideVisible?: (args: GliderEvent<GliderEventMap['glider-slide-visible']>) => void
+}
+
 type CarouselProps = {
   trackPadding?: string
-} & GliderProps
-
-type TrackProps = {
   className?: string
-}
-const Track: React.FC<TrackProps> = ({ className = '', children }) => (
-  <div className={`glider-track ${className}`}>{children}</div>
-)
-
-const RightArrow = <Arrow name="chevron-right" />
-const LeftArrow = <Arrow name="chevron-left" />
+} & Options &
+  GliderEventHandlers
 
 const Carousel: React.FC<CarouselProps> = ({
   children,
   trackPadding = '0',
-  className,
+  className = '',
   slidesToShow = 'auto',
-  ...gliderProps
+  onSlideHidden = () => {},
+  onSlideVisible = () => {},
+  onAdd = () => {},
+  onAnimated = () => {},
+  onDestroy = () => {},
+  onRefresh = () => {},
+  onLoaded = () => {},
+  onRemove = () => {},
+  ...gliderOptions
 }) => {
-  //  The GliderMethods type only has methods and I need the full instance
-  const gliderRef = useRef<GliderMethods & { ele: HTMLDivElement }>()
-  const [arrows, setArrows] = useState<{ prev: HTMLButtonElement; next: HTMLButtonElement } | undefined>(undefined)
+  const nextArrowRef = useRef<HTMLButtonElement>(null)
+  const prevArrowRef = useRef<HTMLButtonElement>(null)
+  const containerRef = useRef<HTMLDivElement>(null)
+  const gliderRef = useRef<HTMLDivElement>(null)
+  const instanceRef = useRef<Glider.Static<HTMLDivElement>>()
 
   useLayoutEffect(() => {
     if (gliderRef.current) {
-      const glider = gliderRef.current.ele
-      const prevArrow = glider.previousSibling as HTMLButtonElement
-      const nextArrow = glider.nextSibling as HTMLButtonElement
-
-      setArrows({ prev: prevArrow, next: nextArrow })
+      //  @ts-ignore there are no typings for gliderjs
+      const gliderInstance = new Glider(gliderRef.current, {
+        skipTrack: true,
+        arrows: {
+          prev: prevArrowRef.current,
+          next: nextArrowRef.current,
+        },
+      })
+      instanceRef.current = gliderInstance
+    }
+    return () => {
+      if (instanceRef.current) {
+        instanceRef.current.destroy()
+      }
     }
   }, [])
 
-  // This is needed because react-glider will render arrows only if the arrows option is undefined, so arrows won't display if you pass an object to StyledGlider
-  React.useLayoutEffect(() => {
-    if (gliderRef.current && arrows) {
-      const { prev: prevArrow, next: nextArrow } = arrows
-      const container = gliderRef.current.ele.parentElement
-      if (container) {
-        container.insertBefore(prevArrow, gliderRef.current.ele)
-        container.appendChild(nextArrow)
+  useLayoutEffect(() => {
+    if (instanceRef.current) {
+      instanceRef.current.setOption(
+        {
+          slidesToShow,
+          ...gliderOptions,
+          skipTrack: true,
+          arrows: {
+            prev: prevArrowRef.current,
+            next: nextArrowRef.current,
+          },
+        },
+        true
+      )
+      instanceRef.current.refresh(true)
+    }
+  }, [gliderOptions, slidesToShow])
+
+  useEffect(() => {
+    const element = gliderRef.current as Element | null
+
+    const setContainerCSS = () => {
+      const isNextArrowDisabled = nextArrowRef.current?.classList.contains('disabled')
+      const isPrevArrowDisabled = prevArrowRef.current?.classList.contains('disabled')
+      if (containerRef.current) {
+        containerRef.current.style.setProperty('--next-arrow-color', isNextArrowDisabled ? 'transparent' : FADE_COLOR)
+        containerRef.current.style.setProperty('--prev-arrow-color', isPrevArrowDisabled ? 'transparent' : FADE_COLOR)
       }
     }
-  }, [arrows])
+    const handleSlideVisible = (event: GliderEvent<GliderEventMap['glider-slide-visible']>) => {
+      if (onSlideVisible) {
+        onSlideVisible(event)
+      }
+      setContainerCSS()
+    }
+
+    const handleSlideHidden = (event: GliderEvent<GliderEventMap['glider-slide-hidden']>) => {
+      if (onSlideHidden) {
+        onSlideHidden(event)
+      }
+      setContainerCSS()
+    }
+    if (element) {
+      element.addEventListener('glider-add', onAdd)
+      element.addEventListener('glider-animated', onAnimated)
+      element.addEventListener('glider-destroy', onDestroy)
+      element.addEventListener('glider-loaded', onLoaded)
+      element.addEventListener('glider-refresh', onRefresh)
+      element.addEventListener('glider-remove', onRemove)
+      element.addEventListener('glider-slide-hidden', handleSlideHidden)
+      element.addEventListener('glider-slide-visible', handleSlideVisible)
+    }
+
+    return () => {
+      if (element) {
+        element.removeEventListener('glider-add', onAdd)
+        element.removeEventListener('glider-animated', onAnimated)
+        element.removeEventListener('glider-destroy', onDestroy)
+        element.removeEventListener('glider-loaded', onLoaded)
+        element.removeEventListener('glider-refresh', onRefresh)
+        element.removeEventListener('glider-remove', onRemove)
+        element.removeEventListener('glider-slide-hidden', onSlideHidden)
+        element.removeEventListener('glider-slide-visible', onSlideVisible)
+      }
+    }
+  }, [onAdd, onAnimated, onDestroy, onLoaded, onRefresh, onRemove, onSlideHidden, onSlideVisible])
 
   return (
-    <Container trackPadding={trackPadding} className={className}>
-      <StyledGlider
-        addTrack
-        skipTrack
-        hasArrows
-        draggable
-        ref={gliderRef as React.RefObject<GliderMethods>}
-        iconLeft={LeftArrow}
-        iconRight={RightArrow}
-        slidesToShow={slidesToShow}
-        // Akward conversion needed until this is resolved: https://github.com/hipstersmoothie/react-glider/issues/36
-        arrows={(arrows as unknown) as { prev: string; next: string }}
-        {...gliderProps}
-      >
-        <Track>{children}</Track>
-      </StyledGlider>
+    <Container className={`glider-contain ${className}`} ref={containerRef}>
+      <Arrow className="glider-prev" icon="chevron-left" ref={prevArrowRef} />
+      <GliderContainer className="glider" ref={gliderRef}>
+        <Track className="glider-track" trackPadding={trackPadding}>
+          {children}
+        </Track>
+      </GliderContainer>
+      <Arrow className="glider-next" icon="chevron-right" ref={nextArrowRef} />
     </Container>
   )
 }
 export default Carousel
+
+declare global {
+  interface Element {
+    addEventListener<K extends keyof Glider.GliderEventMap>(
+      type: K,
+      listener: (event: Glider.GliderEvent<Glider.GliderEventMap[K]>) => void,
+      options?: boolean | AddEventListenerOptions
+    ): void
+    removeEventListener<K extends keyof Glider.GliderEventMap>(
+      type: K,
+      listener: (event: Glider.GliderEvent<Glider.GliderEventMap[K]>) => void,
+      options?: boolean | EventListenerOptions
+    ): void
+  }
+}

+ 298 - 0
src/shared/components/Glider/index.tsx

@@ -0,0 +1,298 @@
+import * as React from 'react'
+
+// tslint:disable-next-line
+import 'glider-js'
+
+export interface BreakPoint {
+  breakpoint: number
+  settings: {
+    slidesToShow: number | 'auto'
+    slidesToScroll: number | 'auto'
+    itemWidth?: number
+    duration?: number
+  }
+}
+
+export type GliderProps = {
+  children: React.ReactNode
+  hasArrows?: boolean
+  hasDots?: boolean
+  className?: string
+  iconLeft?: React.ReactNode
+  iconRight?: React.ReactNode
+  scrollToSlide?: number
+  scrollToPage?: number
+  addTrack?: boolean
+
+  /**
+   * The number of slides to show in container
+   * If this value is set to auto, it will be
+   * automatically calculated based upon the number
+   * of items able to fit within the container viewport.
+   * This requires setting the itemWidth option.
+   *
+   * @default 1
+   */
+  slidesToShow?: number | 'auto'
+  /**
+   * The number of slides to scroll when arrow navigation
+   * is used. If this value is set to auto, it will match
+   * the value of slidesToScroll.
+   *
+   * @default 1
+   */
+  slidesToScroll?: number | 'auto'
+  /** This value is ignored unless slidesToShow is set to auto, in which it is then required. */
+  itemWidth?: number
+  /**
+   * This prevents resizing items to fit when slidesToShow is set to auto.
+   * NOTE: This will yield fractional slides if your container is not sized appropriately
+   */
+  exactWidth?: number
+  /**
+   * If true, Glider.js will lock to the nearest slide on resizing of the window
+   */
+  resizeLock?: number
+  /**
+   * If true, Glider.js will scroll to the beginning/end when its respective endpoint is reached
+   */
+  rewind?: number
+  /**
+   * An aggravator used to control animation speed. Higher is slower!
+   *
+   * @default 0.5
+   */
+  duration?: number
+  /** An string containing the dot container selector */
+  dots?: string
+  /** An object containing the prev/next arrows selectors */
+  arrows?: {
+    prev: string
+    next: string
+  }
+
+  /**
+   * If true, the list can be scrolled by click and dragging with the mouse
+   *
+   * @default false
+   */
+  draggable?: boolean
+  /**
+   * How much to aggravate the velocity of the mouse dragging
+   *
+   * @default 3.3
+   */
+  dragVelocity?: number
+
+  /**
+   * Whether or not to release the scroll events from the container
+   *
+   *  @default false
+   */
+  scrollPropagate?: boolean
+  /**
+   * Whether or not Glider.js events should bubble (useful for binding events to all carousels)
+   *
+   * @default true
+   */
+  propagateEvent?: boolean
+
+  /**
+   * If true, Glider.js will scroll to the nearest slide after any scroll interactions.
+   *
+   * @default false
+   */
+  scrollLock?: boolean
+
+  /**
+   * Whether or not Glider.js should skip wrapping its children with a 'glider-track' <div>.
+   * NOTE: If true, Glider.js will assume that the 'glider-track' element has been added manually. All slides must be children of the track element.
+   *
+   * @default false
+   */
+  skipTrack?: boolean
+  /**
+   * how long to wait after scroll event before locking,
+   * if too low, it might interrupt normal scrolling
+   *
+   * @default 250
+   */
+  scrollLockDelay?: number
+
+  /**
+   * An object containing custom settings per provided breakpoint.
+   * Glider.js breakpoints are mobile-first
+   * be conscious of your ordering,
+   */
+  responsive?: BreakPoint[]
+
+  /** use any custom easing function, compatible with most easing plugins */
+  easing?(x: number, t: number, b: number, c: number, d: number): number
+
+  /** Called after Glider.js is first initialized */
+  onLoad?(context: any, event: Event): void
+  /** Called whenever a Glider.js paging animation is complete */
+  onAnimated?(context: any, event: Event): void
+  /** Called whenever a Glider.js animation is complete */
+  onRemove?(context: any, event: Event): void
+  /** Called whenever a slide a shown. Passed an object containing the slide index */
+  onSlideVisible?(context: any, event: Event): void
+  /** Called whenever Glider.js refreshes it's elements or settings */
+  onRefresh?(context: any, event: Event): void
+  /** Called whenever an item is added to Glider.js */
+  onAdd?(context: any, event: Event): void
+  /** Called whenever a Glider.js is destroyed */
+  onDestroy?(context: any, event: Event): void
+  /** Called whenever a slide a hidden. Passed an object containing the slide index */
+  onSlideHidden?(context: any, event: Event): void
+}
+
+type GliderOptions = Pick<
+  GliderProps,
+  | 'arrows'
+  | 'dots'
+  | 'slidesToShow'
+  | 'slidesToScroll'
+  | 'itemWidth'
+  | 'exactWidth'
+  | 'scrollLock'
+  | 'scrollLockDelay'
+  | 'resizeLock'
+  | 'responsive'
+  | 'rewind'
+  | 'scrollPropagate'
+  | 'draggable'
+  | 'dragVelocity'
+  | 'duration'
+  | 'skipTrack'
+>
+
+export type GliderMethods = {
+  destroy(): void
+  updateControls(): void
+  refresh(rebuildPaging?: boolean): void
+  setOption(options: GliderOptions, global?: boolean): void
+  scrollTo(pixelOffset: number): void
+  scrollItem(slideIndex: number, isActuallyDotIndex?: boolean): void
+}
+
+const makeGliderOptions = (props: GliderProps) => ({
+  ...props,
+  arrows:
+    (props.hasArrows && {
+      next: props?.arrows?.next ?? '.glider-next',
+      prev: props?.arrows?.prev ?? '.glider-prev',
+    }) ||
+    undefined,
+  dots: (props.hasDots && props.dots) || '#dots' || undefined,
+})
+const GliderComponent = React.forwardRef((props: GliderProps, ref: React.Ref<GliderMethods>) => {
+  const innerRef = React.useRef<HTMLDivElement>(null)
+  const gliderRef = React.useRef<GliderMethods>()
+  const isMountedRef = React.useRef<boolean>(false)
+
+  // On mount initialize the glider and hook up events
+  React.useLayoutEffect(() => {
+    if (!innerRef.current) {
+      return
+    }
+
+    // @ts-ignore Glider is not typed
+    const glider = new Glider(innerRef.current, makeGliderOptions(props)) as GliderMethods
+    gliderRef.current = glider
+
+    const addEventListener = (event: string, fn: any) => {
+      if (typeof fn === 'function' && innerRef.current) {
+        innerRef.current.addEventListener(event, fn)
+      }
+    }
+
+    addEventListener('glider-slide-visible', props.onSlideVisible)
+    addEventListener('glider-loaded', props.onLoad)
+    addEventListener('glider-animated', props.onAnimated)
+    addEventListener('glider-remove', props.onRemove)
+    addEventListener('glider-refresh', props.onRefresh)
+    addEventListener('glider-add', props.onAdd)
+    addEventListener('glider-destroy', props.onDestroy)
+    addEventListener('glider-slide-hidden', props.onSlideHidden)
+
+    if (props.scrollToSlide) {
+      glider.scrollItem(props.scrollToSlide - 1)
+    } else if (props.scrollToPage) {
+      glider.scrollItem(props.scrollToPage - 1, true)
+    }
+  }, [])
+
+  React.useEffect(() => {
+    isMountedRef.current = true
+
+    return () => {
+      const removeEventListener = (event: string, fn: any) => {
+        if (typeof fn === 'function' && innerRef.current) {
+          innerRef.current.removeEventListener(event, fn)
+        }
+      }
+
+      removeEventListener('glider-slide-visible', props.onSlideVisible)
+      removeEventListener('glider-loaded', props.onLoad)
+      removeEventListener('glider-animated', props.onAnimated)
+      removeEventListener('glider-remove', props.onRemove)
+      removeEventListener('glider-refresh', props.onRefresh)
+      removeEventListener('glider-add', props.onAdd)
+      removeEventListener('glider-destroy', props.onDestroy)
+      removeEventListener('glider-slide-hidden', props.onSlideHidden)
+
+      if (gliderRef.current) {
+        gliderRef.current.destroy()
+      }
+    }
+  }, [
+    props.onAdd,
+    props.onAnimated,
+    props.onDestroy,
+    props.onLoad,
+    props.onRefresh,
+    props.onRemove,
+    props.onSlideHidden,
+    props.onSlideVisible,
+  ])
+  // When the props update, update the glider
+  React.useEffect(() => {
+    if (!(gliderRef.current && isMountedRef.current)) {
+      return
+    }
+
+    gliderRef.current.setOption(makeGliderOptions(props), true)
+    gliderRef.current.refresh(true)
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [props])
+
+  // Expose the glider instance to the user so they can call the methods too
+  React.useImperativeHandle(ref, () => gliderRef.current as GliderMethods)
+
+  return (
+    <div className="glider-contain">
+      {props.hasArrows && !props.arrows && (
+        <button role="button" className="glider-prev" id="glider-prev">
+          {props.iconLeft || '«'}
+        </button>
+      )}
+
+      <div className={props.className} ref={innerRef}>
+        {props.children}
+      </div>
+
+      {props.hasDots && !props.dots && <div id="dots" />}
+
+      {props.hasArrows && !props.arrows && (
+        <button role="button" className="glider-next" id="glider-next">
+          {props.iconRight || '»'}
+        </button>
+      )}
+    </div>
+  )
+})
+
+GliderComponent.displayName = 'Glider'
+
+export default GliderComponent

+ 9 - 11
yarn.lock

@@ -2772,6 +2772,11 @@
   resolved "https://registry.yarnpkg.com/@types/faker/-/faker-5.1.2.tgz#3d5a97d5648502d7fb1eeb2809ca105edcd0d59b"
   integrity sha512-a3FADSHjjinczCwr7tTejoMZzbSS5vi70VCyns4C1idxJrDSRGZCQG0s27YppXLcoWrBOkwBbBsZ9vDRDpQK7A==
 
+"@types/glider-js@^1.7.3":
+  version "1.7.3"
+  resolved "https://registry.yarnpkg.com/@types/glider-js/-/glider-js-1.7.3.tgz#2adb1220922e8bfd32fbb8909f256f77d84dfac6"
+  integrity sha512-V+NRCK3sIdhXiZ/hG0U/vLEbl4Atz6ySbUuYeCfVPKiyyx4mfN30rBDatCke2uVhkKOgyQ1gRBeCAzpLAJVe0w==
+
 "@types/glob@^7.1.1":
   version "7.1.3"
   resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183"
@@ -8393,10 +8398,10 @@ 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-js@^1.7.3:
+  version "1.7.3"
+  resolved "https://registry.yarnpkg.com/glider-js/-/glider-js-1.7.3.tgz#4d397fb9de0870753953244d146a94248d4eb394"
+  integrity sha512-smiepWalDyBAUtOH6Ev06fHlcQ128OUzGLx97E/9NcR8/fR+uALUVSMytVN6z5pIqO4kDGTzINniqZV2yMf8bg==
 
 glob-base@^0.3.0:
   version "0.3.0"
@@ -14075,13 +14080,6 @@ 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"