oldPath.endsWith(".java")} />
// ))
// .add("Expandable", () => {
// const filesWithLanguage = diffFiles.map((file: FileDiff) => {
// file._links = { lines: { href: "http://example.com/" } };
// return file;
// });
// return ;
// })
// .add("WithLinkToFile", () => )
// .add("Changing Content", () => {
// const ChangingContentDiff = () => {
// const [markdown, setMarkdown] = useState(false);
// return (
//
//
// {/* @ts-ignore */}
//
//
// );
// };
//
// return ;
// })
// .add("External state management", () => {
// const [externalState, setExternalState] = useState({});
//
// const isCollapsed = (file: FileDiff) => {
// return externalState[file.newPath] || false;
// };
//
// const onCollapseStateChange = (file: FileDiff) => {
// setExternalState((current) => ({ ...current, [file.newPath]: !current[file.newPath] }));
// };
//
// return ;
// });
import React, { ReactNode, useEffect, useState } from "react";
import styled from "styled-components";
import type { Meta, StoryObj } from "@storybook/react";
import parser from "gitdiff-parser";
import { Changeset, FileDiff } from "@scm-manager/ui-types";
import Diff from "./Diff";
import DiffButton from "./DiffButton";
import JumpToFileButton from "./JumpToFileButton";
import Toast from "../toast/Toast";
import Button from "../buttons/Button";
import { DiffEventContext, FileControlFactory } from "./DiffTypes";
import { getPath } from "./diffs";
import simpleDiff from "../__resources__/Diff.simple";
import hunksDiff from "../__resources__/Diff.hunks";
import binaryDiff from "../__resources__/Diff.binary";
import markdownDiff from "../__resources__/Diff.markdown";
import { two } from "../__resources__/changesets";
// @ts-ignore ignore unknown png
import hitchhikerImg from "../__resources__/hitchhiker.png";
// @ts-ignore ignore unknown jpg
import marvinImg from "../__resources__/marvin.jpg";
import { MemoryRouter } from "react-router-dom";
// --- Helfer-Funktionen und Mock-Daten (aus der Original-Story übernommen) ---
const Container = styled.div`
padding: 2rem 1rem; // Adjusted padding for better viewing
`;
const diffFiles = parser.parse(simpleDiff);
const fileControlFactory: (changeset: Changeset) => FileControlFactory = (changeset) => (file) => {
const baseUrl = "/repo/hitchhiker/heartOfGold/code/changeset";
const sourceLink = { url: `${baseUrl}/${changeset.id}/${file.newPath}/`, label: "Jump to source" };
const targetLink = changeset._embedded?.parents?.length === 1 && {
url: `${baseUrl}/${changeset._embedded.parents[0].id}/${file.oldPath}`,
label: "Jump to target",
};
const links = [];
switch (file.type) {
case "add":
links.push(sourceLink);
break;
case "delete":
if (targetLink) {
links.push(targetLink);
}
break;
default:
if (targetLink) {
links.push(sourceLink, targetLink);
} else {
links.push(sourceLink);
}
}
return links.map(({ url, label }) => );
};
// Helper-Komponenten für komplexe Stories
const OnClickExample = () => {
const [changeId, setChangeId] = useState();
useEffect(() => {
const interval = setInterval(() => setChangeId(undefined), 2000);
return () => clearInterval(interval);
}, []);
const onClick = (context: DiffEventContext) => setChangeId(context.changeId);
return (
<>
{changeId && }
>
);
};
const ChangingContentExample = () => {
const [markdown, setMarkdown] = useState(false);
return (
{/* @ts-ignore */}
);
};
const ExternalStateExample = () => {
const [externalState, setExternalState] = useState<{ [key: string]: boolean }>({});
const isCollapsed = (file: FileDiff) => externalState[file.newPath] || false;
const onCollapseStateChange = (file: FileDiff) => {
setExternalState((current) => ({ ...current, [file.newPath]: !current[file.newPath] }));
};
return ;
};
// --- Storybook Metadaten ---
const meta: Meta = {
title: "Repositories/Diff",
component: Diff,
decorators: [
(Story) => {Story()},
(Story) => {Story()}],
tags: ["autodocs"],
};
export default meta;
// --- Story-Definitionen ---
type Story = StoryObj;
export const Default: Story = { args: { diff: diffFiles } };
export const SideBySide: Story = { args: { diff: diffFiles, sideBySide: true } };
export const Whitespace: Story = { args: { diff: diffFiles, whitespace: true } };
export const Collapsed: Story = {
args: { diff: diffFiles, defaultCollapse: true, fileControlFactory: fileControlFactory(two) },
};
export const Hunks: Story = { args: { diff: parser.parse(hunksDiff) } };
export const Binaries: Story = { args: { diff: parser.parse(binaryDiff) } };
export const HunkGutterHoverIcon: Story = { args: { diff: parser.parse(hunksDiff), hunkGutterHoverIcon: "\f075" } };
export const HighlightLineOnHover: Story = { args: { diff: parser.parse(hunksDiff), highlightLineOnHover: true } };
export const Expandable: Story = {
args: { diff: diffFiles.map((file) => ({ ...file, _links: { lines: { href: "http://example.com/" } } })) },
};
export const WithLinkToFile: Story = { args: { diff: diffFiles } };
export const FileControls: Story = {
args: {
diff: diffFiles,
fileControlFactory: () => (
alert("Arrrgggghhhh ...")}
/>
),
},
};
export const FileAnnotation: Story = {
args: {
diff: diffFiles,
fileAnnotationFactory: (file) => [Custom File annotation for {file.newPath}
],
},
};
export const LineAnnotation: Story = {
args: {
diff: diffFiles,
annotationFactory: () => ({ N2: Line Annotation
}),
},
};
export const CollapsingWithFunction: Story = {
args: {
diff: diffFiles,
defaultCollapse: (oldPath) => oldPath.endsWith(".java"),
},
};
export const SyntaxHighlighting: Story = {
args: {
diff: diffFiles.map((file) => {
const ext = getPath(file).split(".")[1];
return { ...file, language: ext === "tsx" ? "typescript" : ext };
}),
},
};
export const SyntaxHighlightingMarkdown: Story = {
name: "Syntax Highlighting (Markdown)",
// @ts-ignore
args: { diff: markdownDiff.files },
};
// export const Images: Story = {
// args: {
// diff: [
// { type: "add", newPath: "add.png", isBinary: true, _links: { newFile: { href: hitchhikerImg } } },
// { type: "delete", oldPath: "delete.png", isBinary: true, _links: { oldFile: { href: hitchhikerImg } } },
// { type: "modify", newPath: "modify.png", isBinary: true, _links: { oldFile: { href: hitchhikerImg }, newFile: { href: marvinImg } } },
// ] as FileDiff[],
// },
// };
// Stories with stateful logic use `render`
export const OnClick: Story = { render: () => };
export const ChangingContent: Story = { render: () => };
export const ExternalStateManagement: Story = { render: () => };