tr]:last:border-b-0",
46 | className
47 | )}
48 | {...props}
49 | />
50 | )
51 | }
52 |
53 | function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
54 | return (
55 |
63 | )
64 | }
65 |
66 | function TableHead({ className, ...props }: React.ComponentProps<"th">) {
67 | return (
68 | [role=checkbox]]:translate-y-[2px]",
72 | className
73 | )}
74 | {...props}
75 | />
76 | )
77 | }
78 |
79 | function TableCell({ className, ...props }: React.ComponentProps<"td">) {
80 | return (
81 | | [role=checkbox]]:translate-y-[2px]",
85 | className
86 | )}
87 | {...props}
88 | />
89 | )
90 | }
91 |
92 | function TableCaption({
93 | className,
94 | ...props
95 | }: React.ComponentProps<"caption">) {
96 | return (
97 |
102 | )
103 | }
104 |
105 | export {
106 | Table,
107 | TableHeader,
108 | TableBody,
109 | TableFooter,
110 | TableHead,
111 | TableRow,
112 | TableCell,
113 | TableCaption,
114 | }
115 |
--------------------------------------------------------------------------------
/src/components/ui/breadcrumb.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import { Slot } from "@radix-ui/react-slot";
3 | import ChevronRight from "lucide-react/dist/esm/icons/chevron-right";
4 | import MoreHorizontal from "lucide-react/dist/esm/icons/more-horizontal";
5 |
6 | import { cn } from "@/lib/utils";
7 |
8 | function Breadcrumb({ ...props }: React.ComponentProps<"nav">) {
9 | return ;
10 | }
11 |
12 | function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
13 | return (
14 |
22 | );
23 | }
24 |
25 | function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
26 | return (
27 |
32 | );
33 | }
34 |
35 | function BreadcrumbLink({
36 | asChild,
37 | className,
38 | ...props
39 | }: React.ComponentProps<"a"> & {
40 | asChild?: boolean;
41 | }) {
42 | const Comp = asChild ? Slot : "a";
43 |
44 | return (
45 |
50 | );
51 | }
52 |
53 | function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
54 | return (
55 |
63 | );
64 | }
65 |
66 | function BreadcrumbSeparator({
67 | children,
68 | className,
69 | ...props
70 | }: React.ComponentProps<"li">) {
71 | return (
72 | svg]:size-3.5", className)}
77 | {...props}
78 | >
79 | {children ?? }
80 |
81 | );
82 | }
83 |
84 | function BreadcrumbEllipsis({
85 | className,
86 | ...props
87 | }: React.ComponentProps<"span">) {
88 | return (
89 |
96 |
97 | More
98 |
99 | );
100 | }
101 |
102 | export {
103 | Breadcrumb,
104 | BreadcrumbList,
105 | BreadcrumbItem,
106 | BreadcrumbLink,
107 | BreadcrumbPage,
108 | BreadcrumbSeparator,
109 | BreadcrumbEllipsis,
110 | };
111 |
--------------------------------------------------------------------------------
/src/routes/settings/LanguageSection.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@/components/ui/button";
2 | import {
3 | Command,
4 | CommandEmpty,
5 | CommandGroup,
6 | CommandInput,
7 | CommandItem,
8 | CommandList,
9 | } from "@/components/ui/command";
10 | import {
11 | Popover,
12 | PopoverContent,
13 | PopoverTrigger,
14 | } from "@/components/ui/popover";
15 | import { cn } from "@/lib/utils";
16 | import Check from "lucide-react/dist/esm/icons/check";
17 | import ChevronsUpDown from "lucide-react/dist/esm/icons/chevrons-up-down";
18 | import { useState } from "react";
19 | import { useTranslation } from "react-i18next";
20 |
21 | interface LanguageSectionProps {
22 | appLanguage: string;
23 | setAppLanguage: (language: string) => void;
24 | availableLanguages: { code: string; name: string }[];
25 | i18n: any;
26 | }
27 |
28 | const LanguageSection: React.FC = ({
29 | appLanguage,
30 | setAppLanguage,
31 | availableLanguages,
32 | i18n,
33 | }) => {
34 | const { t } = useTranslation();
35 | const [open, setOpen] = useState(false);
36 |
37 | return (
38 |
39 |
40 | {t("appLanguage")}
41 |
42 | {t("selectAppLanguage")}
43 |
44 |
45 |
46 |
47 |
57 |
58 |
59 |
60 |
61 |
62 | {t("noLanguageFound")}
63 |
64 | {availableLanguages.map((l) => (
65 | {
69 | setAppLanguage(l.code);
70 | i18n.changeLanguage(l.code);
71 | setOpen(false);
72 | }}
73 | >
74 | {l.name}
75 |
81 |
82 | ))}
83 |
84 |
85 |
86 |
87 |
88 |
89 | );
90 | };
91 |
92 | export default LanguageSection;
93 |
--------------------------------------------------------------------------------
/public/locales/zh/translation.json:
--------------------------------------------------------------------------------
1 | {
2 | "appTitle": "CodeQuill",
3 | "newSnippet": "新代码片段",
4 | "filename": "文件名",
5 | "selectLanguage": "选择语言...",
6 | "save": "保存",
7 | "saving": "正在保存...",
8 | "hidePreview": "隐藏预览",
9 | "showPreview": "显示预览",
10 | "noPreview": "无预览",
11 | "toggleSidebar": "切换侧边栏",
12 | "typeToSearch": "输入以搜索代码片段...",
13 | "noSnippetsFound": "未找到代码片段。",
14 | "copy": "复制",
15 | "delete": "删除",
16 | "settings": "设置",
17 | "backToEditor": "返回编辑器",
18 | "customizeYourExperience": "自定义您的 CodeQuill 体验",
19 | "theme": "主题",
20 | "chooseYourPreferredAppearance": "选择您喜欢的应用外观",
21 | "defaultLanguage": "默认语言",
22 | "defaultProgrammingLanguage": "新代码片段的默认编程语言",
23 | "keyboardShortcuts": "键盘快捷键",
24 | "viewCommonKeyboardShortcuts": "查看常用键盘快捷键",
25 | "saveSnippet": "保存代码片段",
26 | "createNewSnippet": "创建新代码片段",
27 | "searchSnippets": "搜索代码片段",
28 | "previewCode": "预览代码",
29 | "openSettings": "打开设置",
30 | "formatCode": "格式化代码",
31 | "undo": "撤销",
32 | "redo": "重做",
33 | "appInfo": "应用信息",
34 | "informationAboutCodeQuill": "关于 CodeQuill 的信息",
35 | "version": "版本",
36 | "installedVersion": "已安装版本",
37 | "license": "许可证",
38 | "openSource": "开源",
39 | "createdBy": "创建者",
40 | "sourceCode": "源代码",
41 | "reportIssue": "报告问题",
42 | "dependencies": "依赖项",
43 | "librariesUsed": "CodeQuill 使用的库",
44 | "production": "生产环境",
45 | "librariesBundled": "生产构建中捆绑的库",
46 | "development": "开发环境",
47 | "librariesUsedDevelopment": "CodeQuill 开发中使用的库",
48 | "productionDependencies": "生产依赖项",
49 | "developmentDependencies": "开发依赖项",
50 | "deleteThisSnippet": "删除这个代码片段?",
51 | "thisActionCannotBeUndone": "此操作无法撤销。这将永久删除该代码片段。",
52 | "cancel": "取消",
53 | "deleting": "正在删除...",
54 | "newSnippetSaved": "新代码片段已保存!",
55 | "snippetSavedSuccessfully": "代码片段保存成功!",
56 | "snippetCopiedToClipboard": "代码片段已复制到剪贴板",
57 | "snippetDeletedSuccessfully": "代码片段删除成功!",
58 | "untitled": "未命名",
59 | "youDonTHaveAnySnippets": "你还没有任何代码片段。现在创建一个吧!",
60 | "createNow": "立即创建!",
61 | "morePages": "更多页面",
62 | "previous": "上一页",
63 | "next": "下一页",
64 | "close": "关闭",
65 | "searchLanguage": "搜索语言...",
66 | "noLanguageFound": "未找到语言。",
67 | "website": "网站",
68 | "themeLight": "浅色",
69 | "themeDark": "深色",
70 | "themeDim": "暗色",
71 | "themeSystem": "跟随系统",
72 | "failedToLoadSnippets": "加载代码片段失败。",
73 | "failedToCreateNewSnippet": "创建新代码片段失败。",
74 | "creatingNewSnippet": "正在创建新代码片段",
75 | "failedToLoadPreviewState": "从本地存储加载预览状态失败。",
76 | "pleaseSelectLanguage": "请选择一种语言。",
77 | "filenameCannotBeEmpty": "文件名不能为空。",
78 | "filenameTooLong": "文件名不能超过1024个字符。",
79 | "savingSnippet": "正在保存代码片段",
80 | "failedToSaveSnippet": "保存代码片段失败。",
81 | "failedToCopySnippet": "复制代码片段失败。",
82 | "failedToRemovePreview": "从本地存储中删除预览失败。",
83 | "deletingSnippet": "正在删除代码片段",
84 | "failedToDeleteSnippet": "删除代码片段失败。",
85 | "appLanguage": "应用语言",
86 | "selectAppLanguage": "选择您的使用语言",
87 | "snippetInformation": "代码片段信息",
88 | "snippetDetails": "查看此代码片段的详细信息",
89 | "id": "ID",
90 | "language": "语言",
91 | "lastSaved": "最后保存",
92 | "info": "信息",
93 | "noPreviewAvailable": "无法提供预览",
94 | "notAvailable": "不可用"
95 | }
96 |
--------------------------------------------------------------------------------
/src/routes/home/LanguageSelector.tsx:
--------------------------------------------------------------------------------
1 | import supportedLanguages from "@/assets/supportedLanguages.json";
2 | import { Button } from "@/components/ui/button";
3 | import {
4 | Command,
5 | CommandEmpty,
6 | CommandGroup,
7 | CommandInput,
8 | CommandItem,
9 | CommandList,
10 | } from "@/components/ui/command";
11 | import {
12 | Popover,
13 | PopoverContent,
14 | PopoverTrigger,
15 | } from "@/components/ui/popover";
16 | import { cn } from "@/lib/utils";
17 | import Check from "lucide-react/dist/esm/icons/check";
18 | import ChevronsUpDown from "lucide-react/dist/esm/icons/chevrons-up-down";
19 | import React, { useEffect, useState } from "react";
20 | import { useTranslation } from "react-i18next";
21 | import { Language } from "./types";
22 |
23 | interface LanguageSelectorProps {
24 | language: Language | null;
25 | setLanguage: (language: Language | null) => void;
26 | }
27 |
28 | const LanguageSelector: React.FC = ({
29 | language,
30 | setLanguage,
31 | }) => {
32 | const [open, setOpen] = useState(false);
33 | const [value, setValue] = useState(""); // Initialize to empty string
34 | const { t } = useTranslation();
35 |
36 | // Update the internal 'value' state whenever the 'language' prop changes.
37 | useEffect(() => {
38 | setValue(language?.id || "");
39 | }, [language]);
40 |
41 | return (
42 |
43 |
44 |
55 |
56 |
57 |
58 |
59 |
60 | {t("noLanguageFound")}
61 |
62 | {supportedLanguages.map((l) => (
63 | {
67 | setValue(currentValue);
68 | setOpen(false);
69 | setLanguage(
70 | supportedLanguages.find(
71 | (l) => l.id === currentValue,
72 | ) as Language,
73 | );
74 | }}
75 | >
76 | {l.name}
77 |
83 |
84 | ))}
85 |
86 |
87 |
88 |
89 |
90 | );
91 | };
92 |
93 | export default LanguageSelector;
94 |
--------------------------------------------------------------------------------
/src/utils/database.ts:
--------------------------------------------------------------------------------
1 | import Database from "@tauri-apps/plugin-sql";
2 |
3 | export interface Snippet {
4 | id: string;
5 | filename: string;
6 | language: string;
7 | code: string;
8 | created_at?: string;
9 | }
10 |
11 | const DB_PATH = "sqlite:codequill.db";
12 |
13 | let db: Database | null = null;
14 |
15 | const initializeDatabase = async (
16 | retryCount: number = 0,
17 | ): Promise => {
18 | if (db) {
19 | return db;
20 | }
21 |
22 | if (retryCount >= 3) {
23 | throw new Error("Failed to initialize database after multiple retries.");
24 | }
25 |
26 | try {
27 | db = await Database.load(DB_PATH);
28 |
29 | // Create the snippets table if it doesn't exist
30 |
31 | // Note: created_at should really be called something like "updated_at" or "last_modified",
32 | // since that's the purpose it serves...
33 | await db.execute(`
34 | CREATE TABLE IF NOT EXISTS snippets (
35 | id TEXT PRIMARY KEY,
36 | filename TEXT NOT NULL,
37 | language TEXT NOT NULL,
38 | code TEXT NOT NULL,
39 | created_at DATETIME DEFAULT CURRENT_TIMESTAMP
40 | )
41 | `);
42 | return db;
43 | } catch (error) {
44 | console.error("Error initializing database:", error);
45 | console.log(
46 | `Retrying database initialization (attempt ${retryCount + 1}) in 1 second...`,
47 | );
48 | await new Promise((resolve) => setTimeout(resolve, 1000));
49 | return initializeDatabase(retryCount + 1); // Recursive call to retry with incremented counter.
50 | }
51 | };
52 |
53 | export const getAllSnippets = async (): Promise => {
54 | const dbInstance = await initializeDatabase();
55 | const result = await dbInstance.select(
56 | "SELECT * FROM snippets ORDER BY created_at DESC",
57 | );
58 | return result;
59 | };
60 |
61 | export const getSnippet = async (id: string): Promise => {
62 | const dbInstance = await initializeDatabase();
63 | const result = await dbInstance.select(
64 | "SELECT * FROM snippets WHERE id = ?",
65 | [id],
66 | );
67 | return result.length > 0 ? result[0] : undefined;
68 | };
69 |
70 | export const saveSnippet = async (snippet: Snippet) => {
71 | const dbInstance = await initializeDatabase();
72 |
73 | try {
74 | // The created at date is implied here. It is auto updated by the database.
75 | // Because it updates on save, the snippet will move to the top of the list as desired.
76 | await dbInstance.execute(
77 | `INSERT OR REPLACE INTO snippets (id, filename, language, code) VALUES (?, ?, ?, ?)`,
78 | [snippet.id, snippet.filename, snippet.language, snippet.code],
79 | );
80 | } catch (error) {
81 | console.error("Error saving snippet:", error);
82 | throw error; // Re-throw the error to be handled by the caller
83 | }
84 | };
85 |
86 | export const deleteSnippet = async (id: string) => {
87 | const dbInstance = await initializeDatabase();
88 | try {
89 | await dbInstance.execute("DELETE FROM snippets WHERE id = ?", [id]);
90 | } catch (error) {
91 | console.error("Error deleting snippet:", error);
92 | throw error; // Re-throw the error to be handled by the caller
93 | }
94 | };
95 |
--------------------------------------------------------------------------------
/src/routes/settings/ProgrammingLanguageSection.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@/components/ui/button";
2 | import {
3 | Command,
4 | CommandEmpty,
5 | CommandGroup,
6 | CommandInput,
7 | CommandItem,
8 | CommandList,
9 | } from "@/components/ui/command";
10 | import {
11 | Popover,
12 | PopoverContent,
13 | PopoverTrigger,
14 | } from "@/components/ui/popover";
15 | import { cn } from "@/lib/utils";
16 | import { Language } from "@/routes/home/types";
17 | import Check from "lucide-react/dist/esm/icons/check";
18 | import ChevronsUpDown from "lucide-react/dist/esm/icons/chevrons-up-down";
19 | import { useState } from "react";
20 | import { useTranslation } from "react-i18next";
21 |
22 | interface LanguageSectionProps {
23 | language: Language;
24 | setLanguage: (language: Language) => void;
25 | supportedLanguages: Language[];
26 | }
27 |
28 | const ProgrammingLanguageSection: React.FC = ({
29 | language,
30 | setLanguage,
31 | supportedLanguages,
32 | }) => {
33 | const { t } = useTranslation();
34 | const [open, setOpen] = useState(false);
35 |
36 | return (
37 |
38 |
39 | {t("defaultLanguage")}
40 |
41 | {t("defaultProgrammingLanguage")}
42 |
43 |
44 |
45 |
46 |
56 |
57 |
58 |
59 |
60 |
61 | {t("noLanguageFound")}
62 |
63 | {supportedLanguages.map((l) => (
64 | {
68 | const selectedLanguage = supportedLanguages.find(
69 | (l) => l.id === currentValue,
70 | ) as Language;
71 | setLanguage(selectedLanguage);
72 | setOpen(false);
73 | }}
74 | >
75 | {l.name}
76 |
82 |
83 | ))}
84 |
85 |
86 |
87 |
88 |
89 |
90 | );
91 | };
92 |
93 | export default ProgrammingLanguageSection;
94 |
--------------------------------------------------------------------------------
/public/locales/ko/translation.json:
--------------------------------------------------------------------------------
1 | {
2 | "appTitle": "CodeQuill",
3 | "newSnippet": "새 스니펫",
4 | "filename": "파일명",
5 | "selectLanguage": "언어 선택...",
6 | "save": "저장",
7 | "saving": "저장 중...",
8 | "hidePreview": "미리보기 숨기기",
9 | "showPreview": "미리보기 표시",
10 | "noPreview": "미리보기 없음",
11 | "toggleSidebar": "사이드바 전환",
12 | "typeToSearch": "스니펫 검색...",
13 | "noSnippetsFound": "스니펫을 찾을 수 없습니다.",
14 | "copy": "복사",
15 | "delete": "삭제",
16 | "settings": "설정",
17 | "backToEditor": "에디터로 돌아가기",
18 | "customizeYourExperience": "CodeQuill 경험 맞춤 설정",
19 | "theme": "테마",
20 | "chooseYourPreferredAppearance": "선호하는 앱 외관 선택",
21 | "defaultLanguage": "기본 언어",
22 | "defaultProgrammingLanguage": "새 스니펫의 기본 프로그래밍 언어",
23 | "keyboardShortcuts": "키보드 단축키",
24 | "viewCommonKeyboardShortcuts": "일반적인 키보드 단축키 보기",
25 | "saveSnippet": "스니펫 저장",
26 | "createNewSnippet": "새 스니펫 만들기",
27 | "searchSnippets": "스니펫 검색",
28 | "previewCode": "코드 미리보기",
29 | "openSettings": "설정 열기",
30 | "formatCode": "코드 포맷",
31 | "undo": "실행 취소",
32 | "redo": "다시 실행",
33 | "appInfo": "앱 정보",
34 | "informationAboutCodeQuill": "CodeQuill에 대한 정보",
35 | "version": "버전",
36 | "installedVersion": "설치된 버전",
37 | "license": "라이선스",
38 | "openSource": "오픈 소스",
39 | "createdBy": "제작자",
40 | "sourceCode": "소스 코드",
41 | "reportIssue": "문제 보고",
42 | "dependencies": "의존성",
43 | "librariesUsed": "CodeQuill에서 사용된 라이브러리",
44 | "production": "프로덕션",
45 | "librariesBundled": "프로덕션 빌드에 포함된 라이브러리",
46 | "development": "개발",
47 | "librariesUsedDevelopment": "CodeQuill 개발에 사용된 라이브러리",
48 | "productionDependencies": "프로덕션 의존성",
49 | "developmentDependencies": "개발 의존성",
50 | "deleteThisSnippet": "이 스니펫을 삭제하시겠습니까?",
51 | "thisActionCannotBeUndone": "이 작업은 취소할 수 없습니다. 스니펫이 영구적으로 삭제됩니다.",
52 | "cancel": "취소",
53 | "deleting": "삭제 중...",
54 | "newSnippetSaved": "새 스니펫이 저장되었습니다!",
55 | "snippetSavedSuccessfully": "스니펫이 성공적으로 저장되었습니다!",
56 | "snippetCopiedToClipboard": "스니펫이 클립보드에 복사되었습니다",
57 | "snippetDeletedSuccessfully": "스니펫이 성공적으로 삭제되었습니다!",
58 | "untitled": "제목 없음",
59 | "youDonTHaveAnySnippets": "아직 스니펫이 없습니다. 지금 만들어보세요!",
60 | "createNow": "지금 만들기!",
61 | "morePages": "더 많은 페이지",
62 | "previous": "이전",
63 | "next": "다음",
64 | "close": "닫기",
65 | "searchLanguage": "언어 검색...",
66 | "noLanguageFound": "언어를 찾을 수 없습니다.",
67 | "website": "웹사이트",
68 | "themeLight": "라이트",
69 | "themeDark": "다크",
70 | "themeDim": "어둡게",
71 | "themeSystem": "시스템",
72 | "failedToLoadSnippets": "스니펫을 불러오지 못했습니다.",
73 | "failedToCreateNewSnippet": "새 스니펫을 만들지 못했습니다.",
74 | "creatingNewSnippet": "새 스니펫 만드는 중",
75 | "failedToLoadPreviewState": "localStorage에서 미리보기 상태를 불러오지 못했습니다.",
76 | "pleaseSelectLanguage": "언어를 선택해주세요.",
77 | "filenameCannotBeEmpty": "파일 이름은 비워둘 수 없습니다.",
78 | "filenameTooLong": "파일 이름은 1024자를 초과할 수 없습니다.",
79 | "savingSnippet": "스니펫 저장 중",
80 | "failedToSaveSnippet": "스니펫을 저장하지 못했습니다.",
81 | "failedToCopySnippet": "스니펫을 복사하지 못했습니다.",
82 | "failedToRemovePreview": "로컬 스토리지에서 미리보기를 제거하지 못했습니다.",
83 | "deletingSnippet": "스니펫 삭제 중",
84 | "failedToDeleteSnippet": "스니펫을 삭제하지 못했습니다.",
85 | "appLanguage": "앱 언어",
86 | "selectAppLanguage": "사용할 언어를 선택하세요",
87 | "snippetInformation": "스니펫 정보",
88 | "snippetDetails": "이 스니펫에 대한 세부 정보 보기",
89 | "id": "ID",
90 | "language": "언어",
91 | "lastSaved": "마지막 저장",
92 | "info": "정보",
93 | "noPreviewAvailable": "미리보기를 사용할 수 없음",
94 | "notAvailable": "사용할 수 없음"
95 | }
96 |
--------------------------------------------------------------------------------
/src/components/ui/pagination.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import ChevronLeftIcon from "lucide-react/dist/esm/icons/chevron-left";
3 | import ChevronRightIcon from "lucide-react/dist/esm/icons/chevron-right";
4 | import MoreHorizontalIcon from "lucide-react/dist/esm/icons/more-horizontal";
5 |
6 | import { cn } from "@/lib/utils";
7 | import { Button, buttonVariants } from "@/components/ui/button";
8 |
9 | function Pagination({ className, ...props }: React.ComponentProps<"nav">) {
10 | return (
11 |
18 | );
19 | }
20 |
21 | function PaginationContent({
22 | className,
23 | ...props
24 | }: React.ComponentProps<"ul">) {
25 | return (
26 |
31 | );
32 | }
33 |
34 | function PaginationItem({ ...props }: React.ComponentProps<"li">) {
35 | return ;
36 | }
37 |
38 | type PaginationLinkProps = {
39 | isActive?: boolean;
40 | } & Pick, "size"> &
41 | React.ComponentProps<"a">;
42 |
43 | function PaginationLink({
44 | className,
45 | isActive,
46 | size = "icon",
47 | ...props
48 | }: PaginationLinkProps) {
49 | return (
50 |
63 | );
64 | }
65 |
66 | function PaginationPrevious({
67 | className,
68 | ...props
69 | }: React.ComponentProps) {
70 | return (
71 |
77 |
78 | Previous
79 |
80 | );
81 | }
82 |
83 | function PaginationNext({
84 | className,
85 | ...props
86 | }: React.ComponentProps) {
87 | return (
88 |
94 | Next
95 |
96 |
97 | );
98 | }
99 |
100 | function PaginationEllipsis({
101 | className,
102 | ...props
103 | }: React.ComponentProps<"span">) {
104 | return (
105 |
111 |
112 | More pages
113 |
114 | );
115 | }
116 |
117 | export {
118 | Pagination,
119 | PaginationContent,
120 | PaginationLink,
121 | PaginationItem,
122 | PaginationPrevious,
123 | PaginationNext,
124 | PaginationEllipsis,
125 | };
126 |
--------------------------------------------------------------------------------
/public/locales/ja/translation.json:
--------------------------------------------------------------------------------
1 | {
2 | "appTitle": "CodeQuill",
3 | "newSnippet": "新規スニペット",
4 | "filename": "ファイル名",
5 | "selectLanguage": "言語を選択...",
6 | "save": "保存",
7 | "saving": "保存中...",
8 | "hidePreview": "プレビューを非表示",
9 | "showPreview": "プレビューを表示",
10 | "noPreview": "プレビューなし",
11 | "toggleSidebar": "サイドバーの切り替え",
12 | "typeToSearch": "スニペットを検索...",
13 | "noSnippetsFound": "スニペットが見つかりません。",
14 | "copy": "コピー",
15 | "delete": "削除",
16 | "settings": "設定",
17 | "backToEditor": "エディターに戻る",
18 | "customizeYourExperience": "CodeQuillの体験をカスタマイズ",
19 | "theme": "テーマ",
20 | "chooseYourPreferredAppearance": "お好みのアプリの外観を選択",
21 | "defaultLanguage": "デフォルト言語",
22 | "defaultProgrammingLanguage": "新規スニペットのデフォルトプログラミング言語",
23 | "keyboardShortcuts": "キーボードショートカット",
24 | "viewCommonKeyboardShortcuts": "一般的なキーボードショートカットを表示",
25 | "saveSnippet": "スニペットを保存",
26 | "createNewSnippet": "新規スニペットを作成",
27 | "searchSnippets": "スニペットを検索",
28 | "previewCode": "コードをプレビュー",
29 | "openSettings": "設定を開く",
30 | "formatCode": "コードをフォーマット",
31 | "undo": "元に戻す",
32 | "redo": "やり直す",
33 | "appInfo": "アプリ情報",
34 | "informationAboutCodeQuill": "CodeQuillについての情報",
35 | "version": "バージョン",
36 | "installedVersion": "インストールされているバージョン",
37 | "license": "ライセンス",
38 | "openSource": "オープンソース",
39 | "createdBy": "作成者",
40 | "sourceCode": "ソースコード",
41 | "reportIssue": "問題を報告",
42 | "dependencies": "依存関係",
43 | "librariesUsed": "CodeQuillで使用されているライブラリ",
44 | "production": "プロダクション",
45 | "librariesBundled": "プロダクションビルドにバンドルされているライブラリ",
46 | "development": "開発",
47 | "librariesUsedDevelopment": "CodeQuill開発で使用されているライブラリ",
48 | "productionDependencies": "プロダクション依存関係",
49 | "developmentDependencies": "開発依存関係",
50 | "deleteThisSnippet": "このスニペットを削除しますか?",
51 | "thisActionCannotBeUndone": "この操作は元に戻せません。スニペットは永久に削除されます。",
52 | "cancel": "キャンセル",
53 | "deleting": "削除中...",
54 | "newSnippetSaved": "新しいスニペットが保存されました!",
55 | "snippetSavedSuccessfully": "スニペットが正常に保存されました!",
56 | "snippetCopiedToClipboard": "スニペットがクリップボードにコピーされました",
57 | "snippetDeletedSuccessfully": "スニペットが正常に削除されました!",
58 | "untitled": "無題",
59 | "youDonTHaveAnySnippets": "まだスニペットがありません。今すぐ作成しましょう!",
60 | "createNow": "今すぐ作成する!",
61 | "morePages": "その他のページ",
62 | "previous": "前へ",
63 | "next": "次へ",
64 | "close": "閉じる",
65 | "searchLanguage": "言語を検索...",
66 | "noLanguageFound": "言語が見つかりません。",
67 | "website": "ウェブサイト",
68 | "themeLight": "ライト",
69 | "themeDark": "ダーク",
70 | "themeDim": "薄暗く",
71 | "themeSystem": "システム",
72 | "failedToLoadSnippets": "スニペットの読み込みに失敗しました。",
73 | "failedToCreateNewSnippet": "新しいスニペットの作成に失敗しました。",
74 | "creatingNewSnippet": "新しいスニペットを作成中",
75 | "failedToLoadPreviewState": "localStorageからプレビュー状態の読み込みに失敗しました。",
76 | "pleaseSelectLanguage": "言語を選択してください。",
77 | "filenameCannotBeEmpty": "ファイル名を空にすることはできません。",
78 | "filenameTooLong": "ファイル名は1024文字を超えることはできません。",
79 | "savingSnippet": "スニペットを保存中",
80 | "failedToSaveSnippet": "スニペットの保存に失敗しました。",
81 | "failedToCopySnippet": "スニペットのコピーに失敗しました。",
82 | "failedToRemovePreview": "localStorageからプレビューの削除に失敗しました。",
83 | "deletingSnippet": "スニペットを削除中",
84 | "failedToDeleteSnippet": "スニペットの削除に失敗しました。",
85 | "appLanguage": "アプリの言語",
86 | "selectAppLanguage": "使用する言語を選択してください",
87 | "snippetInformation": "スニペット情報",
88 | "snippetDetails": "このスニペットの詳細を表示",
89 | "id": "ID",
90 | "language": "言語",
91 | "lastSaved": "最終保存日時",
92 | "info": "情報",
93 | "noPreviewAvailable": "プレビューはありません",
94 | "notAvailable": "利用不可"
95 | }
96 |
--------------------------------------------------------------------------------
/src/routes/settings/AppInfoSection.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@/components/ui/button";
2 | import { Label } from "@/components/ui/label";
3 |
4 | interface AppInfoSectionProps {
5 | packageJson: any;
6 | APP_VERSION: string;
7 | t: any;
8 | }
9 |
10 | const AppInfoSection: React.FC = ({
11 | packageJson,
12 | APP_VERSION,
13 | t,
14 | }) => {
15 | return (
16 |
17 |
18 | {t("appInfo")}
19 |
20 | {t("informationAboutCodeQuill")}
21 |
22 |
23 |
24 |
25 |
26 | {packageJson.name}
27 |
28 | {packageJson.description}
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | {t("installedVersion")}
39 |
40 |
41 |
42 | {APP_VERSION}
43 |
44 |
45 |
46 |
47 |
48 | {t("openSource")}
49 |
50 |
51 | {packageJson.license}
52 |
53 |
54 |
55 |
56 |
74 |
75 |
97 |
98 |
99 | );
100 | };
101 |
102 | export default AppInfoSection;
103 |
--------------------------------------------------------------------------------
/public/locales/ar/translation.json:
--------------------------------------------------------------------------------
1 | {
2 | "appTitle": "كود كويل",
3 | "newSnippet": "مقتطف جديد",
4 | "filename": "اسم الملف",
5 | "selectLanguage": "اختر اللغة...",
6 | "save": "حفظ",
7 | "saving": "جارٍ الحفظ...",
8 | "hidePreview": "إخفاء المعاينة",
9 | "showPreview": "إظهار المعاينة",
10 | "noPreview": "لا توجد معاينة",
11 | "toggleSidebar": "تبديل الشريط الجانبي",
12 | "typeToSearch": "اكتب للبحث عن المقتطفات...",
13 | "noSnippetsFound": "لم يتم العثور على مقتطفات.",
14 | "copy": "نسخ",
15 | "delete": "حذف",
16 | "settings": "الإعدادات",
17 | "backToEditor": "العودة إلى المحرر",
18 | "customizeYourExperience": "خصص تجربتك في كود كويل",
19 | "theme": "السمة",
20 | "chooseYourPreferredAppearance": "اختر مظهر التطبيق المفضل لديك",
21 | "defaultLanguage": "اللغة الافتراضية",
22 | "defaultProgrammingLanguage": "لغة البرمجة الافتراضية للمقتطفات الجديدة",
23 | "keyboardShortcuts": "اختصارات لوحة المفاتيح",
24 | "viewCommonKeyboardShortcuts": "عرض اختصارات لوحة المفاتيح الشائعة",
25 | "saveSnippet": "حفظ المقتطف",
26 | "createNewSnippet": "إنشاء مقتطف جديد",
27 | "searchSnippets": "البحث عن المقتطفات",
28 | "previewCode": "معاينة الكود",
29 | "openSettings": "فتح الإعدادات",
30 | "formatCode": "تنسيق الكود",
31 | "undo": "تراجع",
32 | "redo": "إعادة",
33 | "appInfo": "معلومات التطبيق",
34 | "informationAboutCodeQuill": "معلومات عن CodeQuill",
35 | "version": "الإصدار",
36 | "installedVersion": "الإصدار المثبت",
37 | "license": "الترخيص",
38 | "openSource": "مفتوح المصدر",
39 | "createdBy": "تم إنشاؤه بواسطة",
40 | "sourceCode": "الكود المصدري",
41 | "reportIssue": "الإبلاغ عن مشكلة",
42 | "dependencies": "التبعيات",
43 | "librariesUsed": "المكتبات المستخدمة في CodeQuill",
44 | "production": "الإنتاج",
45 | "librariesBundled": "المكتبات المدمجة في نسخة الإنتاج",
46 | "development": "التطوير",
47 | "librariesUsedDevelopment": "المكتبات المستخدمة في تطوير CodeQuill",
48 | "productionDependencies": "تبعيات الإنتاج",
49 | "developmentDependencies": "تبعيات التطوير",
50 | "deleteThisSnippet": "حذف هذا المقتطف؟",
51 | "thisActionCannotBeUndone": "لا يمكن التراجع عن هذا الإجراء. سيؤدي هذا إلى حذف المقتطف نهائيًا.",
52 | "cancel": "إلغاء",
53 | "deleting": "جارٍ الحذف...",
54 | "newSnippetSaved": "تم حفظ المقتطف الجديد!",
55 | "snippetSavedSuccessfully": "تم حفظ المقتطف بنجاح!",
56 | "snippetCopiedToClipboard": "تم نسخ المقتطف إلى الحافظة",
57 | "snippetDeletedSuccessfully": "تم حذف المقتطف بنجاح!",
58 | "untitled": "بدون عنوان",
59 | "youDonTHaveAnySnippets": "ليس لديك أي مقتطفات بعد. قم بإنشاء واحد الآن!",
60 | "createNow": "أنشئ واحدًا الآن!",
61 | "morePages": "المزيد من الصفحات",
62 | "previous": "السابق",
63 | "next": "التالي",
64 | "close": "إغلاق",
65 | "searchLanguage": "البحث عن لغة...",
66 | "noLanguageFound": "لم يتم العثور على لغة.",
67 | "website": "الموقع الإلكتروني",
68 | "themeLight": "فاتح",
69 | "themeDark": "داكن",
70 | "themeDim": "خافت",
71 | "themeSystem": "النظام",
72 | "failedToLoadSnippets": "فشل تحميل المقتطفات.",
73 | "failedToCreateNewSnippet": "فشل إنشاء مقتطف جديد.",
74 | "creatingNewSnippet": "جارٍ إنشاء مقتطف جديد",
75 | "failedToLoadPreviewState": "فشل تحميل حالة المعاينة من التخزين المحلي.",
76 | "pleaseSelectLanguage": "الرجاء اختيار لغة.",
77 | "filenameCannotBeEmpty": "لا يمكن أن يكون اسم الملف فارغًا.",
78 | "filenameTooLong": "لا يمكن أن يكون اسم الملف أطول من 1024 حرفًا.",
79 | "savingSnippet": "جارٍ حفظ المقتطف",
80 | "failedToSaveSnippet": "فشل حفظ المقتطف.",
81 | "failedToCopySnippet": "فشل نسخ المقتطف.",
82 | "failedToRemovePreview": "فشل إزالة المعاينة من التخزين المحلي.",
83 | "deletingSnippet": "جارٍ حذف المقتطف",
84 | "failedToDeleteSnippet": "فشل حذف المقتطف.",
85 | "appLanguage": "لغة التطبيق",
86 | "selectAppLanguage": "اختر لغتك المحكية",
87 | "snippetInformation": "معلومات المقتطف",
88 | "snippetDetails": "عرض تفاصيل هذا المقتطف",
89 | "id": "المعرّف",
90 | "language": "اللغة",
91 | "lastSaved": "آخر حفظ",
92 | "info": "معلومات",
93 | "noPreviewAvailable": "لا تتوفر معاينة",
94 | "notAvailable": "غير متوفر"
95 | }
96 |
--------------------------------------------------------------------------------
/src/routes/home/SnippetInfoDialog.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Dialog,
3 | DialogContent,
4 | DialogDescription,
5 | DialogHeader,
6 | DialogTitle,
7 | } from "@/components/ui/dialog";
8 | import { Input } from "@/components/ui/input";
9 | import { Label } from "@/components/ui/label";
10 | import { Snippet } from "@/utils/database";
11 | import Calendar from "lucide-react/dist/esm/icons/calendar";
12 | import File from "lucide-react/dist/esm/icons/file";
13 | import Hash from "lucide-react/dist/esm/icons/hash";
14 | import Languages from "lucide-react/dist/esm/icons/languages";
15 | import { useTranslation } from "react-i18next";
16 |
17 | interface SnippetInfoDialogProps {
18 | isOpen: boolean;
19 | setOpen: (open: boolean) => void;
20 | snippet: Snippet | null;
21 | }
22 |
23 | const SnippetInfoDialog: React.FC = ({
24 | isOpen,
25 | setOpen,
26 | snippet,
27 | }) => {
28 | const { t } = useTranslation();
29 |
30 | if (!snippet) {
31 | return null; // Or render a message like "No snippet selected"
32 | }
33 |
34 | return (
35 |
112 | );
113 | };
114 |
115 | export default SnippetInfoDialog;
116 |
--------------------------------------------------------------------------------
/public/locales/en/translation.json:
--------------------------------------------------------------------------------
1 | {
2 | "appTitle": "CodeQuill",
3 | "newSnippet": "New Snippet",
4 | "filename": "Filename",
5 | "selectLanguage": "Select language...",
6 | "save": "Save",
7 | "saving": "Saving...",
8 | "hidePreview": "Hide Preview",
9 | "showPreview": "Show Preview",
10 | "noPreview": "No Preview",
11 | "toggleSidebar": "Toggle Sidebar",
12 | "typeToSearch": "Type to search snippets...",
13 | "noSnippetsFound": "No snippets found.",
14 | "copy": "Copy",
15 | "delete": "Delete",
16 | "settings": "Settings",
17 | "backToEditor": "Back to Editor",
18 | "customizeYourExperience": "Customize your CodeQuill experience",
19 | "theme": "Theme",
20 | "chooseYourPreferredAppearance": "Choose your preferred app appearance",
21 | "defaultLanguage": "Default Language",
22 | "defaultProgrammingLanguage": "Default programming language for new snippets",
23 | "keyboardShortcuts": "Keyboard Shortcuts",
24 | "viewCommonKeyboardShortcuts": "View common keyboard shortcuts",
25 | "saveSnippet": "Save Snippet",
26 | "createNewSnippet": "Create New Snippet",
27 | "searchSnippets": "Search Snippets",
28 | "previewCode": "Preview Code",
29 | "openSettings": "Open Settings",
30 | "formatCode": "Format Code",
31 | "undo": "Undo",
32 | "redo": "Redo",
33 | "appInfo": "App Info",
34 | "informationAboutCodeQuill": "Information about CodeQuill",
35 | "version": "Version",
36 | "installedVersion": "Installed version",
37 | "license": "License",
38 | "openSource": "Open source",
39 | "createdBy": "Created By",
40 | "sourceCode": "Source Code",
41 | "reportIssue": "Report Issue",
42 | "dependencies": "Dependencies",
43 | "librariesUsed": "Libraries used in CodeQuill",
44 | "production": "Production",
45 | "librariesBundled": "Libraries bundled in the production build",
46 | "development": "Development",
47 | "librariesUsedDevelopment": "Libraries used in CodeQuill development",
48 | "productionDependencies": "Production Dependencies",
49 | "developmentDependencies": "Development Dependencies",
50 | "deleteThisSnippet": "Delete this snippet?",
51 | "thisActionCannotBeUndone": "This action cannot be undone. This will permanently delete the snippet.",
52 | "cancel": "Cancel",
53 | "deleting": "Deleting...",
54 | "newSnippetSaved": "New snippet saved!",
55 | "snippetSavedSuccessfully": "Snippet saved successfully!",
56 | "snippetCopiedToClipboard": "Snippet copied to clipboard",
57 | "snippetDeletedSuccessfully": "Snippet deleted successfully!",
58 | "untitled": "Untitled",
59 | "youDonTHaveAnySnippets": "You don't have any snippets yet. Create one now!",
60 | "createNow": "Create one now!",
61 | "morePages": "More pages",
62 | "previous": "Previous",
63 | "next": "Next",
64 | "close": "Close",
65 | "searchLanguage": "Search language...",
66 | "noLanguageFound": "No language found.",
67 | "website": "Website",
68 | "themeLight": "Light",
69 | "themeDark": "Dark",
70 | "themeDim": "Dim",
71 | "themeSystem": "System",
72 | "failedToLoadSnippets": "Failed to load snippets.",
73 | "failedToCreateNewSnippet": "Failed to create new snippet.",
74 | "creatingNewSnippet": "Creating new snippet",
75 | "failedToLoadPreviewState": "Failed to load preview state from localStorage.",
76 | "pleaseSelectLanguage": "Please select a language.",
77 | "filenameCannotBeEmpty": "Filename cannot be empty.",
78 | "filenameTooLong": "Filename cannot be longer than 1024 characters.",
79 | "savingSnippet": "Saving snippet",
80 | "failedToSaveSnippet": "Failed to save snippet.",
81 | "failedToCopySnippet": "Failed to copy snippet.",
82 | "failedToRemovePreview": "Failed to remove preview from localStorage.",
83 | "deletingSnippet": "Deleting snippet",
84 | "failedToDeleteSnippet": "Failed to delete snippet.",
85 | "appLanguage": "App Language",
86 | "selectAppLanguage": "Choose your spoken language",
87 | "snippetInformation": "Snippet info",
88 | "snippetDetails": "View details about this snippet",
89 | "id": "ID",
90 | "language": "Language",
91 | "lastSaved": "Last Saved",
92 | "info": "Info",
93 | "noPreviewAvailable": "No preview available",
94 | "notAvailable": "Not available"
95 | }
96 |
--------------------------------------------------------------------------------
/public/locales/nl/translation.json:
--------------------------------------------------------------------------------
1 | {
2 | "appTitle": "CodeQuill",
3 | "newSnippet": "Nieuw fragment",
4 | "filename": "Bestandsnaam",
5 | "selectLanguage": "Selecteer taal...",
6 | "save": "Opslaan",
7 | "saving": "Bezig met opslaan...",
8 | "hidePreview": "Verberg voorbeeld",
9 | "showPreview": "Toon voorbeeld",
10 | "noPreview": "Geen voorbeeld",
11 | "toggleSidebar": "Zijbalk in-/uitschakelen",
12 | "typeToSearch": "Typ om fragmenten te zoeken...",
13 | "noSnippetsFound": "Geen fragmenten gevonden.",
14 | "copy": "Kopiëren",
15 | "delete": "Verwijderen",
16 | "settings": "Instellingen",
17 | "backToEditor": "Terug naar editor",
18 | "customizeYourExperience": "Pas je CodeQuill-ervaring aan",
19 | "theme": "Thema",
20 | "chooseYourPreferredAppearance": "Kies je gewenste app-uiterlijk",
21 | "defaultLanguage": "Standaardtaal",
22 | "defaultProgrammingLanguage": "Standaard programmeertaal voor nieuwe fragmenten",
23 | "keyboardShortcuts": "Sneltoetsen",
24 | "viewCommonKeyboardShortcuts": "Bekijk veelgebruikte sneltoetsen",
25 | "saveSnippet": "Fragment opslaan",
26 | "createNewSnippet": "Nieuw fragment maken",
27 | "searchSnippets": "Zoek snippets",
28 | "previewCode": "Voorbeeldweergave code",
29 | "openSettings": "Instellingen openen",
30 | "formatCode": "Code formatteren",
31 | "undo": "Ongedaan maken",
32 | "redo": "Opnieuw uitvoeren",
33 | "appInfo": "App-informatie",
34 | "informationAboutCodeQuill": "Informatie over CodeQuill",
35 | "version": "Versie",
36 | "installedVersion": "Geïnstalleerde versie",
37 | "license": "Licentie",
38 | "openSource": "Open source",
39 | "createdBy": "Gemaakt door",
40 | "sourceCode": "Broncode",
41 | "reportIssue": "Probleem melden",
42 | "dependencies": "Afhankelijkheden",
43 | "librariesUsed": "Bibliotheken gebruikt in CodeQuill",
44 | "production": "Productie",
45 | "librariesBundled": "Bibliotheken gebundeld in de productiebuild",
46 | "development": "Ontwikkeling",
47 | "librariesUsedDevelopment": "Bibliotheken gebruikt in CodeQuill-ontwikkeling",
48 | "productionDependencies": "Productie-afhankelijkheden",
49 | "developmentDependencies": "Ontwikkelingsafhankelijkheden",
50 | "deleteThisSnippet": "Deze snippet verwijderen?",
51 | "thisActionCannotBeUndone": "Deze actie kan niet ongedaan worden gemaakt. Dit zal de snippet permanent verwijderen.",
52 | "cancel": "Annuleren",
53 | "deleting": "Bezig met verwijderen...",
54 | "newSnippetSaved": "Nieuw snippet opgeslagen!",
55 | "snippetSavedSuccessfully": "Snippet succesvol opgeslagen!",
56 | "snippetCopiedToClipboard": "Snippet gekopieerd naar klembord",
57 | "snippetDeletedSuccessfully": "Snippet succesvol verwijderd!",
58 | "untitled": "Naamloos",
59 | "youDonTHaveAnySnippets": "Je hebt nog geen snippets. Maak er nu een!",
60 | "createNow": "Maak er nu een!",
61 | "morePages": "Meer pagina's",
62 | "previous": "Vorige",
63 | "next": "Volgende",
64 | "close": "Sluiten",
65 | "searchLanguage": "Zoek taal...",
66 | "noLanguageFound": "Geen taal gevonden.",
67 | "website": "Website",
68 | "themeLight": "Licht",
69 | "themeDark": "Donker",
70 | "themeDim": "Gedimd",
71 | "themeSystem": "Systeem",
72 | "failedToLoadSnippets": "Laden van snippets mislukt.",
73 | "failedToCreateNewSnippet": "Aanmaken van nieuw snippet mislukt.",
74 | "creatingNewSnippet": "Nieuw snippet aanmaken",
75 | "failedToLoadPreviewState": "Laden van voorbeeldstatus uit localStorage mislukt.",
76 | "pleaseSelectLanguage": "Selecteer alsjeblieft een taal.",
77 | "filenameCannotBeEmpty": "Bestandsnaam mag niet leeg zijn.",
78 | "filenameTooLong": "De bestandsnaam mag niet langer zijn dan 1024 tekens.",
79 | "savingSnippet": "Snippet opslaan",
80 | "failedToSaveSnippet": "Kon de snippet niet opslaan.",
81 | "failedToCopySnippet": "Kon de snippet niet kopiëren.",
82 | "failedToRemovePreview": "Kon de preview niet verwijderen uit de localStorage.",
83 | "deletingSnippet": "Snippet verwijderen",
84 | "failedToDeleteSnippet": "Kon de snippet niet verwijderen.",
85 | "appLanguage": "App-taal",
86 | "selectAppLanguage": "Kies je gesproken taal",
87 | "snippetInformation": "Snippet-informatie",
88 | "snippetDetails": "Bekijk details over deze snippet",
89 | "id": "ID",
90 | "language": "Taal",
91 | "lastSaved": "Laatst opgeslagen",
92 | "info": "Info",
93 | "noPreviewAvailable": "Geen voorbeeld beschikbaar",
94 | "notAvailable": "Niet beschikbaar"
95 | }
96 |
--------------------------------------------------------------------------------
/src/routes/home/index.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { useIsMobile } from "@/hooks/use-mobile";
4 | import { useEffect, useState } from "react";
5 | import { useTranslation } from "react-i18next";
6 | import DeleteDialog from "./DeleteDialog";
7 | import Editor from "./Editor";
8 | import Header from "./Header";
9 | import SnippetSearchDialog from "./SnippetSearchDialog";
10 | import SnippetSidebar from "./SnippetSidebar";
11 | import { useSnippets } from "./useSnippets";
12 |
13 | // Static Imports for Preview Components
14 | import HTMLPreview from "./previews/html";
15 | import MarkdownPreview from "./previews/markdown";
16 |
17 | // Preview component map:
18 | const previewComponents: { [key: string]: React.FC<{ code: string }> } = {
19 | html: HTMLPreview,
20 | markdown: MarkdownPreview,
21 | };
22 |
23 | interface PreviewComponentProps {
24 | code: string;
25 | }
26 |
27 | const PreviewComponent: React.FC<
28 | PreviewComponentProps & { languageId: string | undefined }
29 | > = ({ code, languageId }) => {
30 | const { t } = useTranslation();
31 |
32 | const Preview =
33 | previewComponents[languageId as keyof typeof previewComponents] ||
34 | (() => {t("noPreviewAvailable")} );
35 |
36 | return ;
37 | };
38 |
39 | const SIDEBAR_OPEN_KEY = "codequill_sidebar_open";
40 |
41 | function Home() {
42 | const isMobile = useIsMobile();
43 |
44 | // Initialize showSidebar from session storage, defaulting to !isMobile
45 | const [showSidebar, setShowSidebar] = useState(() => {
46 | if (typeof window === "undefined") return !isMobile;
47 | try {
48 | const storedState = sessionStorage.getItem(SIDEBAR_OPEN_KEY);
49 | return storedState ? JSON.parse(storedState) : !isMobile;
50 | } catch (error) {
51 | console.error("Error parsing session storage:", error);
52 | return !isMobile;
53 | }
54 | });
55 |
56 | const snippetHelpers = useSnippets();
57 | const {
58 | isDeleteOpen,
59 | setDeleteOpen,
60 | deleting,
61 | deleteCurrentSnippet,
62 | filteredSnippets,
63 | loadSnippetInEditor,
64 | isPreviewing,
65 | language,
66 | setDeletingSnippetId,
67 | createNewSnippet,
68 | snippets,
69 | } = snippetHelpers;
70 |
71 | const [isSearchDialogOpen, setIsSearchDialogOpen] = useState(false);
72 |
73 | const toggleSidebar = () => {
74 | setShowSidebar(!showSidebar);
75 | };
76 |
77 | // Update session storage whenever showSidebar changes
78 | useEffect(() => {
79 | if (typeof window !== "undefined") {
80 | sessionStorage.setItem(SIDEBAR_OPEN_KEY, JSON.stringify(showSidebar));
81 | }
82 | }, [showSidebar]);
83 |
84 | const hasSnippets = snippets.length > 0;
85 |
86 | return (
87 |
88 |
95 |
96 | {hasSnippets && }
97 |
105 | {isPreviewing && hasSnippets && (
106 |
112 | )}
113 |
114 |
115 |
121 |
127 |
128 | );
129 | }
130 |
131 | export default Home;
132 |
--------------------------------------------------------------------------------
/public/locales/pt/translation.json:
--------------------------------------------------------------------------------
1 | {
2 | "appTitle": "CodeQuill",
3 | "newSnippet": "Novo trecho",
4 | "filename": "Nome do arquivo",
5 | "selectLanguage": "Selecionar idioma...",
6 | "save": "Salvar",
7 | "saving": "Salvando...",
8 | "hidePreview": "Ocultar pré-visualização",
9 | "showPreview": "Mostrar pré-visualização",
10 | "noPreview": "Sem pré-visualização",
11 | "toggleSidebar": "Alternar barra lateral",
12 | "typeToSearch": "Digite para pesquisar trechos...",
13 | "noSnippetsFound": "Nenhum trecho encontrado.",
14 | "copy": "Copiar",
15 | "delete": "Excluir",
16 | "settings": "Configurações",
17 | "backToEditor": "Voltar ao editor",
18 | "customizeYourExperience": "Personalize sua experiência no CodeQuill",
19 | "theme": "Tema",
20 | "chooseYourPreferredAppearance": "Escolha a aparência preferida do aplicativo",
21 | "defaultLanguage": "Idioma padrão",
22 | "defaultProgrammingLanguage": "Linguagem de programação padrão para novos trechos",
23 | "keyboardShortcuts": "Atalhos de teclado",
24 | "viewCommonKeyboardShortcuts": "Ver atalhos de teclado comuns",
25 | "saveSnippet": "Salvar trecho",
26 | "createNewSnippet": "Criar novo trecho",
27 | "searchSnippets": "Pesquisar snippets",
28 | "previewCode": "Visualizar código",
29 | "openSettings": "Abrir configurações",
30 | "formatCode": "Formatar código",
31 | "undo": "Desfazer",
32 | "redo": "Refazer",
33 | "appInfo": "Informações do app",
34 | "informationAboutCodeQuill": "Informações sobre o CodeQuill",
35 | "version": "Versão",
36 | "installedVersion": "Versão instalada",
37 | "license": "Licença",
38 | "openSource": "Código aberto",
39 | "createdBy": "Criado por",
40 | "sourceCode": "Código-fonte",
41 | "reportIssue": "Reportar problema",
42 | "dependencies": "Dependências",
43 | "librariesUsed": "Bibliotecas usadas no CodeQuill",
44 | "production": "Produção",
45 | "librariesBundled": "Bibliotecas incluídas na versão de produção",
46 | "development": "Desenvolvimento",
47 | "librariesUsedDevelopment": "Bibliotecas usadas no desenvolvimento do CodeQuill",
48 | "productionDependencies": "Dependências de produção",
49 | "developmentDependencies": "Dependências de desenvolvimento",
50 | "deleteThisSnippet": "Excluir este snippet?",
51 | "thisActionCannotBeUndone": "Esta ação não pode ser desfeita. Isso excluirá permanentemente o snippet.",
52 | "cancel": "Cancelar",
53 | "deleting": "Excluindo...",
54 | "newSnippetSaved": "Novo snippet salvo!",
55 | "snippetSavedSuccessfully": "Snippet salvo com sucesso!",
56 | "snippetCopiedToClipboard": "Snippet copiado para a área de transferência",
57 | "snippetDeletedSuccessfully": "Snippet excluído com sucesso!",
58 | "untitled": "Sem título",
59 | "youDonTHaveAnySnippets": "Você ainda não tem nenhum snippet. Crie um agora!",
60 | "createNow": "Crie um agora!",
61 | "morePages": "Mais páginas",
62 | "previous": "Anterior",
63 | "next": "Próximo",
64 | "close": "Fechar",
65 | "searchLanguage": "Pesquisar idioma...",
66 | "noLanguageFound": "Nenhum idioma encontrado.",
67 | "website": "Site",
68 | "themeLight": "Claro",
69 | "themeDark": "Escuro",
70 | "themeDim": "Escurecer",
71 | "themeSystem": "Sistema",
72 | "failedToLoadSnippets": "Falha ao carregar snippets.",
73 | "failedToCreateNewSnippet": "Falha ao criar novo snippet.",
74 | "creatingNewSnippet": "Criando novo snippet",
75 | "failedToLoadPreviewState": "Falha ao carregar o estado de visualização do localStorage.",
76 | "pleaseSelectLanguage": "Por favor, selecione um idioma.",
77 | "filenameCannotBeEmpty": "O nome do arquivo não pode estar vazio.",
78 | "filenameTooLong": "O nome do arquivo não pode ter mais de 1024 caracteres.",
79 | "savingSnippet": "Salvando trecho",
80 | "failedToSaveSnippet": "Falha ao salvar o trecho.",
81 | "failedToCopySnippet": "Falha ao copiar o trecho.",
82 | "failedToRemovePreview": "Falha ao remover a pré-visualização do localStorage.",
83 | "deletingSnippet": "Excluindo trecho",
84 | "failedToDeleteSnippet": "Falha ao excluir o trecho.",
85 | "appLanguage": "Idioma do aplicativo",
86 | "selectAppLanguage": "Escolha seu idioma falado",
87 | "snippetInformation": "Informações do snippet",
88 | "snippetDetails": "Ver detalhes sobre este snippet",
89 | "id": "ID",
90 | "language": "Idioma",
91 | "lastSaved": "Última salvamento",
92 | "info": "Informações",
93 | "noPreviewAvailable": "Nenhuma pré-visualização disponível",
94 | "notAvailable": "Não disponível"
95 | }
96 |
--------------------------------------------------------------------------------
/public/locales/ru/translation.json:
--------------------------------------------------------------------------------
1 | {
2 | "appTitle": "CodeQuill",
3 | "newSnippet": "Новый сниппет",
4 | "filename": "Имя файла",
5 | "selectLanguage": "Выберите язык...",
6 | "save": "Сохранить",
7 | "saving": "Сохранение...",
8 | "hidePreview": "Скрыть предпросмотр",
9 | "showPreview": "Показать предпросмотр",
10 | "noPreview": "Нет предпросмотра",
11 | "toggleSidebar": "Переключить боковую панель",
12 | "typeToSearch": "Введите для поиска сниппетов...",
13 | "noSnippetsFound": "Сниппеты не найдены.",
14 | "copy": "Копировать",
15 | "delete": "Удалить",
16 | "settings": "Настройки",
17 | "backToEditor": "Вернуться в редактор",
18 | "customizeYourExperience": "Настройте ваш опыт работы с CodeQuill",
19 | "theme": "Тема",
20 | "chooseYourPreferredAppearance": "Выберите предпочитаемый внешний вид приложения",
21 | "defaultLanguage": "Язык по умолчанию",
22 | "defaultProgrammingLanguage": "Язык программирования по умолчанию для новых сниппетов",
23 | "keyboardShortcuts": "Горячие клавиши",
24 | "viewCommonKeyboardShortcuts": "Просмотреть основные горячие клавиши",
25 | "saveSnippet": "Сохранить сниппет",
26 | "createNewSnippet": "Создать новый сниппет",
27 | "searchSnippets": "Поиск сниппетов",
28 | "previewCode": "Предпросмотр кода",
29 | "openSettings": "Открыть настройки",
30 | "formatCode": "Форматировать код",
31 | "undo": "Отменить",
32 | "redo": "Повторить",
33 | "appInfo": "Информация о приложении",
34 | "informationAboutCodeQuill": "Информация о CodeQuill",
35 | "version": "Версия",
36 | "installedVersion": "Установленная версия",
37 | "license": "Лицензия",
38 | "openSource": "Открытый исходный код",
39 | "createdBy": "Создано",
40 | "sourceCode": "Исходный код",
41 | "reportIssue": "Сообщить о проблеме",
42 | "dependencies": "Зависимости",
43 | "librariesUsed": "Библиотеки, используемые в CodeQuill",
44 | "production": "Продакшн",
45 | "librariesBundled": "Библиотеки, включенные в сборку продакшн",
46 | "development": "Разработка",
47 | "librariesUsedDevelopment": "Библиотеки, используемые при разработке CodeQuill",
48 | "productionDependencies": "Зависимости продакшн",
49 | "developmentDependencies": "Зависимости разработки",
50 | "deleteThisSnippet": "Удалить этот сниппет?",
51 | "thisActionCannotBeUndone": "Это действие нельзя отменить. Сниппет будет удален навсегда.",
52 | "cancel": "Отмена",
53 | "deleting": "Удаление...",
54 | "newSnippetSaved": "Новый сниппет сохранен!",
55 | "snippetSavedSuccessfully": "Сниппет успешно сохранен!",
56 | "snippetCopiedToClipboard": "Сниппет скопирован в буфер обмена",
57 | "snippetDeletedSuccessfully": "Сниппет успешно удален!",
58 | "untitled": "Без названия",
59 | "youDonTHaveAnySnippets": "У вас пока нет сниппетов. Создайте один сейчас!",
60 | "createNow": "Создать сейчас!",
61 | "morePages": "Больше страниц",
62 | "previous": "Предыдущая",
63 | "next": "Следующая",
64 | "close": "Закрыть",
65 | "searchLanguage": "Поиск языка...",
66 | "noLanguageFound": "Язык не найден.",
67 | "website": "Веб-сайт",
68 | "themeLight": "Светлая",
69 | "themeDark": "Темная",
70 | "themeDim": "Тусклый",
71 | "themeSystem": "Системная",
72 | "failedToLoadSnippets": "Не удалось загрузить сниппеты.",
73 | "failedToCreateNewSnippet": "Не удалось создать новый сниппет.",
74 | "creatingNewSnippet": "Создание нового сниппета",
75 | "failedToLoadPreviewState": "Не удалось загрузить состояние предпросмотра из localStorage.",
76 | "pleaseSelectLanguage": "Пожалуйста, выберите язык.",
77 | "filenameCannotBeEmpty": "Имя файла не может быть пустым.",
78 | "filenameTooLong": "Имя файла не может быть длиннее 1024 символов.",
79 | "savingSnippet": "Сохранение фрагмента кода",
80 | "failedToSaveSnippet": "Не удалось сохранить фрагмент кода.",
81 | "failedToCopySnippet": "Не удалось скопировать фрагмент кода.",
82 | "failedToRemovePreview": "Не удалось удалить предварительный просмотр из localStorage.",
83 | "deletingSnippet": "Удаление фрагмента кода",
84 | "failedToDeleteSnippet": "Не удалось удалить фрагмент кода.",
85 | "appLanguage": "Язык приложения",
86 | "selectAppLanguage": "Выберите ваш разговорный язык",
87 | "snippetInformation": "Информация о сниппете",
88 | "snippetDetails": "Просмотр подробностей об этом сниппете",
89 | "id": "ID",
90 | "language": "Язык",
91 | "lastSaved": "Последнее сохранение",
92 | "info": "Информация",
93 | "noPreviewAvailable": "Предварительный просмотр недоступен",
94 | "notAvailable": "Недоступно"
95 | }
96 |
--------------------------------------------------------------------------------
/public/locales/it/translation.json:
--------------------------------------------------------------------------------
1 | {
2 | "appTitle": "CodeQuill",
3 | "newSnippet": "Nuovo frammento",
4 | "filename": "Nome del file",
5 | "selectLanguage": "Seleziona lingua...",
6 | "save": "Salva",
7 | "saving": "Salvataggio in corso...",
8 | "hidePreview": "Nascondi anteprima",
9 | "showPreview": "Mostra anteprima",
10 | "noPreview": "Nessuna anteprima",
11 | "toggleSidebar": "Attiva/disattiva barra laterale",
12 | "typeToSearch": "Digita per cercare frammenti...",
13 | "noSnippetsFound": "Nessun frammento trovato.",
14 | "copy": "Copia",
15 | "delete": "Elimina",
16 | "settings": "Impostazioni",
17 | "backToEditor": "Torna all'editor",
18 | "customizeYourExperience": "Personalizza la tua esperienza CodeQuill",
19 | "theme": "Tema",
20 | "chooseYourPreferredAppearance": "Scegli l'aspetto preferito dell'app",
21 | "defaultLanguage": "Lingua predefinita",
22 | "defaultProgrammingLanguage": "Linguaggio di programmazione predefinito per nuovi frammenti",
23 | "keyboardShortcuts": "Scorciatoie da tastiera",
24 | "viewCommonKeyboardShortcuts": "Visualizza le scorciatoie da tastiera comuni",
25 | "saveSnippet": "Salva frammento",
26 | "createNewSnippet": "Crea nuovo frammento",
27 | "searchSnippets": "Cerca Snippet",
28 | "previewCode": "Anteprima Codice",
29 | "openSettings": "Apri Impostazioni",
30 | "formatCode": "Formatta Codice",
31 | "undo": "Annulla",
32 | "redo": "Ripeti",
33 | "appInfo": "Informazioni sull'App",
34 | "informationAboutCodeQuill": "Informazioni su CodeQuill",
35 | "version": "Versione",
36 | "installedVersion": "Versione installata",
37 | "license": "Licenza",
38 | "openSource": "Open source",
39 | "createdBy": "Creato da",
40 | "sourceCode": "Codice sorgente",
41 | "reportIssue": "Segnala un problema",
42 | "dependencies": "Dipendenze",
43 | "librariesUsed": "Librerie utilizzate in CodeQuill",
44 | "production": "Produzione",
45 | "librariesBundled": "Librerie incluse nella build di produzione",
46 | "development": "Sviluppo",
47 | "librariesUsedDevelopment": "Librerie utilizzate nello sviluppo di CodeQuill",
48 | "productionDependencies": "Dipendenze di produzione",
49 | "developmentDependencies": "Dipendenze di sviluppo",
50 | "deleteThisSnippet": "Eliminare questo snippet?",
51 | "thisActionCannotBeUndone": "Questa azione non può essere annullata. Lo snippet verrà eliminato definitivamente.",
52 | "cancel": "Annulla",
53 | "deleting": "Eliminazione in corso...",
54 | "newSnippetSaved": "Nuovo snippet salvato!",
55 | "snippetSavedSuccessfully": "Snippet salvato con successo!",
56 | "snippetCopiedToClipboard": "Snippet copiato negli appunti",
57 | "snippetDeletedSuccessfully": "Snippet eliminato con successo!",
58 | "untitled": "Senza titolo",
59 | "youDonTHaveAnySnippets": "Non hai ancora nessuno snippet. Creane uno ora!",
60 | "createNow": "Creane uno ora!",
61 | "morePages": "Altre pagine",
62 | "previous": "Precedente",
63 | "next": "Successivo",
64 | "close": "Chiudi",
65 | "searchLanguage": "Cerca lingua...",
66 | "noLanguageFound": "Nessuna lingua trovata.",
67 | "website": "Sito web",
68 | "themeLight": "Chiaro",
69 | "themeDark": "Scuro",
70 | "themeDim": "Attenuato",
71 | "themeSystem": "Sistema",
72 | "failedToLoadSnippets": "Impossibile caricare gli snippet.",
73 | "failedToCreateNewSnippet": "Impossibile creare un nuovo snippet.",
74 | "creatingNewSnippet": "Creazione di un nuovo snippet",
75 | "failedToLoadPreviewState": "Impossibile caricare lo stato di anteprima dal localStorage.",
76 | "pleaseSelectLanguage": "Seleziona una lingua.",
77 | "filenameCannotBeEmpty": "Il nome del file non può essere vuoto.",
78 | "filenameTooLong": "Il nome del file non può essere più lungo di 1024 caratteri.",
79 | "savingSnippet": "Salvataggio dello snippet in corso",
80 | "failedToSaveSnippet": "Impossibile salvare lo snippet.",
81 | "failedToCopySnippet": "Impossibile copiare lo snippet.",
82 | "failedToRemovePreview": "Impossibile rimuovere l'anteprima dal localStorage.",
83 | "deletingSnippet": "Eliminazione dello snippet in corso",
84 | "failedToDeleteSnippet": "Impossibile eliminare lo snippet.",
85 | "appLanguage": "Lingua dell'app",
86 | "selectAppLanguage": "Scegli la tua lingua parlata",
87 | "snippetInformation": "Informazioni snippet",
88 | "snippetDetails": "Visualizza dettagli di questo snippet",
89 | "id": "ID",
90 | "language": "Lingua",
91 | "lastSaved": "Ultimo salvataggio",
92 | "info": "Info",
93 | "noPreviewAvailable": "Anteprima non disponibile",
94 | "notAvailable": "Non disponibile"
95 | }
96 |
--------------------------------------------------------------------------------
/public/locales/es/translation.json:
--------------------------------------------------------------------------------
1 | {
2 | "appTitle": "CodeQuill",
3 | "newSnippet": "Nuevo Fragmento",
4 | "filename": "Nombre del Archivo",
5 | "selectLanguage": "Seleccionar lenguaje...",
6 | "save": "Guardar",
7 | "saving": "Guardando...",
8 | "hidePreview": "Ocultar Vista Previa",
9 | "showPreview": "Mostrar Vista Previa",
10 | "noPreview": "Sin Vista Previa",
11 | "toggleSidebar": "Alternar Barra Lateral",
12 | "typeToSearch": "Escribe para buscar fragmentos...",
13 | "noSnippetsFound": "No se encontraron fragmentos.",
14 | "copy": "Copiar",
15 | "delete": "Borrar",
16 | "settings": "Ajustes",
17 | "backToEditor": "Volver al Editor",
18 | "customizeYourExperience": "Personaliza tu experiencia en CodeQuill",
19 | "theme": "Tema",
20 | "chooseYourPreferredAppearance": "Elige tu apariencia preferida para la aplicación",
21 | "defaultLanguage": "Idioma Predeterminado",
22 | "defaultProgrammingLanguage": "Lenguaje de programación predeterminado para nuevos fragmentos",
23 | "keyboardShortcuts": "Atajos de Teclado",
24 | "viewCommonKeyboardShortcuts": "Ver atajos de teclado comunes",
25 | "saveSnippet": "Guardar Fragmento",
26 | "createNewSnippet": "Crear Nuevo Fragmento",
27 | "searchSnippets": "Buscar Fragmentos",
28 | "previewCode": "Vista Previa del Código",
29 | "openSettings": "Abrir Ajustes",
30 | "formatCode": "Formatear Código",
31 | "undo": "Deshacer",
32 | "redo": "Rehacer",
33 | "appInfo": "Información de la Aplicación",
34 | "informationAboutCodeQuill": "Información sobre CodeQuill",
35 | "version": "Versión",
36 | "installedVersion": "Versión instalada",
37 | "license": "Licencia",
38 | "openSource": "Código abierto",
39 | "createdBy": "Creado por",
40 | "sourceCode": "Código Fuente",
41 | "reportIssue": "Reportar Problema",
42 | "dependencies": "Dependencias",
43 | "librariesUsed": "Librerías usadas en CodeQuill",
44 | "production": "Producción",
45 | "librariesBundled": "Librerías incluidas en la compilación de producción",
46 | "development": "Desarrollo",
47 | "librariesUsedDevelopment": "Librerías usadas en el desarrollo de CodeQuill",
48 | "productionDependencies": "Dependencias de Producción",
49 | "developmentDependencies": "Dependencias de Desarrollo",
50 | "deleteThisSnippet": "¿Borrar este fragmento?",
51 | "thisActionCannotBeUndone": "Esta acción no se puede deshacer. Borrará el fragmento permanentemente.",
52 | "cancel": "Cancelar",
53 | "deleting": "Borrando...",
54 | "newSnippetSaved": "¡Nuevo fragmento guardado!",
55 | "snippetSavedSuccessfully": "¡Fragmento guardado con éxito!",
56 | "snippetCopiedToClipboard": "Fragmento copiado al portapapeles",
57 | "snippetDeletedSuccessfully": "¡Fragmento borrado con éxito!",
58 | "untitled": "Sin título",
59 | "youDonTHaveAnySnippets": "Aún no tienes ningún fragmento. ¡Crea uno ahora!",
60 | "createNow": "¡Crear uno ahora!",
61 | "morePages": "Más páginas",
62 | "previous": "Anterior",
63 | "next": "Siguiente",
64 | "close": "Cerrar",
65 | "searchLanguage": "Buscar lenguaje...",
66 | "noLanguageFound": "No se encontró ningún lenguaje.",
67 | "website": "Sitio web",
68 | "themeLight": "Claro",
69 | "themeDark": "Oscuro",
70 | "themeDim": "Tenue",
71 | "themeSystem": "Sistema",
72 | "failedToLoadSnippets": "Error al cargar los fragmentos.",
73 | "failedToCreateNewSnippet": "Error al crear un nuevo fragmento.",
74 | "creatingNewSnippet": "Creando nuevo fragmento",
75 | "failedToLoadPreviewState": "Error al cargar el estado de la vista previa desde el almacenamiento local.",
76 | "pleaseSelectLanguage": "Por favor, seleccione un idioma.",
77 | "filenameCannotBeEmpty": "El nombre del archivo no puede estar vacío.",
78 | "filenameTooLong": "El nombre del archivo no puede tener más de 1024 caracteres.",
79 | "savingSnippet": "Guardando fragmento",
80 | "failedToSaveSnippet": "Error al guardar el fragmento.",
81 | "failedToCopySnippet": "Error al copiar el fragmento.",
82 | "failedToRemovePreview": "Error al eliminar la vista previa del almacenamiento local.",
83 | "deletingSnippet": "Borrando fragmento",
84 | "failedToDeleteSnippet": "Error al borrar el fragmento.",
85 | "appLanguage": "Idioma de la aplicación",
86 | "selectAppLanguage": "Elige tu idioma hablado",
87 | "snippetInformation": "Información del fragmento",
88 | "snippetDetails": "Ver detalles de este fragmento",
89 | "id": "ID",
90 | "language": "Lenguaje",
91 | "lastSaved": "Última guardado",
92 | "info": "Información",
93 | "noPreviewAvailable": "Vista previa no disponible",
94 | "notAvailable": "No disponible"
95 | }
96 |
--------------------------------------------------------------------------------
/src/routes/settings/DependenciesSection.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Accordion,
3 | AccordionContent,
4 | AccordionItem,
5 | AccordionTrigger,
6 | } from "@/components/ui/accordion";
7 | import { Label } from "@/components/ui/label";
8 |
9 | interface DependenciesSectionProps {
10 | packageJson: any;
11 | t: any;
12 | }
13 |
14 | const DependenciesSection: React.FC = ({
15 | packageJson,
16 | t,
17 | }) => {
18 | const productionDependencies = packageJson.dependencies || {};
19 | const developmentDependencies = packageJson.devDependencies || {};
20 |
21 | return (
22 |
23 |
24 | {t("dependencies")}
25 | {t("librariesUsed")}
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | {t("librariesBundled")}
34 |
35 |
36 |
37 | {Object.keys(productionDependencies).length}
38 |
39 |
40 |
41 |
42 |
43 |
44 | {t("librariesUsedDevelopment")}
45 |
46 |
47 |
48 | {Object.keys(developmentDependencies).length}
49 |
50 |
51 |
52 |
53 |
54 |
55 | {t("productionDependencies")}
56 |
57 |
58 | {Object.entries(productionDependencies).map(([name, version]) => (
59 |
76 | ))}
77 |
78 |
79 |
80 |
81 |
82 | {t("developmentDependencies")}
83 |
84 |
85 | {Object.entries(developmentDependencies).map(
86 | ([name, version]) => (
87 |
104 | ),
105 | )}
106 |
107 |
108 |
109 |
110 |
111 | );
112 | };
113 |
114 | export default DependenciesSection;
115 |
--------------------------------------------------------------------------------
/public/locales/de/translation.json:
--------------------------------------------------------------------------------
1 | {
2 | "appTitle": "CodeQuill",
3 | "newSnippet": "Neues Snippet",
4 | "filename": "Dateiname",
5 | "selectLanguage": "Sprache auswählen...",
6 | "save": "Speichern",
7 | "saving": "Wird gespeichert...",
8 | "hidePreview": "Vorschau ausblenden",
9 | "showPreview": "Vorschau anzeigen",
10 | "noPreview": "Keine Vorschau",
11 | "toggleSidebar": "Seitenleiste ein-/ausblenden",
12 | "typeToSearch": "Tippen, um Snippets zu suchen...",
13 | "noSnippetsFound": "Keine Snippets gefunden.",
14 | "copy": "Kopieren",
15 | "delete": "Löschen",
16 | "settings": "Einstellungen",
17 | "backToEditor": "Zurück zum Editor",
18 | "customizeYourExperience": "Passen Sie Ihr CodeQuill-Erlebnis an",
19 | "theme": "Design",
20 | "chooseYourPreferredAppearance": "Wählen Sie Ihr bevorzugtes App-Erscheinungsbild",
21 | "defaultLanguage": "Standardsprache",
22 | "defaultProgrammingLanguage": "Standardprogrammiersprache für neue Snippets",
23 | "keyboardShortcuts": "Tastaturkürzel",
24 | "viewCommonKeyboardShortcuts": "Häufig verwendete Tastaturkürzel anzeigen",
25 | "saveSnippet": "Snippet speichern",
26 | "createNewSnippet": "Neues Snippet erstellen",
27 | "searchSnippets": "Snippets durchsuchen",
28 | "previewCode": "Code-Vorschau",
29 | "openSettings": "Einstellungen öffnen",
30 | "formatCode": "Code formatieren",
31 | "undo": "Rückgängig",
32 | "redo": "Wiederholen",
33 | "appInfo": "App-Info",
34 | "informationAboutCodeQuill": "Informationen über CodeQuill",
35 | "version": "Version",
36 | "installedVersion": "Installierte Version",
37 | "license": "Lizenz",
38 | "openSource": "Open Source",
39 | "createdBy": "Erstellt von",
40 | "sourceCode": "Quellcode",
41 | "reportIssue": "Problem melden",
42 | "dependencies": "Abhängigkeiten",
43 | "librariesUsed": "In CodeQuill verwendete Bibliotheken",
44 | "production": "Produktion",
45 | "librariesBundled": "Im Produktions-Build gebündelte Bibliotheken",
46 | "development": "Entwicklung",
47 | "librariesUsedDevelopment": "In der CodeQuill-Entwicklung verwendete Bibliotheken",
48 | "productionDependencies": "Produktionsabhängigkeiten",
49 | "developmentDependencies": "Entwicklungsabhängigkeiten",
50 | "deleteThisSnippet": "Diesen Snippet löschen?",
51 | "thisActionCannotBeUndone": "Diese Aktion kann nicht rückgängig gemacht werden. Der Snippet wird dauerhaft gelöscht.",
52 | "cancel": "Abbrechen",
53 | "deleting": "Wird gelöscht...",
54 | "newSnippetSaved": "Neuer Schnipsel gespeichert!",
55 | "snippetSavedSuccessfully": "Schnipsel erfolgreich gespeichert!",
56 | "snippetCopiedToClipboard": "Schnipsel in die Zwischenablage kopiert",
57 | "snippetDeletedSuccessfully": "Schnipsel erfolgreich gelöscht!",
58 | "untitled": "Unbenannt",
59 | "youDonTHaveAnySnippets": "Du hast noch keine Schnipsel. Erstelle jetzt einen!",
60 | "createNow": "Jetzt erstellen!",
61 | "morePages": "Weitere Seiten",
62 | "previous": "Zurück",
63 | "next": "Weiter",
64 | "close": "Schließen",
65 | "searchLanguage": "Sprache suchen...",
66 | "noLanguageFound": "Keine Sprache gefunden.",
67 | "website": "Website",
68 | "themeLight": "Hell",
69 | "themeDark": "Dunkel",
70 | "themeDim": "Gedimmt",
71 | "themeSystem": "System",
72 | "failedToLoadSnippets": "Fehler beim Laden der Schnipsel.",
73 | "failedToCreateNewSnippet": "Fehler beim Erstellen eines neuen Schnipsels.",
74 | "creatingNewSnippet": "Neuer Schnipsel wird erstellt",
75 | "failedToLoadPreviewState": "Fehler beim Laden des Vorschau-Status aus dem localStorage.",
76 | "pleaseSelectLanguage": "Bitte wähle eine Sprache aus.",
77 | "filenameCannotBeEmpty": "Der Dateiname darf nicht leer sein.",
78 | "filenameTooLong": "Der Dateiname darf nicht länger als 1024 Zeichen sein.",
79 | "savingSnippet": "Snippet wird gespeichert",
80 | "failedToSaveSnippet": "Snippet konnte nicht gespeichert werden.",
81 | "failedToCopySnippet": "Snippet konnte nicht kopiert werden.",
82 | "failedToRemovePreview": "Vorschau konnte nicht aus dem localStorage entfernt werden.",
83 | "deletingSnippet": "Snippet wird gelöscht",
84 | "failedToDeleteSnippet": "Snippet konnte nicht gelöscht werden.",
85 | "appLanguage": "App-Sprache",
86 | "selectAppLanguage": "Wählen Sie Ihre gesprochene Sprache",
87 | "snippetInformation": "Snippet-Info",
88 | "snippetDetails": "Details zu diesem Snippet anzeigen",
89 | "id": "ID",
90 | "language": "Sprache",
91 | "lastSaved": "Zuletzt gespeichert",
92 | "info": "Info",
93 | "noPreviewAvailable": "Keine Vorschau verfügbar",
94 | "notAvailable": "Nicht verfügbar"
95 | }
96 |
--------------------------------------------------------------------------------
/src/routes/settings/index.tsx:
--------------------------------------------------------------------------------
1 | import supportedLanguages from "@/assets/supportedLanguages.json";
2 | import { Button } from "@/components/ui/button";
3 | import {
4 | Card,
5 | CardContent,
6 | CardDescription,
7 | CardHeader,
8 | CardTitle,
9 | } from "@/components/ui/card";
10 | import { Separator } from "@/components/ui/separator";
11 | import { getConfig, updateConfig } from "@/utils/config";
12 | import { useTheme } from "next-themes";
13 | import { useEffect, useState } from "react";
14 | import { useTranslation } from "react-i18next";
15 | import { useNavigate } from "react-router-dom";
16 | import packageJson from "../../../package.json";
17 | import { Language } from "../home/types";
18 | import AppInfoSection from "./AppInfoSection";
19 | import DependenciesSection from "./DependenciesSection";
20 | import KeyboardShortcutsSection from "./KeyboardShortcutsSection";
21 | import LanguageSection from "./LanguageSection";
22 | import ProgrammingLanguageSection from "./ProgrammingLanguageSection";
23 | import ThemeSection from "./ThemeSection";
24 |
25 | const APP_VERSION = packageJson.version;
26 |
27 | function Settings() {
28 | const { t, i18n } = useTranslation();
29 | const navigate = useNavigate();
30 | const { theme, setTheme } = useTheme();
31 | const [language, setLanguage] = useState(
32 | getConfig().defaultLanguage,
33 | );
34 |
35 | const [appLanguage, setAppLanguage] = useState(i18n.language || "en");
36 |
37 | const handleBack = () => {
38 | navigate("/");
39 | };
40 |
41 | useEffect(() => {
42 | const handleKeyDown = (event: KeyboardEvent) => {
43 | if (event.key === "Escape") {
44 | navigate("/");
45 | }
46 | };
47 |
48 | window.addEventListener("keydown", handleKeyDown);
49 |
50 | return () => {
51 | window.removeEventListener("keydown", handleKeyDown);
52 | };
53 | }, [navigate]);
54 |
55 | useEffect(() => {
56 | // Update the config whenever the programming language changes
57 | updateConfig({ defaultLanguage: language });
58 | }, [language]);
59 |
60 | const availableLanguages = [
61 | { code: "en", name: "English" },
62 | { code: "fr", name: "Français" },
63 | { code: "es", name: "Español" },
64 | { code: "de", name: "Deutsch" },
65 | { code: "it", name: "Italiano" },
66 | { code: "pt", name: "Português" },
67 | { code: "nl", name: "Nederlands" },
68 | { code: "zh", name: "中文" },
69 | { code: "ja", name: "日本語" },
70 | { code: "ko", name: "한국어" },
71 | { code: "ru", name: "Русский" },
72 | { code: "ar", name: "العربية" },
73 | ];
74 |
75 | return (
76 |
77 |
78 |
79 |
80 |
81 |
82 | {t("settings")}
83 |
84 |
85 | {t("customizeYourExperience")}
86 |
87 |
88 |
91 |
92 |
93 |
94 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 | );
132 | }
133 |
134 | export default Settings;
135 |
--------------------------------------------------------------------------------
/src/components/ui/form.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import * as LabelPrimitive from "@radix-ui/react-label";
3 | import { Slot } from "@radix-ui/react-slot";
4 | import {
5 | Controller,
6 | FormProvider,
7 | useFormContext,
8 | useFormState,
9 | type ControllerProps,
10 | type FieldPath,
11 | type FieldValues,
12 | } from "react-hook-form";
13 |
14 | import { cn } from "@/lib/utils";
15 | import { Label } from "@/components/ui/label";
16 |
17 | const Form = FormProvider;
18 |
19 | type FormFieldContextValue<
20 | TFieldValues extends FieldValues = FieldValues,
21 | TName extends FieldPath = FieldPath,
22 | > = {
23 | name: TName;
24 | };
25 |
26 | const FormFieldContext = React.createContext(
27 | {} as FormFieldContextValue,
28 | );
29 |
30 | const FormField = <
31 | TFieldValues extends FieldValues = FieldValues,
32 | TName extends FieldPath = FieldPath,
33 | >({
34 | ...props
35 | }: ControllerProps) => {
36 | return (
37 |
38 |
39 |
40 | );
41 | };
42 |
43 | const useFormField = () => {
44 | const fieldContext = React.useContext(FormFieldContext);
45 | const itemContext = React.useContext(FormItemContext);
46 | const { getFieldState } = useFormContext();
47 | const formState = useFormState({ name: fieldContext.name });
48 | const fieldState = getFieldState(fieldContext.name, formState);
49 |
50 | if (!fieldContext) {
51 | throw new Error("useFormField should be used within ");
52 | }
53 |
54 | const { id } = itemContext;
55 |
56 | return {
57 | id,
58 | name: fieldContext.name,
59 | formItemId: `${id}-form-item`,
60 | formDescriptionId: `${id}-form-item-description`,
61 | formMessageId: `${id}-form-item-message`,
62 | ...fieldState,
63 | };
64 | };
65 |
66 | type FormItemContextValue = {
67 | id: string;
68 | };
69 |
70 | const FormItemContext = React.createContext(
71 | {} as FormItemContextValue,
72 | );
73 |
74 | function FormItem({ className, ...props }: React.ComponentProps<"div">) {
75 | const id = React.useId();
76 |
77 | return (
78 |
79 |
84 |
85 | );
86 | }
87 |
88 | function FormLabel({
89 | className,
90 | ...props
91 | }: React.ComponentProps) {
92 | const { error, formItemId } = useFormField();
93 |
94 | return (
95 |
102 | );
103 | }
104 |
105 | function FormControl({ ...props }: React.ComponentProps) {
106 | const { error, formItemId, formDescriptionId, formMessageId } =
107 | useFormField();
108 |
109 | return (
110 |
121 | );
122 | }
123 |
124 | function FormDescription({ className, ...props }: React.ComponentProps<"p">) {
125 | const { formDescriptionId } = useFormField();
126 |
127 | return (
128 |
134 | );
135 | }
136 |
137 | function FormMessage({ className, ...props }: React.ComponentProps<"p">) {
138 | const { error, formMessageId } = useFormField();
139 | const body = error ? String(error?.message ?? "") : props.children;
140 |
141 | if (!body) {
142 | return null;
143 | }
144 |
145 | return (
146 |
152 | {body}
153 |
154 | );
155 | }
156 |
157 | export {
158 | useFormField,
159 | Form,
160 | FormItem,
161 | FormLabel,
162 | FormControl,
163 | FormDescription,
164 | FormMessage,
165 | FormField,
166 | };
167 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "codequill",
3 | "description": "Organize, edit, and preview code efficiently",
4 | "private": true,
5 | "version": "2.0.7",
6 | "type": "module",
7 | "author": {
8 | "name": "The-Best-Codes",
9 | "email": "bestcodes.official@gmail.com",
10 | "url": "https://github.com/The-Best-Codes"
11 | },
12 | "homepage": "https://github.com/The-Best-Codes/codequill",
13 | "repository": {
14 | "type": "git",
15 | "url": "https://github.com/The-Best-Codes/codequill.git"
16 | },
17 | "license": "MIT",
18 | "scripts": {
19 | "dev": "vite",
20 | "build": "vite build",
21 | "preview": "vite preview",
22 | "icon": "npm run tauri icon public/icon.svg",
23 | "tauri": "tauri",
24 | "translate": "lingo.dev i18n",
25 | "test:frontend": "bun run build",
26 | "test:cargo": "cd src-tauri && cargo check && cargo test && cd ..",
27 | "test": "npm run test:frontend && npm run test:cargo",
28 | "upgrade": "npm-check-updates --upgrade --doctor && cd src-tauri && cargo update && cargo upgrade || echo \"Cargo upgrade command is not installed\" && cd .. && bun run test"
29 | },
30 | "dependencies": {
31 | "@hookform/resolvers": "^5.2.2",
32 | "@monaco-editor/react": "^4.7.0",
33 | "@radix-ui/react-accordion": "^1.2.12",
34 | "@radix-ui/react-alert-dialog": "^1.1.15",
35 | "@radix-ui/react-aspect-ratio": "^1.1.8",
36 | "@radix-ui/react-avatar": "^1.1.11",
37 | "@radix-ui/react-checkbox": "^1.3.3",
38 | "@radix-ui/react-collapsible": "^1.1.12",
39 | "@radix-ui/react-context-menu": "^2.2.16",
40 | "@radix-ui/react-dialog": "^1.1.15",
41 | "@radix-ui/react-dropdown-menu": "^2.1.16",
42 | "@radix-ui/react-hover-card": "^1.1.15",
43 | "@radix-ui/react-label": "^2.1.8",
44 | "@radix-ui/react-menubar": "^1.1.16",
45 | "@radix-ui/react-navigation-menu": "^1.2.14",
46 | "@radix-ui/react-popover": "^1.1.15",
47 | "@radix-ui/react-progress": "^1.1.8",
48 | "@radix-ui/react-radio-group": "^1.3.8",
49 | "@radix-ui/react-scroll-area": "^1.2.10",
50 | "@radix-ui/react-select": "^2.2.6",
51 | "@radix-ui/react-separator": "^1.1.8",
52 | "@radix-ui/react-slider": "^1.3.6",
53 | "@radix-ui/react-slot": "^1.2.4",
54 | "@radix-ui/react-switch": "^1.2.6",
55 | "@radix-ui/react-tabs": "^1.1.13",
56 | "@radix-ui/react-toast": "^1.2.15",
57 | "@radix-ui/react-toggle": "^1.1.10",
58 | "@radix-ui/react-toggle-group": "^1.1.11",
59 | "@radix-ui/react-tooltip": "^1.2.8",
60 | "@sentry/react": "^10.27.0",
61 | "@sentry/vite-plugin": "^4.6.1",
62 | "@tauri-apps/api": "^2.9.0",
63 | "@tauri-apps/plugin-deep-link": "^2.4.5",
64 | "@tauri-apps/plugin-opener": "^2.5.2",
65 | "@tauri-apps/plugin-sql": "^2.3.1",
66 | "babel-plugin-react-compiler": "^1.0.0",
67 | "class-variance-authority": "^0.7.1",
68 | "clsx": "^2.1.1",
69 | "cmdk": "^1.1.1",
70 | "date-fns": "^4.1.0",
71 | "embla-carousel-react": "^8.6.0",
72 | "i18next": "^25.6.3",
73 | "i18next-browser-languagedetector": "^8.2.0",
74 | "i18next-http-backend": "^3.0.2",
75 | "input-otp": "^1.4.2",
76 | "lucide-react": "^0.555.0",
77 | "monaco-editor": "0.52",
78 | "motion": "^12.23.24",
79 | "next-themes": "^0.4.6",
80 | "react": "^19.2.0",
81 | "react-day-picker": "^9.11.2",
82 | "react-dom": "^19.2.0",
83 | "react-hook-form": "^7.67.0",
84 | "react-i18next": "^16.3.5",
85 | "react-markdown": "^10.1.0",
86 | "react-resizable-panels": "^3.0.6",
87 | "react-router-dom": "^7.9.6",
88 | "recharts": "^3.5.1",
89 | "rehype-raw": "^7.0.0",
90 | "remark-gfm": "^4.0.1",
91 | "sonner": "^2.0.7",
92 | "tailwind-merge": "^3.4.0",
93 | "tailwindcss-animate": "^1.0.7",
94 | "uuid": "^13.0.0",
95 | "vaul": "^1.1.2",
96 | "vite-bundle-analyzer": "^1.2.3",
97 | "zod": "^4.1.13"
98 | },
99 | "devDependencies": {
100 | "@tailwindcss/postcss": "^4.1.17",
101 | "@tailwindcss/typography": "^0.5.19",
102 | "@tauri-apps/cli": "^2.9.4",
103 | "@types/node": "^24.10.1",
104 | "@types/react": "^19.2.7",
105 | "@types/react-dom": "^19.2.3",
106 | "@vitejs/plugin-react": "^5.1.1",
107 | "lingo.dev": "^0.117.4",
108 | "npm-check-updates": "^19.1.2",
109 | "postcss": "^8.5.6",
110 | "tailwindcss": "^4.1.17",
111 | "typescript": "~5.9.3",
112 | "vite": "^7.2.4",
113 | "vite-plugin-static-copy": "^3.1.4"
114 | },
115 | "trustedDependencies": [
116 | "@sentry/cli",
117 | "@tailwindcss/oxide",
118 | "esbuild",
119 | "sharp"
120 | ]
121 | }
122 |
--------------------------------------------------------------------------------
/public/locales/fr/translation.json:
--------------------------------------------------------------------------------
1 | {
2 | "appTitle": "CodeQuill",
3 | "newSnippet": "Nouveau snippet",
4 | "filename": "Nom du fichier",
5 | "selectLanguage": "Sélectionner la langue...",
6 | "save": "Enregistrer",
7 | "saving": "Enregistrement en cours...",
8 | "hidePreview": "Masquer l'aperçu",
9 | "showPreview": "Afficher l'aperçu",
10 | "noPreview": "Pas d'aperçu",
11 | "toggleSidebar": "Afficher/masquer la barre latérale",
12 | "typeToSearch": "Tapez pour rechercher des snippets...",
13 | "noSnippetsFound": "Aucun snippet trouvé.",
14 | "copy": "Copier",
15 | "delete": "Supprimer",
16 | "settings": "Paramètres",
17 | "backToEditor": "Retour à l'éditeur",
18 | "customizeYourExperience": "Personnalisez votre expérience CodeQuill",
19 | "theme": "Thème",
20 | "chooseYourPreferredAppearance": "Choisissez l'apparence de l'application que vous préférez",
21 | "defaultLanguage": "Langue par défaut",
22 | "defaultProgrammingLanguage": "Langage de programmation par défaut pour les nouveaux snippets",
23 | "keyboardShortcuts": "Raccourcis clavier",
24 | "viewCommonKeyboardShortcuts": "Voir les raccourcis clavier courants",
25 | "saveSnippet": "Enregistrer le snippet",
26 | "createNewSnippet": "Créer un nouveau snippet",
27 | "searchSnippets": "Rechercher des extraits",
28 | "previewCode": "Aperçu du code",
29 | "openSettings": "Ouvrir les paramètres",
30 | "formatCode": "Formater le code",
31 | "undo": "Annuler",
32 | "redo": "Rétablir",
33 | "appInfo": "Infos sur l'application",
34 | "informationAboutCodeQuill": "Informations sur CodeQuill",
35 | "version": "Version",
36 | "installedVersion": "Version installée",
37 | "license": "Licence",
38 | "openSource": "Open source",
39 | "createdBy": "Créé par",
40 | "sourceCode": "Code source",
41 | "reportIssue": "Signaler un problème",
42 | "dependencies": "Dépendances",
43 | "librariesUsed": "Bibliothèques utilisées dans CodeQuill",
44 | "production": "Production",
45 | "librariesBundled": "Bibliothèques intégrées dans la version de production",
46 | "development": "Développement",
47 | "librariesUsedDevelopment": "Bibliothèques utilisées dans le développement de CodeQuill",
48 | "productionDependencies": "Dépendances de production",
49 | "developmentDependencies": "Dépendances de développement",
50 | "deleteThisSnippet": "Supprimer cet extrait ?",
51 | "thisActionCannotBeUndone": "Cette action ne peut pas être annulée. Cela supprimera définitivement l'extrait.",
52 | "cancel": "Annuler",
53 | "deleting": "Suppression en cours...",
54 | "newSnippetSaved": "Nouveau snippet enregistré !",
55 | "snippetSavedSuccessfully": "Snippet enregistré avec succès !",
56 | "snippetCopiedToClipboard": "Snippet copié dans le presse-papiers",
57 | "snippetDeletedSuccessfully": "Snippet supprimé avec succès !",
58 | "untitled": "Sans titre",
59 | "youDonTHaveAnySnippets": "Vous n'avez pas encore de snippets. Créez-en un maintenant !",
60 | "createNow": "Créez-en un maintenant !",
61 | "morePages": "Plus de pages",
62 | "previous": "Précédent",
63 | "next": "Suivant",
64 | "close": "Fermer",
65 | "searchLanguage": "Rechercher une langue...",
66 | "noLanguageFound": "Aucune langue trouvée.",
67 | "website": "Site web",
68 | "themeLight": "Clair",
69 | "themeDark": "Sombre",
70 | "themeDim": "Tamisé",
71 | "themeSystem": "Système",
72 | "failedToLoadSnippets": "Échec du chargement des snippets.",
73 | "failedToCreateNewSnippet": "Échec de la création d'un nouveau snippet.",
74 | "creatingNewSnippet": "Création d'un nouveau snippet",
75 | "failedToLoadPreviewState": "Échec du chargement de l'état de prévisualisation depuis le localStorage.",
76 | "pleaseSelectLanguage": "Veuillez sélectionner une langue.",
77 | "filenameCannotBeEmpty": "Le nom du fichier ne peut pas être vide.",
78 | "filenameTooLong": "Le nom du fichier ne peut pas dépasser 1024 caractères.",
79 | "savingSnippet": "Enregistrement du snippet",
80 | "failedToSaveSnippet": "Échec de l'enregistrement du snippet.",
81 | "failedToCopySnippet": "Échec de la copie du snippet.",
82 | "failedToRemovePreview": "Échec de la suppression de l'aperçu du localStorage.",
83 | "deletingSnippet": "Suppression du snippet",
84 | "failedToDeleteSnippet": "Échec de la suppression du snippet.",
85 | "appLanguage": "Langue de l'application",
86 | "selectAppLanguage": "Choisissez votre langue parlée",
87 | "snippetInformation": "Infos sur l'extrait",
88 | "snippetDetails": "Voir les détails de cet extrait",
89 | "id": "ID",
90 | "language": "Langue",
91 | "lastSaved": "Dernière sauvegarde",
92 | "info": "Infos",
93 | "noPreviewAvailable": "Aucun aperçu disponible",
94 | "notAvailable": "Non disponible"
95 | }
96 |
--------------------------------------------------------------------------------
/src/components/ui/alert-dialog.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import * as React from "react";
4 | import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
5 |
6 | import { cn } from "@/lib/utils";
7 | import { buttonVariants } from "@/components/ui/button";
8 |
9 | function AlertDialog({
10 | ...props
11 | }: React.ComponentProps) {
12 | return ;
13 | }
14 |
15 | function AlertDialogTrigger({
16 | ...props
17 | }: React.ComponentProps) {
18 | return (
19 |
20 | );
21 | }
22 |
23 | function AlertDialogPortal({
24 | ...props
25 | }: React.ComponentProps) {
26 | return (
27 |
28 | );
29 | }
30 |
31 | function AlertDialogOverlay({
32 | className,
33 | ...props
34 | }: React.ComponentProps) {
35 | return (
36 |
44 | );
45 | }
46 |
47 | function AlertDialogContent({
48 | className,
49 | ...props
50 | }: React.ComponentProps) {
51 | return (
52 |
53 |
54 |
62 |
63 | );
64 | }
65 |
66 | function AlertDialogHeader({
67 | className,
68 | ...props
69 | }: React.ComponentProps<"div">) {
70 | return (
71 |
76 | );
77 | }
78 |
79 | function AlertDialogFooter({
80 | className,
81 | ...props
82 | }: React.ComponentProps<"div">) {
83 | return (
84 |
92 | );
93 | }
94 |
95 | function AlertDialogTitle({
96 | className,
97 | ...props
98 | }: React.ComponentProps) {
99 | return (
100 |
105 | );
106 | }
107 |
108 | function AlertDialogDescription({
109 | className,
110 | ...props
111 | }: React.ComponentProps) {
112 | return (
113 |
118 | );
119 | }
120 |
121 | function AlertDialogAction({
122 | className,
123 | ...props
124 | }: React.ComponentProps) {
125 | return (
126 |
130 | );
131 | }
132 |
133 | function AlertDialogCancel({
134 | className,
135 | ...props
136 | }: React.ComponentProps) {
137 | return (
138 |
142 | );
143 | }
144 |
145 | export {
146 | AlertDialog,
147 | AlertDialogPortal,
148 | AlertDialogOverlay,
149 | AlertDialogTrigger,
150 | AlertDialogContent,
151 | AlertDialogHeader,
152 | AlertDialogFooter,
153 | AlertDialogTitle,
154 | AlertDialogDescription,
155 | AlertDialogAction,
156 | AlertDialogCancel,
157 | };
158 |
--------------------------------------------------------------------------------
/src/components/ui/dialog.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import * as DialogPrimitive from "@radix-ui/react-dialog";
3 | import XIcon from "lucide-react/dist/esm/icons/x";
4 |
5 | import { cn } from "@/lib/utils";
6 |
7 | function Dialog({
8 | ...props
9 | }: React.ComponentProps) {
10 | return ;
11 | }
12 |
13 | function DialogTrigger({
14 | ...props
15 | }: React.ComponentProps) {
16 | return ;
17 | }
18 |
19 | function DialogPortal({
20 | ...props
21 | }: React.ComponentProps) {
22 | return ;
23 | }
24 |
25 | function DialogClose({
26 | ...props
27 | }: React.ComponentProps) {
28 | return ;
29 | }
30 |
31 | function DialogOverlay({
32 | className,
33 | ...props
34 | }: React.ComponentProps) {
35 | return (
36 |
44 | );
45 | }
46 |
47 | function DialogContent({
48 | className,
49 | children,
50 | showCloseButton = true,
51 | ...props
52 | }: React.ComponentProps & {
53 | showCloseButton?: boolean;
54 | }) {
55 | return (
56 |
57 |
58 |
66 | {children}
67 | {showCloseButton && (
68 |
72 |
73 | Close
74 |
75 | )}
76 |
77 |
78 | );
79 | }
80 |
81 | function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
82 | return (
83 |
88 | );
89 | }
90 |
91 | function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
92 | return (
93 |
101 | );
102 | }
103 |
104 | function DialogTitle({
105 | className,
106 | ...props
107 | }: React.ComponentProps) {
108 | return (
109 |
114 | );
115 | }
116 |
117 | function DialogDescription({
118 | className,
119 | ...props
120 | }: React.ComponentProps) {
121 | return (
122 |
127 | );
128 | }
129 |
130 | export {
131 | Dialog,
132 | DialogClose,
133 | DialogContent,
134 | DialogDescription,
135 | DialogFooter,
136 | DialogHeader,
137 | DialogOverlay,
138 | DialogPortal,
139 | DialogTitle,
140 | DialogTrigger,
141 | };
142 |
--------------------------------------------------------------------------------
/src/components/ui/sheet.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import * as SheetPrimitive from "@radix-ui/react-dialog";
3 | import XIcon from "lucide-react/dist/esm/icons/x";
4 |
5 | import { cn } from "@/lib/utils";
6 |
7 | function Sheet({ ...props }: React.ComponentProps) {
8 | return ;
9 | }
10 |
11 | function SheetTrigger({
12 | ...props
13 | }: React.ComponentProps) {
14 | return ;
15 | }
16 |
17 | function SheetClose({
18 | ...props
19 | }: React.ComponentProps) {
20 | return ;
21 | }
22 |
23 | function SheetPortal({
24 | ...props
25 | }: React.ComponentProps) {
26 | return ;
27 | }
28 |
29 | function SheetOverlay({
30 | className,
31 | ...props
32 | }: React.ComponentProps) {
33 | return (
34 |
42 | );
43 | }
44 |
45 | function SheetContent({
46 | className,
47 | children,
48 | side = "right",
49 | ...props
50 | }: React.ComponentProps & {
51 | side?: "top" | "right" | "bottom" | "left";
52 | }) {
53 | return (
54 |
55 |
56 |
72 | {children}
73 |
74 |
75 | Close
76 |
77 |
78 |
79 | );
80 | }
81 |
82 | function SheetHeader({ className, ...props }: React.ComponentProps<"div">) {
83 | return (
84 |
89 | );
90 | }
91 |
92 | function SheetFooter({ className, ...props }: React.ComponentProps<"div">) {
93 | return (
94 |
99 | );
100 | }
101 |
102 | function SheetTitle({
103 | className,
104 | ...props
105 | }: React.ComponentProps) {
106 | return (
107 |
112 | );
113 | }
114 |
115 | function SheetDescription({
116 | className,
117 | ...props
118 | }: React.ComponentProps) {
119 | return (
120 |
125 | );
126 | }
127 |
128 | export {
129 | Sheet,
130 | SheetTrigger,
131 | SheetClose,
132 | SheetContent,
133 | SheetHeader,
134 | SheetFooter,
135 | SheetTitle,
136 | SheetDescription,
137 | };
138 |
--------------------------------------------------------------------------------
/src/components/ui/drawer.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import { Drawer as DrawerPrimitive } from "vaul";
3 |
4 | import { cn } from "@/lib/utils";
5 |
6 | function Drawer({
7 | ...props
8 | }: React.ComponentProps) {
9 | return ;
10 | }
11 |
12 | function DrawerTrigger({
13 | ...props
14 | }: React.ComponentProps) {
15 | return ;
16 | }
17 |
18 | function DrawerPortal({
19 | ...props
20 | }: React.ComponentProps) {
21 | return ;
22 | }
23 |
24 | function DrawerClose({
25 | ...props
26 | }: React.ComponentProps) {
27 | return ;
28 | }
29 |
30 | function DrawerOverlay({
31 | className,
32 | ...props
33 | }: React.ComponentProps) {
34 | return (
35 |
43 | );
44 | }
45 |
46 | function DrawerContent({
47 | className,
48 | children,
49 | ...props
50 | }: React.ComponentProps) {
51 | return (
52 |
53 |
54 |
66 |
67 | {children}
68 |
69 |
70 | );
71 | }
72 |
73 | function DrawerHeader({ className, ...props }: React.ComponentProps<"div">) {
74 | return (
75 |
83 | );
84 | }
85 |
86 | function DrawerFooter({ className, ...props }: React.ComponentProps<"div">) {
87 | return (
88 |
93 | );
94 | }
95 |
96 | function DrawerTitle({
97 | className,
98 | ...props
99 | }: React.ComponentProps) {
100 | return (
101 |
106 | );
107 | }
108 |
109 | function DrawerDescription({
110 | className,
111 | ...props
112 | }: React.ComponentProps) {
113 | return (
114 |
119 | );
120 | }
121 |
122 | export {
123 | Drawer,
124 | DrawerPortal,
125 | DrawerOverlay,
126 | DrawerTrigger,
127 | DrawerClose,
128 | DrawerContent,
129 | DrawerHeader,
130 | DrawerFooter,
131 | DrawerTitle,
132 | DrawerDescription,
133 | };
134 |
--------------------------------------------------------------------------------
|