import { DownloadIcon } from "@chakra-ui/icons";
import {
Box,
Collapse,
Stack,
StackProps,
Text,
Tooltip,
useDisclosure,
} from "@chakra-ui/react";
import { Assembly } from "@jsii/spec";
import { Fragment, FunctionComponent, ReactNode } from "react";
import spdx from "spdx-license-list";
import { ToggleButton } from "./ToggleButton";
import { PackageLinkConfig } from "../../../api/config";
import { Metadata } from "../../../api/package/metadata";
import { PackageStats } from "../../../api/stats";
import { ExternalLink } from "../../../components/ExternalLink";
import { Highlight } from "../../../components/Highlight";
import { LicenseLink } from "../../../components/LicenseLink";
import { NavLink } from "../../../components/NavLink";
import { Time } from "../../../components/Time";
import { FORMATS } from "../../../constants/dates";
import { useConfigValue } from "../../../hooks/useConfigValue";
import { useStats } from "../../../hooks/useStats";
import { highlightsFrom } from "../../../util/package";
import { getRepoUrlAndHost, getSearchPath } from "../../../util/url";
import { usePackageState } from "../PackageState";
interface DetailsProps extends StackProps {}
const WithLabel: FunctionComponent<{ label: ReactNode; tooltip?: string }> = ({
children,
label,
tooltip,
}) => (
{label}{" "}
{children}
);
const Downloads: FunctionComponent<{ downloads: number }> = ({ downloads }) => (
{downloads.toLocaleString()}
>
}
tooltip="Download numbers are periodically sourced from the npm registry"
>
Weekly downloads
);
const getDetailItemsFromPackage = ({
assembly,
metadata,
name,
packageLinks,
stats,
}: {
assembly?: Assembly;
metadata?: Metadata;
stats?: PackageStats;
packageLinks?: PackageLinkConfig[];
name: string;
}): ReactNode[] => {
const items: ReactNode[] = [];
if (assembly || metadata || stats || packageLinks) {
const downloads: number | undefined =
stats?.packages?.[name]?.downloads?.npm;
if (downloads !== undefined) {
items.push();
}
const username = assembly?.author.name;
const repository = assembly?.repository;
const license = assembly?.license;
if (username) {
const author = (
{username}
);
items.push({author});
}
const date = metadata?.date;
if (date) {
const publishDate = (
);
items.push({publishDate});
}
if (repository) {
const repo = getRepoUrlAndHost(repository.url);
if (repo) {
const repoLink = (
{repo.hostname}
);
items.push({repoLink});
}
}
if (license && license in spdx) {
const licenseLink = ;
items.push({licenseLink});
}
if (packageLinks?.length) {
packageLinks.forEach(({ linkLabel, configKey, linkText }) => {
const target = (metadata?.packageLinks ?? {})[configKey];
if (target) {
const link = (
{linkText ?? target}
);
items.push(
{linkLabel}: {link}
);
}
});
}
const registry =
metadata?.links?.npm ??
`https://www.npmjs.com/package/${assembly?.name}/v/${assembly?.version}`;
if (registry) {
const registryLink = (
{new URL(registry).hostname}
);
items.push({registryLink});
}
}
return items.map((item, i) => {item});
};
export const Details: FunctionComponent = (props) => {
const state = usePackageState();
const stats = useStats().data;
const collapse = useDisclosure({ defaultIsOpen: true });
const packageLinks = useConfigValue("packageLinks");
const assembly = state.assembly.data;
const metadata = state.metadata.data;
const name = state.scope ? `${state.scope}/${state.name}` : state.name;
const [highlight] = highlightsFrom(metadata?.packageTags);
const items = getDetailItemsFromPackage({
assembly,
metadata,
name,
packageLinks,
stats,
});
if (!items.length) return null;
const alwaysShow = items.slice(0, 2);
const showWithCollapse = items.slice(2, items.length);
return (
{highlight && }
{/* TODO: Highlight element */}
{alwaysShow}
{showWithCollapse.length > 0 && (
<>
{showWithCollapse}
>
)}
);
};