Skip to content

Commit e437038

Browse files
committedSep 3, 2023
feat: use zustand and daisyui
1 parent abc8f78 commit e437038

12 files changed

+696
-126
lines changed
 

‎package.json

+6-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
"build": "next build && next export",
88
"start": "next start",
99
"lint": "next lint . --ignore-path .gitignore",
10-
"lint:fix": "next lint . --fix --ignore-path .gitignore"
10+
"lint:fix": "next lint . --fix --ignore-path .gitignore",
11+
"preview": "serve out"
1112
},
1213
"dependencies": {
1314
"@monaco-editor/react": "^4.5.2",
@@ -16,16 +17,19 @@
1617
"next": "13.2.4",
1718
"react": "18.2.0",
1819
"react-dom": "18.2.0",
19-
"typescript": "5.0.2"
20+
"typescript": "5.0.2",
21+
"zustand": "^4.4.1"
2022
},
2123
"devDependencies": {
2224
"@debbl/eslint-config": "^0.0.53",
2325
"@types/node": "18.15.10",
2426
"@types/react": "18.0.30",
2527
"@types/react-dom": "18.0.11",
2628
"autoprefixer": "^10.4.15",
29+
"daisyui": "^3.6.4",
2730
"eslint-config-next": "13.2.4",
2831
"postcss": "^8.4.29",
32+
"serve": "^14.2.1",
2933
"tailwindcss": "^3.3.3"
3034
}
3135
}

‎pnpm-lock.yaml

+480-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎src/assets/images/github-dark.svg

+15
Loading

‎src/components/Footer.tsx

-14
This file was deleted.

‎src/components/GitHubInfo.tsx

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import Image from "next/image";
2+
import GithubIcon from "~/assets/images/github.svg";
3+
import useMainStore from "~/store/useMainStore";
4+
import GithubIconDark from "~/assets/images/github-dark.svg";
5+
6+
function GitHubInfo() {
7+
const theme = useMainStore((s) => (s.theme === "vs-dark" ? "dark" : "light"));
8+
return (
9+
<div className="ml-8 flex h-[16px] w-[16px] justify-center">
10+
<a
11+
href="https://github.com/Debbl/code-diff"
12+
target="_blank"
13+
rel="noreferrer"
14+
>
15+
<Image
16+
src={theme === "light" ? GithubIcon : GithubIconDark}
17+
alt="https://github.com/Debbl/code-diff"
18+
unoptimized
19+
></Image>
20+
</a>
21+
</div>
22+
);
23+
}
24+
25+
export default GitHubInfo;

‎src/components/Header.tsx

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import GitHubInfo from "./GitHubInfo";
2+
import useMainStore from "~/store/useMainStore";
3+
import type { Theme } from "~/types";
4+
5+
const Header: React.FC = () => {
6+
const [
7+
{ language, languages, theme, renderSideBySide },
8+
{ setLanguage, setTheme, setRenderSideBySide },
9+
] = useMainStore((s) => [
10+
{
11+
language: s.language,
12+
languages: s.languages,
13+
theme: s.theme,
14+
renderSideBySide: s.renderSideBySide,
15+
},
16+
{
17+
setLanguage: s.setLanguage,
18+
setLanguages: s.setLanguages,
19+
setTheme: s.setTheme,
20+
setRenderSideBySide: s.setRenderSideBySide,
21+
},
22+
]);
23+
24+
const handleLanguageChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
25+
setLanguage(e.target.value);
26+
};
27+
const handleThemeChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
28+
setTheme(e.target.value as Theme);
29+
};
30+
const handleRenderSideBySideChange = (
31+
e: React.ChangeEvent<HTMLInputElement>
32+
) => {
33+
setRenderSideBySide(e.target.checked);
34+
};
35+
36+
return (
37+
<header className="flex items-center gap-x-3 p-3">
38+
<div className="flex items-center">
39+
<label>
40+
选择语言:
41+
<select
42+
value={language}
43+
onChange={handleLanguageChange}
44+
className="select select-bordered select-xs ml-3 w-60 border"
45+
>
46+
{languages.map((lang) => (
47+
<option value={lang.id} key={lang.id}>
48+
{lang.id}
49+
</option>
50+
))}
51+
</select>
52+
</label>
53+
</div>
54+
55+
<div className="flex items-center">
56+
<label>
57+
选择主题:
58+
<select
59+
value={theme}
60+
onChange={handleThemeChange}
61+
className="select select-bordered select-xs ml-3 w-60 border"
62+
>
63+
<option value="light">light</option>
64+
<option value="vs-dark">vs-dark</option>
65+
</select>
66+
</label>
67+
</div>
68+
69+
<div className="form-control">
70+
<label className="label cursor-pointer">
71+
<span className="label-text">并排显示:</span>
72+
<input
73+
className="checkbox checkbox-xs ml-3"
74+
type="checkbox"
75+
checked={renderSideBySide}
76+
onChange={handleRenderSideBySideChange}
77+
/>
78+
</label>
79+
</div>
80+
81+
<GitHubInfo />
82+
</header>
83+
);
84+
};
85+
86+
export default Header;

‎src/hooks/useDiffEditor.ts

-52
This file was deleted.

‎src/hooks/useTheme.ts

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { useEffect } from "react";
2+
import useMainStore from "~/store/useMainStore";
3+
4+
const useTheme = () => {
5+
const theme = useMainStore((s) => (s.theme === "vs-dark" ? "dark" : "light"));
6+
7+
useEffect(() => {
8+
const html = document.querySelector("html");
9+
html!.dataset.theme = theme;
10+
}, [theme]);
11+
};
12+
13+
export default useTheme;

‎src/pages/index.tsx

+25-54
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,29 @@
1+
import type { DiffOnMount, Monaco } from "@monaco-editor/react";
12
import { DiffEditor } from "@monaco-editor/react";
23
import Head from "next/head";
34
import nextConfig from "../../next.config";
4-
import Footer from "~/components/Footer";
5-
import type { Theme } from "~/hooks/useDiffEditor";
6-
import useDiffEditor from "~/hooks/useDiffEditor";
5+
import useMainStore from "~/store/useMainStore";
6+
import Header from "~/components/Header";
7+
import useTheme from "~/hooks/useTheme";
78

89
export default function Index() {
9-
const [
10-
{ language, languages, theme, renderSideBySide },
11-
{ setTheme, setRenderSideBySide, handleChange, handleOnMount },
12-
] = useDiffEditor();
10+
useTheme();
11+
12+
const [{ language, theme, renderSideBySide }, { setLanguages }] =
13+
useMainStore((s) => [
14+
{
15+
language: s.language,
16+
theme: s.theme,
17+
renderSideBySide: s.renderSideBySide,
18+
},
19+
{
20+
setLanguages: s.setLanguages,
21+
},
22+
]);
23+
24+
const handleOnMount: DiffOnMount = (_, monaco: Monaco) => {
25+
setLanguages(monaco.languages.getLanguages());
26+
};
1327

1428
return (
1529
<>
@@ -21,53 +35,12 @@ export default function Index() {
2135
type="image/x-icon"
2236
/>
2337
</Head>
24-
<div className="flex h-screen flex-col">
38+
<div className="flex h-screen flex-col items-center">
2539
<h1 className="my-2 text-center text-xl font-medium">Code Diff</h1>
2640

27-
<div className="flex gap-x-3 p-3">
28-
<div>
29-
<label>
30-
选择语言:
31-
<select
32-
value={language}
33-
onChange={handleChange}
34-
className="ml-3 w-60 border"
35-
>
36-
{languages.map((lang) => (
37-
<option value={lang.id} key={lang.id}>
38-
{lang.id}
39-
</option>
40-
))}
41-
</select>
42-
</label>
43-
</div>
44-
<div>
45-
<label>
46-
选择主题:
47-
<select
48-
value={theme}
49-
onChange={(e) => setTheme(e.target.value as Theme)}
50-
className="ml-3 w-60 border"
51-
>
52-
<option value="light">light</option>
53-
<option value="vs-dark">vs-dark</option>
54-
</select>
55-
</label>
56-
</div>
57-
<div>
58-
<label>
59-
并排显示:
60-
<input
61-
className="ml-3"
62-
type="checkbox"
63-
checked={renderSideBySide}
64-
onChange={(e) => setRenderSideBySide(e.target.checked)}
65-
/>
66-
</label>
67-
</div>
68-
</div>
41+
<Header />
6942

70-
<div className="h-full">
43+
<main className="h-full w-full">
7144
<DiffEditor
7245
options={{
7346
originalEditable: true,
@@ -78,9 +51,7 @@ export default function Index() {
7851
theme={theme}
7952
language={language}
8053
/>
81-
</div>
82-
83-
<Footer />
54+
</main>
8455
</div>
8556
</>
8657
);

‎src/store/useMainStore.ts

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { create } from "zustand";
2+
import type * as monaco from "monaco-editor/esm/vs/editor/editor.api";
3+
import type { Theme } from "~/types";
4+
5+
export interface MainStoreState {
6+
language: monaco.languages.ILanguageExtensionPoint["id"];
7+
languages: monaco.languages.ILanguageExtensionPoint[];
8+
theme: Theme;
9+
renderSideBySide: boolean;
10+
}
11+
12+
export interface MainStoreActions {
13+
setLanguage: (language: MainStoreState["language"]) => void;
14+
setLanguages: (languages: MainStoreState["languages"]) => void;
15+
setTheme: (theme: MainStoreState["theme"]) => void;
16+
setRenderSideBySide: (
17+
renderSideBySide: MainStoreState["renderSideBySide"]
18+
) => void;
19+
}
20+
21+
const useMainStore = create<MainStoreState & MainStoreActions>()((set) => ({
22+
language: "plaintext",
23+
languages: [],
24+
theme: "light",
25+
renderSideBySide: true,
26+
27+
setLanguage: (language) => set({ language }),
28+
setLanguages: (languages) => set({ languages }),
29+
setTheme: (theme) => set({ theme }),
30+
setRenderSideBySide: (renderSideBySide) => set({ renderSideBySide }),
31+
}));
32+
33+
export default useMainStore;

‎src/types/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export type Theme = "light" | "vs-dark";

‎tailwind.config.js

+12-1
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,16 @@ module.exports = {
1111
theme: {
1212
extend: {},
1313
},
14-
plugins: [],
14+
plugins: [require("daisyui")],
15+
daisyui: {
16+
themes: [
17+
"light",
18+
{
19+
dark: {
20+
...require("daisyui/src/theming/themes")["[data-theme=dark]"],
21+
"base-100": "#1E1E1E",
22+
},
23+
},
24+
],
25+
},
1526
};

0 commit comments

Comments
 (0)
Please sign in to comment.