From 3324540b3fcfa1ad414b1795027957bfff4a995b Mon Sep 17 00:00:00 2001 From: chrox Date: Tue, 1 Oct 2024 18:49:40 +0200 Subject: [PATCH] Add library page and daisyUI --- apps/readest-app/package.json | 3 + apps/readest-app/postcss.config.mjs | 1 + apps/readest-app/src-tauri/Cargo.lock | 49 +++++++ apps/readest-app/src-tauri/Cargo.toml | 4 +- .../src-tauri/capabilities/default.json | 19 ++- apps/readest-app/src-tauri/src/lib.rs | 1 + apps/readest-app/src-tauri/tauri.conf.json | 5 +- apps/readest-app/src/app/globals.css | 9 ++ apps/readest-app/src/app/layout.tsx | 28 ++-- apps/readest-app/src/app/page.tsx | 94 ++++++++---- apps/readest-app/src/context/AuthContext.tsx | 26 ++++ apps/readest-app/src/context/EnvContext.tsx | 23 +++ apps/readest-app/src/services/environment.ts | 13 +- .../src/services/nativeAppService.ts | 46 ++++-- apps/readest-app/src/types/system.ts | 28 +--- apps/readest-app/tailwind.config.ts | 15 +- pnpm-lock.yaml | 134 ++++++++++++++++-- 17 files changed, 398 insertions(+), 100 deletions(-) create mode 100644 apps/readest-app/src/context/AuthContext.tsx create mode 100644 apps/readest-app/src/context/EnvContext.tsx diff --git a/apps/readest-app/package.json b/apps/readest-app/package.json index 7b094dd0..3200b469 100644 --- a/apps/readest-app/package.json +++ b/apps/readest-app/package.json @@ -14,6 +14,7 @@ "@tauri-apps/plugin-dialog": "2.0.0-rc.1", "@tauri-apps/plugin-fs": "2.0.0-rc.2", "@tauri-apps/plugin-log": "2.0.0-rc.1", + "@tauri-apps/plugin-os": "2.0.0-rc.1", "epubjs": "^0.3.93", "js-md5": "^0.8.3", "lucide-react": "^0.446.0", @@ -26,6 +27,8 @@ "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", + "autoprefixer": "^10.4.20", + "daisyui": "^4.12.10", "eslint": "^8", "eslint-config-next": "14.2.13", "postcss": "^8", diff --git a/apps/readest-app/postcss.config.mjs b/apps/readest-app/postcss.config.mjs index 1a69fd2a..2ef30fcf 100644 --- a/apps/readest-app/postcss.config.mjs +++ b/apps/readest-app/postcss.config.mjs @@ -2,6 +2,7 @@ const config = { plugins: { tailwindcss: {}, + autoprefixer: {}, }, }; diff --git a/apps/readest-app/src-tauri/Cargo.lock b/apps/readest-app/src-tauri/Cargo.lock index db79469a..e7ca7be5 100644 --- a/apps/readest-app/src-tauri/Cargo.lock +++ b/apps/readest-app/src-tauri/Cargo.lock @@ -1438,6 +1438,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "gethostname" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" +dependencies = [ + "libc", + "windows-targets 0.48.5", +] + [[package]] name = "getrandom" version = "0.1.16" @@ -2455,6 +2465,17 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "os_info" +version = "3.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae99c7fa6dd38c7cafe1ec085e804f8f555a2f8659b0dbe03f1f9963a9b51092" +dependencies = [ + "log", + "serde", + "windows-sys 0.52.0", +] + [[package]] name = "overload" version = "0.1.1" @@ -2968,6 +2989,7 @@ dependencies = [ "tauri-plugin-dialog", "tauri-plugin-fs", "tauri-plugin-log", + "tauri-plugin-os", ] [[package]] @@ -3663,6 +3685,15 @@ dependencies = [ "futures-core", ] +[[package]] +name = "sys-locale" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e801cf239ecd6ccd71f03d270d67dd53d13e90aab208bf4b8fe4ad957ea949b0" +dependencies = [ + "libc", +] + [[package]] name = "system-deps" version = "6.2.2" @@ -3931,6 +3962,24 @@ dependencies = [ "time", ] +[[package]] +name = "tauri-plugin-os" +version = "2.0.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee761edd532fce2232453e9c8e0f7d9c0b6fe125c4b90b3eb4362ee84224" +dependencies = [ + "gethostname", + "log", + "os_info", + "serde", + "serde_json", + "serialize-to-javascript", + "sys-locale", + "tauri", + "tauri-plugin", + "thiserror", +] + [[package]] name = "tauri-runtime" version = "2.0.0-rc.12" diff --git a/apps/readest-app/src-tauri/Cargo.toml b/apps/readest-app/src-tauri/Cargo.toml index f45918f6..e8a7361a 100644 --- a/apps/readest-app/src-tauri/Cargo.toml +++ b/apps/readest-app/src-tauri/Cargo.toml @@ -21,7 +21,9 @@ tauri-build = { version = "2.0.0-rc.12", features = [] } serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } log = "0.4" -tauri = { version = "2.0.0-rc.15", features = ["protocol-asset"] } +# FIXME: remove the devtools feature in production +tauri = { version = "2.0.0-rc.15", features = ["protocol-asset", "devtools"] } tauri-plugin-log = "2.0.0-rc" tauri-plugin-fs = "2.0.0-rc" tauri-plugin-dialog = "2.0.0-rc" +tauri-plugin-os = "2.0.0-rc" diff --git a/apps/readest-app/src-tauri/capabilities/default.json b/apps/readest-app/src-tauri/capabilities/default.json index f4a58551..2a54361b 100644 --- a/apps/readest-app/src-tauri/capabilities/default.json +++ b/apps/readest-app/src-tauri/capabilities/default.json @@ -17,6 +17,23 @@ ], "deny": [] }, - "dialog:default" + { + "identifier": "fs:allow-appdata-read", + "allow": [ + { + "path": "$APPDATA/settings.json" + } + ] + }, + { + "identifier": "fs:allow-appdata-write", + "allow": [ + { + "path": "$APPDATA/settings.json" + } + ] + }, + "dialog:default", + "os:default" ] } \ No newline at end of file diff --git a/apps/readest-app/src-tauri/src/lib.rs b/apps/readest-app/src-tauri/src/lib.rs index ae0aca25..61fd3145 100644 --- a/apps/readest-app/src-tauri/src/lib.rs +++ b/apps/readest-app/src-tauri/src/lib.rs @@ -1,6 +1,7 @@ #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() + .plugin(tauri_plugin_os::init()) .plugin(tauri_plugin_dialog::init()) .plugin(tauri_plugin_fs::init()) .setup(|app| { diff --git a/apps/readest-app/src-tauri/tauri.conf.json b/apps/readest-app/src-tauri/tauri.conf.json index 98c11401..153f6b60 100644 --- a/apps/readest-app/src-tauri/tauri.conf.json +++ b/apps/readest-app/src-tauri/tauri.conf.json @@ -17,11 +17,12 @@ "width": 800, "height": 600, "resizable": true, - "fullscreen": false + "fullscreen": false, + "maximized": true } ], "security": { - "csp": "default-src 'self' ipc: http://ipc.localhost; img-src 'self' asset: http://asset.localhost", + "csp": "default-src 'self' ipc: http://ipc.localhost; img-src 'self' data: asset: http://asset.localhost", "assetProtocol": { "enable": true, "scope": { diff --git a/apps/readest-app/src/app/globals.css b/apps/readest-app/src/app/globals.css index 13d40b89..398d8776 100644 --- a/apps/readest-app/src/app/globals.css +++ b/apps/readest-app/src/app/globals.css @@ -25,3 +25,12 @@ body { text-wrap: balance; } } + +/* Hide scrollbar for Chrome, Safari and Opera */ +::-webkit-scrollbar { + display: none; +} +/* Hide scrollbar for IE and Edge */ +*{ + -ms-overflow-style: none; +} \ No newline at end of file diff --git a/apps/readest-app/src/app/layout.tsx b/apps/readest-app/src/app/layout.tsx index 47c63092..132d8fd2 100644 --- a/apps/readest-app/src/app/layout.tsx +++ b/apps/readest-app/src/app/layout.tsx @@ -1,18 +1,8 @@ import type { Metadata } from 'next'; -import localFont from 'next/font/local'; +import { AuthProvider } from '../context/AuthContext'; +import { EnvProvider } from '../context/EnvContext'; import './globals.css'; -const geistSans = localFont({ - src: './fonts/GeistVF.woff', - variable: '--font-geist-sans', - weight: '100 900', -}); -const geistMono = localFont({ - src: './fonts/GeistMonoVF.woff', - variable: '--font-geist-mono', - weight: '100 900', -}); - export const metadata: Metadata = { title: 'Readest', description: 'read to learn', @@ -25,10 +15,16 @@ export default function RootLayout({ }>) { return ( - - {children} + + + + + + {children} + ); diff --git a/apps/readest-app/src/app/page.tsx b/apps/readest-app/src/app/page.tsx index 0392e14d..bfd400fc 100644 --- a/apps/readest-app/src/app/page.tsx +++ b/apps/readest-app/src/app/page.tsx @@ -4,49 +4,83 @@ import * as React from 'react'; import { useState } from 'react'; import Image from 'next/image'; import { LayoutGrid, LayoutList } from 'lucide-react'; +import { Book } from '../types/book'; +import { useEnv } from '../context/EnvContext'; import styles from './library.module.css'; -const BOOKS_DIR = '/Users/chrox/Documents/DigestLibrary/books'; +type AppState = 'Init' | 'Loading' | 'Library' | 'Reader'; -const books = [ - { title: 'Book 1', thumbnail: `asset://localhost/${BOOKS_DIR}/book1.png` }, - { title: 'Book 2', thumbnail: `asset://localhost/${BOOKS_DIR}/book2.png` }, - { title: 'Book 3', thumbnail: `asset://localhost/${BOOKS_DIR}/book3.png` }, -]; - -export default function LibraryPage() { +const LibraryPage = () => { + const { envConfig } = useEnv(); + const [appState, setAppState] = useState('Init'); const [view, setView] = useState<'grid' | 'list'>('grid'); + const [books, setBooks] = useState([]); + const [loadingInfo, setLoadingInfo] = useState(''); + + React.useEffect(() => { + if (appState !== 'Init') return; + setAppState('Loading'); + setLoadingInfo('Loading library books...'); + envConfig.appService().then((appService) => { + appService.loadSettings().then((settings) => { + console.log('Settings', settings); + appService + .loadLibraryBooks() + .then((books) => { + console.log('Library books:', books); + setBooks(books); + setAppState('Library'); + setLoadingInfo(''); + }) + .catch((err) => { + console.error(err); + setLoadingInfo(''); + appService.showMessage('Failed to load library books', 'error'); + }); + }); + }); + }, [envConfig, appState]); return (
- -
- -
- {books.map((book, index) => ( -
- {book.title} -

{book.title}

+ {loadingInfo && ( +
+ +

{loadingInfo}

+
+ )} + {books.length > 0 ? ( +
+ {books.map((book, index) => ( +
+ {book.title} +

{book.title}

+
+ ))} +
+ ) : ( +
+
+
+

Your Library

+

+ Welcome to your library. You can upload your books here and read them anytime. +

+ +
- ))} -
+
+ )}
); -} +}; + +export default LibraryPage; diff --git a/apps/readest-app/src/context/AuthContext.tsx b/apps/readest-app/src/context/AuthContext.tsx new file mode 100644 index 00000000..f072f6e1 --- /dev/null +++ b/apps/readest-app/src/context/AuthContext.tsx @@ -0,0 +1,26 @@ +'use client'; + +import React, { createContext, useState, useContext, ReactNode } from 'react'; + +interface AuthContextType { + token: string | null; + login: (token: string) => void; + logout: () => void; +} + +const AuthContext = createContext(undefined); + +export const AuthProvider = ({ children }: { children: ReactNode }) => { + const [token, setToken] = useState(null); + + const login = (newToken: string) => setToken(newToken); + const logout = () => setToken(null); + + return {children}; +}; + +export const useAuth = (): AuthContextType => { + const context = useContext(AuthContext); + if (!context) throw new Error('useAuth must be used within AuthProvider'); + return context; +}; diff --git a/apps/readest-app/src/context/EnvContext.tsx b/apps/readest-app/src/context/EnvContext.tsx new file mode 100644 index 00000000..ad31270f --- /dev/null +++ b/apps/readest-app/src/context/EnvContext.tsx @@ -0,0 +1,23 @@ +'use client'; + +import React, { createContext, useContext, useState, ReactNode } from 'react'; +import { EnvConfigType } from '../services/environment'; +import env from '../services/environment'; + +interface EnvContextType { + envConfig: EnvConfigType; +} + +const EnvContext = createContext(undefined); + +export const EnvProvider = ({ children }: { children: ReactNode }) => { + const [envConfig] = useState(env); + + return {children}; +}; + +export const useEnv = (): EnvContextType => { + const context = useContext(EnvContext); + if (!context) throw new Error('useEnv must be used within EnvProvider'); + return context; +}; diff --git a/apps/readest-app/src/services/environment.ts b/apps/readest-app/src/services/environment.ts index 9f4b7d08..eff59610 100644 --- a/apps/readest-app/src/services/environment.ts +++ b/apps/readest-app/src/services/environment.ts @@ -1,11 +1,14 @@ import { AppService } from '../types/system'; -import { nativeAppService } from './nativeAppService'; +export interface EnvConfigType { + appService: () => Promise; +} -const environmentConfig: { - appService: AppService; -} = { - appService: nativeAppService, +const environmentConfig: EnvConfigType = { + appService: async () => { + const { nativeAppService } = await import('./nativeAppService'); + return nativeAppService; + }, }; export default environmentConfig; diff --git a/apps/readest-app/src/services/nativeAppService.ts b/apps/readest-app/src/services/nativeAppService.ts index 53258a86..0c759796 100644 --- a/apps/readest-app/src/services/nativeAppService.ts +++ b/apps/readest-app/src/services/nativeAppService.ts @@ -9,7 +9,15 @@ import { remove, BaseDirectory, } from '@tauri-apps/plugin-fs'; -import { appConfigDir, appDataDir, appCacheDir, appLogDir } from '@tauri-apps/api/path'; +import { type as osType } from '@tauri-apps/plugin-os'; +import { + join, + appConfigDir, + appDataDir, + appCacheDir, + appLogDir, + documentDir, +} from '@tauri-apps/api/path'; import { convertFileSrc } from '@tauri-apps/api/core'; import { open, message } from '@tauri-apps/plugin-dialog'; @@ -17,7 +25,9 @@ import { Book } from '../types/book'; import { SystemSettings } from '../types/settings'; import { AppService, BaseDir, ToastType } from '../types/system'; -let BOOKS_DIR: string; +const IS_MOBILE = osType() === 'ios' || osType() === 'android'; +const BOOKS_SUBDIR = 'DigestLibrary/Books'; +let BOOKS_DIR = ''; function resolvePath( fp: string, @@ -34,8 +44,8 @@ function resolvePath( return { baseDir: BaseDirectory.AppLog, fp, base, dir: appLogDir }; case 'Books': return { - baseDir: BaseDirectory.Document, - fp: `${BOOKS_DIR}/${fp}`, + baseDir: IS_MOBILE ? BaseDirectory.AppData : BaseDirectory.Document, + fp: `${BOOKS_SUBDIR}/${fp}`, base, dir: () => new Promise((r) => r(`${BOOKS_DIR}/`)), }; @@ -113,8 +123,12 @@ export const nativeAppService: AppService = { const txt = await nativeAppService.fs.readFile(fp, base, 'text'); settings = JSON.parse(txt as string); } catch { + const INIT_BOOKS_DIR = await join( + IS_MOBILE ? await appDataDir() : await documentDir(), + BOOKS_SUBDIR, + ); settings = { - localBooksDir: '', + localBooksDir: INIT_BOOKS_DIR, globalReadSettings: { themeType: 'auto', fontFamily: '', @@ -124,7 +138,7 @@ export const nativeAppService: AppService = { }, }; - await nativeAppService.fs.createDir(fp, base, true); + await nativeAppService.fs.createDir('', base, true); await nativeAppService.fs.writeFile(fp, base, JSON.stringify(settings)); } @@ -133,7 +147,7 @@ export const nativeAppService: AppService = { }, saveSettings: async (settings: SystemSettings) => { const { fp, base } = SETTINGS_PATH; - await nativeAppService.fs.createDir(fp, base, true); + await nativeAppService.fs.createDir('', base, true); await nativeAppService.fs.writeFile(fp, base, JSON.stringify(settings)); BOOKS_DIR = settings.localBooksDir; }, @@ -162,7 +176,23 @@ export const nativeAppService: AppService = { showMessage: async (msg: string, kind: ToastType = 'info', title?: string, okLabel?: string) => { await message(msg, { kind, title, okLabel }); }, - getCoverUrl: (book: Book) => { + + loadLibraryBooks: async () => { + let books: Book[] = []; + try { + const txt = await nativeAppService.fs.readFile('books.json', 'Books', 'text'); + books = JSON.parse(txt as string); + } catch { + await nativeAppService.fs.writeFile('books.json', 'Books', '[]'); + } + + books.forEach((book) => { + book.coverImageUrl = nativeAppService.generateCoverUrl(book); + }); + + return books; + }, + generateCoverUrl: (book: Book) => { return convertFileSrc(`${BOOKS_DIR}/${book.id}/cover.png`); }, }; diff --git a/apps/readest-app/src/types/system.ts b/apps/readest-app/src/types/system.ts index 8e2943bb..460df23e 100644 --- a/apps/readest-app/src/types/system.ts +++ b/apps/readest-app/src/types/system.ts @@ -5,21 +5,10 @@ export type BaseDir = 'Books' | 'Settings' | 'Data' | 'Log' | 'Cache' | 'None'; export type ToastType = 'info' | 'warning' | 'error'; export interface FileSystem { - readFile( - path: string, - base: BaseDir, - mode: 'text' | 'binary', - ): Promise; - writeFile( - path: string, - base: BaseDir, - content: string | ArrayBuffer, - ): Promise; + readFile(path: string, base: BaseDir, mode: 'text' | 'binary'): Promise; + writeFile(path: string, base: BaseDir, content: string | ArrayBuffer): Promise; removeFile(path: string, base: BaseDir): Promise; - readDir( - path: string, - base: BaseDir, - ): Promise<{ path: string; isDir: boolean }[]>; + readDir(path: string, base: BaseDir): Promise<{ path: string; isDir: boolean }[]>; createDir(path: string, base: BaseDir, recursive?: boolean): Promise; removeDir(path: string, base: BaseDir, recursive?: boolean): Promise; exists(path: string, base: BaseDir): Promise; @@ -32,11 +21,8 @@ export interface AppService { saveSettings(settings: SystemSettings): Promise; selectDirectory(title: string): Promise; selectFiles(name: string, extensions: string[]): Promise; - showMessage( - msg: string, - kind?: ToastType, - title?: string, - okLabel?: string, - ): Promise; - getCoverUrl(book: Book): string; + showMessage(msg: string, kind?: ToastType, title?: string, okLabel?: string): Promise; + + loadLibraryBooks(): Promise; + generateCoverUrl(book: Book): string; } diff --git a/apps/readest-app/tailwind.config.ts b/apps/readest-app/tailwind.config.ts index 021c3937..ae9c9bbb 100644 --- a/apps/readest-app/tailwind.config.ts +++ b/apps/readest-app/tailwind.config.ts @@ -1,19 +1,20 @@ -import type { Config } from "tailwindcss"; +import type { Config } from 'tailwindcss'; +import daisyui from 'daisyui'; const config: Config = { content: [ - "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", - "./src/components/**/*.{js,ts,jsx,tsx,mdx}", - "./src/app/**/*.{js,ts,jsx,tsx,mdx}", + './src/pages/**/*.{js,ts,jsx,tsx,mdx}', + './src/components/**/*.{js,ts,jsx,tsx,mdx}', + './src/app/**/*.{js,ts,jsx,tsx,mdx}', ], theme: { extend: { colors: { - background: "var(--background)", - foreground: "var(--foreground)", + background: 'var(--background)', + foreground: 'var(--foreground)', }, }, }, - plugins: [], + plugins: [daisyui], }; export default config; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0a03fdc0..5639dff4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -47,6 +47,9 @@ importers: '@tauri-apps/plugin-log': specifier: 2.0.0-rc.1 version: 2.0.0-rc.1 + '@tauri-apps/plugin-os': + specifier: 2.0.0-rc.1 + version: 2.0.0-rc.1 epubjs: specifier: ^0.3.93 version: 0.3.93 @@ -78,6 +81,12 @@ importers: '@types/react-dom': specifier: ^18 version: 18.3.0 + autoprefixer: + specifier: ^10.4.20 + version: 10.4.20(postcss@8.4.47) + daisyui: + specifier: ^4.12.10 + version: 4.12.13(postcss@8.4.47) eslint: specifier: ^8 version: 8.57.1 @@ -341,6 +350,9 @@ packages: '@tauri-apps/plugin-log@2.0.0-rc.1': resolution: {integrity: sha512-+Tz0zo4FDtC/5j7neeIq5ievgKbUXBV2+X5HtbaR8ZZ2bcksCp8UqeHd6cyyN+FSk4qaU01LIGkuExtxk1h/FA==} + '@tauri-apps/plugin-os@2.0.0-rc.1': + resolution: {integrity: sha512-PV8zlSTmYfiN2xzILUmlDSEycS7UYbH2yXk/ZqF+qQU6/s+OVQvmSth4EhllFjcpvPbtqELvpzfjw+2qEouchA==} + '@tsconfig/node10@1.0.11': resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} @@ -523,6 +535,13 @@ packages: ast-types-flow@0.0.8: resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} + autoprefixer@10.4.20: + resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -552,6 +571,11 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} + browserslist@4.24.0: + resolution: {integrity: sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + busboy@1.6.0: resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} engines: {node: '>=10.16.0'} @@ -614,6 +638,9 @@ packages: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} + css-selector-tokenizer@0.8.0: + resolution: {integrity: sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==} + cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -622,10 +649,18 @@ packages: csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + culori@3.3.0: + resolution: {integrity: sha512-pHJg+jbuFsCjz9iclQBqyL3B2HLCBF71BwVNujUYEvCeQMvV97R59MNK3R2+jgJ3a1fcZgI9B3vYgz8lzr/BFQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + d@1.0.2: resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==} engines: {node: '>=0.12'} + daisyui@4.12.13: + resolution: {integrity: sha512-BnXyQoOByUF/7wSdIKubyhXxbtL8gxwY3u2cNMkxGP39TSVJqMmlItqtpY903fQnLI/NokC+bc+ZV+PEPsppPw==} + engines: {node: '>=16.9.0'} + damerau-levenshtein@1.0.8: resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} @@ -694,6 +729,9 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + electron-to-chromium@1.5.36: + resolution: {integrity: sha512-HYTX8tKge/VNp6FGO+f/uVDmUkq+cEfcxYhKf15Akc4M5yxt5YmorwlAitKWjWhWQnKcDRBAQKXkhqqXMqcrjw==} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -752,6 +790,10 @@ packages: resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==} engines: {node: '>=0.12'} + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} @@ -892,6 +934,9 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + fastparse@1.1.2: + resolution: {integrity: sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==} + fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} @@ -921,6 +966,9 @@ packages: resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} engines: {node: '>=14'} + fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -1333,10 +1381,17 @@ packages: sass: optional: true + node-releases@2.0.18: + resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} + normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} + normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -1848,6 +1903,12 @@ packages: undici-types@6.19.8: resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + update-browserslist-db@1.1.1: + resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -2101,6 +2162,10 @@ snapshots: dependencies: '@tauri-apps/api': 2.0.0-rc.5 + '@tauri-apps/plugin-os@2.0.0-rc.1': + dependencies: + '@tauri-apps/api': 2.0.0-rc.5 + '@tsconfig/node10@1.0.11': optional: true @@ -2332,6 +2397,16 @@ snapshots: ast-types-flow@0.0.8: {} + autoprefixer@10.4.20(postcss@8.4.47): + dependencies: + browserslist: 4.24.0 + caniuse-lite: 1.0.30001663 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.1.0 + postcss: 8.4.47 + postcss-value-parser: 4.2.0 + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.0.0 @@ -2357,6 +2432,13 @@ snapshots: dependencies: fill-range: 7.1.1 + browserslist@4.24.0: + dependencies: + caniuse-lite: 1.0.30001663 + electron-to-chromium: 1.5.36 + node-releases: 2.0.18 + update-browserslist-db: 1.1.1(browserslist@4.24.0) + busboy@1.6.0: dependencies: streamsearch: 1.1.0 @@ -2421,15 +2503,31 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + css-selector-tokenizer@0.8.0: + dependencies: + cssesc: 3.0.0 + fastparse: 1.1.2 + cssesc@3.0.0: {} csstype@3.1.3: {} + culori@3.3.0: {} + d@1.0.2: dependencies: es5-ext: 0.10.64 type: 2.7.3 + daisyui@4.12.13(postcss@8.4.47): + dependencies: + css-selector-tokenizer: 0.8.0 + culori: 3.3.0 + picocolors: 1.1.0 + postcss-js: 4.0.1(postcss@8.4.47) + transitivePeerDependencies: + - postcss + damerau-levenshtein@1.0.8: {} data-view-buffer@1.0.1: @@ -2510,6 +2608,8 @@ snapshots: eastasianwidth@0.2.0: {} + electron-to-chromium@1.5.36: {} + emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -2653,6 +2753,8 @@ snapshots: d: 1.0.2 ext: 1.7.0 + escalade@3.2.0: {} + escape-string-regexp@4.0.0: {} eslint-config-next@14.2.13(eslint@8.57.1)(typescript@5.6.2): @@ -2663,8 +2765,8 @@ snapshots: '@typescript-eslint/parser': 8.7.0(eslint@8.57.1)(typescript@5.6.2) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1))(eslint@8.57.1) - eslint-plugin-import: 2.30.0(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.57.1) + eslint-plugin-import: 2.30.0(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) eslint-plugin-jsx-a11y: 6.10.0(eslint@8.57.1) eslint-plugin-react: 7.36.1(eslint@8.57.1) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.1) @@ -2687,37 +2789,37 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1))(eslint@8.57.1): + eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.57.1): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.3.7 enhanced-resolve: 5.17.1 eslint: 8.57.1 - eslint-module-utils: 2.11.1(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.11.1(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) fast-glob: 3.3.2 get-tsconfig: 4.8.1 is-bun-module: 1.2.1 is-glob: 4.0.3 optionalDependencies: - eslint-plugin-import: 2.30.0(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-plugin-import: 2.30.0(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) transitivePeerDependencies: - '@typescript-eslint/parser' - eslint-import-resolver-node - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.11.1(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): + eslint-module-utils@2.11.1(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.7.0(eslint@8.57.1)(typescript@5.6.2) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1))(eslint@8.57.1) + eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.57.1) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.30.0(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): + eslint-plugin-import@2.30.0(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -2728,7 +2830,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.11.1(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.11.1(@typescript-eslint/parser@8.7.0(eslint@8.57.1)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) hasown: 2.0.2 is-core-module: 2.15.1 is-glob: 4.0.3 @@ -2889,6 +2991,8 @@ snapshots: fast-levenshtein@2.0.6: {} + fastparse@1.1.2: {} + fastq@1.17.1: dependencies: reusify: 1.0.4 @@ -2923,6 +3027,8 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 + fraction.js@4.3.7: {} + fs.realpath@1.0.0: {} fsevents@2.3.3: @@ -3335,8 +3441,12 @@ snapshots: - '@babel/core' - babel-plugin-macros + node-releases@2.0.18: {} + normalize-path@3.0.0: {} + normalize-range@0.1.2: {} + object-assign@4.1.1: {} object-hash@3.0.0: {} @@ -3858,6 +3968,12 @@ snapshots: undici-types@6.19.8: {} + update-browserslist-db@1.1.1(browserslist@4.24.0): + dependencies: + browserslist: 4.24.0 + escalade: 3.2.0 + picocolors: 1.1.0 + uri-js@4.4.1: dependencies: punycode: 2.3.1