1import type { ElementType } from "react";
2import type { SourceControlProviderInfo } from "@t3tools/contracts";
3import { sourceControlClients } from "@t3tools/client-runtime/source-control-clients";
4import type {
5 ChangeRequestTerminology,
6 SourceControlDefinition,
7} from "@t3tools/client-runtime/source-control-clients";
8import { PullRequestGlyph } from "~/components/pullRequest/pullRequestIcons";
9import { SourceControlIconArtwork } from "./components/SourceControlIconArtwork";
10
11export type { ChangeRequestTerminology } from "@t3tools/client-runtime/source-control-clients";
12
13type SourceControlIcon = ElementType<{ className?: string }>;
14
15const SOURCE_CONTROL_ICONS = new WeakMap<SourceControlDefinition, SourceControlIcon>();
16
17/** One component per definition, so a host's icon keeps its identity across renders. */
18export function sourceControlIcon(definition: SourceControlDefinition): SourceControlIcon {
19 const artwork = definition.icon;
20 if (artwork === null) return PullRequestGlyph.pullRequest;
21 let Icon = SOURCE_CONTROL_ICONS.get(definition);
22 if (Icon === undefined) {
23 Icon = (props: { className?: string }) => (
24 <SourceControlIconArtwork {...props} icon={artwork} />
25 );
26 SOURCE_CONTROL_ICONS.set(definition, Icon);
27 }
28 return Icon;
29}
30
31export interface SourceControlPresentation {
32 readonly definition: SourceControlDefinition;
33 readonly providerName: string;
34 readonly terminology: ChangeRequestTerminology;
35 readonly Icon: SourceControlIcon;
36}
37
38function presentDefinition(
39 definition: SourceControlDefinition,
40 providerName: string,
41): SourceControlPresentation {
42 return {
43 definition,
44 providerName,
45 terminology: definition.changeRequest,
46 Icon: sourceControlIcon(definition),
47 };
48}
49
50export function getSourceControlPresentation(
51 provider: SourceControlProviderInfo | null | undefined,
52): SourceControlPresentation {
53 const definition = sourceControlClients.get(provider?.kind);
54 return presentDefinition(definition, provider?.name || definition.label);
55}
56
57export function getSourceControlPresentationForKind(kind: string): SourceControlPresentation {
58 const definition = sourceControlClients.get(kind);
59 return presentDefinition(definition, definition.label);
60}