From f7f1535695d0265a0cff89fd5ef79ff8413911b6 Mon Sep 17 00:00:00 2001 From: Kenta420 Date: Wed, 21 Feb 2024 15:17:54 +0700 Subject: [PATCH] add recipe viewer --- client-electron/package-lock.json | 219 ++++++++++++++++++ client-electron/package.json | 6 + client-electron/src/App.tsx | 23 +- client-electron/src/assets/tao_logo.svg | 16 ++ client-electron/src/components/navbar.tsx | 2 +- client-electron/src/components/ui/avatar.tsx | 48 ++++ .../src/components/ui/resizable.tsx | 43 ++++ .../src/components/ui/scroll-area.tsx | 46 ++++ client-electron/src/components/ui/switch.tsx | 27 +++ .../src/components/ui/textarea.tsx | 24 ++ client-electron/src/components/ui/tooltip.tsx | 28 +++ client-electron/src/hooks/android-switcher.ts | 20 ++ client-electron/src/hooks/axios.ts | 39 +--- .../src/hooks/filemanager-android.ts | 33 ++- client-electron/src/hooks/localStorage.ts | 14 ++ client-electron/src/hooks/recipe-dashboard.ts | 27 ++- client-electron/src/hooks/userAuth.ts | 6 +- client-electron/src/layouts/MainLayout.tsx | 47 ++-- client-electron/src/lib/taoAxios.ts | 54 +++++ client-electron/src/models/recipe/schema.ts | 200 ++++++++++++++++ client-electron/src/pages/Home.tsx | 20 -- client-electron/src/pages/Login.tsx | 2 +- .../android/components/file-manager-tab.tsx | 13 +- .../android-switcher.tsx | 53 +++++ .../recipe-editor-components/nav.tsx | 73 ++++++ .../recipe-display.tsx | 180 ++++++++++++++ .../recipe-editor.tsx | 198 ++++++++++++++++ .../recipe-editor-components/recipe-list.tsx | 71 ++++++ .../src/pages/recipes/recipe-table.tsx | 113 +++++++-- .../src/pages/recipes/select-country.tsx | 25 -- server/routers/auth.go | 13 +- 31 files changed, 1532 insertions(+), 151 deletions(-) create mode 100644 client-electron/src/assets/tao_logo.svg create mode 100644 client-electron/src/components/ui/avatar.tsx create mode 100644 client-electron/src/components/ui/resizable.tsx create mode 100644 client-electron/src/components/ui/scroll-area.tsx create mode 100644 client-electron/src/components/ui/switch.tsx create mode 100644 client-electron/src/components/ui/textarea.tsx create mode 100644 client-electron/src/components/ui/tooltip.tsx create mode 100644 client-electron/src/hooks/android-switcher.ts create mode 100644 client-electron/src/lib/taoAxios.ts delete mode 100644 client-electron/src/pages/Home.tsx create mode 100644 client-electron/src/pages/recipes/components/recipe-editor-components/android-switcher.tsx create mode 100644 client-electron/src/pages/recipes/components/recipe-editor-components/nav.tsx create mode 100644 client-electron/src/pages/recipes/components/recipe-editor-components/recipe-display.tsx create mode 100644 client-electron/src/pages/recipes/components/recipe-editor-components/recipe-editor.tsx create mode 100644 client-electron/src/pages/recipes/components/recipe-editor-components/recipe-list.tsx delete mode 100644 client-electron/src/pages/recipes/select-country.tsx diff --git a/client-electron/package-lock.json b/client-electron/package-lock.json index 472edc3..4490b59 100644 --- a/client-electron/package-lock.json +++ b/client-electron/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "@hookform/resolvers": "^3.3.4", "@postman/node-keytar": "^7.9.3", + "@radix-ui/react-avatar": "^1.0.4", "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dropdown-menu": "^2.0.6", @@ -18,11 +19,14 @@ "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-popover": "^1.0.7", "@radix-ui/react-radio-group": "^1.1.3", + "@radix-ui/react-scroll-area": "^1.0.5", "@radix-ui/react-select": "^2.0.0", "@radix-ui/react-separator": "^1.0.3", "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-switch": "^1.0.3", "@radix-ui/react-tabs": "^1.0.4", "@radix-ui/react-toast": "^1.1.5", + "@radix-ui/react-tooltip": "^1.0.7", "@tanstack/match-sorter-utils": "^8.11.8", "@tanstack/react-query": "^5.17.19", "@tanstack/react-table": "^8.11.7", @@ -48,12 +52,14 @@ "cmdk": "^0.2.0", "date-fns": "^3.3.1", "jszip": "^3.10.1", + "lucide-react": "^0.334.0", "next-themes": "^0.2.1", "react": "^18.2.0", "react-day-picker": "^8.10.0", "react-dom": "^18.2.0", "react-dropzone": "^14.2.3", "react-hook-form": "^7.49.3", + "react-resizable-panels": "^2.0.9", "react-router-dom": "^6.21.1", "sonner": "^1.4.0", "tailwind-merge": "^2.2.1", @@ -3128,6 +3134,32 @@ } } }, + "node_modules/@radix-ui/react-avatar": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.0.4.tgz", + "integrity": "sha512-kVK2K7ZD3wwj3qhle0ElXhOjbezIgyl2hVvgwfIdexL3rN6zJmy5AqqIf+D31lxVppdzV8CjAfZ6PklkmInZLw==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-checkbox": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.0.4.tgz", @@ -3660,6 +3692,37 @@ } } }, + "node_modules/@radix-ui/react-scroll-area": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.0.5.tgz", + "integrity": "sha512-b6PAgH4GQf9QEn8zbT2XUHpW5z8BzqEc7Kl11TwDrvuTrxlkcjTD5qa/bxgKr+nmuXKu4L/W5UZ4mlP/VG/5Gw==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/number": "1.0.1", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-direction": "1.0.1", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-select": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.0.0.tgz", @@ -3744,6 +3807,35 @@ } } }, + "node_modules/@radix-ui/react-switch": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.0.3.tgz", + "integrity": "sha512-mxm87F88HyHztsI7N+ZUmEoARGkC22YVW5CaC+Byc+HRpuvCrOBPTAnXgf+tZ/7i0Sg/eOePGdMhUKhPaQEqow==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-controllable-state": "1.0.1", + "@radix-ui/react-use-previous": "1.0.1", + "@radix-ui/react-use-size": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-tabs": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.0.4.tgz", @@ -3808,6 +3900,40 @@ } } }, + "node_modules/@radix-ui/react-tooltip": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.0.7.tgz", + "integrity": "sha512-lPh5iKNFVQ/jav/j6ZrWq3blfDJ0OH9R6FlNUHPMqdLuQ9vwDgFsRxvl8b7Asuy5c8xmoojHUxKHQSOAvMHxyw==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.5", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-popper": "1.1.3", + "@radix-ui/react-portal": "1.0.4", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2", + "@radix-ui/react-use-controllable-state": "1.0.1", + "@radix-ui/react-visually-hidden": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-use-callback-ref": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz", @@ -9806,6 +9932,14 @@ "yallist": "^3.0.2" } }, + "node_modules/lucide-react": { + "version": "0.334.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.334.0.tgz", + "integrity": "sha512-y0Rv/Xx6qAq4FutZ3L/efl3O9vl6NC/1p0YOg6mBfRbQ4k1JCE2rz0rnV7WC8Moxq1RY99vLATvjcqUegGJTvA==", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/make-fetch-happen": { "version": "10.2.1", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", @@ -11557,6 +11691,15 @@ } } }, + "node_modules/react-resizable-panels": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-2.0.9.tgz", + "integrity": "sha512-ZylBvs7oG7Y/INWw3oYGolqgpFvoPW8MPeg9l1fURDeKpxrmUuCHBUmPj47BdZ11MODImu3kZYXG85rbySab7w==", + "peerDependencies": { + "react": "^16.14.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-router": { "version": "6.21.1", "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.21.1.tgz", @@ -15824,6 +15967,18 @@ "@radix-ui/react-primitive": "1.0.3" } }, + "@radix-ui/react-avatar": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.0.4.tgz", + "integrity": "sha512-kVK2K7ZD3wwj3qhle0ElXhOjbezIgyl2hVvgwfIdexL3rN6zJmy5AqqIf+D31lxVppdzV8CjAfZ6PklkmInZLw==", + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1" + } + }, "@radix-ui/react-checkbox": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.0.4.tgz", @@ -16099,6 +16254,23 @@ "@radix-ui/react-use-controllable-state": "1.0.1" } }, + "@radix-ui/react-scroll-area": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.0.5.tgz", + "integrity": "sha512-b6PAgH4GQf9QEn8zbT2XUHpW5z8BzqEc7Kl11TwDrvuTrxlkcjTD5qa/bxgKr+nmuXKu4L/W5UZ4mlP/VG/5Gw==", + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/number": "1.0.1", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-direction": "1.0.1", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1" + } + }, "@radix-ui/react-select": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.0.0.tgz", @@ -16146,6 +16318,21 @@ "@radix-ui/react-compose-refs": "1.0.1" } }, + "@radix-ui/react-switch": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.0.3.tgz", + "integrity": "sha512-mxm87F88HyHztsI7N+ZUmEoARGkC22YVW5CaC+Byc+HRpuvCrOBPTAnXgf+tZ/7i0Sg/eOePGdMhUKhPaQEqow==", + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-controllable-state": "1.0.1", + "@radix-ui/react-use-previous": "1.0.1", + "@radix-ui/react-use-size": "1.0.1" + } + }, "@radix-ui/react-tabs": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.0.4.tgz", @@ -16182,6 +16369,26 @@ "@radix-ui/react-visually-hidden": "1.0.3" } }, + "@radix-ui/react-tooltip": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.0.7.tgz", + "integrity": "sha512-lPh5iKNFVQ/jav/j6ZrWq3blfDJ0OH9R6FlNUHPMqdLuQ9vwDgFsRxvl8b7Asuy5c8xmoojHUxKHQSOAvMHxyw==", + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.5", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-popper": "1.1.3", + "@radix-ui/react-portal": "1.0.4", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2", + "@radix-ui/react-use-controllable-state": "1.0.1", + "@radix-ui/react-visually-hidden": "1.0.3" + } + }, "@radix-ui/react-use-callback-ref": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz", @@ -20624,6 +20831,12 @@ "yallist": "^3.0.2" } }, + "lucide-react": { + "version": "0.334.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.334.0.tgz", + "integrity": "sha512-y0Rv/Xx6qAq4FutZ3L/efl3O9vl6NC/1p0YOg6mBfRbQ4k1JCE2rz0rnV7WC8Moxq1RY99vLATvjcqUegGJTvA==", + "requires": {} + }, "make-fetch-happen": { "version": "10.2.1", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", @@ -21848,6 +22061,12 @@ "tslib": "^2.0.0" } }, + "react-resizable-panels": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-2.0.9.tgz", + "integrity": "sha512-ZylBvs7oG7Y/INWw3oYGolqgpFvoPW8MPeg9l1fURDeKpxrmUuCHBUmPj47BdZ11MODImu3kZYXG85rbySab7w==", + "requires": {} + }, "react-router": { "version": "6.21.1", "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.21.1.tgz", diff --git a/client-electron/package.json b/client-electron/package.json index 4b16abc..142ce66 100644 --- a/client-electron/package.json +++ b/client-electron/package.json @@ -23,6 +23,7 @@ "dependencies": { "@hookform/resolvers": "^3.3.4", "@postman/node-keytar": "^7.9.3", + "@radix-ui/react-avatar": "^1.0.4", "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dropdown-menu": "^2.0.6", @@ -30,11 +31,14 @@ "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-popover": "^1.0.7", "@radix-ui/react-radio-group": "^1.1.3", + "@radix-ui/react-scroll-area": "^1.0.5", "@radix-ui/react-select": "^2.0.0", "@radix-ui/react-separator": "^1.0.3", "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-switch": "^1.0.3", "@radix-ui/react-tabs": "^1.0.4", "@radix-ui/react-toast": "^1.1.5", + "@radix-ui/react-tooltip": "^1.0.7", "@tanstack/match-sorter-utils": "^8.11.8", "@tanstack/react-query": "^5.17.19", "@tanstack/react-table": "^8.11.7", @@ -60,12 +64,14 @@ "cmdk": "^0.2.0", "date-fns": "^3.3.1", "jszip": "^3.10.1", + "lucide-react": "^0.334.0", "next-themes": "^0.2.1", "react": "^18.2.0", "react-day-picker": "^8.10.0", "react-dom": "^18.2.0", "react-dropzone": "^14.2.3", "react-hook-form": "^7.49.3", + "react-resizable-panels": "^2.0.9", "react-router-dom": "^6.21.1", "sonner": "^1.4.0", "tailwind-merge": "^2.2.1", diff --git a/client-electron/src/App.tsx b/client-electron/src/App.tsx index 2c09dc3..0e2a8a2 100644 --- a/client-electron/src/App.tsx +++ b/client-electron/src/App.tsx @@ -1,26 +1,19 @@ -import { createBrowserRouter, createHashRouter, RouterProvider, type RouteObject } from 'react-router-dom' +import { createBrowserRouter, createHashRouter, RouterProvider, type RouteObject, Navigate } from 'react-router-dom' import AuthCallBack from './AuthCallBack' import MainLayout from './layouts/MainLayout' -import HomePage from './pages/home' import LoginPage from './pages/login' import AndroidPage from './pages/android/android' import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import UploadPage from './pages/upload' import { type MenuList } from './components/sidebar' -import { DashboardIcon, FileTextIcon, RocketIcon, UploadIcon } from '@radix-ui/react-icons' -import SelectCountryPage from './pages/recipes/select-country' +import { FileTextIcon, RocketIcon, UploadIcon } from '@radix-ui/react-icons' import RecipesTablePage from './pages/recipes/recipe-table' const sideBarMenuList: MenuList = [ - { - title: 'Home', - icon: DashboardIcon, - link: '/' - }, { title: 'Recipes', icon: FileTextIcon, - link: '/recipes/select-country' + link: '/recipes' }, { title: 'Android', @@ -41,15 +34,11 @@ function router() { element: , children: [ { - path: '/', - element: + path: '', + element: }, { - path: 'recipes/select-country', - element: - }, - { - path: 'recipes/:country_id/:filename', + path: 'recipes', element: }, { diff --git a/client-electron/src/assets/tao_logo.svg b/client-electron/src/assets/tao_logo.svg new file mode 100644 index 0000000..4d8f190 --- /dev/null +++ b/client-electron/src/assets/tao_logo.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/client-electron/src/components/navbar.tsx b/client-electron/src/components/navbar.tsx index 1458c5f..9914976 100644 --- a/client-electron/src/components/navbar.tsx +++ b/client-electron/src/components/navbar.tsx @@ -14,7 +14,7 @@ import { import { Link } from 'react-router-dom' import userAuthStore from '@/hooks/userAuth' import { Button } from './ui/button' -import Logo from '@/assets/vite.svg' +import Logo from '@/assets/tao_logo.svg' const DropdownMenuUser: React.FC = () => { return ( diff --git a/client-electron/src/components/ui/avatar.tsx b/client-electron/src/components/ui/avatar.tsx new file mode 100644 index 0000000..991f56e --- /dev/null +++ b/client-electron/src/components/ui/avatar.tsx @@ -0,0 +1,48 @@ +import * as React from "react" +import * as AvatarPrimitive from "@radix-ui/react-avatar" + +import { cn } from "@/lib/utils" + +const Avatar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +Avatar.displayName = AvatarPrimitive.Root.displayName + +const AvatarImage = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarImage.displayName = AvatarPrimitive.Image.displayName + +const AvatarFallback = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName + +export { Avatar, AvatarImage, AvatarFallback } diff --git a/client-electron/src/components/ui/resizable.tsx b/client-electron/src/components/ui/resizable.tsx new file mode 100644 index 0000000..35784da --- /dev/null +++ b/client-electron/src/components/ui/resizable.tsx @@ -0,0 +1,43 @@ +import { DragHandleDots2Icon } from "@radix-ui/react-icons" +import * as ResizablePrimitive from "react-resizable-panels" + +import { cn } from "@/lib/utils" + +const ResizablePanelGroup = ({ + className, + ...props +}: React.ComponentProps) => ( + +) + +const ResizablePanel = ResizablePrimitive.Panel + +const ResizableHandle = ({ + withHandle, + className, + ...props +}: React.ComponentProps & { + withHandle?: boolean +}) => ( + div]:rotate-90", + className + )} + {...props} + > + {withHandle && ( +
+ +
+ )} +
+) + +export { ResizablePanelGroup, ResizablePanel, ResizableHandle } diff --git a/client-electron/src/components/ui/scroll-area.tsx b/client-electron/src/components/ui/scroll-area.tsx new file mode 100644 index 0000000..cf253cf --- /dev/null +++ b/client-electron/src/components/ui/scroll-area.tsx @@ -0,0 +1,46 @@ +import * as React from "react" +import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area" + +import { cn } from "@/lib/utils" + +const ScrollArea = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + {children} + + + + +)) +ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName + +const ScrollBar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, orientation = "vertical", ...props }, ref) => ( + + + +)) +ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName + +export { ScrollArea, ScrollBar } diff --git a/client-electron/src/components/ui/switch.tsx b/client-electron/src/components/ui/switch.tsx new file mode 100644 index 0000000..455c23b --- /dev/null +++ b/client-electron/src/components/ui/switch.tsx @@ -0,0 +1,27 @@ +import * as React from "react" +import * as SwitchPrimitives from "@radix-ui/react-switch" + +import { cn } from "@/lib/utils" + +const Switch = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)) +Switch.displayName = SwitchPrimitives.Root.displayName + +export { Switch } diff --git a/client-electron/src/components/ui/textarea.tsx b/client-electron/src/components/ui/textarea.tsx new file mode 100644 index 0000000..d1258e4 --- /dev/null +++ b/client-electron/src/components/ui/textarea.tsx @@ -0,0 +1,24 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +export interface TextareaProps + extends React.TextareaHTMLAttributes {} + +const Textarea = React.forwardRef( + ({ className, ...props }, ref) => { + return ( +