react-feather#ChevronLeft JavaScript Examples

The following examples show how to use react-feather#ChevronLeft. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Card.js    From ucurtmetre with GNU General Public License v3.0 6 votes vote down vote up
function Card({
  children,
  className,
  title,
  desc,
  withHomeButton = true,
  ...otherProps
}) {
  return (
    <div className={cls(styles.donateCard, className)} {...otherProps}>
      {withHomeButton && (
        <div className={styles.breadcrumbLink}>
          <Link to="/">
            <ChevronLeft />
            Anasayfa&apos;ya dön
          </Link>
        </div>
      )}
      {(title || desc) && (
        <div>
          {title && <h1>{title}</h1>}
          {desc && <p>{desc}</p>}
        </div>
      )}
      {children}
    </div>
  );
}
Example #2
Source File: SinglePost.js    From ecomloop.github.io with MIT License 5 votes vote down vote up
SinglePostTemplate = ({
    title,
    featuredImage,
    localImage,
    date,
    body,
    nextPostURL,
    prevPostURL,
    categories = []
}) => {
    let pageFeaturedImage = featuredImage.startsWith('http') ? featuredImage : ('../' + featuredImage);
    if (localImage && localImage.childImageSharp) pageFeaturedImage = localImage.childImageSharp.fluid.src;
    return (
        <main>
            <PageHeader
                backgroundImage={pageFeaturedImage}
            />
            <article
                className="SinglePost section light"
                itemScope
                itemType="http://schema.org/BlogPosting"
            >
                <div className="container skinny">
                    <Link className="SinglePost--BackButton" to="/blog/">
                        <ChevronLeft /> BACK
                    </Link>
                    <div className="SinglePost--Content relative">
                        <div className="SinglePost--Meta">
                            {date}
                            {categories && (
                                <Fragment>
                                    <span> |</span>
                                    {categories.map((cat, index) => (
                                        <span
                                            key={cat.category}
                                            className="SinglePost--Meta--Category"
                                        >
                                            {cat.category}
                                            {/* Add a comma on all but last category */}
                                            {index !== categories.length - 1 ? ',' : ''}
                                        </span>
                                    ))}
                                </Fragment>
                            )}
                        </div>

                        {title && (
                            <h1 className="SinglePost--Title" itemProp="title">
                                {title}
                            </h1>
                        )}

                        <div className="SinglePost--InnerContent">
                            <Content source={body} />
                        </div>

                        <div className="SinglePost--Pagination">
                            {prevPostURL && (
                                <Link
                                    className="SinglePost--Pagination--Link prev"
                                    to={prevPostURL}
                                >
                                    Previous Post
                                </Link>
                            )}
                            {nextPostURL && (
                                <Link
                                    className="SinglePost--Pagination--Link next"
                                    to={nextPostURL}
                                >
                                    Next Post
                                </Link>
                            )}
                        </div>
                    </div>
                </div>
            </article>
        </main>
    )
}
Example #3
Source File: ContextMenuPlaylists.js    From spotify-react with MIT License 5 votes vote down vote up
render() {
    const userId = localStorage.getItem(USER_ID);
    const {totalPages, loadMore} = this.props;
    const {pending, items, total, loadMorePending} = this.props.playlists;

    const userPlaylists = pending
      ? [{ name: <div className="loader"><Loader /></div> }]
      : items.filter(playlist => {
         return playlist.ownerId === userId;
        });

    const loadData = () => loadMore(items.length);
    return (
      <div>
        <div
          className={`select__title ${totalPages === 1
            ? "select__title_not-active"
            : ""
          }`}
          onClick={this.backOnFirstPage}
        >
          {totalPages > 1 && <ChevronLeft />} Add to playlist
        </div>
        <InfiniteScroll
          total={total}
          dataLength={items.length}
          loadData={loadData}
          pending={loadMorePending}
          containerSelector=".select__inner.custom-scrollbar"
          disable={this.state.disableInfiniteScroll}
          hideLoader={true}
        >
          <ContextMenuItems
            items={userPlaylists}
            handler={this.addTrack}
            disableInfiniteScroll={this.disableInfiniteScroll}
            loadMorePending={loadMorePending}
            emptyMsg="Playlists not found"
          />
        </InfiniteScroll>
      </div>
    );
  }
Example #4
Source File: CustomTable.jsx    From CRM with Apache License 2.0 5 votes vote down vote up
CustomTable = ({ columns, data, title }) => {
  const tableIcons = {
    Add: forwardRef((props, ref) => <Plus {...props} ref={ref} />),
    Check: forwardRef((props, ref) => <Check {...props} ref={ref} />),
    Clear: forwardRef((props, ref) => <X {...props} ref={ref} />),
    Delete: forwardRef((props, ref) => <Trash {...props} ref={ref} />),
    DetailPanel: forwardRef((props, ref) => (
      <ChevronRight {...props} ref={ref} />
    )),
    Edit: forwardRef((props, ref) => <Edit2 {...props} ref={ref} />),
    Export: forwardRef((props, ref) => <Save {...props} ref={ref} />),
    Filter: forwardRef((props, ref) => (
      <Filter {...props} ref={ref} strokeWidth={1.5} width={15} />
    )),
    FirstPage: forwardRef((props, ref) => (
      <ChevronsLeft {...props} ref={ref} />
    )),
    LastPage: forwardRef((props, ref) => (
      <ChevronsRight {...props} ref={ref} />
    )),
    NextPage: forwardRef((props, ref) => <ChevronRight {...props} ref={ref} />),
    PreviousPage: forwardRef((props, ref) => (
      <ChevronLeft {...props} ref={ref} />
    )),
    ResetSearch: forwardRef((props, ref) => <X {...props} ref={ref} />),
    Search: forwardRef((props, ref) => (
      <Search {...props} ref={ref} strokeWidth={1.5} width={18} />
    )),
    SortArrow: forwardRef((props, ref) => (
      <ChevronsDown {...props} ref={ref} />
    )),
    ThirdStateCheck: forwardRef((props, ref) => (
      <XCircle {...props} ref={ref} />
    )),
    ViewColumn: forwardRef((props, ref) => <Eye {...props} ref={ref} />),
  };

  return (
    <React.Fragment>
      <MaterialTable
        icons={tableIcons}
        columns={columns}
        data={data}
        title={title}
        options={{
          filtering: true,
          sorting: true,
          grouping: true,
          exportButton: true,
          headerStyle: {
            backgroundColor: "#3358f4",
            background: "linear-gradient(90deg, #3358f4, #1d8cf8)",
            color: "#FFF",
            backgroundRepeat: "no-repeat",
            textTransform: "uppercase",
          },
          rowStyle: (rowData) => ({
            backgroundColor: "rgb(0,0,0,0)",
          }),
        }}
      />
    </React.Fragment>
  );
}
Example #5
Source File: NewsPost.js    From ecomloop.github.io with MIT License 4 votes vote down vote up
NewsPostTemplate = ({
    author,
    comment,
    dateadded,
    excerpt,
    extractedkeywords,
    headerimage,
    highlight,
    highlight2,
    images,
    image,
    id,
    keywords,

    relativepopularity,
    source,
    source2,
    tags,
    title,
    url,
    body,
    nextPostURL,
    articleid,
    prevPostURL,
    relatedNews,
    relatedPosts,
    categories = (extractedkeywords + "," + tags + "," + keywords).split(",")
}) => {
    //filter out null, and all tags beginning with *
    categories = _.filter(categories, tag => tag != "null" && !tag.startsWith("*"))
    console.log("********** relatedNews (in display) ", relatedNews)
    return (
        <main>
            <PageHeader title={title} backgroundImage={'https://source.unsplash.com/1600x900/?abstract.' + articleid} />
            <article
                className="SinglePost section light"
                itemScope
                itemType="http://schema.org/BlogPosting"
            >
                <div className="container skinny">
                    <Link className="SinglePost--BackButton" to="/news/">
                        <ChevronLeft /> BACK
                    </Link>
                    <div className="SinglePost--Content relative">
                        <div className="SinglePost--Meta">
                            Posted: {dateadded} <br />

                        </div>

                        {title && (
                            <h1 className="SinglePost--Title" itemProp="title">
                                {title}
                            </h1>
                        )}

                        {image && (
                            <div className="SinglePost--InnerContent">
                                <img src={image} title={title} width="100%" />
                            </div>
                        )}

                        <div className="SinglePost--InnerContent">
                            <Content source={comment} />
                        </div>

                        <div className="SinglePost--InnerContent">
                            {author && source &&
                                <div>From {author} at {source}</div>
                            }
                            {publishdate &&
                                <div>Originally published {publishdate}</div>
                            }
                        </div>

                        <div className="SinglePost--InnerContent">
                            <blockquote>{highlight}</blockquote>
                        </div>

                        <div className="SinglePost--InnerContent">
                            <blockquote>{highlight2}</blockquote>
                        </div>

                        <div className="SinglePost--Pagination">
                            <a href={url} target="_blank" className="Nav--CTA animated jello fadeInDown delay-2s">Read the original post &gt;</a>
                        </div>
                        <br />
                        {categories && categories.length > 0 && (
                            <Fragment>
                                <i>Tags:
                                {categories.map((cat, index) => (
                                    <span
                                        key={cat}
                                        className="SinglePost--Meta--Category"
                                    >
                                        <a href={`/news/?tag=${cat.trim()}`}>
                                            {cat.trim()}
                                        </a>
                                        {/* Add a comma on all but last category */}
                                        {index !== categories.length - 1 ? ',' : ''}
                                    </span>
                                ))}</i>
                            </Fragment>
                        )}
                        <div className="SinglePost--Pagination">
                            {prevPostURL && (
                                <Link
                                    className="SinglePost--Pagination--Link prev"
                                    to={prevPostURL}
                                >
                                    Previous Post
                                </Link>
                            )}
                            {nextPostURL && (
                                <Link
                                    className="SinglePost--Pagination--Link next"
                                    to={nextPostURL}
                                >
                                    Next Post
                                </Link>
                            )}
                        </div>
                    </div>
                </div>
                <div className="container skinny">
                    {relatedNews && relatedNews.length > 0 &&
                        <h3 style={{ marginTop: "2rem" }}>Related News</h3>
                    }
                    <div className="PostSection">
                        <div className="PostSection--Grid" style={{ gridTemplateColumns: "repeat(2, 1fr)" }}>
                            {relatedNews && relatedNews.map(({ news }, index) => (
                                <Link key={index} to={`/news/${news.node.articleid}/`} className="PostCard">
                                    <div className="PostCard--Image relative">
                                        <Image background src={'https://source.unsplash.com/1600x900/?abstract.' + news.node.articleid} alt={news.node.title} />
                                    </div>
                                    <div className="PostCard--Content">
                                        {news.node.title && <h3 className="PostCard--Title">{news.node.title}</h3>}
                                        {news.node.dateadded && <div className="PostCard--Category">{moment(new Date(news.node.dateadded)).format("dddd MMMM DD, YYYY")}</div>}
                                        {news.node.comment && <div className="PostCard--Excerpt">{news.node.comment}</div>}
                                    </div>
                                </Link>
                            ))}
                        </div>
                    </div>
                </div>
                {!!relatedPosts.length && (
                    <article className="SinglePost section light" style={{ padding: "1px" }}>
                        <div className="container skinny">
                            <h3>Related Posts</h3>
                            <div className="SinglePost--Content relative" style={{ padding: "0" }}>
                                <PostSection posts={relatedPosts} />
                            </div>
                        </div>
                    </article>
                )}
            </article>
        </main>
    )
}
Example #6
Source File: ProductPage.js    From ecomloop.github.io with MIT License 4 votes vote down vote up
ProductPage = ({ data }) => {
    const product = data.shopifyProduct
    console.log(product)

    //find posts corresponding to current product
    const productBlogTagMap = {
      "ecommerce-platform-strategy-plan" : "digital commerce",
      "conversion-rate-optimization" : "conversion rate optimization",
      "shopify-help" : "Shopify",
      "gatsbyjs" : "gatsby",
      "paid-search-help" : "search"
    };
    const searchTag = productBlogTagMap[product.handle];
    console.log("******* searchTag = "+searchTag)
    console.log("******* product.handle = "+product.handle)
    const filterdPostEdges = [];
    const filterdProjectEdges = [];
    if(searchTag){
      //Filtering Posts as per the tag
      const postEdges = data.allPosts.edges;      
      postEdges.map((edge)=>{
        if(edge.node.frontmatter.tags) {
          edge.node.frontmatter.tags.map((tag)=>{
            if(tag && tag.toLowerCase().includes(searchTag.toLowerCase()))
              {
                filterdPostEdges.push(edge.node)
                return;
              }
          });        
        }
      });
      //console.log(filterdPostEdges)
      //Filtering Projects as per the tag
      const projectEdges = data.allProjects.edges;      
      projectEdges.map((edge)=>{
        if(edge.node.frontmatter.tags) {
          edge.node.frontmatter.tags.map((tag)=>{
            if(tag && tag.toLowerCase().includes(searchTag.toLowerCase()))
              {
                filterdProjectEdges.push(edge.node)
                return;
              }
          });        
        }
      });
      console.log(filterdProjectEdges)
    }

    const thisEdge = data.allServices.edges.find(edge => edge.node.id === product.id);
  
    const solutionEdge = data.allSolutions.edges.find(edge => edge.node.fileAbsolutePath.indexOf(product.handle)>=0)
    let solutionMetaTitle = "";
    let solutionMetaDescription = "";
    let solutionContent = null;
    if(solutionEdge){
      solutionMetaTitle = solutionEdge.node.frontmatter.meta_title;
      solutionMetaDescription = solutionEdge.node.frontmatter.meta_description;
      solutionContent = solutionEdge.node.html;
    }
    //console.log("**** solutionEdge = ",solutionEdge)

    return (
        <Layout title={product.title || false} description={solutionMetaDescription || product.description || false} meta={{title: solutionMetaTitle}}>
            <article
                className="SingleService section light"
                itemScope
                itemType="http://schema.org/BlogPosting"
            >
                <div className="container skinny">
                    <Link className="SingleService--BackButton" to="/solutions/">
                        <ChevronLeft /> BACK
                    </Link>
                    <div className="SingleService--Content relative">

                        <ProductGalleryThumbnails productimages={product.images} />

                        {product.title && (
                            <h1 className="SingleService--Title" itemProp="title">
                                {product.title}
                            </h1>
                        )}

                        <div className="SingleService--InnerContent">
                            <ProductForm product={product} />
                            <Tabs>
                              <TabList>
                                <Tab>Description</Tab>
                                {solutionContent &&
                                  <Tab>Guide</Tab>
                                }
                                <Tab>Blog Posts</Tab>
                                <Tab>Projects</Tab>
                              </TabList>
                              <TabPanel>
                                <div dangerouslySetInnerHTML={{ __html: product.descriptionHtml }} />
                              </TabPanel>
                              {solutionContent &&
                                <TabPanel>
                                  <div dangerouslySetInnerHTML={{__html:solutionContent}} />                                  
                                </TabPanel>
                              }
                              <TabPanel>
                                {!!filterdPostEdges.length && (
                                  <div className="ProductPostSection--Grid" style={{gridGap: "1rem"}}>
                                    {filterdPostEdges.map((post, index) => (
                                      <PostCard key={index}
                                        featuredImage={`../${post.frontmatter.featuredImage}`}
                                        localImage={post.frontmatter.localImage}
                                        title={post.frontmatter.title}
                                        excerpt={post.excerpt}
                                        date={post.frontmatter.date}
                                        slug={post.fields.slug}
                                      />
                                    ))}
                                  </div>
                                )}
                              </TabPanel>
                              <TabPanel>
                                {!!filterdProjectEdges.length && (
                                  <div className="ProductPostSection--Grid" style={{gridGap: "1rem"}}>
                                    {filterdProjectEdges.map((post, index) => (
                                      <PostCard key={index}
                                        featuredImage={`../${post.frontmatter.featuredImage}`}
                                        localImage={post.frontmatter.localImage}
                                        title={post.frontmatter.title}
                                        excerpt={post.frontmatter.excerpt}
                                        date={post.frontmatter.date}
                                        slug={post.fields.slug}
                                      />
                                    ))}
                                  </div>
                                )}
                              </TabPanel>
                            </Tabs>
                        </div>

                        <div className="SingleService--Pagination">
                            {thisEdge && thisEdge.previous && thisEdge.previous.handle && (
                                <Link
                                    className="SingleService--Pagination--Link prev"
                                    to={`/solution/${thisEdge.previous.handle}`}
                                >
                                    Previous Service
                                </Link>
                            )}
                            {thisEdge && thisEdge.next && thisEdge.next.handle && (
                                <Link
                                    className="SingleService--Pagination--Link next"
                                    to={`/solution/${thisEdge.next.handle}`}
                                >
                                    Next Service
                                </Link>
                            )}
                        </div>
                    </div>
                </div>
            </article>
        </Layout >
    )
}
Example #7
Source File: TransactionHistoryTable.js    From ucurtmetre with GNU General Public License v3.0 4 votes vote down vote up
function TransactionHistoryTable({ data }) {
  const breakpoint = useBreakpoints();
  const isMobile = breakpoint === 'isMobile';

  const columns = useMemo(
    () => [
      {
        Header: 'Kimden',
        accessor: 'from.name',
        Cell: ({ value }) => (
          <div className="person with-icon">
            <div>{value || 'Anonim'}</div>
            <div className="icon">
              <ArrowRight />
            </div>
          </div>
        ),
      },

      {
        Header: 'Kime',
        accessor: 'to.name',
        Cell: ({
          value,
          row: {
            original: { to },
          },
        }) => {
          let Element = 'div';
          let linkProps;
          if (to.campaignCode && to.campaignCode !== 'donate-all') {
            Element = 'a';
            linkProps = {
              href: `https://www.ucurtmaprojesi.com/campaign/${to.campaignCode}`,
            };
          }
          return (
            <Element className="person" {...linkProps}>
              {value}
            </Element>
          );
        },
      },
      {
        Header: 'Ne Zaman',
        accessor: 'when',
        id: 'when',
        Cell: ({ value }) => <div>{dayjs().to(dayjs(value * 1000))}</div>,
      },
      {
        Header: 'Ne Kadar',
        accessor: 'amount',
        Cell: ({
          value,
          row: {
            original: { tokenName },
          },
        }) => (
          <div className="amount">{`${
            typeof value === 'number' ? Math.floor(value) : value
          } ${tokenName}`}</div>
        ),
      },
    ],
    []
  );

  const defaultSort = useMemo(() => [{ id: 'when', desc: true }], []);

  const tableInstance = useTable(
    {
      columns,
      data,
      initialState: { sortBy: defaultSort, pageSize: 10, pageIndex: 0 },
      disableMultiSort: true,
      disableSortRemove: true,
    },
    useFlexLayout,
    useSortBy,
    usePagination
  );
  const {
    getTableProps,
    headerGroups,
    prepareRow,
    page,
    canPreviousPage,
    canNextPage,
    pageOptions,
    pageCount,
    gotoPage,
    nextPage,
    previousPage,
    state: { pageIndex },
  } = tableInstance;

  return (
    <div className="table-wrapper">
      <div {...(!isMobile && getTableProps())} className="table">
        {!isMobile &&
          headerGroups.map(headerGroup => (
            <div {...headerGroup.getHeaderGroupProps({})} className="tr">
              {headerGroup.headers.map(column => (
                <div
                  {...column.getHeaderProps(column.getSortByToggleProps())}
                  className="th title"
                >
                  {column.render('Header')}
                  {column.isSorted ? (
                    column.isSortedDesc ? (
                      <ChevronDown />
                    ) : (
                      <ChevronUp />
                    )
                  ) : (
                    ''
                  )}
                </div>
              ))}
            </div>
          ))}
        <div className="tbody">
          {page.map(row => {
            prepareRow(row);
            return (
              <div {...row.getRowProps()} className="tr">
                {row.cells.map(cell => {
                  return (
                    <div {...cell.getCellProps()} className="td">
                      {isMobile && (
                        <div className="td-header">{cell.render('Header')}</div>
                      )}
                      <div className="td-content">{cell.render('Cell')}</div>
                    </div>
                  );
                })}
              </div>
            );
          })}
        </div>
      </div>
      <div className="pagination">
        <div>
          <button
            className="button icon-button"
            type="button"
            onClick={() => gotoPage(0)}
            disabled={!canPreviousPage}
          >
            <ChevronsLeft />
          </button>
          <button
            className="button icon-button"
            type="button"
            onClick={() => previousPage()}
            disabled={!canPreviousPage}
          >
            <ChevronLeft />
          </button>
          <button
            className="button icon-button"
            type="button"
            onClick={() => nextPage()}
            disabled={!canNextPage}
          >
            <ChevronRight />
          </button>
          <button
            className="button icon-button"
            type="button"
            onClick={() => gotoPage(pageCount - 1)}
            disabled={!canNextPage}
          >
            <ChevronsRight />
          </button>
        </div>
        <span>
          Toplam {pageOptions.length} sayfadan
          <strong>{pageIndex + 1}.</strong>
          sayfayı görüntülüyorsunuz.
        </span>
      </div>
    </div>
  );
}
Example #8
Source File: Track.test.js    From spotify-react with MIT License 4 votes vote down vote up
describe("<Track />", () => {
  it("track should have the 'track_active' class", () => {
    const props = {
      trackList: [{}, {}, {}],
      source: {name: "test"},
      track: {isActive: true},
    };
    const wrapper = shallow(<Track {...props} />);
    expect(wrapper.find(".track_active")).toHaveLength(1);
  });

  it("play and pause buttons should toggle correctly", () => {
    const props = {
      track: {isActive: true},
      trackContext: {name: "album", tracks: [{}, {}, {}]},
      player: {
        ...initialPlayerState,
        trackPaused: true,
      },
    };
    const wrapper = shallow(<CoverImage {...props} />);
    expect(wrapper.find(".track__cover-art_has-image")).toHaveLength(0);
    expect(wrapper.find("img")).toHaveLength(0);
    expect(wrapper.find(PlayButton)).toHaveLength(1);
    wrapper.setProps({
      player: {
        ...initialPlayerState,
        trackPaused: false,
      },
    });
    expect(wrapper.find(PlayButton)).toHaveLength(0);
    expect(wrapper.find(PauseButton)).toHaveLength(1);

    wrapper.setProps({track: {isActive: false}});
    expect(wrapper.find(PlayButton)).toHaveLength(1);
    expect(wrapper.find(PauseButton)).toHaveLength(0);
  });

  it("should render the count of tracks correctly", () => {
    const props = {
      charts: true,
      track: {key: 5, authors: []},
    };
    const wrapper = shallow(<TrackInfo {...props} />);
    expect(wrapper.find(".track__chart-number")).toHaveLength(1);
    expect(wrapper.find(".track__chart-number").at(0).text()).toEqual("05");
    wrapper.setProps({track: {key: 15, authors: []}});
    expect(wrapper.find(".track__chart-number").at(0).text()).toEqual("15");
  });

  it("context menu should work correctly", () => {
    const props = {
      playlists: initialListUserPlaylistsState,
      addTrackToPlaylist: jest.fn(),
      totalPages: 2,
      navigateToPage: jest.fn(),
      trackUri: "",
      closeContextMenu: jest.fn(),
      loadUserPlaylists: jest.fn(),
    };
    const wrapper = shallow(<ContextMenuPlaylists {...props} />);
    expect(props.loadUserPlaylists.mock.calls.length).toBe(1);
    expect(wrapper.find(".select__title_not-active")).toHaveLength(0);
    expect(wrapper.find(ChevronLeft)).toHaveLength(1);

    wrapper.find(".select__title").simulate("click");
    expect(props.navigateToPage.mock.calls.length).toBe(1);

    wrapper.setProps({totalPages: 1});
    wrapper.find(".select__title").simulate("click");
    expect(props.navigateToPage.mock.calls.length).toBe(1);
  });

  it("play button should work correctly", () => {
    const props = {
      context: {},
      track: {preview_url: null},
    };

    const wrapper = shallow(<PlayButton {...props}/>);
    wrapper.instance().play = jest.fn();

    expect(wrapper.find(".track__icon.disabled")).toHaveLength(1);
    wrapper.find(".track__icon.disabled").simulate("click");
    expect(wrapper.instance().play.mock.calls.length).toBe(0);

    wrapper.setProps({track: {preview_url: "test"}});
    expect(wrapper.find(".track__icon.disabled")).toHaveLength(0);
    wrapper.find(".track__icon").simulate("click");
    expect(wrapper.instance().play.mock.calls.length).toBe(1);
  });

  it("play method should work correctly", () => {
    const props = {
      context: {},
      track: {preview_url: "test", isActive: true},
    };
    playerAPI.resumeTrack = jest.fn();
    playerAPI.playTrack = jest.fn();
    const wrapper = shallow(<PlayButton {...props}/>);

    wrapper.find(".track__icon").simulate("click");
    expect(playerAPI.resumeTrack.mock.calls.length).toBe(1);
    expect(playerAPI.playTrack.mock.calls.length).toBe(0);

    wrapper.setProps({track: {preview_url: "test", isActive: false}});

    wrapper.find(".track__icon").simulate("click");
    expect(playerAPI.playTrack.mock.calls.length).toBe(1);
  });
});
Example #9
Source File: Calendar.js    From covid19india-react with MIT License 4 votes vote down vote up
function Calendar({date, dates, slider}) {
  const [view, setView] = useState('month');
  const [activeStartDate, setActiveStartDate] = useState(parseIndiaDate(date));

  const minDate = parseIndiaDate(dates[0]);
  const maxDate = parseIndiaDate(dates[dates.length - 1]);

  const isDateDisabled = ({date, view}) => {
    return (
      view === 'month' &&
      !dates.includes(formatISO(date, {representation: 'date'}))
    );
  };

  const handleCalendarClick = (value) => {
    const clickedDate = formatISO(value, {representation: 'date'});
    slider.moveToSlide(dates.indexOf(clickedDate));
  };

  const handleViewButton = ({view}) => {
    setView(view);
  };

  const handleNavigationButton = ({activeStartDate}) => {
    setActiveStartDate(activeStartDate);
  };

  const handleNavigation = (direction) => {
    const newDate = add(
      activeStartDate,
      view === 'month' ? {months: direction} : {years: direction}
    );
    const lower =
      view === 'month' ? startOfMonth(minDate) : startOfYear(minDate);
    const upper = view === 'month' ? endOfMonth(maxDate) : endOfYear(maxDate);
    if (lower <= newDate && newDate <= upper) {
      setActiveStartDate(newDate);
    }
  };

  const swipeHandlers = useSwipeable({
    onSwipedRight: handleNavigation.bind(this, -1),
    onSwipedLeft: handleNavigation.bind(this, 1),
  });

  const handleWheel = (event) => {
    if (event.deltaX !== 0) {
      handleNavigation(Math.sign(event.deltaX));
    }
  };

  return (
    <div className="Calendar" onWheel={handleWheel} {...swipeHandlers}>
      <ReactCalendar
        value={parseIndiaDate(date)}
        tileDisabled={isDateDisabled}
        {...{minDate, maxDate, activeStartDate, view}}
        onActiveStartDateChange={handleNavigationButton}
        onViewChange={handleViewButton}
        minDetail="year"
        showFixedNumberOfWeeks
        onChange={handleCalendarClick}
        prevLabel={
          <div>
            <ChevronLeft size={18} />
          </div>
        }
        nextLabel={
          <div>
            <ChevronRight size={18} />
          </div>
        }
        prev2Label={
          <div>
            <ChevronsLeft size={18} />
          </div>
        }
        next2Label={
          <div>
            <ChevronsRight size={18} />
          </div>
        }
      />
    </div>
  );
}
Example #10
Source File: Table.js    From covid19india-react with MIT License 4 votes vote down vote up
function Table({
  data: states,
  date: timelineDate,
  regionHighlighted,
  setRegionHighlighted,
  expandTable,
  setExpandTable,
  hideDistrictData,
  hideDistrictTestData,
  hideVaccinated,
  lastDataDate,
  noDistrictDataStates,
}) {
  const {t} = useTranslation();
  const [sortData, setSortData] = useSessionStorage('sortData', {
    sortColumn: 'confirmed',
    isAscending: false,
    delta: false,
  });
  const [page, setPage] = useState(0);
  const [delta7Mode, setDelta7Mode] = useState(false);

  const [tableContainerRef, {width: tableWidth}] = useMeasure();

  const handleSortClick = useCallback(
    (statistic) => {
      if (sortData.sortColumn !== statistic) {
        setSortData(
          produce(sortData, (draftSortData) => {
            if (
              sortData.sortColumn === 'regionName' ||
              statistic === 'regionName'
            ) {
              draftSortData.isAscending = !sortData.isAscending;
            }
            draftSortData.sortColumn = statistic;
          })
        );
      } else {
        setSortData(
          produce(sortData, (draftSortData) => {
            draftSortData.isAscending = !sortData.isAscending;
          })
        );
      }
    },
    [sortData, setSortData]
  );

  const trail = useTrail(5, {
    from: {transform: 'translate3d(0, 10px, 0)', opacity: 0},
    to: {transform: 'translate3d(0, 0px, 0)', opacity: 1},
    config: config.wobbly,
  });

  const [allDistricts, setAllDistricts] = useState();

  const [tableOption, setTableOption] = useState('States');
  const [isPerLakh, setIsPerLakh] = useState(false);
  const [isInfoVisible, setIsInfoVisible] = useState(false);

  const getTableStatistic = useCallback(
    (data, statistic, type) => {
      const statisticConfig = STATISTIC_CONFIGS[statistic];
      if (type == 'total' && statisticConfig?.onlyDelta7) {
        type = 'delta7';
      }

      if (statisticConfig?.showDelta && type === 'total' && delta7Mode) {
        type = 'delta7';
      }

      return getStatistic(data, type, statistic, {
        expiredDate: lastDataDate,
        normalizedByPopulationPer: isPerLakh ? 'lakh' : null,
      });
    },
    [isPerLakh, lastDataDate, delta7Mode]
  );

  const districts = useMemo(() => {
    if (!isPerLakh) {
      return allDistricts;
    } else {
      return Object.keys(allDistricts || {})
        .filter(
          (districtKey) =>
            getStatistic(allDistricts[districtKey], 'total', 'population') > 0
        )
        .reduce((res, districtKey) => {
          res[districtKey] = allDistricts[districtKey];
          return res;
        }, {});
    }
  }, [isPerLakh, allDistricts]);

  const numPages = Math.ceil(
    Object.keys(districts || {}).length / DISTRICT_TABLE_COUNT
  );

  const sortingFunction = useCallback(
    (regionKeyA, regionKeyB) => {
      if (sortData.sortColumn !== 'regionName') {
        const statisticConfig = STATISTIC_CONFIGS[sortData.sortColumn];
        const dataType =
          sortData.delta && statisticConfig?.showDelta ? 'delta' : 'total';

        const statisticA = getTableStatistic(
          districts?.[regionKeyA] || states[regionKeyA],
          sortData.sortColumn,
          dataType
        );
        const statisticB = getTableStatistic(
          districts?.[regionKeyB] || states[regionKeyB],
          sortData.sortColumn,
          dataType
        );
        return sortData.isAscending
          ? statisticA - statisticB
          : statisticB - statisticA;
      } else {
        const regionNameA =
          districts?.[regionKeyA]?.districtName || STATE_NAMES[regionKeyA];
        const regionNameB =
          districts?.[regionKeyB]?.districtName || STATE_NAMES[regionKeyB];
        return sortData.isAscending
          ? regionNameA.localeCompare(regionNameB)
          : regionNameB.localeCompare(regionNameA);
      }
    },
    [
      districts,
      getTableStatistic,
      sortData.delta,
      sortData.isAscending,
      sortData.sortColumn,
      states,
    ]
  );

  const _setTableOption = useCallback(() => {
    setTableOption((prevTableOption) =>
      prevTableOption === 'States' ? 'Districts' : 'States'
    );
  }, []);

  useEffect(() => {
    const workerInstance = worker();
    workerInstance.getDistricts(states);
    workerInstance.addEventListener('message', (message) => {
      if (message.data.type !== 'RPC') {
        setAllDistricts(message.data);
        workerInstance.terminate();
      }
    });
  }, [tableOption, states]);

  useEffect(() => {
    setPage((p) => Math.max(0, Math.min(p, numPages - 1)));
  }, [numPages]);

  const handlePageClick = (direction) => {
    if (Math.abs(direction) === 1) {
      setPage(Math.min(Math.max(0, page + direction), numPages - 1));
    } else if (direction < 0) {
      setPage(0);
    } else if (direction > 0) {
      setPage(numPages - 1);
    }
  };

  const transition = useTransition(isInfoVisible, {
    from: TABLE_FADE_OUT,
    enter: TABLE_FADE_IN,
    leave: TABLE_FADE_OUT,
  });

  const tableStatistics = (
    expandTable ? TABLE_STATISTICS_EXPANDED : TABLE_STATISTICS
  ).filter(
    (statistic) =>
      (tableOption === 'States' ||
        STATISTIC_CONFIGS[statistic]?.category !== 'tested' ||
        !hideDistrictTestData) &&
      (STATISTIC_CONFIGS[statistic]?.category !== 'vaccinated' ||
        !hideVaccinated)
  );

  const showDistricts = tableOption === 'Districts' && !hideDistrictData;

  useEffect(() => {
    if (!showDistricts) {
      setPage(0);
    }
  }, [showDistricts]);

  useKeyPressEvent('?', () => {
    setIsInfoVisible(!isInfoVisible);
  });

  return (
    <div className="Table">
      <div className="table-top">
        <div className="table-top-left">
          <Tooltip message={'Toggle between states/districts'} hold>
            <animated.div
              className={classnames('toggle', 'option-toggle', {
                'is-highlighted': showDistricts,
                disabled: hideDistrictData,
              })}
              onClick={_setTableOption}
              style={trail[0]}
            >
              <DistrictIcon />
            </animated.div>
          </Tooltip>

          <Tooltip message={'Per lakh people'} hold>
            <animated.div
              className={classnames('toggle', 'lakh-toggle', {
                'is-highlighted': isPerLakh,
              })}
              onClick={setIsPerLakh.bind(this, !isPerLakh)}
              style={trail[1]}
            >
              <PerLakhIcon />
            </animated.div>
          </Tooltip>

          <Tooltip message={'Last 7 day values'} hold>
            <animated.div
              className={classnames('toggle', 'delta-toggle', {
                'is-highlighted': delta7Mode,
              })}
              style={trail[2]}
              onClick={setDelta7Mode.bind(this, !delta7Mode)}
            >
              <Delta7Icon />
            </animated.div>
          </Tooltip>

          <animated.div
            className={classnames('toggle', 'info-toggle', {
              'is-highlighted': isInfoVisible,
            })}
            onClick={setIsInfoVisible.bind(this, !isInfoVisible)}
            style={trail[3]}
          >
            <QuestionIcon size={14} />
          </animated.div>
        </div>

        <Tooltip message={`${expandTable ? 'Collapse' : 'Expand'} table`} hold>
          <animated.div
            className={classnames('toggle', 'expand-table-toggle', {
              'is-highlighted': expandTable,
            })}
            style={trail[4]}
            onClick={setExpandTable.bind(this, !expandTable)}
          >
            <FoldDownIcon size={16} />
          </animated.div>
        </Tooltip>
      </div>

      {transition(
        (style, item) =>
          item && (
            <animated.div className="table-helper" {...{style}}>
              <div className="helper-top">
                <div className="helper-left">
                  <div className="info-item">
                    <div>
                      <OrganizationIcon size={14} />
                    </div>
                    <p>{t('Toggle between States/Districts')}</p>
                  </div>

                  <div className="info-item">
                    <div>
                      <PeopleIcon size={16} />
                    </div>
                    <p>{t('Per Lakh People')}</p>
                  </div>

                  <div className="info-item">
                    <div>
                      <PulseIcon size={16} />
                    </div>
                    <p>{t('Last 7 day values')}</p>
                  </div>

                  <div className="info-item sort">
                    <div>
                      <SortDescIcon size={14} />
                    </div>
                    <p>{t('Sorted by Descending')}</p>
                  </div>

                  <div className="info-item sort">
                    <div>
                      <SortAscIcon size={14} />
                    </div>
                    <p>{t('Sorted by Ascending')}</p>
                  </div>

                  <div className="info-item sort">
                    <TableDeltaHelper />
                  </div>

                  <div className="info-item notes">
                    <div>
                      <InfoIcon size={15} />
                    </div>
                    <p>{t('Notes')}</p>
                  </div>
                </div>

                <div className="helper-right">
                  <div className="info-item">
                    <p>{t('Units')}</p>
                  </div>
                  {Object.entries({'1K': 3, '1L': 5, '1Cr': 7}).map(
                    ([abbr, exp]) => (
                      <div className="info-item abbr" key={abbr}>
                        <h5>{abbr}</h5>
                        <p>
                          10
                          <sup>{exp}</sup>
                        </p>
                      </div>
                    )
                  )}
                </div>
              </div>

              <h5 className="text">
                {t('Compiled from State Govt. numbers')},{' '}
                <Link to="/about">{t('know more')}!</Link>
              </h5>
            </animated.div>
          )
      )}

      <div className="table-container" ref={tableContainerRef}>
        <div
          className="table fadeInUp"
          style={{
            gridTemplateColumns: `repeat(${tableStatistics.length + 1}, auto)`,
          }}
        >
          <div className="row heading">
            <div
              className="cell heading"
              onClick={handleSortClick.bind(this, 'regionName')}
            >
              <div>{t(!showDistricts ? 'State/UT' : 'District')}</div>
              {sortData.sortColumn === 'regionName' && (
                <div className={'sort-icon'}>
                  {sortData.isAscending ? (
                    <SortAscIcon size={12} />
                  ) : (
                    <SortDescIcon size={12} />
                  )}
                </div>
              )}
            </div>

            {tableStatistics.map((statistic) => (
              <HeaderCell
                key={statistic}
                {...{
                  statistic,
                  sortData,
                  setSortData,
                }}
                handleSort={handleSortClick.bind(this, statistic)}
              />
            ))}
          </div>

          {!showDistricts &&
            Object.keys(states)
              .filter(
                (stateCode) =>
                  stateCode !== 'TT' &&
                  !(stateCode === UNASSIGNED_STATE_CODE && isPerLakh)
              )
              .sort((a, b) => sortingFunction(a, b))
              .map((stateCode) => {
                return (
                  <Row
                    key={stateCode}
                    data={states[stateCode]}
                    noDistrictData={noDistrictDataStates[stateCode]}
                    {...{
                      stateCode,
                      regionHighlighted,
                      setRegionHighlighted,
                      expandTable,
                      tableStatistics,
                      getTableStatistic,
                      tableWidth,
                    }}
                  />
                );
              })}

          {showDistricts && !districts && <TableLoader />}

          {showDistricts &&
            districts &&
            Object.keys(districts)
              .sort((a, b) => sortingFunction(a, b))
              .slice(
                page * DISTRICT_TABLE_COUNT,
                (page + 1) * DISTRICT_TABLE_COUNT
              )
              .map((districtKey) => {
                const noDistrictData =
                  noDistrictDataStates[districts[districtKey].stateCode];
                return (
                  <Row
                    key={districtKey}
                    data={districts[districtKey]}
                    districtName={districts[districtKey].districtName}
                    {...{
                      regionHighlighted,
                      setRegionHighlighted,
                      expandTable,
                      tableStatistics,
                      getTableStatistic,
                      noDistrictData,
                    }}
                  />
                );
              })}

          <Row
            key={'TT'}
            data={states['TT']}
            stateCode={'TT'}
            {...{
              regionHighlighted,
              setRegionHighlighted,
              expandTable,
              tableStatistics,
              getTableStatistic,
            }}
          />
        </div>
      </div>
      {showDistricts && (
        <div className="paginate">
          <div
            className={classnames('left', {disabled: page === 0})}
            onClick={handlePageClick.bind(this, -2)}
          >
            <ChevronsLeft size={16} />
          </div>
          <div
            className={classnames('left', {disabled: page === 0})}
            onClick={handlePageClick.bind(this, -1)}
          >
            <ChevronLeft size={16} />
          </div>
          <h5>{`${page + 1} / ${numPages}`}</h5>
          <div
            className={classnames('right', {disabled: page === numPages - 1})}
            onClick={handlePageClick.bind(this, 1)}
          >
            <ChevronRight size={16} />
          </div>
          <div
            className={classnames('right', {disabled: page === numPages - 1})}
            onClick={handlePageClick.bind(this, 2)}
          >
            <ChevronsRight size={16} />
          </div>
        </div>
      )}
    </div>
  );
}
Example #11
Source File: date-nav.js    From covid19-dashboard with MIT License 4 votes vote down vote up
DateNav = ({disabled}) => {
  // Creating a event listener on each stroke to avoid the issue of data not being refreshed inside the function
  // This is due to functionnal component relying on closure and the function passed to the event being "pulled" on top
  useEffect(() => {
    // Checking if we are on the client or server side
    if (typeof window !== 'undefined') {
      window.addEventListener('keydown', handleKeyDown)
      // Remove event listeners on cleanup
      return () => {
        window.removeEventListener('keydown', handleKeyDown)
      }
    }
  })

  const themeContext = useContext(ThemeContext)
  const {date, setDate} = useContext(AppContext)
  const formatedDate = formatDate(date)
  const previousDate = getPreviousDate(date)
  const nextDate = getNextDate(date)

  const handleKeyDown = event => {
    if (!disabled) {
      if (event.key === 'ArrowLeft' && previousDate) {
        setDate(previousDate)
      } else if (event.key === 'ArrowRight' && nextDate) {
        setDate(nextDate)
      }
    }
  }

  return (
    <div className='menu-header'>
      {!disabled && (
        <>
          <div
            className={`report-nav ${previousDate ? '' : 'disabled'}`}
            onClick={previousDate ? () => setDate(previousDate) : null}
          >
            <ChevronLeft />
          </div>
          <h3>Données au {formatedDate}</h3>
          <div
            className={`report-nav ${nextDate ? '' : 'disabled'}`}
            onClick={nextDate ? () => setDate(nextDate) : null}
          >
            <ChevronRight />
          </div>
        </>
      )}

      <style jsx>{`
        .menu-header {
          z-index: 2;
          display: flex;
          flex-flow: nowrap;
          justify-content: space-between;
          align-items: center;
          text-align: center;
          padding: 0 1em;
          background-color: ${themeContext.primary};
          color: #fff;
        }

        .menu-header h3 {
          margin: 0.5em;
        }

        .report-nav {
          display: flex;
          justify-content: center;
          align-items: center;
        }

        .report-nav.disabled {
          color: #ffffff55;
        }

        .report-nav.disabled:hover {
          cursor: initial;
        }

        .report-nav:hover {
          cursor: pointer;
        }

        @media (max-width: ${theme.mobileDisplay}) {
          .menu-header {
            font-size: small;
            padding: ${disabled ? '1.7em 1em' : '0.5em 1em'};
          }

          .menu-header h3 {
            margin: 0.2em;
          }
        }

        @media (max-width: 1320px) {
          .menu-header {
            font-size: small;
          }
        }
      `}</style>
    </div>
  )
}
Example #12
Source File: indicators-map.js    From covid19-dashboard with MIT License 4 votes vote down vote up
IndicatorsMap = ({hovered, isDROM}) => {
  const {selectedLocation, setSelectedLocation, isMobileDevice} = useContext(AppContext)
  const {selectedDate, selectedStat} = useContext(IndicatorsContext)
  const {code = '', region = ''} = hovered && hovered.feature ? hovered.feature.properties : {}

  const [indicators, setIndicators] = useState([])

  const handleBack = event => {
    event.stopPropagation()
    setSelectedLocation('FRA')
  }

  const getSelectedRegion = useCallback(() => {
    const [locationType, code] = selectedLocation.split('-')
    if (locationType !== 'FRA') {
      return locationType === 'REG' ? code : departements.find(d => d.code === code).region
    }

    return null
  }, [selectedLocation])

  const selectedRegion = getSelectedRegion()

  useEffect(() => {
    const getIndicatorsData = async () => {
      const {history} = await getReport(selectedDate, 'DEP')
      setIndicators(history.filter(({date}) => selectedDate === date).map(dep => {
        return {
          ...dep,
          code: dep.code.split('-')[1]
        }
      }))
    }

    getIndicatorsData()
  }, [selectedDate])

  const getColors = useCallback(() => {
    const colors = ['match', ['get', 'code']]

    indicators.forEach(indicator => {
      const color = COLORS[indicator[`${selectedStat}Color`]] || defaultColor
      colors.push(indicator.code, color)
    })

    colors.push(defaultColor)

    return colors.length > 3 ? colors : defaultColor
  }, [indicators, selectedStat])

  const getOpacity = useCallback(() => {
    return ['case', ['==', ['get', 'code'], region || code], 0, 0.5]
  }, [code, region])

  if (indicators) {
    const indicateurSynthese = {
      id: 'indicateur',
      'source-layer': 'departements',
      type: 'fill',
      paint: {
        'fill-color': getColors(),
        'fill-outline-color': '#ffffff'
      }
    }

    const regionsLayer = {
      id: 'regions-fill',
      'source-layer': 'regions',
      type: 'fill',
      filter: selectedRegion ? ['!=', ['get', 'code'], selectedRegion] : ['has', 'code'],
      paint: {
        'fill-opacity': getOpacity(),
        'fill-color': '#fff',
        'fill-outline-color': colors.darkBlue
      }
    }

    return (
      <>
        {!isDROM && selectedLocation !== 'FRA' && (
          <div className={`back ${isMobileDevice ? 'mobile' : ''}`} onClick={handleBack}>
            <ChevronLeft /> Retour
          </div>
        )}
        <Source
          id='decoupage-administratif'
          type='vector'
          attribution='Données Ministère des Solidarités et de la santé'
          url='https://etalab-tiles.fr/data/decoupage-administratif.json'
        >
          <Layer beforeId='place-town' {...indicateurSynthese} />
          <Layer beforeId='place-town' {...regionsLayer} />
        </Source>

        <style jsx>{`
          .back {
            z-index: 2;
            position: absolute;
            display: flex;
            align-items: center;
            top: 0;
            left: calc(240px + 0.5em); // 240px is the width of <MapSelector />
            margin: 0.5em;
            padding: 0.5em;
            border-radius: 4px;
            color: #fff;
            background-color: #000000aa;
          }

          .back.mobile {
            left: 0;
          }

          .back:hover {
            cursor: pointer;
            background-color: #000;
          }
          `}</style>
      </>
    )
  }

  return null
}
Example #13
Source File: Layout.js    From popper.js.org with MIT License 4 votes vote down vote up
Layout = ({ children, location, pageResources, ...props }) => {
  const path = location.pathname;
  function getPrevNextRoutes(routes) {
    const validRoutes = flatten(createTree(processRoutes(routes, path)));

    const currentPathIndex = validRoutes.findIndex(
      route => route.slug === path
    );

    return {
      prev: validRoutes[currentPathIndex - 1],
      next: validRoutes[currentPathIndex + 1],
    };
  }

  // HACK: remove this if the plugin can somehow work by default...
  // Fixes the anchor not being scrolled to on page load
  useLayoutEffect(anchorScroll, []);

  return (
    <MDXProvider components={components}>
      <Global
        styles={css`
          h1,
          h2,
          h3,
          h4,
          h5,
          h6 {
            color: #f4e0f1;
            font-weight: bold;
          }

          h1 {
            font-size: 40px;
            margin-top: 20px;
            padding-top: 20px;
            line-height: 1.1;
          }

          h2 {
            font-size: 32px;
            line-height: 1.3;
          }

          h3 {
            font-size: 24px;
            margin-bottom: 10px;
            margin-top: 40px;
          }

          h4 {
            font-size: 20px;
            margin-bottom: 10px;
          }

          h5 {
            font-size: 18px;
          }

          h2::before {
            content: ' ';
            display: block;
            border-bottom: 1px solid #44395d;
            padding-top: 20px;
            margin-bottom: 40px;
          }

          blockquote {
            margin: 0;
            padding: 0.5em 30px;
            border-radius: 0px 10px 10px 0px;
            background-color: rgba(135, 82, 27, 0.25);
            color: #ddc5a1;
            border-left: 2px dashed #ddc5a1;
          }

          h3 > code[class*='language-'] {
            color: #ffe69d;
          }

          ul {
            padding-left: 20px;
          }

          li {
            margin-bottom: 5px;
          }

          a {
            color: #ffe69d;
            text-decoration: none;
            padding-bottom: 1px;
            border-bottom: 2px solid rgba(255, 228, 148, 0.25);
            transition: border-bottom-color 0.15s ease-in-out;

            &:hover {
              border-bottom: 2px solid rgba(255, 228, 148, 1);
            }

            &:active {
              border-bottom-style: dashed;
            }
          }

          ${media.md} {
            pre[class*='language-'] {
              padding: 15px 20px;
            }
          }

          h1 .gatsby-link-icon {
            display: none;
          }

          h2,
          h3,
          h4,
          h5,
          h6 {
            &:hover {
              .gatsby-link-icon {
                opacity: 1;
              }
            }
          }

          .gatsby-link-icon {
            fill: #ffb6b3;
            border: none;
            margin-left: -30px;
            padding-right: 10px;
            opacity: 0;
            transition: opacity 0.15s ease-in-out;
            float: right;

            ${media.md} {
              float: left;
            }

            &:focus {
              opacity: 1;
            }

            &:hover {
              border: none;
            }

            svg {
              width: 20px;
              height: 20px;
            }
          }
        `}
      />
      <div>
        {pageResources && (
          <SEO
            title={
              pageResources.json.pageContext.frontmatter.title ||
              pageResources.json.pageContext.frontmatter.navigationLabel
            }
          />
        )}
        <Navigation root="/" target="location" path={path} />
        <Main>
          <Container>
            {children}
            <EditPage path={path} />
          </Container>
          <MdxRoutes>
            {routes => {
              const { prev, next } = getPrevNextRoutes(routes);
              return (
                <NavButtonWrapper>
                  <NavButtonContainer>
                    <NavButtonCell>
                      {prev && (
                        <NavButton to={`${prev.slug}`} data-first>
                          <NavButtonDirection data-prev>
                            <ChevronLeft size={28} css={arrowCss} />
                          </NavButtonDirection>
                          {prev.navigationLabel}
                        </NavButton>
                      )}
                    </NavButtonCell>
                    <NavDivider />
                    <NavButtonCell>
                      {next && (
                        <NavButton to={`${next.slug}`} data-last>
                          {next.navigationLabel}
                          <NavButtonDirection data-next>
                            <ChevronRight size={28} css={arrowCss} />
                          </NavButtonDirection>
                        </NavButton>
                      )}
                    </NavButtonCell>
                  </NavButtonContainer>
                </NavButtonWrapper>
              );
            }}
          </MdxRoutes>
        </Main>
        <FooterStyled>© {new Date().getFullYear()} MIT License</FooterStyled>
      </div>
    </MDXProvider>
  );
}