Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using it's URL and the proper URL extention.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <div id="root"></div>
              
            
!

CSS

              
                :root {
  --padding-offset: 2rem;

  --transition-duration-300: 300ms;
  --transition-duration-100: 100ms;
  --transition-delay: 80ms;

  --body-background: rgb(225, 225, 225);

  // colors
  --white: #fff;
  --black: #000;
  --gray-light: #6d6d6d;
  --gray-dark: #494949;
  --blue-tint-light: hsl(216, 100%, 50%);
  --blue-tint-dark: hsl(216, 100%, 35%);
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  width: 100%;
  min-height: 100vh;
  background: var(--body-background);
  font-family: Ubuntu, "Montserrat", sans-serif;
  overflow-x: hidden;
}

input,
button {
  border: none;
  outline: none;
}

button {
  cursor: pointer;
  &:disabled {
    cursor: not-allowed;
  }
  &:focus {
    outline: none;
  }
}

header {
  position: relative;
  width: 100%;
  height: 80px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 2rem;
  margin-bottom: 2rem;

  .btn.home {
    display: flex;
    justify-content: center;
    align-items: center;
    background: none;

    .icon {
      --size: 30px;
      width: var(--size);
      height: var(--size);
      svg {
        fill: var(--blue-tint-light);
        width: 100%;
        height: 100%;
        animation: hue-rotation 5000ms linear alternate-reverse infinite;
        animation-play-state: paused;
      }
    }
    span {
      color: var(--gray-dark);
      font-size: 1.2rem;
      font-weight: bold;
      text-transform: uppercase;
      margin-left: 0.5rem;
    }
    &:hover {
      .icon {
        svg {
          animation-play-state: running;
        }
      }
    }
  }

  form {
    display: flex;
    justify-content: center;
    align-items: center;

    input[type="text"] {
      width: 100%;
      height: 100%;
      padding: 10px 15px;
      padding-right: 35%;
      border-top-left-radius: var(--border-radius);
      border-bottom-left-radius: var(--border-radius);
      &::placeholder {
        color: rgba(0, 0, 0, 0.45);
      }
    }

    button.search {
      background: var(--blue-tint-light);
      color: var(--white);
      transition: background var(--transition-duration-100) ease,
        filter var(--transition-duration-100) ease;
      &:not(:disabled) {
        filter: grayscale(0);
        &:hover,
        &:focus {
          background: var(--blue-tint-dark);
        }
      }
      &:disabled {
        filter: grayscale(0.98);
      }
    }

    .form-group {
      --border-radius: 0.5em;
      position: relative;
      width: 300px;
      border-radius: var(--border-radius);
      overflow: hidden;

      .icon {
        --size: 12px;
        width: var(--size);
        height: var(--size);
        transition: margin var(--transition-duration-100) ease;
        svg {
          fill: var(--white);
          width: 100%;
          height: 100%;
        }
      }

      &.g-1 {
        input[type="text"] {
          &:focus {
            ~ button {
              &:not(:disabled) {
                transform: translateX(-55%);
                .icon {
                  margin-right: 4px;
                }
              }
            }
          }
        }

        .btn.search {
          position: absolute;
          top: 0;
          right: -20%;
          transform: translateX(-50%);
          width: 32%;
          height: 100%;
          display: flex;
          justify-content: center;
          align-items: center;
          border-top-right-radius: var(--border-radius);
          border-bottom-right-radius: var(--border-radius);
          transition: transform var(--transition-duration-100) ease;
          padding-right: 15px;
          padding-left: 0;
          span {
            margin-left: 5px;
          }
        }
      }

      &.g-2 {
        width: auto;
        button.search {
          width: 30px;
          height: 30px;
          display: flex;
          justify-content: center;
          align-items: center;
          background: none;

          .icon {
            --size: 20px;
            svg {
              fill: var(--gray-light);
            }
          }
        }
      }
    }

    .floating--container {
      position: absolute;
      left: 0%;
      top: 0%;
      width: 100%;
      height: 130%;
      display: flex;
      flex-direction: column;
      justify-content: space-around;
      align-items: center;
      background: var(--gray-dark);
      transition: transform var(--transition-duration-300) ease;

      .input--container {
        width: 80%;
        height: 40%;
        display: grid;
        grid-template-columns: 0.75fr 0.25fr;
        border-radius: 0.4rem;
        overflow: hidden;
        margin-top: 0.8rem;

        input[type="text"] {
          padding-right: 1rem;
          &:focus {
            ~ button {
              &:not(:disabled):hover {
                background: var(--blue-tint-dark);
              }
            }
          }
        }

        button.search {
          width: 100%;
          height: 100%;
        }
      }

      button.close {
        --size: 30px;
        width: var(--size);
        height: var(--size);
        display: flex;
        justify-content: center;
        align-items: center;
        background: none;

        .icon {
          width: calc(var(--size) / 1.6);
          height: calc(var(--size) / 1.6);
          svg {
            width: 100%;
            height: 100%;
            fill: #fb3958;
          }
        }
      }

      &.hide {
        transform: translateY(-100%);
      }
    }
  }
}

.masonry {
  width: 100%;
  height: auto;
  padding: 0 1rem 1rem 1rem;
  display: grid;
  grid-gap: 1rem;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  grid-auto-rows: 0;

  .masonry-brick {
    .image-card {
      --card-options-height: 60px;

      position: relative;
      display: flex;
      background: var(--white);
      box-shadow: 0 6.7px 5.3px rgba(0, 0, 0, 0.016), 0 22.3px 17.9px rgba(0, 0, 0, 0.024),
        0 100px 80px rgba(0, 0, 0, 0.04);
      overflow: hidden;

      &::after {
        content: "";
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        background: linear-gradient(to top, rgba(0, 0, 0, 0.75) 0%, transparent 100%);
        opacity: 0;
        transition: opacity var(--transition-duration-300) ease;
        transition-delay: var(--transition-delay);
        z-index: 1;
      }

      &:hover {
        &::after {
          opacity: 1;
        }
        img.image {
          --image-transform-offset: -30px;
        }
        .image-card--options {
          --tranform-y: 0;
        }
      }

      img.image {
        width: 100%;
        height: 100%;
        object-fit: cover;
        transition: transform var(--transition-duration-300) ease;
        transform: translateY(var(--image-transform-offset, 0%));
        transition-delay: var(--transition-delay);
      }

      &--clickable-area {
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: calc(100% - var(--card-options-height));
        z-index: 20;
        cursor: pointer;
      }

      &--options {
        position: absolute;
        left: 0;
        bottom: 0;
        width: 100%;
        height: var(--card-options-height);
        display: grid;
        grid-template-columns: 1fr 0.35fr;
        align-items: center;
        background: var(--white);
        transition: transform var(--transition-duration-300) ease;
        transform: translateY(var(--tranform-y, 100%));
        transition-delay: var(--transition-delay);
        z-index: 5;
        cursor: default;

        .user-info {
          height: 100%;
          display: flex;
          align-items: center;
          padding: 0 0.5em;
          a {
            width: 35px;
            height: 35px;
            border-radius: 50%;
            overflow: hidden;
            img {
              width: 100%;
              height: 100%;
              object-fit: cover;
            }
          }
          h3 {
            margin-left: 6px;
            font-size: 0.8em;
            // white-space: nowrap;
          }
        }
        .links {
          width: 100%;
          height: 100%;
          display: flex;
          justify-content: flex-end;
          align-items: center;
          padding-right: 0.8em;
          .link {
            .icon {
              --size: 20px;
              width: var(--size);
              height: var(--size);
              margin-left: 12px;
              svg {
                fill: var(--fill, rgba(0, 0, 0, 0.6));
                width: 100%;
                height: 100%;
                transition: fill var(--transition-duration-100) ease;
              }
            }
            &:hover {
              .icon {
                &.instagram {
                  --fill: #fb3958;
                }
                &.twitter {
                  --fill: #00acee;
                }
                &.download {
                  --fill: var(--black);
                }
              }
            }
          }
        }
      }

      .image-card-fg {
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        z-index: 10;
        transform-origin: left center;
        transform: scaleX(1);
        transition: transform var(--transition-duration-300) ease;
        pointer-events: none;

        &.hide {
          transform-origin: right center;
          transform: scaleX(0);
        }
      }
    }
  }
}

.modal {
  position: fixed;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  z-index: 35;
  background: rgba(0, 0, 0, 0.9);
  backdrop-filter: blur(2px);
  display: flex;
  justify-content: center;
  align-items: center;
  .image-container {
    --icon-size: 20px;

    position: relative;
    // height: attr(data-container-height-percentage);
    width: auto;
    margin-top: -2rem;

    img {
      height: 100%;
      object-fit: cover;
    }

    button.close {
      position: absolute;
      top: 0;
      right: calc(-2 * var(--icon-size));
      transform: translate(-50%, -50%);
      width: calc(var(--icon-size) * 2);
      height: calc(var(--icon-size) * 2);
      background: rgb(255, 79, 79);
      border-radius: 50%;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .icon {
      width: calc(var(--icon-size));
      height: calc(var(--icon-size));
      svg {
        fill: var(--white);
        width: 100%;
        height: 100%;
      }
    }

    .options--container {
      position: absolute;
      bottom: 0;
      left: 0;
      transform: translateY(100%);
      width: 100%;
      height: 50px;
      display: flex;
      justify-content: flex-end;
      align-items: center;
      background: var(--white);
      border-bottom-left-radius: 0.4rem;
      border-bottom-right-radius: 0.4rem;

      .icon {
        svg {
          fill: var(--gray-light);
        }
      }

      .group {
        display: flex;
        height: 32px;
        margin: 0 10px;

        a,
        button {
          --border-color: rgba(0, 0, 0, 0.25);
          color: var(--gray-light);
          font-size: 0.85rem;
          text-transform: capitalize;
          font-weight: 800;
          height: 100%;
          display: flex;
          justify-content: center;
          align-items: center;
          cursor: pointer;
          border: 1px solid var(--border-color);
          background: var(--white);
          border-radius: 4px;
          transition: border var(--transition-duration-100) ease,
            color var(--transition-duration-100) ease;

          &:hover {
            --border-color: rgba(0, 0, 0, 1);
            border: 1px solid var(--border-color);
            color: var(--black);

            .icon {
              svg {
                fill: var(--black);
              }
            }
          }
        }

        &.g-1 {
          a {
            text-decoration: none;
            padding: 0 15px;
            border-top-right-radius: 0;
            border-bottom-right-radius: 0;
          }
          .dropdown-btn--container {
            --size: 32px;
            position: relative;
            width: var(--size);
            height: var(--size);
            button {
              width: 100%;
              height: 100%;
              border-top-left-radius: 0;
              border-bottom-left-radius: 0;
              .icon {
                transform: rotate(180deg);
              }
            }

            .dropdown--menu {
              position: absolute;
              right: 5%;
              bottom: 135%;
              background: var(--black);
              width: 240px;
              border-radius: 0.45rem;
              transform-origin: 95% 115%;
              transform: scale(1);
              transition: transform var(--transition-duration-300)
                cubic-bezier(0.65, -0.65, 0.25, 1.25),
                opacity var(--transition-duration-300)
                cubic-bezier(0.65, -0.65, 0.25, 1.25);
              &::after {
                --size: 12px;
                content: "";
                position: absolute;
                right: calc(0.8 * var(--size));
                bottom: calc(-0.5 * var(--size));
                transform: rotate(45deg);
                width: var(--size);
                height: var(--size);
                background: var(--black);
              }
              &.hide {
                opacity: 0;
                transform: scale(0.5);
              }

              ul {
                padding: 5px 0;
                li {
                  list-style: none;
                  // height: 35px;
                  padding: 10px 0;
                  width: 100%;
                  cursor: pointer;
                  a {
                    display: block;
                    text-align: right;
                    border-radius: 0;
                    border: 0;
                    background: none;
                    font-weight: normal;
                    font-size: 0.95rem;
                    color: var(--white);
                    transition: color var(--transition-duration-100) ease;
                    span {
                      color: var(--gray-light);
                    }
                  }
                  &:last-child {
                    border-top: 1px solid var(----gray-light);
                  }

                  &:hover,
                  &:focus {
                    a {
                      color: var(--gray-light);
                    }
                  }
                }
              }
            }
          }
        }

        &.g-2 {
          button {
            padding: 0 8px;
            .icon {
              padding: 2px;
            }
          }
        }
      }
    }

    .image-info--container {
      position: fixed;
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
      background: rgba(0, 0, 0, 0.65);
      display: flex;
      justify-content: center;
      align-items: center;
      backdrop-filter: blur(2px);
      padding: 0 2rem;

      .image-info--modal {
        position: relative;
        width: 550px;
        border-radius: 0.35rem;
        background-position: center;
        background-size: cover;

        .btn.close {
          background: rgb(153, 153, 153);
        }

        .row {
          padding: 18px 25px;
          &--1 {
            h1 {
              margin: 0;
              font-weight: 400;
              font-size: 1.5rem;
            }
            span {
              font-size: 0.8rem;
            }
          }
          &--2 {
            display: flex;
            .image-info {
              margin-right: 30px;
              .info {
                display: flex;
                align-items: center;
                padding: 5px 0;
                .icon {
                  --size: 16px;
                  width: var(--size);
                  height: var(--size);
                  svg {
                    fill: var(--black);
                  }
                }
                &--title {
                  font-size: 0.8rem;
                  padding: 0 5px;
                  font-weight: 500;
                }
                &--value {
                  font-weight: bold;
                  letter-spacing: 1px;
                  padding-left: 0.4rem;
                }
              }
              .monthly-stats {
                font-size: 0.75rem;
                color: var(--gray-light);
              }
              &.likes--container {
                .icon {
                  svg {
                    stroke: var(--black);
                    stroke-width: 3px;
                    fill: none;
                  }
                }
              }
            }
          }
          &--3 {
            display: grid;
            grid-template-columns: repeat(3, minmax(100px, 1fr));
            grid-template-rows: repeat(3, 1fr);
            grid-gap: 1rem;
            .camera-info {
              .info--title {
                font-size: 0.75rem;
                color: var(--gray-dark);
                margin-bottom: 6px;
                display: block;
              }
              .info--value {
                font-size: 0.85rem;
              }
            }
          }
        }
        .hr-line {
          width: 95%;
          height: 1px;
          background: var(--gray-light);
          opacity: 0.5;
          margin: auto;
        }
      }
    }
  }
}

.btn.load-more {
  border: none;
  margin: 5rem auto 20px auto;
  background: hsl(0, 0%, 55%);
  padding: 10px 20px;
  border-radius: 0.5em;
  color: var(--white);
  text-transform: capitalize;
  transition: background var(--transition-duration-300) ease;
  box-shadow: 0 6.7px 5.3px rgba(0, 0, 0, 0.016), 0 22.3px 17.9px rgba(0, 0, 0, 0.024),
    0 100px 80px rgba(0, 0, 0, 0.04);

  &:hover {
    background: hsl(0, 0%, 40%);
  }

  &.loading {
    background: hsl(0, 0%, 40%);
    cursor: not-allowed;
  }

  #wave {
    position: relative;
    width: 100%;
    height: 100%;
    .dot {
      --size: 6px;
      display: inline-block;
      width: var(--size);
      height: var(--size);
      border-radius: 50%;
      margin-right: 3px;
      background: var(--white);
      animation: wave 1.2s ease infinite;
      &:nth-child(2) {
        animation-delay: -1.1s;
      }
      &:nth-child(3) {
        animation-delay: -0.9s;
      }
    }
  }
}

.loading-text {
  width: 100%;
  text-align: center;
  color: var(--gray-dark);
  font-size: 2rem;
}

.failed-info-container {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 100%;
  .failed-text,
  p {
    text-align: center;
    color: var(--gray-dark);
  }
  .failed-text {
    font-size: 4rem;
    margin-bottom: 0.4rem;
  }
  p {
    text-transform: uppercase;
    font-weight: 700;
  }
}

.no-image-found-info {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 100%;
  text-align: center;
  color: var(--gray-dark);
  h3 {
    font-size: 4rem;
    margin-bottom: 1rem;
  }
}
.text-info {
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  margin-bottom: 15px;
  &.type-something-info {
    font-size: 1.5rem;
    color: var(--gray-light);
  }
}

@media only screen and (max-width: 900px) {
  .modal {
    .image-container {
      width: 90%;
      img {
        width: 100%;
      }
    }
  }
}

@media only screen and (max-width: 550px) {
  header {
    position: sticky;
    background: var(--body-background);
    z-index: 30;
    top: 0;
    padding: 0 1rem;

    form {
      .form-group {
        &.g-1 {
          display: none;
        }
      }
    }
  }
}
@media only screen and (min-width: 550px) {
  header {
    form {
      .form-group {
        &.g-2 {
          display: none;
        }
      }

      .floating--container {
        display: none;
      }
    }
  }
}

@media only screen and (max-width: 400px) {
  .modal {
    .image-container .image-info--container .image-info--modal {
      .row--3 {
        grid-template-columns: repeat(2, 1fr);
      }
    }
  }
}

@keyframes wave {
  0%,
  60%,
  100% {
    transform: initial;
  }

  30% {
    transform: translateY(-100%);
  }
}

@keyframes hue-rotation {
  0% {
    filter: hue-rotate(360deg);
  }
  100% {
    filter: hue-rotate(0deg);
  }
}

              
            
!

JS

              
                
console.clear()

const { useEffect, useState, Fragment, useRef } = React;


const API = 'https://api.unsplash.com';
const CLIENT_ID = '8e31e45f4a0e8959d456ba2914723451b8262337f75bcea2e04ae535491df16d';
const DEFAULT_IMAGE_COUNT = 25;
const IMAGE_INCREMENT_COUNT = 10;

function App() {
  const [images, setImages] = useState([]);
  const [query, setQuery] = useState("");
  const [prevQuery, setPrevQuery] = useState("");
  const [clickedImage, setClickedImage] = useState({});
  const [isModalActive, setModalActive] = useState(false);
  const [failedToLoad, setFailedToLoad] = useState(false);
  const [perPageCount, setPerPageCount] = useState(DEFAULT_IMAGE_COUNT);
  const [totalResults, setTotalResults] = useState(0);
  const [state, setState] = useState("loading");
  const [queryChanged, setqueryChanged] = useState(false);
  const [page, setPage] = useState("home");

  const loadButtonEl = useRef();

  const getRandomPhotos = () => {
    setState("loading");
    axios(`${API}/photos/random`, {
      params: {
        count: DEFAULT_IMAGE_COUNT,
        client_id: CLIENT_ID,
      },
    })
      .then((res) => {
      setImages(res.data);
      if (failedToLoad) setFailedToLoad(false);
    })
      .catch(() => setFailedToLoad(true));
  };

  useEffect(getRandomPhotos, [failedToLoad]);

  useEffect(waitForImages, [images]);

  const searchQuery = () => {
    if (query !== "") {
      setState("loading");
      setPage("search");
      axios(`${API}/search/photos/`, {
        params: {
          query: query,
          per_page: perPageCount,
          client_id: CLIENT_ID,
        },
      })
        .then((res) => {
        setImages(res.data.results);
        setTotalResults(res.data.total);
        if (failedToLoad) setFailedToLoad(false);
      })
        .catch(() => setFailedToLoad(true));
    }
  };

  useEffect(searchQuery, [perPageCount]);

  useEffect(() => {
    if (page === "home") {
      setQuery("");
      setPrevQuery("");
    }
  }, [page]);

  useEffect(() => {
    let loaded = 0;
    let cards = document.getElementsByClassName("image-card");
    for (let i = 0; i < cards.length; i++) {
      // eslint-disable-next-line no-loop-func
      imagesLoaded(cards[i], (instance) => {
        if (instance.isComplete) loaded++;
        if (loaded === perPageCount) setState("loaded");
      });
    }
  }, [images, perPageCount]);

  const handleSearch = () => {
    if (query !== prevQuery && query !== "") {
      setPerPageCount(DEFAULT_IMAGE_COUNT);
      setPrevQuery(query);
      searchQuery();
    }
  };

  const handleImageClick = (img) => {
    setClickedImage(img);
    setModalActive(true);
  };

  return (
    <Fragment>
      <Header
        onQueryChange={(q) => {
          setQuery(q);
          setqueryChanged(true);
        }}
        onQuerySearch={handleSearch}
        onGenarateRandomImages={() => getRandomPhotos()}
        onPageChange={(p) => setPage(p)}
        />

      {prevQuery !== "" && page !== "home" && (
        <span className="text-info">
          <span>
            search results for <strong>"{prevQuery}"</strong>
          </span>
          <span className="total-results">
            found <strong>{totalResults}</strong> matching results
          </span>
        </span>
      )}

      {query === "" && queryChanged && !failedToLoad && (
        <h3 className="text-info type-something-info">Type something!</h3>
      )}

      {prevQuery !== "" && totalResults === 0 && (
        <div className="no-image-found-info">
          <h3>No Images Found</h3>
          <span>
            Try searching <strong>dogs</strong> or <strong>cats</strong>
          </span>
        </div>
      )}

      {(!failedToLoad && (
        <main>
          <ImageCardList
            images={images}
            onImageClicked={(img) => handleImageClick(img)}
            />
          <h3
            className="text-info loading-text"
            style={{
              display: state === "loading" && !queryChanged ? "block" : "none",
            }}
            >
            Loading...
          </h3>
          <button
            className={`btn load-more ${state === "loading" ? "loading" : ""}`}
            ref={loadButtonEl}
            onClick={() => {
              setPerPageCount(perPageCount + IMAGE_INCREMENT_COUNT);
              setState("loading");
            }}
            style={{
              display:
              perPageCount >= totalResults || page === "home" ? "none" : "block",
                pointerEvents: state === "loading" ? "none" : "all",
            }}
            >
            {(state !== "loading" && "load more") || (
              <div id="wave">
                <span className="dot"></span>
                <span className="dot"></span>
                <span className="dot"></span>
              </div>
            )}
          </button>
        </main>
      )) ||
        (failedToLoad && (
        <div className="failed-info-container">
          <h1 className="failed-text">Failed To Load</h1>
          <p>check your connection</p>
        </div>
      ))}

      {isModalActive && (
        <Modal
          imageData={clickedImage}
          onModalActive={(isActive) => setModalActive(isActive)}
          />
      )}
    </Fragment>
  );
}

function resizeMasonryItem(item) {
  let grid = document.getElementsByClassName("masonry")[0],
      rowGap = parseInt(window.getComputedStyle(grid).getPropertyValue("grid-row-gap")),
      rowHeight = parseInt(window.getComputedStyle(grid).getPropertyValue("grid-auto-rows"));
  let rowSpan = Math.ceil(
    (item.querySelector(".masonry-content").getBoundingClientRect().height + rowGap) /
    (rowHeight + rowGap)
  );
  item.style.gridRowEnd = "span " + rowSpan;
}

function resizeAllMasonryItems() {
  let allItems = document.getElementsByClassName("masonry-brick");
  for (let i = 0; i < allItems.length; i++) {
    resizeMasonryItem(allItems[i]);
  }
}

function waitForImages() {
  let allItems = document.getElementsByClassName("masonry-brick");
  for (let i = 0; i < allItems.length; i++) {
    imagesLoaded(allItems[i], (instance) => {
      const item = instance.elements[0];
      const cardForegroundEl = instance.images[0].img.parentElement.parentElement.querySelector(
        ".image-card-fg"
      );
      item.style.display = "block";
      let t = setTimeout(() => {
        cardForegroundEl.classList.add("hide");
        clearTimeout(t);
      }, 200 + +cardForegroundEl.parentElement.getAttribute("data-card-index") * 120);
      resizeMasonryItem(item);
    });
  }
}

const events = ["load", "resize"];
events.forEach((event) => {
  window.addEventListener(event, resizeAllMasonryItems);
});


const Header = ({ onQueryChange, onQuerySearch, onGenarateRandomImages, onPageChange }) => {
  const [isFloatingInputActive, setFloatingInputActive] = useState(false);

  const inputEl = useRef();
  const floatingInputEl = useRef();

  const handleSubmit = (e) => {
    e.preventDefault();
    // onQuerySearch();
  };

  const handleHomePage = () => {
    onPageChange("home");
    onGenarateRandomImages();
    inputEl.current.value = "";
    floatingInputEl.current.value = "";
  };

  return (
    <header>
      <button className="btn home" onClick={handleHomePage}>
        <div className="icon gallery">
          <svg viewBox="0 0 388.309 388.309" xmlns="http://www.w3.org/2000/svg">
            <path
              d="M201.173,307.042c-11.291-0.174-22.177-4.233-30.825-11.494l-56.947-50.155c-8.961-8.373-22.664-9.036-32.392-1.567
                 L0.03,303.384v38.661c-0.582,10.371,7.355,19.25,17.726,19.832c0.534,0.03,1.07,0.037,1.605,0.021h286.824
                 c11.494,0,22.988-8.359,22.988-19.853V240.691L226.25,300.25C218.684,304.798,210.001,307.15,201.173,307.042z"
              />
            <circle cx="196.993" cy="182.699" r="22.988" />
            <path
              d="M383.508,67.238c-3.335-4.544-8.487-7.406-14.106-7.837L84.667,26.487c-5.551-0.465-11.091,1.012-15.673,4.18
                 c-4.058,3.524-6.817,8.307-7.837,13.584l-4.702,40.751h249.731c23.809,0.54,43.061,19.562,43.886,43.363v184.424
                 c0-1.045,4.702-2.09,6.792-4.18c4.326-3.397,6.834-8.606,6.792-14.106L388.21,82.389
                 C388.753,76.91,387.057,71.445,383.508,67.238z"
              />
            <path
              d="M306.185,105.899H19.361c-11.494,0-19.331,10.971-19.331,22.465v148.898l68.963-50.155
                 c17.506-12.986,41.724-11.895,57.992,2.612l57.469,50.155c8.666,7.357,21.044,8.406,30.824,2.612l113.894-66.351v-87.771
                 C328.382,116.099,318.465,106.408,306.185,105.899z M196.993,226.584c-24.237,0-43.886-19.648-43.886-43.886
                 c0-24.237,19.648-43.886,43.886-43.886c24.237,0,43.886,19.648,43.886,43.886C240.879,206.936,221.231,226.584,196.993,226.584z"
              />
          </svg>
        </div>
        <span className="title">Gallery</span>
      </button>

      <form onSubmit={handleSubmit}>
        <div className="form-group g-1">
          <input
            type="text"
            placeholder="Type here"
            onChange={() => onQueryChange(inputEl.current.value)}
            ref={inputEl}
            />
          <button
            className="btn search"
            onClick={onQuerySearch}
            disabled={
              inputEl.current !== undefined && inputEl.current.value.length === 0
                ? true
              : false
            }
            >
            <div className="icon search">
              <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
                <path d="M505 442.7L405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c48.3 0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9 0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7 0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7 0 128 57.2 128 128 0 70.7-57.2 128-128 128z"></path>
              </svg>
            </div>
            <span>search</span>
          </button>
        </div>
        <div className="form-group g-2">
          <button className="btn search" onClick={() => setFloatingInputActive(true)}>
            <div className="icon search">
              <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
                <path d="M505 442.7L405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c48.3 0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9 0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7 0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7 0 128 57.2 128 128 0 70.7-57.2 128-128 128z"></path>
              </svg>
            </div>
          </button>
        </div>

        <div className={`floating--container ${isFloatingInputActive ? "" : "hide"}`}>
          <div className="input--container">
            <input
              type="text"
              placeholder="Type here"
              onChange={() => onQueryChange(floatingInputEl.current.value)}
              ref={floatingInputEl}
              />
            <button
              className="btn search"
              onClick={onQuerySearch}
              disabled={
                floatingInputEl.current !== undefined &&
                  floatingInputEl.current.value.length === 0
                  ? true
                : false
              }
              >
              search
            </button>
          </div>

          <button className="btn close" onClick={() => setFloatingInputActive(false)}>
            <div className="icon cross">
              <svg
                viewBox="0 0 512 512"
                xmlns="http://www.w3.org/2000/svg"
                aria-hidden="false"
                >
                <path d="M443.6,387.1L312.4,255.4l131.5-130c5.4-5.4,5.4-14.2,0-19.6l-37.4-37.6c-2.6-2.6-6.1-4-9.8-4c-3.7,0-7.2,1.5-9.8,4  L256,197.8L124.9,68.3c-2.6-2.6-6.1-4-9.8-4c-3.7,0-7.2,1.5-9.8,4L68,105.9c-5.4,5.4-5.4,14.2,0,19.6l131.5,130L68.4,387.1  c-2.6,2.6-4.1,6.1-4.1,9.8c0,3.7,1.4,7.2,4.1,9.8l37.4,37.6c2.7,2.7,6.2,4.1,9.8,4.1c3.5,0,7.1-1.3,9.8-4.1L256,313.1l130.7,131.1  c2.7,2.7,6.2,4.1,9.8,4.1c3.5,0,7.1-1.3,9.8-4.1l37.4-37.6c2.6-2.6,4.1-6.1,4.1-9.8C447.7,393.2,446.2,389.7,443.6,387.1z" />
              </svg>
            </div>
          </button>
        </div>
      </form>
    </header>
  );
};



const ImageCard = ({ imageData, imageIndex, onImageClicked }) => {
  const { urls, alt_description, user, links, color } = imageData;

  return (
    <div className="masonry-brick" style={{ display: "none" }}>
      <div
        className="image-card masonry-content"
        style={{
          background: color,
        }}
        data-card-index={`${imageIndex}`}
        >
        <img className="image" src={urls.regular} alt={alt_description} />
        <div
          className="image-card--clickable-area"
          onClick={() => {
            onImageClicked(imageData);
            document.title = alt_description;
          }}
          />
        <div className="image-card--options">
          <div className="user-info">
            <a href={user.links.html} target="_blank_" tabIndex="-1">
              <img src={user.profile_image.medium} alt={user.name} />
            </a>
            <h3>{user.name}</h3>
          </div>
          <div className="links">
            <a
              className="link"
              href={`https://instagram.com/${user.instagram_username}`}
              style={{
                display: user.instagram_username ? "block" : "none",
              }}
              target="_blank_"
              tabIndex="-1"
              >
              <div className="icon instagram">
                <svg
                  viewBox="0 0 448 512"
                  xmlns="http://www.w3.org/2000/svg"
                  aria-hidden="false"
                  >
                  <path d="M224.1 141c-63.6 0-114.9 51.3-114.9 114.9s51.3 114.9 114.9 114.9S339 319.5 339 255.9 287.7 141 224.1 141zm0 189.6c-41.1 0-74.7-33.5-74.7-74.7s33.5-74.7 74.7-74.7 74.7 33.5 74.7 74.7-33.6 74.7-74.7 74.7zm146.4-194.3c0 14.9-12 26.8-26.8 26.8-14.9 0-26.8-12-26.8-26.8s12-26.8 26.8-26.8 26.8 12 26.8 26.8zm76.1 27.2c-1.7-35.9-9.9-67.7-36.2-93.9-26.2-26.2-58-34.4-93.9-36.2-37-2.1-147.9-2.1-184.9 0-35.8 1.7-67.6 9.9-93.9 36.1s-34.4 58-36.2 93.9c-2.1 37-2.1 147.9 0 184.9 1.7 35.9 9.9 67.7 36.2 93.9s58 34.4 93.9 36.2c37 2.1 147.9 2.1 184.9 0 35.9-1.7 67.7-9.9 93.9-36.2 26.2-26.2 34.4-58 36.2-93.9 2.1-37 2.1-147.8 0-184.8zM398.8 388c-7.8 19.6-22.9 34.7-42.6 42.6-29.5 11.7-99.5 9-132.1 9s-102.7 2.6-132.1-9c-19.6-7.8-34.7-22.9-42.6-42.6-11.7-29.5-9-99.5-9-132.1s-2.6-102.7 9-132.1c7.8-19.6 22.9-34.7 42.6-42.6 29.5-11.7 99.5-9 132.1-9s102.7-2.6 132.1 9c19.6 7.8 34.7 22.9 42.6 42.6 11.7 29.5 9 99.5 9 132.1s2.7 102.7-9 132.1z"></path>
                </svg>
              </div>
            </a>

            <a
              className="link"
              href={`https://twitter.com/${user.twitter_username}`}
              style={{
                display: user.twitter_username ? "block" : "none",
              }}
              target="_blank_"
              tabIndex="-1"
              >
              <div className="icon twitter">
                <svg
                  viewBox="0 0 512 512"
                  xmlns="http://www.w3.org/2000/svg"
                  aria-hidden="false"
                  >
                  <path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"></path>
                </svg>
              </div>
            </a>

            <a className="link" href={`${links.download}?force=true`} tabIndex="-1">
              <div className="icon download">
                <svg
                  viewBox="0 0 32 32"
                  xmlns="http://www.w3.org/2000/svg"
                  aria-hidden="false"
                  >
                  <path d="M25.8 15.5l-7.8 7.2v-20.7h-4v20.7l-7.8-7.2-2.7 3 12.5 11.4 12.5-11.4z"></path>
                </svg>
              </div>
            </a>
          </div>
        </div>
        <div
          className="image-card-fg"
          style={{
            background: color,
          }}
          />
      </div>
    </div>
  );
};


const ImageCardList = ({ images, onImageClicked }) => {
  return (
    <div className="masonry">
      {images.map((image, index) => (
        <ImageCard
          imageData={image}
          key={image.id}
          imageIndex={index}
          onImageClicked={(img) => onImageClicked(img)}
          />
      ))}
    </div>
  );
};



const months = [
  "January",
  "February",
  "March",
  "April",
  "May",
  "June",
  "July",
  "August",
  "September",
  "October",
  "November",
  "December",
];

const Modal = ({ imageData, onModalActive }) => {
  const { urls, alt_description, color, links, height, width, created_at, exif } = imageData;

  const date = new Date(created_at);

  const [dropdownActive, setDropdownActive] = useState(false);
  const [infoActive, setInfoActive] = useState(false);
  const [views, setViews] = useState(0);
  const [downloads, setDownloads] = useState(0);
  const [likes, setLikes] = useState(0);
  const [viewsLastMonth, setViewsLastMonth] = useState(0);
  const [downloadsLastMonth, setDownloadsLastMonth] = useState(0);
  const [likesLastMonth, setLikesLastMonth] = useState(0);

  const modalEl = useRef();
  const imageEl = useRef();

  const handleClose = () => {
    modalEl.current.style.display = "none";
    onModalActive(false);
    document.title = "Image Gallery | UNSPLASH";
  };

  const handleDropdown = () => {
    setDropdownActive(!dropdownActive);
  };

  const fetchStats = () => {
    axios(`${API}/photos/${imageData.id}/statistics`, {
      params: {
        client_id: CLIENT_ID,
      },
    }).then((res) => {
      // get all the values in an array
      const lastMonthViewValues = res.data.views.historical.values.map((e) => e.value);
      const lastMonthDownloadValues = res.data.downloads.historical.values.map(
        (e) => e.value
      );
      const lastMonthLikeValues = res.data.likes.historical.values.map((e) => e.value);

      // add up the array
      const lastMonthTotalViews = numberFormatter(returnTotal(lastMonthViewValues), 1);
      const lastMonthTotalDownloads = numberFormatter(
        returnTotal(lastMonthDownloadValues),
        1
      );
      const lastMonthTotalLikes = numberFormatter(returnTotal(lastMonthLikeValues), 1);

      // set all the values
      setViews(res.data.views.total);
      setDownloads(res.data.downloads.total);
      setLikes(res.data.likes.total);
      setViewsLastMonth(lastMonthTotalViews);
      setDownloadsLastMonth(lastMonthTotalDownloads);
      setLikesLastMonth(lastMonthTotalLikes);
    });
  };

  useEffect(fetchStats, []);

  return (
    <div className="modal" ref={modalEl}>
      <div
        className="image-container"
        style={{
          background: color,
            height: width / height > 2 ? "50%" : "80%",
        }}
        >
        <img src={urls.full} alt={alt_description} ref={imageEl} />
        <button className="btn close" onClick={handleClose}>
          <div className="icon">
            <svg
              viewBox="0 0 512 512"
              xmlns="http://www.w3.org/2000/svg"
              aria-hidden="false"
              >
              <path d="M443.6,387.1L312.4,255.4l131.5-130c5.4-5.4,5.4-14.2,0-19.6l-37.4-37.6c-2.6-2.6-6.1-4-9.8-4c-3.7,0-7.2,1.5-9.8,4  L256,197.8L124.9,68.3c-2.6-2.6-6.1-4-9.8-4c-3.7,0-7.2,1.5-9.8,4L68,105.9c-5.4,5.4-5.4,14.2,0,19.6l131.5,130L68.4,387.1  c-2.6,2.6-4.1,6.1-4.1,9.8c0,3.7,1.4,7.2,4.1,9.8l37.4,37.6c2.7,2.7,6.2,4.1,9.8,4.1c3.5,0,7.1-1.3,9.8-4.1L256,313.1l130.7,131.1  c2.7,2.7,6.2,4.1,9.8,4.1c3.5,0,7.1-1.3,9.8-4.1l37.4-37.6c2.6-2.6,4.1-6.1,4.1-9.8C447.7,393.2,446.2,389.7,443.6,387.1z" />
            </svg>
          </div>
        </button>

        <div className="options--container">
          <div className="group g-1">
            <a href={`${links.download}?force=true`} className="download">
              download
            </a>
            <div className="dropdown-btn--container">
              <button className="btn dropdown" onClick={handleDropdown}>
                <div className="icon">
                  <svg viewBox="0 0 32 32" aria-hidden="false">
                    <path d="M9.9 11.5l6.1 6.1 6.1-6.1 1.9 1.9-8 8-8-8 1.9-1.9z"></path>
                  </svg>
                </div>
              </button>
              
              <div className={`dropdown--menu ${dropdownActive ? "" : "hide"}`} tabIndex="-1">
                <ul>
                  <li>
                    <a href={`${links.download}?force=true&w=640`}>
                      Small <span>(640x960)</span>
                    </a>
                  </li>
                  <li>
                    <a href={`${links.download}?force=true&w=1920`}>
                      Medium <span>(1920x2880)</span>
                    </a>
                  </li>
                  <li>
                    <a href={`${links.download}?force=true&w=2400`}>
                      Large <span>(2400x3600)</span>
                    </a>
                  </li>
                  <li>
                    <a href={`${links.download}?force=true`}>
                      Original Size{" "}
                      <span>
                        ({height}x{width})
                      </span>
                    </a>
                  </li>
                </ul>
              </div>
            </div>
          </div>

          <div className="group g-2">
            <button className="btn info" onClick={() => setInfoActive(true)}>
              <div className="icon">
                <svg
                  viewBox="0 0 512 512"
                  xmlns="http://www.w3.org/2000/svg"
                  aria-hidden="true"
                  >
                  <path d="M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z"></path>
                </svg>
              </div>
            </button>
          </div>
        </div>

        <div
          className="image-info--container"
          style={{
            display: infoActive ? "flex" : "none",
          }}
          >
          <div
            className="image-info--modal"
            style={{
              backgroundImage: `linear-gradient(rgba(255, 255, 255, 0.8), white 150px), url("${urls.thumb}&auto=format&fit=crop&w=200&q=60&blur=20")`,
            }}
            >
            <button className="btn close" onClick={() => setInfoActive(false)}>
              <div className="icon">
                <svg
                  viewBox="0 0 512 512"
                  xmlns="http://www.w3.org/2000/svg"
                  aria-hidden="false"
                  >
                  <path d="M443.6,387.1L312.4,255.4l131.5-130c5.4-5.4,5.4-14.2,0-19.6l-37.4-37.6c-2.6-2.6-6.1-4-9.8-4c-3.7,0-7.2,1.5-9.8,4  L256,197.8L124.9,68.3c-2.6-2.6-6.1-4-9.8-4c-3.7,0-7.2,1.5-9.8,4L68,105.9c-5.4,5.4-5.4,14.2,0,19.6l131.5,130L68.4,387.1  c-2.6,2.6-4.1,6.1-4.1,9.8c0,3.7,1.4,7.2,4.1,9.8l37.4,37.6c2.7,2.7,6.2,4.1,9.8,4.1c3.5,0,7.1-1.3,9.8-4.1L256,313.1l130.7,131.1  c2.7,2.7,6.2,4.1,9.8,4.1c3.5,0,7.1-1.3,9.8-4.1l37.4-37.6c2.6-2.6,4.1-6.1,4.1-9.8C447.7,393.2,446.2,389.7,443.6,387.1z" />
                </svg>
              </div>
            </button>

            <div className="row row--1">
              <h1>Info</h1>
              <span>
                Published on {months[date.getMonth()]} {date.getDate()},{" "}
                {date.getFullYear()}
              </span>
            </div>
            <div className="row row--2">
              <div className="image-info views--container">
                <div className="info">
                  <div className="icon">
                    <svg
                      version="1.1"
                      viewBox="0 0 32 32"
                      width="32"
                      height="32"
                      aria-hidden="false"
                      >
                      <path d="M31.8 15.1l-.2-.4c-3.5-6.9-9.7-11.5-15.6-11.5-6.3 0-12.3 4.5-15.7 11.7l-.2.4c-.2.5-.2 1.1 0 1.6l.2.4c3.6 7 9.7 11.5 15.6 11.5 6.3 0 12.3-4.5 15.6-11.6l.2-.4c.4-.5.4-1.2.1-1.7zm-2 1.2c-3 6.5-8.3 10.5-13.8 10.5-5.2 0-10.6-4.1-13.8-10.4l-.2-.4.1-.3c3.1-6.5 8.4-10.5 13.9-10.5 5.2 0 10.6 4.1 13.8 10.4l.2.4-.2.3zm-13.8-6.6c-3.5 0-6.3 2.8-6.3 6.3s2.8 6.3 6.3 6.3 6.3-2.8 6.3-6.3-2.8-6.3-6.3-6.3zm0 10.6c-2.4 0-4.3-1.9-4.3-4.3s1.9-4.3 4.3-4.3 4.3 1.9 4.3 4.3-1.9 4.3-4.3 4.3z"></path>
                    </svg>
                  </div>
                  <span className="info--title">Views</span>
                </div>
                <div className="info info--value">
                  <span className="total-views">{beautifyNumber(views)}</span>
                </div>
                <div className="monthly-stats">
                  <span className="views-stat">+{viewsLastMonth}</span> since last
                  month
                </div>
              </div>
              <div className="image-info downloads--container">
                <div className="info">
                  <div className="icon">
                    <svg
                      version="1.1"
                      viewBox="0 0 32 32"
                      width="32"
                      height="32"
                      aria-hidden="false"
                      >
                      <path d="M27.5 18.08a1 1 0 0 0-1.42 0l-9.08 8.59v-23.67a1 1 0 0 0-2 0v23.67l-9.08-8.62a1 1 0 1 0-1.38 1.45l10.77 10.23a1.19 1.19 0 0 0 .15.09.54.54 0 0 0 .16.1.94.94 0 0 0 .76 0 .54.54 0 0 0 .16-.1l.15-.09 10.77-10.23a1 1 0 0 0 .04-1.42z"></path>
                    </svg>
                  </div>
                  <span className="info info--title">Downloads</span>
                </div>
                <div className="info info--value">
                  <span className="total-views">{beautifyNumber(downloads)}</span>
                </div>
                <div className="monthly-stats">
                  <span className="downloads-stat">+{downloadsLastMonth}</span>{" "}
                  since last month
                </div>
              </div>
              <div className="image-info likes--container">
                <div className="info">
                  <div className="icon">
                    <svg
                      version="1.1"
                      viewBox="0 -4 32 40"
                      width="32"
                      height="32"
                      aria-hidden="false"
                      >
                      <path d="M17.4 29c-.8.8-2 .8-2.8 0l-12.3-12.8c-3.1-3.1-3.1-8.2 0-11.4 3.1-3.1 8.2-3.1 11.3 0l2.4 2.8 2.3-2.8c3.1-3.1 8.2-3.1 11.3 0 3.1 3.1 3.1 8.2 0 11.4l-12.2 12.8z"></path>
                    </svg>
                  </div>
                  <span className="info info--title">Likes</span>
                </div>
                <div className="info info--value">
                  <span className="total-views">{beautifyNumber(likes)}</span>
                </div>
                <div className="monthly-stats">
                  <span className="likes-stat">+{likesLastMonth}</span> since last
                  month
                </div>
              </div>
            </div>
            <div className="hr-line"></div>
            <div className="row row--3">
              <div className="camera-info">
                <span className="info--title">Camera Make</span>
                <span className="info--value">
                  {exif !== undefined ? exif.make : "--"}
                </span>
              </div>
              <div className="camera-info">
                <span className="info--title">Camera Model</span>
                <span className="info--value">
                  {exif !== undefined ? exif.model : "--"}
                </span>
              </div>
              <div className="camera-info">
                <span className="info--title">Focal Length</span>
                <span className="info--value">
                  {exif !== undefined ? `${exif.focal_length}mm` : "--"}
                </span>
              </div>
              <div className="camera-info">
                <span className="info--title">Aperture</span>
                <span className="info--value">
                  {exif !== undefined ? `ƒ/${exif.aperture}` : "--"}
                </span>
              </div>
              <div className="camera-info">
                <span className="info--title">Shutter Speed</span>
                <span className="info--value">
                  {exif !== undefined ? `${exif.exposure_time}s` : "--"}
                </span>
              </div>
              <div className="camera-info">
                <span className="info--title">ISO</span>
                <span className="info--value">
                  {exif !== undefined ? exif.iso : "--"}
                </span>
              </div>
              <div className="camera-info">
                <span className="info--title">Dimensions</span>
                <span className="info--value">
                  {`${width} × ${height}` || "--"}
                </span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

function numberFormatter(num, digits) {
  let si = [
    { value: 1, symbol: "" },
    { value: 1e3, symbol: "k" },
    { value: 1e6, symbol: "M" },
    { value: 1e9, symbol: "G" },
    { value: 1e12, symbol: "T" },
    { value: 1e15, symbol: "P" },
    { value: 1e18, symbol: "E" },
  ];
  let rx = /\.0+$|(\.[0-9]*[1-9])0+$/;
  let i;
  for (i = si.length - 1; i > 0; i--) {
    if (num >= si[i].value) {
      break;
    }
  }
  return (num / si[i].value).toFixed(digits).replace(rx, "$1") + si[i].symbol;
}

function beautifyNumber(num) {
  return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

function returnTotal(arrOfValues) {
  return arrOfValues.reduce((a, c) => (a += c));
}


ReactDOM.render(
  <App />,
  document.getElementById('root')
);
              
            
!
999px

Console