.ts
TypeScript
(application/typescript)
// 1st-party
import type { ReactIsland } from "@ethicdevs/react-monolith";
// 3rd-party
import React from "react";
import styled, { css } from "styled-components";
// generated via script[generate:prisma]
import type { Organization, Repository } from "@prisma/client";
// app
import type {
  RepositoryForkedFromRepoMeta,
  WithThemeSchemeProp,
} from "../types";
import { buildRouteLink } from "../utils/shared";
import { ButtonAnchor } from "../components/Button.styled";
import { BackIcon } from "../components/icons/BackIcon";
import { GitForkIcon } from "../components/icons/GitForkIcon";
import { Grid } from "../components/Grid";
import { AppRoute } from "../routes.defs";
import { Colors, NamedColors } from "../utils/style";
// import { useMediaQuery } from "../utils/hooks/useMediaQuery";
// import { theme } from "../theme";

export interface RepositoryHeroProps {
  parentOrg: Organization;
  repo: Repository;
  forkedFromRepo?: RepositoryForkedFromRepoMeta | null;
  forksCount?: number;
  path?: string;
  separator?: string;
  showForkButton?: boolean;
  showNewButton?: boolean;
  newButtonUrl?: string;
  newButtonText?: string | JSX.Element;
}

const RepositoryHero: ReactIsland<
  RepositoryHeroProps & WithThemeSchemeProp
> = ({
  themeScheme,
  parentOrg,
  repo,
  forkedFromRepo = null,
  forksCount = 0,
  path = undefined,
  // separator = "∙",
  showForkButton = true,
  showNewButton = false,
  newButtonUrl = undefined,
  newButtonText = "New Repository",
}) => {
  // const isMobile = useMediaQuery("sm");

  return (
    <Grid.Col
      fluid
      style={{
        margin: "0 -16px",
        padding: "12px 16px",
        width: "calc(100% + 32px)",
        background: NamedColors.BACKGROUND[themeScheme],
        borderBottom: `1px solid ${NamedColors.BORDER_DEFAULT[themeScheme]}`,
      }}
    >
      <Grid.Col fluid gap={16}>
        <Grid.Row fluid nowrap alignItems={"center"}>
          <StyledActionIconButtonAnchor
            themeScheme={themeScheme}
            onClick={
              typeof window !== "undefined"
                ? () => window.history.back()
                : undefined
            }
            visible
          >
            <BackIcon color={NamedColors.TEXT_DEFAULT[themeScheme]} size={24} />
          </StyledActionIconButtonAnchor>
          <Grid.Col
            nowrap
            flex={"1 0 270px"}
            style={{ minWidth: 270, marginLeft: 12 }}
          >
            <h2 style={{ margin: 0, fontSize: 20 }}>
              <a
                style={{ whiteSpace: "nowrap" }}
                href={buildRouteLink(AppRoute.ORGANIZATION_DETAILS, {
                  orgSlug: parentOrg.slug,
                })}
              >
                {parentOrg.displayName || parentOrg.slug}
              </a>
              {" / "}
              <a
                style={{ whiteSpace: "nowrap" }}
                href={buildRouteLink(AppRoute.REPOSITORY_DETAILS, {
                  orgSlug: parentOrg.slug,
                  repoSlug: repo.slug,
                })}
              >
                {repo.displayName || repo.slug}
              </a>
            </h2>
            <div style={{ flex: 1 }}>
              <h3
                style={{
                  whiteSpace: "nowrap",
                  margin: 0,
                  marginTop: 4,
                  fontSize: 16,
                  fontWeight: "700",
                  fontFamily: "monospace",
                }}
              >
                {path || "Files"}
              </h3>
            </div>
            <div style={{ flex: 1 }}>
              {repo.isFork && forkedFromRepo != null && (
                <h5 style={{ margin: 0, marginTop: 8 }}>
                  <span>Forked From</span>
                  {" ∙ "}
                  <a
                    href={buildRouteLink(AppRoute.ORGANIZATION_DETAILS, {
                      orgSlug: forkedFromRepo.organization.slug,
                    })}
                  >
                    {forkedFromRepo.organization.displayName ||
                      forkedFromRepo.organization.slug}
                  </a>
                  {" / "}
                  <a
                    href={buildRouteLink(AppRoute.REPOSITORY_DETAILS, {
                      orgSlug: forkedFromRepo.organization.slug,
                      repoSlug: forkedFromRepo.slug,
                    })}
                  >
                    {forkedFromRepo.displayName || forkedFromRepo.slug}
                  </a>
                </h5>
              )}
            </div>
          </Grid.Col>
          {showForkButton && (
            <ButtonAnchor
              href={buildRouteLink(AppRoute.REPOSITORY_FORK, {
                orgSlug: parentOrg.slug,
                repoSlug: repo.slug,
              })}
            >
              <Grid.Row
                nowrap
                justifyContent={"center"}
                alignItems={"center"}
                gap={8}
              >
                <GitForkIcon color={Colors.WHITE_01} size={24} />
                <span>Fork</span>
                <span
                  style={{
                    padding: "2px 6px",
                    minWidth: 20,
                    background: "rgba(0,0,0,0.1)",
                    borderRadius: 8,
                    fontSize: 12,
                  }}
                >
                  {forksCount}
                </span>
              </Grid.Row>
            </ButtonAnchor>
          )}
          {showNewButton && (
            <ButtonAnchor href={newButtonUrl}>{newButtonText}</ButtonAnchor>
          )}
        </Grid.Row>
      </Grid.Col>
    </Grid.Col>
  );
};

RepositoryHero.displayName = "RepositoryHero";
export default RepositoryHero;

const StyledActionIconButtonAnchor = styled.button<
  WithThemeSchemeProp & { visible?: boolean }
>`
  ${({ themeScheme, visible = true }) => css`
    display: ${visible ? "flex" : "none"};

    justify-content: center;
    align-items: center;

    width: 44px;
    min-width: 44px;
    max-width: 44px;
    height: 44px;
    min-height: 44px;
    max-height: 44px;

    padding-top: -2px;

    font-size: 14px;
    font-weight: thin;
    color: ${NamedColors.TEXT_MUTED[themeScheme]};
    background: ${NamedColors.CARD_OVERLAY[themeScheme]};
    border-image: none;
    border: none;
    border-radius: 22px;
    cursor: pointer;

    &.active,
    &:hover {
      color: ${NamedColors.TEXT_DEFAULT[themeScheme]};
      background: ${NamedColors.CARD[themeScheme]};
    }

    &:active {
      font-size: 22px;
    }
  `}
`;