@lobehub/ui
Version:
Lobe UI is an open-source UI component library for building AIGC web apps
122 lines (119 loc) • 3.71 kB
JavaScript
'use client';
import FlexBasic_default from "../Flex/FlexBasic.mjs";
import MaterialFileTypeIcon_default from "../MaterialFileTypeIcon/MaterialFileTypeIcon.mjs";
import { headerVariants, prefix, styles, variants } from "./style.mjs";
import { memo, useMemo } from "react";
import { jsx, jsxs } from "react/jsx-runtime";
import { cx } from "antd-style";
import { MultiFileDiff } from "@pierre/diffs/react";
//#region src/CodeDiff/CodeDiff.tsx
const countContentChanges = (oldContent, newContent) => {
const oldLines = oldContent.split("\n");
const newLines = newContent.split("\n");
const oldSet = new Set(oldLines);
const newSet = new Set(newLines);
let deletions = 0;
let additions = 0;
for (const line of oldLines) if (!newSet.has(line)) deletions++;
for (const line of newLines) if (!oldSet.has(line)) additions++;
return {
additions,
deletions
};
};
const CodeDiff = memo(({ oldContent, newContent, language, fileName, viewMode = "split", showHeader = true, variant = "filled", className, classNames, styles: customStyles, actionsRender, diffOptions, ...rest }) => {
const displayName = useMemo(() => {
if (fileName) return fileName;
if (language) return language;
return "diff";
}, [fileName, language]);
const { additions, deletions } = useMemo(() => countContentChanges(oldContent, newContent), [oldContent, newContent]);
const actions = useMemo(() => {
if (!actionsRender) return null;
return actionsRender({
newContent,
oldContent,
originalNode: null
});
}, [
actionsRender,
oldContent,
newContent
]);
const oldFile = useMemo(() => ({
contents: oldContent,
lang: language,
name: fileName || "file"
}), [
oldContent,
language,
fileName
]);
const newFile = useMemo(() => ({
contents: newContent,
lang: language,
name: fileName || "file"
}), [
newContent,
language,
fileName
]);
const options = useMemo(() => ({
diffStyle: viewMode,
disableFileHeader: true,
...diffOptions
}), [viewMode, diffOptions]);
return /* @__PURE__ */ jsxs(FlexBasic_default, {
className: cx(variants({ variant }), className),
"data-code-type": "code-diff",
...rest,
children: [showHeader && /* @__PURE__ */ jsxs("div", {
className: cx(headerVariants({ variant }), classNames?.header),
style: customStyles?.header,
children: [/* @__PURE__ */ jsxs(FlexBasic_default, {
align: "center",
gap: 8,
horizontal: true,
children: [/* @__PURE__ */ jsx(MaterialFileTypeIcon_default, {
filename: fileName || displayName,
size: 18,
type: "file"
}), /* @__PURE__ */ jsx("span", { children: displayName })]
}), /* @__PURE__ */ jsxs(FlexBasic_default, {
align: "center",
gap: 8,
horizontal: true,
children: [(deletions > 0 || additions > 0) && /* @__PURE__ */ jsxs(FlexBasic_default, {
className: styles.stats,
gap: 8,
horizontal: true,
children: [deletions > 0 && /* @__PURE__ */ jsxs("span", {
className: styles.deletions,
children: ["-", deletions]
}), additions > 0 && /* @__PURE__ */ jsxs("span", {
className: styles.additions,
children: ["+", additions]
})]
}), actions && /* @__PURE__ */ jsx(FlexBasic_default, {
align: "center",
className: cx(`${prefix}-actions`, styles.actions),
gap: 4,
children: actions
})]
})]
}), /* @__PURE__ */ jsx("div", {
className: cx(styles.body, classNames?.body),
style: customStyles?.body,
children: /* @__PURE__ */ jsx(MultiFileDiff, {
newFile,
oldFile,
options
})
})]
});
});
CodeDiff.displayName = "CodeDiff";
var CodeDiff_default = CodeDiff;
//#endregion
export { CodeDiff_default as default };
//# sourceMappingURL=CodeDiff.mjs.map