Add library page and daisyUI

This commit is contained in:
chrox
2024-10-01 18:49:40 +02:00
parent 63107506b7
commit 3324540b3f
17 changed files with 398 additions and 100 deletions
+3
View File
@@ -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",
+1
View File
@@ -2,6 +2,7 @@
const config = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
+49
View File
@@ -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"
+3 -1
View File
@@ -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"
@@ -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"
]
}
+1
View File
@@ -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| {
+3 -2
View File
@@ -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": {
+9
View File
@@ -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;
}
+12 -16
View File
@@ -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 (
<html lang='en'>
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
{children}
<head>
<meta
name='viewport'
content='width=device-width, height=device-height, initial-scale=1.0'
/>
</head>
<body>
<EnvProvider>
<AuthProvider>{children}</AuthProvider>
</EnvProvider>
</body>
</html>
);
+64 -30
View File
@@ -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<AppState>('Init');
const [view, setView] = useState<'grid' | 'list'>('grid');
const [books, setBooks] = useState<Book[]>([]);
const [loadingInfo, setLoadingInfo] = useState<string>('');
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 (
<div className={styles['libraryContainer']}>
<div className={styles['viewToggle']}>
<button
onClick={() => setView('grid')}
className={view === 'grid' ? styles['active'] : ''}
>
<button onClick={() => setView('grid')} className={view === 'grid' ? styles['active'] : ''}>
<LayoutGrid />
</button>
<button
onClick={() => setView('list')}
className={view === 'list' ? styles['active'] : ''}
>
<button onClick={() => setView('list')} className={view === 'list' ? styles['active'] : ''}>
<LayoutList />
</button>
</div>
<div className={view === 'grid' ? styles['grid'] : styles['list']}>
{books.map((book, index) => (
<div key={index} className={styles['bookCard']}>
<Image
src={book.thumbnail}
alt={book.title}
width={20}
height={30}
/>
<h3>{book.title}</h3>
{loadingInfo && (
<div>
<span className='loading loading-dots loading-lg'></span>
<p>{loadingInfo}</p>
</div>
)}
{books.length > 0 ? (
<div className={view === 'grid' ? styles['grid'] : styles['list']}>
{books.map((book, index) => (
<div key={index} className={styles['bookCard']}>
<Image src={book.coverImageUrl!} alt={book.title} width={20} height={30} />
<h3>{book.title}</h3>
</div>
))}
</div>
) : (
<div className='hero min-h-screen'>
<div className='hero-content text-neutral-content text-center'>
<div className='max-w-md'>
<h1 className='mb-5 text-5xl font-bold'>Your Library</h1>
<p className='mb-5'>
Welcome to your library. You can upload your books here and read them anytime.
</p>
<button className='btn btn-primary'>Upload Books</button>
</div>
</div>
))}
</div>
</div>
)}
</div>
);
}
};
export default LibraryPage;
@@ -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<AuthContextType | undefined>(undefined);
export const AuthProvider = ({ children }: { children: ReactNode }) => {
const [token, setToken] = useState<string | null>(null);
const login = (newToken: string) => setToken(newToken);
const logout = () => setToken(null);
return <AuthContext.Provider value={{ token, login, logout }}>{children}</AuthContext.Provider>;
};
export const useAuth = (): AuthContextType => {
const context = useContext(AuthContext);
if (!context) throw new Error('useAuth must be used within AuthProvider');
return context;
};
@@ -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<EnvContextType | undefined>(undefined);
export const EnvProvider = ({ children }: { children: ReactNode }) => {
const [envConfig] = useState<EnvConfigType>(env);
return <EnvContext.Provider value={{ envConfig }}>{children}</EnvContext.Provider>;
};
export const useEnv = (): EnvContextType => {
const context = useContext(EnvContext);
if (!context) throw new Error('useEnv must be used within EnvProvider');
return context;
};
+8 -5
View File
@@ -1,11 +1,14 @@
import { AppService } from '../types/system';
import { nativeAppService } from './nativeAppService';
export interface EnvConfigType {
appService: () => Promise<AppService>;
}
const environmentConfig: {
appService: AppService;
} = {
appService: nativeAppService,
const environmentConfig: EnvConfigType = {
appService: async () => {
const { nativeAppService } = await import('./nativeAppService');
return nativeAppService;
},
};
export default environmentConfig;
@@ -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`);
},
};
+7 -21
View File
@@ -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<string | ArrayBuffer>;
writeFile(
path: string,
base: BaseDir,
content: string | ArrayBuffer,
): Promise<void>;
readFile(path: string, base: BaseDir, mode: 'text' | 'binary'): Promise<string | ArrayBuffer>;
writeFile(path: string, base: BaseDir, content: string | ArrayBuffer): Promise<void>;
removeFile(path: string, base: BaseDir): Promise<void>;
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<void>;
removeDir(path: string, base: BaseDir, recursive?: boolean): Promise<void>;
exists(path: string, base: BaseDir): Promise<boolean>;
@@ -32,11 +21,8 @@ export interface AppService {
saveSettings(settings: SystemSettings): Promise<void>;
selectDirectory(title: string): Promise<string>;
selectFiles(name: string, extensions: string[]): Promise<string[]>;
showMessage(
msg: string,
kind?: ToastType,
title?: string,
okLabel?: string,
): Promise<void>;
getCoverUrl(book: Book): string;
showMessage(msg: string, kind?: ToastType, title?: string, okLabel?: string): Promise<void>;
loadLibraryBooks(): Promise<Book[]>;
generateCoverUrl(book: Book): string;
}
+8 -7
View File
@@ -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;
+125 -9
View File
@@ -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