chore: migrate to new flowbite-react

This commit is contained in:
Kentai Radiquum 2025-04-04 00:29:19 +05:00
parent 8daab3b3c1
commit 329448c9fc
Signed by: Radiquum
GPG key ID: 858E8EE696525EED
32 changed files with 650 additions and 344 deletions

2
.flowbite-react/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
class-list.json
pid

View file

@ -0,0 +1,9 @@
{
"$schema": "https://unpkg.com/flowbite-react/schema.json",
"components": [],
"dark": true,
"prefix": "",
"path": "src/components",
"tsx": true,
"rsc": true
}

View file

@ -4,7 +4,7 @@ import { usePreferencesStore } from "./store/preferences";
import { Navbar } from "./components/Navbar/NavbarUpdate"; import { Navbar } from "./components/Navbar/NavbarUpdate";
import { Inter } from "next/font/google"; import { Inter } from "next/font/google";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { Button, Modal } from "flowbite-react"; import { Button, Modal, ModalBody, ModalFooter, ModalHeader } from "flowbite-react";
import { Spinner } from "./components/Spinner/Spinner"; import { Spinner } from "./components/Spinner/Spinner";
import { ChangelogModal } from "#/components/ChangelogModal/ChangelogModal"; import { ChangelogModal } from "#/components/ChangelogModal/ChangelogModal";
import PlausibleProvider from "next-plausible"; import PlausibleProvider from "next-plausible";
@ -80,8 +80,8 @@ export const App = (props) => {
show={preferencesStore.params.isFirstLaunch} show={preferencesStore.params.isFirstLaunch}
onClose={() => preferencesStore.setParams({ isFirstLaunch: false })} onClose={() => preferencesStore.setParams({ isFirstLaunch: false })}
> >
<Modal.Header>Внимание</Modal.Header> <ModalHeader>Внимание</ModalHeader>
<Modal.Body> <ModalBody>
<p> <p>
Данный сайт не связан с разработчиками приложения Anixart, это Данный сайт не связан с разработчиками приложения Anixart, это
неофициальная имплементация веб клиента для этого приложения. неофициальная имплементация веб клиента для этого приложения.
@ -94,15 +94,15 @@ export const App = (props) => {
На сайте могут присутствовать ошибки и не доработки, а так-же На сайте могут присутствовать ошибки и не доработки, а так-же
отсутствующий функционал. отсутствующий функционал.
</p> </p>
</Modal.Body> </ModalBody>
<Modal.Footer> <ModalFooter>
<Button <Button
color={"blue"} color={"blue"}
onClick={() => preferencesStore.setParams({ isFirstLaunch: false })} onClick={() => preferencesStore.setParams({ isFirstLaunch: false })}
> >
Принимаю Принимаю
</Button> </Button>
</Modal.Footer> </ModalFooter>
</Modal> </Modal>
{preferencesStore.flags.enableAnalytics && ( {preferencesStore.flags.enableAnalytics && (
<PlausibleProvider <PlausibleProvider

View file

@ -1,6 +1,14 @@
"use client"; "use client";
import { Modal, Accordion } from "flowbite-react"; import {
Accordion,
AccordionContent,
AccordionPanel,
AccordionTitle,
Modal,
ModalBody,
ModalHeader,
} from "flowbite-react";
import Markdown from "markdown-to-jsx"; import Markdown from "markdown-to-jsx";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import Styles from "./ChangelogModal.module.css"; import Styles from "./ChangelogModal.module.css";
@ -37,8 +45,8 @@ export const ChangelogModal = (props: {
return ( return (
<Modal show={props.isOpen} onClose={() => props.setIsOpen(false)}> <Modal show={props.isOpen} onClose={() => props.setIsOpen(false)}>
<Modal.Header>Список изменений v{props.version}</Modal.Header> <ModalHeader>Список изменений v{props.version}</ModalHeader>
<Modal.Body> <ModalBody>
<Markdown className={Styles.markdown}> <Markdown className={Styles.markdown}>
{currentVersionChangelog} {currentVersionChangelog}
</Markdown> </Markdown>
@ -46,8 +54,8 @@ export const ChangelogModal = (props: {
{props.previousVersions.length > 0 && {props.previousVersions.length > 0 &&
props.previousVersions.map((version) => { props.previousVersions.map((version) => {
return ( return (
<Accordion.Panel key={version}> <AccordionPanel key={version}>
<Accordion.Title <AccordionTitle
onClickCapture={(e) => { onClickCapture={(e) => {
if (!previousVersionsChangelog.hasOwnProperty(version)) { if (!previousVersionsChangelog.hasOwnProperty(version)) {
_fetchVersionChangelog(version).then((data) => { _fetchVersionChangelog(version).then((data) => {
@ -62,19 +70,19 @@ export const ChangelogModal = (props: {
}} }}
> >
Список изменений v{version} Список изменений v{version}
</Accordion.Title> </AccordionTitle>
<Accordion.Content> <AccordionContent>
{previousVersionsChangelog.hasOwnProperty(version) ? {previousVersionsChangelog.hasOwnProperty(version) ?
<Markdown className={Styles.markdown}> <Markdown className={Styles.markdown}>
{previousVersionsChangelog[version]} {previousVersionsChangelog[version]}
</Markdown> </Markdown>
: <div>Загрузка ...</div>} : <div>Загрузка ...</div>}
</Accordion.Content> </AccordionContent>
</Accordion.Panel> </AccordionPanel>
); );
})} })}
</Accordion> </Accordion>
</Modal.Body> </ModalBody>
</Modal> </Modal>
); );
}; };

View file

@ -1,4 +1,4 @@
import { Button, Modal, ToggleSwitch, Label, Textarea } from "flowbite-react"; import { Button, Label, Modal, ModalBody, ModalHeader, Textarea, ToggleSwitch } from "flowbite-react";
import { CommentsComment } from "./Comments.Comment"; import { CommentsComment } from "./Comments.Comment";
import { useState } from "react"; import { useState } from "react";
import { ENDPOINTS } from "#/api/config"; import { ENDPOINTS } from "#/api/config";
@ -68,12 +68,12 @@ export const CommentsAddModal = (props: {
show={props.isOpen} show={props.isOpen}
onClose={() => props.setIsOpen(false)} onClose={() => props.setIsOpen(false)}
> >
<Modal.Header> <ModalHeader>
<p className="text-lg font-bold text-gray-900 lg:text-2xl dark:text-white"> <p className="text-lg font-bold text-gray-900 lg:text-2xl dark:text-white">
{props.isReply ? "Ответ на комментарий" : "Оставить комментарий"} {props.isReply ? "Ответ на комментарий" : "Оставить комментарий"}
</p> </p>
</Modal.Header> </ModalHeader>
<Modal.Body> <ModalBody>
{props.isReply && ( {props.isReply && (
<div className="mb-4"> <div className="mb-4">
<CommentsComment <CommentsComment
@ -98,7 +98,7 @@ export const CommentsAddModal = (props: {
<form className="flex flex-col gap-4" onSubmit={(e) => _sendComment(e)}> <form className="flex flex-col gap-4" onSubmit={(e) => _sendComment(e)}>
<div> <div>
<div className="block mb-2 sr-only"> <div className="block mb-2 sr-only">
<Label htmlFor="comment" value="Ваш комментарий." /> <Label htmlFor="comment">Ваш комментарий.</Label>
</div> </div>
<Textarea <Textarea
id="comment" id="comment"
@ -132,7 +132,7 @@ export const CommentsAddModal = (props: {
</Button> </Button>
</div> </div>
</form> </form>
</Modal.Body> </ModalBody>
</Modal> </Modal>
); );
}; };

View file

@ -1,7 +1,7 @@
import { unixToDate, sinceUnixDate } from "#/api/utils"; import { unixToDate, sinceUnixDate } from "#/api/utils";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { ENDPOINTS } from "#/api/config"; import { ENDPOINTS } from "#/api/config";
import { Button, Dropdown } from "flowbite-react"; import { Button, Dropdown, DropdownItem } from "flowbite-react";
import Link from "next/link"; import Link from "next/link";
import { CommentsAddModal } from "./Comments.Add"; import { CommentsAddModal } from "./Comments.Add";
import { CommentsEditModal } from "./Comments.Edit"; import { CommentsEditModal } from "./Comments.Edit";
@ -183,12 +183,12 @@ export const CommentsComment = (props: {
<span className="w-6 h-6 bg-gray-400 iconify mdi--more-horiz hover:bg-gray-800 active:bg-gray-800"></span> <span className="w-6 h-6 bg-gray-400 iconify mdi--more-horiz hover:bg-gray-800 active:bg-gray-800"></span>
)} )}
> >
<Dropdown.Item onClick={() => setIsEditCommentsOpen(true)}> <DropdownItem onClick={() => setIsEditCommentsOpen(true)}>
Редактировать Редактировать
</Dropdown.Item> </DropdownItem>
<Dropdown.Item onClick={() => _deleteComment()}> <DropdownItem onClick={() => _deleteComment()}>
Удалить Удалить
</Dropdown.Item> </DropdownItem>
</Dropdown> </Dropdown>
)} )}
</footer> </footer>

View file

@ -1,4 +1,4 @@
import { Button, Modal, ToggleSwitch, Label, Textarea } from "flowbite-react"; import { Button, Label, Modal, ModalBody, ModalHeader, Textarea, ToggleSwitch } from "flowbite-react";
import { useState } from "react"; import { useState } from "react";
import { ENDPOINTS } from "#/api/config"; import { ENDPOINTS } from "#/api/config";
@ -56,16 +56,16 @@ export const CommentsEditModal = (props: {
show={props.isOpen} show={props.isOpen}
onClose={() => props.setIsOpen(false)} onClose={() => props.setIsOpen(false)}
> >
<Modal.Header> <ModalHeader>
<p className="text-lg font-bold text-gray-900 lg:text-2xl dark:text-white"> <p className="text-lg font-bold text-gray-900 lg:text-2xl dark:text-white">
Редактировать комментарий Редактировать комментарий
</p> </p>
</Modal.Header> </ModalHeader>
<Modal.Body> <ModalBody>
<form className="flex flex-col gap-4" onSubmit={(e) => _sendComment(e)}> <form className="flex flex-col gap-4" onSubmit={(e) => _sendComment(e)}>
<div> <div>
<div className="block mb-2 sr-only"> <div className="block mb-2 sr-only">
<Label htmlFor="comment" value="Редактировать ваш комментарий." /> <Label htmlFor="comment" >Редактировать ваш комментарий.</Label>
</div> </div>
<Textarea <Textarea
id="comment" id="comment"
@ -99,7 +99,7 @@ export const CommentsEditModal = (props: {
</Button> </Button>
</div> </div>
</form> </form>
</Modal.Body> </ModalBody>
</Modal> </Modal>
); );
}; };

View file

@ -1,4 +1,4 @@
import { Card, Button, Modal, Spinner } from "flowbite-react"; import { Button, Card, Modal, ModalHeader, Spinner } from "flowbite-react";
import { CommentsComment } from "./Comments.Comment"; import { CommentsComment } from "./Comments.Comment";
import { useState, useEffect, useCallback } from "react"; import { useState, useEffect, useCallback } from "react";
import { ENDPOINTS } from "#/api/config"; import { ENDPOINTS } from "#/api/config";
@ -149,7 +149,7 @@ const CommentsAllModal = (props: {
show={props.isOpen} show={props.isOpen}
onClose={() => props.setIsOpen(false)} onClose={() => props.setIsOpen(false)}
> >
<Modal.Header> <ModalHeader>
<div className="flex flex-col gap-1"> <div className="flex flex-col gap-1">
<h2 className="text-lg font-bold text-gray-900 lg:text-2xl dark:text-white"> <h2 className="text-lg font-bold text-gray-900 lg:text-2xl dark:text-white">
Все комментарии Все комментарии
@ -158,7 +158,7 @@ const CommentsAllModal = (props: {
всего: {isLoading ? "загрузка..." : data[0].total_count} всего: {isLoading ? "загрузка..." : data[0].total_count}
</p> </p>
</div> </div>
</Modal.Header> </ModalHeader>
<div <div
className="flex flex-col gap-2 p-4 overflow-y-auto" className="flex flex-col gap-2 p-4 overflow-y-auto"
onScroll={handleScroll} onScroll={handleScroll}

View file

@ -1,7 +1,7 @@
import React, { useRef } from "react"; import React, { useRef } from "react";
import Cropper, { ReactCropperElement } from "react-cropper"; import Cropper, { ReactCropperElement } from "react-cropper";
import "cropperjs/dist/cropper.css"; import "cropperjs/dist/cropper.css";
import { Button, Modal } from "flowbite-react"; import { Button, Modal, ModalBody, ModalFooter, ModalHeader } from "flowbite-react";
type CropModalProps = { type CropModalProps = {
isOpen: boolean; isOpen: boolean;
@ -71,8 +71,8 @@ export const CropModal: React.FC<CropModalProps> = ({
}} }}
size={"7xl"} size={"7xl"}
> >
<Modal.Header>Обрезать изображение</Modal.Header> <ModalHeader>Обрезать изображение</ModalHeader>
<Modal.Body> <ModalBody>
<Cropper <Cropper
src={selectedImage} src={selectedImage}
style={{ height: 400, width: "100%" }} style={{ height: 400, width: "100%" }}
@ -95,8 +95,8 @@ export const CropModal: React.FC<CropModalProps> = ({
</p> </p>
<p>Используйте колёсико мыши что-бы изменить масштаб</p> <p>Используйте колёсико мыши что-бы изменить масштаб</p>
</div> </div>
</Modal.Body> </ModalBody>
<Modal.Footer> <ModalFooter>
<Button <Button
color={"blue"} color={"blue"}
disabled={isActionsDisabled} disabled={isActionsDisabled}
@ -120,7 +120,7 @@ export const CropModal: React.FC<CropModalProps> = ({
> >
Отменить Отменить
</Button> </Button>
</Modal.Footer> </ModalFooter>
</Modal> </Modal>
); );
}; };

View file

@ -1,6 +1,6 @@
import { ENDPOINTS } from "#/api/config"; import { ENDPOINTS } from "#/api/config";
import { tryCatchAPI, unixToDate, useSWRfetcher } from "#/api/utils"; import { tryCatchAPI, unixToDate, useSWRfetcher } from "#/api/utils";
import { Avatar, Button, Modal, useThemeMode } from "flowbite-react"; import { Avatar, Button, Modal, ModalHeader, useThemeMode } from "flowbite-react";
import { useCallback, useEffect, useState } from "react"; import { useCallback, useEffect, useState } from "react";
import useSWRInfinite from "swr/infinite"; import useSWRInfinite from "swr/infinite";
import { Spinner } from "../Spinner/Spinner"; import { Spinner } from "../Spinner/Spinner";
@ -130,7 +130,7 @@ export const ProfileBlockedUsersModal = (props: {
onClose={() => props.setIsOpen(false)} onClose={() => props.setIsOpen(false)}
size={"7xl"} size={"7xl"}
> >
<Modal.Header>Заблокированные пользователи</Modal.Header> <ModalHeader>Заблокированные пользователи</ModalHeader>
<div <div
className="flex flex-col gap-2 p-4 overflow-y-auto" className="flex flex-col gap-2 p-4 overflow-y-auto"
onScroll={handleScroll} onScroll={handleScroll}

View file

@ -1,6 +1,6 @@
"use client"; "use client";
import { Button, Modal, Textarea, useThemeMode } from "flowbite-react"; import { Button, Modal, ModalBody, ModalFooter, ModalHeader, Textarea, useThemeMode } from "flowbite-react";
import { ENDPOINTS } from "#/api/config"; import { ENDPOINTS } from "#/api/config";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useSWRConfig } from "swr"; import { useSWRConfig } from "swr";
@ -138,8 +138,8 @@ export const ProfileEditLoginModal = (props: {
onClose={() => props.setIsOpen(false)} onClose={() => props.setIsOpen(false)}
size={"4xl"} size={"4xl"}
> >
<Modal.Header>Изменить никнейм</Modal.Header> <ModalHeader>Изменить никнейм</ModalHeader>
<Modal.Body> <ModalBody>
{loading ? {loading ?
<div className="flex items-center justify-center py-8"> <div className="flex items-center justify-center py-8">
<Spinner /> <Spinner />
@ -173,8 +173,8 @@ export const ProfileEditLoginModal = (props: {
} }
</> </>
} }
</Modal.Body> </ModalBody>
<Modal.Footer> <ModalFooter>
{_loginData.is_change_available && ( {_loginData.is_change_available && (
<Button <Button
color="blue" color="blue"
@ -191,7 +191,7 @@ export const ProfileEditLoginModal = (props: {
> >
Отмена Отмена
</Button> </Button>
</Modal.Footer> </ModalFooter>
</Modal> </Modal>
); );
}; };

View file

@ -1,6 +1,6 @@
"use client"; "use client";
import { FileInput, Label, Modal, useThemeMode } from "flowbite-react"; import { FileInput, Label, Modal, ModalBody, ModalHeader, useThemeMode } from "flowbite-react";
import { Spinner } from "../Spinner/Spinner"; import { Spinner } from "../Spinner/Spinner";
import useSWR from "swr"; import useSWR from "swr";
import { ENDPOINTS } from "#/api/config"; import { ENDPOINTS } from "#/api/config";
@ -201,8 +201,8 @@ export const ProfileEditModal = (props: {
onClose={() => props.setIsOpen(false)} onClose={() => props.setIsOpen(false)}
size={"7xl"} size={"7xl"}
> >
<Modal.Header>Редактирование профиля</Modal.Header> <ModalHeader>Редактирование профиля</ModalHeader>
<Modal.Body> <ModalBody>
{prefLoading ? {prefLoading ?
<Spinner /> <Spinner />
: <div className="flex flex-col gap-4"> : <div className="flex flex-col gap-4">
@ -394,7 +394,7 @@ export const ProfileEditModal = (props: {
</div> </div>
</div> </div>
} }
</Modal.Body> </ModalBody>
</Modal> </Modal>
{props.token ? {props.token ?
<> <>

View file

@ -1,6 +1,6 @@
"use client"; "use client";
import { Modal, useThemeMode } from "flowbite-react"; import { Modal, ModalBody, ModalHeader, useThemeMode } from "flowbite-react";
import { ENDPOINTS } from "#/api/config"; import { ENDPOINTS } from "#/api/config";
import { useState } from "react"; import { useState } from "react";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
@ -98,8 +98,8 @@ export const ProfileEditPrivacyModal = (props: {
onClose={() => props.setIsOpen(false)} onClose={() => props.setIsOpen(false)}
size={"4xl"} size={"4xl"}
> >
<Modal.Header>{setting_text[props.setting]}</Modal.Header> <ModalHeader>{setting_text[props.setting]}</ModalHeader>
<Modal.Body> <ModalBody>
{props.setting != "none" ? {props.setting != "none" ?
<> <>
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
@ -202,7 +202,7 @@ export const ProfileEditPrivacyModal = (props: {
</div> </div>
</> </>
: ""} : ""}
</Modal.Body> </ModalBody>
</Modal> </Modal>
); );
}; };

View file

@ -1,6 +1,15 @@
"use client"; "use client";
import { Button, Modal, Label, TextInput, useThemeMode } from "flowbite-react"; import {
Button,
Label,
Modal,
ModalBody,
ModalFooter,
ModalHeader,
TextInput,
useThemeMode,
} from "flowbite-react";
import { Spinner } from "../Spinner/Spinner"; import { Spinner } from "../Spinner/Spinner";
import { ENDPOINTS } from "#/api/config"; import { ENDPOINTS } from "#/api/config";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
@ -164,8 +173,8 @@ export const ProfileEditSocialModal = (props: {
onClose={() => props.setIsOpen(false)} onClose={() => props.setIsOpen(false)}
size={"4xl"} size={"4xl"}
> >
<Modal.Header>Соц. сети</Modal.Header> <ModalHeader>Соц. сети</ModalHeader>
<Modal.Body> <ModalBody>
<p className="p-2 text-gray-400 border-2 border-gray-200 rounded-md dark:border-gray-500 dark:text-gray-300"> <p className="p-2 text-gray-400 border-2 border-gray-200 rounded-md dark:border-gray-500 dark:text-gray-300">
Укажите ссылки на свои социальные сети, чтобы другие пользователи Укажите ссылки на свои социальные сети, чтобы другие пользователи
могли с вами связаться могли с вами связаться
@ -177,7 +186,7 @@ export const ProfileEditSocialModal = (props: {
: <div className="flex flex-col gap-4 py-4"> : <div className="flex flex-col gap-4 py-4">
<div> <div>
<div className="block mb-2"> <div className="block mb-2">
<Label htmlFor="vk-page" value="ВКонтакте" /> <Label htmlFor="vk-page">ВКонтакте</Label>
</div> </div>
<TextInput <TextInput
id="vk-page" id="vk-page"
@ -189,7 +198,7 @@ export const ProfileEditSocialModal = (props: {
</div> </div>
<div> <div>
<div className="block mb-2"> <div className="block mb-2">
<Label htmlFor="tg-page" value="Telegram" /> <Label htmlFor="tg-page">Telegram</Label>
</div> </div>
<TextInput <TextInput
id="tg-page" id="tg-page"
@ -201,7 +210,7 @@ export const ProfileEditSocialModal = (props: {
</div> </div>
<div> <div>
<div className="block mb-2"> <div className="block mb-2">
<Label htmlFor="discord-page" value="Discord" /> <Label htmlFor="discord-page">Discord</Label>
</div> </div>
<TextInput <TextInput
id="discord-page" id="discord-page"
@ -213,7 +222,7 @@ export const ProfileEditSocialModal = (props: {
</div> </div>
<div> <div>
<div className="block mb-2"> <div className="block mb-2">
<Label htmlFor="inst-page" value="Instagram" /> <Label htmlFor="inst-page">Instagram</Label>
</div> </div>
<TextInput <TextInput
id="inst-page" id="inst-page"
@ -225,7 +234,7 @@ export const ProfileEditSocialModal = (props: {
</div> </div>
<div> <div>
<div className="block mb-2"> <div className="block mb-2">
<Label htmlFor="tt-page" value="TikTok" /> <Label htmlFor="tt-page">TikTok</Label>
</div> </div>
<TextInput <TextInput
id="tt-page" id="tt-page"
@ -237,8 +246,8 @@ export const ProfileEditSocialModal = (props: {
</div> </div>
</div> </div>
} }
</Modal.Body> </ModalBody>
<Modal.Footer> <ModalFooter>
<Button <Button
color="blue" color="blue"
onClick={() => _setSocialSetting()} onClick={() => _setSocialSetting()}
@ -253,7 +262,7 @@ export const ProfileEditSocialModal = (props: {
> >
Отмена Отмена
</Button> </Button>
</Modal.Footer> </ModalFooter>
</Modal> </Modal>
); );
}; };

View file

@ -1,6 +1,6 @@
"use client"; "use client";
import { Button, Modal, Textarea, useThemeMode } from "flowbite-react"; import { Button, Modal, ModalBody, ModalFooter, ModalHeader, Textarea, useThemeMode } from "flowbite-react";
import { ENDPOINTS } from "#/api/config"; import { ENDPOINTS } from "#/api/config";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useSWRConfig } from "swr"; import { useSWRConfig } from "swr";
@ -96,8 +96,8 @@ export const ProfileEditStatusModal = (props: {
onClose={() => props.setIsOpen(false)} onClose={() => props.setIsOpen(false)}
size={"4xl"} size={"4xl"}
> >
<Modal.Header>Изменить статус</Modal.Header> <ModalHeader>Изменить статус</ModalHeader>
<Modal.Body> <ModalBody>
<Textarea <Textarea
disabled={loading} disabled={loading}
rows={3} rows={3}
@ -111,8 +111,8 @@ export const ProfileEditStatusModal = (props: {
<p className="text-sm text-right text-gray-500 dark:text-gray-300"> <p className="text-sm text-right text-gray-500 dark:text-gray-300">
{_stringLength}/80 {_stringLength}/80
</p> </p>
</Modal.Body> </ModalBody>
<Modal.Footer> <ModalFooter>
<Button <Button
color="blue" color="blue"
onClick={() => _setStatusSetting()} onClick={() => _setStatusSetting()}
@ -123,7 +123,7 @@ export const ProfileEditStatusModal = (props: {
<Button color="red" onClick={() => props.setIsOpen(false)}> <Button color="red" onClick={() => props.setIsOpen(false)}>
Отмена Отмена
</Button> </Button>
</Modal.Footer> </ModalFooter>
</Modal> </Modal>
); );
}; };

View file

@ -1,10 +1,4 @@
import { import { Button, Card, Modal, ModalHeader, Rating, RatingStar } from "flowbite-react";
Card,
RatingStar,
Rating,
Modal,
Button,
} from "flowbite-react";
import { unixToDate, useSWRfetcher } from "#/api/utils"; import { unixToDate, useSWRfetcher } from "#/api/utils";
import Link from "next/link"; import Link from "next/link";
@ -119,7 +113,7 @@ const ProfileReleaseRatingsModal = (props: {
onClose={() => props.setIsOpen(false)} onClose={() => props.setIsOpen(false)}
size={"4xl"} size={"4xl"}
> >
<Modal.Header>Оценки</Modal.Header> <ModalHeader>Оценки</ModalHeader>
<div <div
className="flex flex-col gap-2 p-4 overflow-y-auto" className="flex flex-col gap-2 p-4 overflow-y-auto"
onScroll={handleScroll} onScroll={handleScroll}

View file

@ -1,4 +1,4 @@
import { Card, Table } from "flowbite-react"; import { Card, Table, TableBody, TableCell, TableRow } from "flowbite-react";
import { ReleaseInfoSearchLink } from "#/components/ReleaseInfo/ReleaseInfo.SearchLink"; import { ReleaseInfoSearchLink } from "#/components/ReleaseInfo/ReleaseInfo.SearchLink";
import { unixToDate, minutesToTime } from "#/api/utils"; import { unixToDate, minutesToTime } from "#/api/utils";
const weekDay = [ const weekDay = [
@ -30,9 +30,9 @@ export const ReleaseInfoInfo = (props: {
return ( return (
<Card> <Card>
<Table> <Table>
<Table.Body> <TableBody>
<Table.Row> <TableRow>
<Table.Cell className="py-0"> <TableCell className="py-0">
{props.country ? {props.country ?
props.country.toLowerCase() == "япония" ? props.country.toLowerCase() == "япония" ?
<span className="w-8 h-8 iconify-color twemoji--flag-for-japan"></span> <span className="w-8 h-8 iconify-color twemoji--flag-for-japan"></span>
@ -40,45 +40,45 @@ export const ReleaseInfoInfo = (props: {
: <span className="w-8 h-8 iconify-color twemoji--flag-for-united-nations "></span> : <span className="w-8 h-8 iconify-color twemoji--flag-for-united-nations "></span>
} }
</Table.Cell> </TableCell>
<Table.Cell className="font-medium text-gray-900 whitespace-nowrap dark:text-white"> <TableCell className="font-medium text-gray-900 whitespace-nowrap dark:text-white">
{props.country && props.country} {props.country && props.country}
{(props.aired_on_date != 0 || props.year) && ", "} {(props.aired_on_date != 0 || props.year) && ", "}
{props.season && props.season != 0 ? {props.season && props.season != 0 ?
`${YearSeason[props.season]} ` `${YearSeason[props.season]} `
: ""} : ""}
{props.year && `${props.year} г.`} {props.year && `${props.year} г.`}
</Table.Cell> </TableCell>
</Table.Row> </TableRow>
<Table.Row> <TableRow>
<Table.Cell className="py-0"> <TableCell className="py-0">
<span className="w-8 h-8 iconify-color mdi--animation-play-outline dark:invert"></span> <span className="w-8 h-8 iconify-color mdi--animation-play-outline dark:invert"></span>
</Table.Cell> </TableCell>
<Table.Cell className="font-medium text-gray-900 whitespace-nowrap dark:text-white"> <TableCell className="font-medium text-gray-900 whitespace-nowrap dark:text-white">
{props.episodes.released ? props.episodes.released : "?"} {props.episodes.released ? props.episodes.released : "?"}
{"/"} {"/"}
{props.episodes.total ? props.episodes.total + " эп. " : "? эп. "} {props.episodes.total ? props.episodes.total + " эп. " : "? эп. "}
{props.duration != 0 && {props.duration != 0 &&
`по ${minutesToTime(props.duration, "daysHours")}`} `по ${minutesToTime(props.duration, "daysHours")}`}
</Table.Cell> </TableCell>
</Table.Row> </TableRow>
<Table.Row> <TableRow>
<Table.Cell className="py-0"> <TableCell className="py-0">
<span className="w-8 h-8 iconify-color mdi--calendar-outline dark:invert"></span> <span className="w-8 h-8 iconify-color mdi--calendar-outline dark:invert"></span>
</Table.Cell> </TableCell>
<Table.Cell className="font-medium text-gray-900 dark:text-white"> <TableCell className="font-medium text-gray-900 dark:text-white">
{props.category} {props.category}
{", "} {", "}
{props.broadcast == 0 ? {props.broadcast == 0 ?
props.status.toLowerCase() props.status.toLowerCase()
: `выходит ${weekDay[props.broadcast]}`} : `выходит ${weekDay[props.broadcast]}`}
</Table.Cell> </TableCell>
</Table.Row> </TableRow>
<Table.Row> <TableRow>
<Table.Cell className="py-0"> <TableCell className="py-0">
<span className="w-8 h-8 iconify-color mdi--people-group-outline dark:invert"></span> <span className="w-8 h-8 iconify-color mdi--people-group-outline dark:invert"></span>
</Table.Cell> </TableCell>
<Table.Cell className="font-medium text-gray-900 dark:text-white"> <TableCell className="font-medium text-gray-900 dark:text-white">
{props.studio && ( {props.studio && (
<> <>
{"Студия: "} {"Студия: "}
@ -117,13 +117,13 @@ export const ReleaseInfoInfo = (props: {
/> />
</> </>
)} )}
</Table.Cell> </TableCell>
</Table.Row> </TableRow>
<Table.Row> <TableRow>
<Table.Cell className="py-0"> <TableCell className="py-0">
<span className="w-8 h-8 iconify-color mdi--tag-outline dark:invert"></span> <span className="w-8 h-8 iconify-color mdi--tag-outline dark:invert"></span>
</Table.Cell> </TableCell>
<Table.Cell className="font-medium text-gray-900 dark:text-white"> <TableCell className="font-medium text-gray-900 dark:text-white">
{props.genres && {props.genres &&
props.genres.split(", ").map((genre: string, index: number) => { props.genres.split(", ").map((genre: string, index: number) => {
return ( return (
@ -133,14 +133,14 @@ export const ReleaseInfoInfo = (props: {
</div> </div>
); );
})} })}
</Table.Cell> </TableCell>
</Table.Row> </TableRow>
{props.status.toLowerCase() == "анонс" && ( {props.status.toLowerCase() == "анонс" && (
<Table.Row> <TableRow>
<Table.Cell className="py-0"> <TableCell className="py-0">
<span className="w-8 h-8 iconify-color mdi--clock-outline dark:invert"></span> <span className="w-8 h-8 iconify-color mdi--clock-outline dark:invert"></span>
</Table.Cell> </TableCell>
<Table.Cell className="font-medium text-gray-900 whitespace-nowrap dark:text-white"> <TableCell className="font-medium text-gray-900 whitespace-nowrap dark:text-white">
{props.aired_on_date != 0 ? {props.aired_on_date != 0 ?
unixToDate(props.aired_on_date, "full") unixToDate(props.aired_on_date, "full")
: props.year ? : props.year ?
@ -151,10 +151,10 @@ export const ReleaseInfoInfo = (props: {
{props.year && `${props.year} г.`} {props.year && `${props.year} г.`}
</> </>
: "Скоро"} : "Скоро"}
</Table.Cell> </TableCell>
</Table.Row> </TableRow>
)} )}
</Table.Body> </TableBody>
</Table> </Table>
</Card> </Card>
); );

View file

@ -1,20 +1,26 @@
import { import {
Card,
Rating,
Flowbite,
Button, Button,
CustomFlowbiteTheme, Card,
Modal, Modal,
ModalBody,
ModalFooter,
ModalHeader,
Rating,
RatingAdvanced,
RatingStar,
RatingAdvancedTheme,
} from "flowbite-react"; } from "flowbite-react";
import { numberDeclension } from "#/api/utils"; import { numberDeclension } from "#/api/utils";
import { useState } from "react"; import { useState } from "react";
import { ENDPOINTS } from "#/api/config"; import { ENDPOINTS } from "#/api/config";
const RatingTheme: CustomFlowbiteTheme = { const CustomRatingTheme: RatingAdvancedTheme = {
ratingAdvanced: { base: "flex items-center",
progress: { label: "text-sm font-medium text-cyan-600 dark:text-cyan-500",
base: "mx-4 h-5 w-3/4 rounded bg-gray-200 dark:bg-gray-700", progress: {
}, base: "mx-4 h-5 w-3/4 rounded bg-gray-200 dark:bg-gray-700",
fill: "h-5 rounded bg-yellow-400",
label: "text-sm font-medium text-cyan-600 dark:text-cyan-500",
}, },
}; };
export const ReleaseInfoRating = (props: { export const ReleaseInfoRating = (props: {
@ -39,7 +45,7 @@ export const ReleaseInfoRating = (props: {
<Card> <Card>
<div className="flex flex-col gap-2 sm:items-center sm:flex-row"> <div className="flex flex-col gap-2 sm:items-center sm:flex-row">
<Rating> <Rating>
<Rating.Star /> <RatingStar />
<p className="ml-2 text-sm font-bold dark:text-white"> <p className="ml-2 text-sm font-bold dark:text-white">
{props.grade.toFixed(2)} из 5 {props.grade.toFixed(2)} из 5
</p> </p>
@ -48,7 +54,7 @@ export const ReleaseInfoRating = (props: {
<> <>
<span className="mx-1.5 h-1 w-1 rounded-full bg-gray-500 dark:bg-gray-400 hidden lg:block" /> <span className="mx-1.5 h-1 w-1 rounded-full bg-gray-500 dark:bg-gray-400 hidden lg:block" />
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
{vote ? ( {vote ?
<> <>
<p className="text-sm font-medium text-gray-500 dark:text-gray-400"> <p className="text-sm font-medium text-gray-500 dark:text-gray-400">
ваша оценка: {vote} ваша оценка: {vote}
@ -62,8 +68,7 @@ export const ReleaseInfoRating = (props: {
изменить изменить
</Button> </Button>
</> </>
) : ( : <Button
<Button
size={"xs"} size={"xs"}
className="text-gray-500 border border-gray-600 rounded-full hover:bg-black hover:text-white hover:border-black dark:text-gray-400 dark:border-gray-500" className="text-gray-500 border border-gray-600 rounded-full hover:bg-black hover:text-white hover:border-black dark:text-gray-400 dark:border-gray-500"
color="inline" color="inline"
@ -71,7 +76,7 @@ export const ReleaseInfoRating = (props: {
> >
оценить оценить
</Button> </Button>
)} }
</div> </div>
</> </>
)} )}
@ -80,47 +85,50 @@ export const ReleaseInfoRating = (props: {
{props.votes.total}{" "} {props.votes.total}{" "}
{numberDeclension(props.votes.total, "голос", "голоса", "голосов")} {numberDeclension(props.votes.total, "голос", "голоса", "голосов")}
</p> </p>
<Flowbite theme={{ theme: RatingTheme }}> <RatingAdvanced
<Rating.Advanced theme={CustomRatingTheme}
percentFilled={Math.floor( percentFilled={Math.floor(
(props.votes["5"] / props.votes.total) * 100 (props.votes["5"] / props.votes.total) * 100
)} )}
className="mb-2" className="mb-2"
> >
5 5
</Rating.Advanced> </RatingAdvanced>
<Rating.Advanced <RatingAdvanced
percentFilled={Math.floor( theme={CustomRatingTheme}
(props.votes["4"] / props.votes.total) * 100 percentFilled={Math.floor(
)} (props.votes["4"] / props.votes.total) * 100
className="mb-2" )}
> className="mb-2"
4 >
</Rating.Advanced> 4
<Rating.Advanced </RatingAdvanced>
percentFilled={Math.floor( <RatingAdvanced
(props.votes["3"] / props.votes.total) * 100 theme={CustomRatingTheme}
)} percentFilled={Math.floor(
className="mb-2" (props.votes["3"] / props.votes.total) * 100
> )}
3 className="mb-2"
</Rating.Advanced> >
<Rating.Advanced 3
percentFilled={Math.floor( </RatingAdvanced>
(props.votes["2"] / props.votes.total) * 100 <RatingAdvanced
)} theme={CustomRatingTheme}
className="mb-2" percentFilled={Math.floor(
> (props.votes["2"] / props.votes.total) * 100
2 )}
</Rating.Advanced> className="mb-2"
<Rating.Advanced >
percentFilled={Math.floor( 2
(props.votes["1"] / props.votes.total) * 100 </RatingAdvanced>
)} <RatingAdvanced
> theme={CustomRatingTheme}
1 percentFilled={Math.floor(
</Rating.Advanced> (props.votes["1"] / props.votes.total) * 100
</Flowbite> )}
>
1
</RatingAdvanced>
</Card> </Card>
<ReleaseInfoRatingModal <ReleaseInfoRatingModal
isOpen={isRatingModalOpen} isOpen={isRatingModalOpen}
@ -178,8 +186,8 @@ const ReleaseInfoRatingModal = (props: {
show={props.isOpen} show={props.isOpen}
onClose={() => props.setIsOpen(false)} onClose={() => props.setIsOpen(false)}
> >
<Modal.Header>Оценка</Modal.Header> <ModalHeader>Оценка</ModalHeader>
<Modal.Body> <ModalBody>
<div> <div>
<div className="block sm:hidden"> <div className="block sm:hidden">
<Rating size="md" className="justify-center"> <Rating size="md" className="justify-center">
@ -191,7 +199,7 @@ const ReleaseInfoRatingModal = (props: {
onMouseOut={() => setCurElement(0)} onMouseOut={() => setCurElement(0)}
onClick={() => setVote(element)} onClick={() => setVote(element)}
> >
<Rating.Star <RatingStar
filled={index + 1 <= curElement || index + 1 <= vote} filled={index + 1 <= curElement || index + 1 <= vote}
/> />
</Button> </Button>
@ -208,7 +216,7 @@ const ReleaseInfoRatingModal = (props: {
onMouseOut={() => setCurElement(0)} onMouseOut={() => setCurElement(0)}
onClick={() => setVote(element)} onClick={() => setVote(element)}
> >
<Rating.Star <RatingStar
filled={index + 1 <= curElement || index + 1 <= vote} filled={index + 1 <= curElement || index + 1 <= vote}
/> />
</Button> </Button>
@ -216,8 +224,8 @@ const ReleaseInfoRatingModal = (props: {
</Rating> </Rating>
</div> </div>
</div> </div>
</Modal.Body> </ModalBody>
<Modal.Footer> <ModalFooter>
<div className="flex gap-1 ml-auto"> <div className="flex gap-1 ml-auto">
<Button <Button
disabled={isSending} disabled={isSending}
@ -241,7 +249,7 @@ const ReleaseInfoRatingModal = (props: {
Оценить Оценить
</Button> </Button>
</div> </div>
</Modal.Footer> </ModalFooter>
</Modal> </Modal>
); );
}; };

View file

@ -5,7 +5,7 @@ import useSWRInfinite from "swr/infinite";
import { useCallback, useEffect, useState } from "react"; import { useCallback, useEffect, useState } from "react";
import { tryCatchAPI, useSWRfetcher } from "#/api/utils"; import { tryCatchAPI, useSWRfetcher } from "#/api/utils";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { useThemeMode } from "flowbite-react"; import { DropdownItem, ModalHeader, useThemeMode } from "flowbite-react";
const lists = [ const lists = [
{ list: 0, name: "Не смотрю" }, { list: 0, name: "Не смотрю" },
@ -174,12 +174,12 @@ export const ReleaseInfoUserList = (props: {
disabled={listEventDisabled} disabled={listEventDisabled}
> >
{lists.map((list) => ( {lists.map((list) => (
<Dropdown.Item <DropdownItem
key={list.list} key={list.list}
onClick={() => _addToList(list.list)} onClick={() => _addToList(list.list)}
> >
{list.name} {list.name}
</Dropdown.Item> </DropdownItem>
))} ))}
</Dropdown> </Dropdown>
<Button <Button
@ -321,7 +321,7 @@ const AddReleaseToCollectionModal = (props: {
show={props.isOpen} show={props.isOpen}
onClose={() => props.setIsOpen(false)} onClose={() => props.setIsOpen(false)}
> >
<Modal.Header>Выбор коллекции</Modal.Header> <ModalHeader>Выбор коллекции</ModalHeader>
<div <div
className="flex flex-col gap-2 p-4 overflow-y-auto" className="flex flex-col gap-2 p-4 overflow-y-auto"
onScroll={handleScroll} onScroll={handleScroll}

View file

@ -3,7 +3,7 @@
import { Spinner } from "#/components/Spinner/Spinner"; import { Spinner } from "#/components/Spinner/Spinner";
import { useUserStore } from "#/store/auth"; import { useUserStore } from "#/store/auth";
import { useUserPlayerPreferencesStore } from "#/store/player"; import { useUserPlayerPreferencesStore } from "#/store/player";
import { Card, Dropdown, Button } from "flowbite-react"; import { Button, Card, Dropdown, DropdownItem } from "flowbite-react";
import { ENDPOINTS } from "#/api/config"; import { ENDPOINTS } from "#/api/config";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { Swiper, SwiperSlide } from "swiper/react"; import { Swiper, SwiperSlide } from "swiper/react";
@ -270,14 +270,14 @@ export const ReleasePlayer = (props: { id: number }) => {
theme={DropdownTheme} theme={DropdownTheme}
> >
{voiceoverInfo.map((voiceover: any) => ( {voiceoverInfo.map((voiceover: any) => (
<Dropdown.Item <DropdownItem
key={`voiceover_${voiceover.id}`} key={`voiceover_${voiceover.id}`}
onClick={() => onClick={() =>
setSelectedVoiceoverAndSaveAsPreferred(voiceover) setSelectedVoiceoverAndSaveAsPreferred(voiceover)
} }
> >
{voiceover.name} {voiceover.name}
</Dropdown.Item> </DropdownItem>
))} ))}
</Dropdown> </Dropdown>
<Dropdown <Dropdown
@ -286,12 +286,12 @@ export const ReleasePlayer = (props: { id: number }) => {
theme={DropdownTheme} theme={DropdownTheme}
> >
{sourcesInfo.map((source: any) => ( {sourcesInfo.map((source: any) => (
<Dropdown.Item <DropdownItem
key={`source_${source.id}`} key={`source_${source.id}`}
onClick={() => setSelectedPlayerAndSaveAsPreferred(source)} onClick={() => setSelectedPlayerAndSaveAsPreferred(source)}
> >
{source.name} {source.name}
</Dropdown.Item> </DropdownItem>
))} ))}
</Dropdown> </Dropdown>
</div> </div>

View file

@ -1,6 +1,6 @@
"use client"; "use client";
import { Dropdown } from "flowbite-react"; import { Dropdown, DropdownItem } from "flowbite-react";
import { numberDeclension } from "#/api/utils"; import { numberDeclension } from "#/api/utils";
import { useUserPlayerPreferencesStore } from "#/store/player"; import { useUserPlayerPreferencesStore } from "#/store/player";
@ -55,7 +55,7 @@ export const SourceSelector = (props: {
)} )}
> >
{props.availableSource.map((source: Source) => ( {props.availableSource.map((source: Source) => (
<Dropdown.Item <DropdownItem
key={`source_${source.id}`} key={`source_${source.id}`}
onClick={() => { onClick={() => {
playerPreferenceStore.setPreferredPlayer( playerPreferenceStore.setPreferredPlayer(
@ -69,7 +69,7 @@ export const SourceSelector = (props: {
}} }}
> >
<DropdownItem {...source} /> <DropdownItem {...source} />
</Dropdown.Item> </DropdownItem>
))} ))}
</Dropdown> </Dropdown>
); );

View file

@ -1,6 +1,6 @@
"use client"; "use client";
import { Dropdown } from "flowbite-react"; import { Dropdown, DropdownItem } from "flowbite-react";
import { numberDeclension } from "#/api/utils"; import { numberDeclension } from "#/api/utils";
import { useUserPlayerPreferencesStore } from "#/store/player"; import { useUserPlayerPreferencesStore } from "#/store/player";
@ -26,7 +26,7 @@ const DropdownTrigger = ({ icon, name, pinned }: Voiceover) => {
); );
}; };
const DropdownItem = ({ const DropdownItemInternal = ({
icon, icon,
name, name,
pinned, pinned,
@ -80,7 +80,7 @@ export const VoiceoverSelector = (props: {
)} )}
> >
{props.availableVoiceover.map((voiceover: Voiceover) => ( {props.availableVoiceover.map((voiceover: Voiceover) => (
<Dropdown.Item <DropdownItem
className="w-fit" className="w-fit"
key={`voiceover_${voiceover.id}`} key={`voiceover_${voiceover.id}`}
onClick={() => { onClick={() => {
@ -94,8 +94,8 @@ export const VoiceoverSelector = (props: {
}); });
}} }}
> >
<DropdownItem {...voiceover} /> <DropdownItemInternal {...voiceover} />
</Dropdown.Item> </DropdownItem>
))} ))}
</Dropdown> </Dropdown>
); );

View file

@ -4,12 +4,16 @@ import { CURRENT_APP_VERSION } from "#/api/config";
import { useUserStore } from "#/store/auth"; import { useUserStore } from "#/store/auth";
import { usePreferencesStore } from "#/store/preferences"; import { usePreferencesStore } from "#/store/preferences";
import { import {
Modal,
Button, Button,
useThemeMode, ButtonGroup,
ToggleSwitch,
HR,
Dropdown, Dropdown,
DropdownItem,
HR,
Modal,
ModalBody,
ModalHeader,
ToggleSwitch,
useThemeMode,
} from "flowbite-react"; } from "flowbite-react";
import Link from "next/link"; import Link from "next/link";
@ -54,8 +58,8 @@ export const SettingsModal = (props: { isOpen: boolean; setIsOpen: any }) => {
show={props.isOpen} show={props.isOpen}
onClose={() => props.setIsOpen(false)} onClose={() => props.setIsOpen(false)}
> >
<Modal.Header>Настройки</Modal.Header> <ModalHeader>Настройки</ModalHeader>
<Modal.Body> <ModalBody>
<div className="space-y-6"> <div className="space-y-6">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span className="w-6 h-6 iconify material-symbols--palette-outline"></span> <span className="w-6 h-6 iconify material-symbols--palette-outline"></span>
@ -63,7 +67,7 @@ export const SettingsModal = (props: { isOpen: boolean; setIsOpen: any }) => {
</div> </div>
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<p className=" dark:text-white">Тема</p> <p className=" dark:text-white">Тема</p>
<Button.Group> <ButtonGroup>
<Button <Button
color={computedMode == "light" ? "blue" : "gray"} color={computedMode == "light" ? "blue" : "gray"}
onClick={() => setMode("light")} onClick={() => setMode("light")}
@ -76,7 +80,7 @@ export const SettingsModal = (props: { isOpen: boolean; setIsOpen: any }) => {
> >
Темная Темная
</Button> </Button>
</Button.Group> </ButtonGroup>
</div> </div>
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<p className=" dark:text-white max-w-96"> <p className=" dark:text-white max-w-96">
@ -121,7 +125,7 @@ export const SettingsModal = (props: { isOpen: boolean; setIsOpen: any }) => {
> >
{Object.keys(HomeCategory).map((key) => { {Object.keys(HomeCategory).map((key) => {
return ( return (
<Dropdown.Item <DropdownItem
key={key} key={key}
onClick={() => onClick={() =>
preferenceStore.setParams({ preferenceStore.setParams({
@ -133,7 +137,7 @@ export const SettingsModal = (props: { isOpen: boolean; setIsOpen: any }) => {
} }
> >
{HomeCategory[key]} {HomeCategory[key]}
</Dropdown.Item> </DropdownItem>
); );
})} })}
</Dropdown> </Dropdown>
@ -152,7 +156,7 @@ export const SettingsModal = (props: { isOpen: boolean; setIsOpen: any }) => {
> >
{Object.keys(BookmarksCategory).map((key) => { {Object.keys(BookmarksCategory).map((key) => {
return ( return (
<Dropdown.Item <DropdownItem
key={key} key={key}
onClick={() => onClick={() =>
preferenceStore.setParams({ preferenceStore.setParams({
@ -164,7 +168,7 @@ export const SettingsModal = (props: { isOpen: boolean; setIsOpen: any }) => {
} }
> >
{BookmarksCategory[key]} {BookmarksCategory[key]}
</Dropdown.Item> </DropdownItem>
); );
})} })}
</Dropdown> </Dropdown>
@ -182,7 +186,7 @@ export const SettingsModal = (props: { isOpen: boolean; setIsOpen: any }) => {
{Object.keys(NavbarTitles).map( {Object.keys(NavbarTitles).map(
(key: "always" | "links" | "selected" | "never") => { (key: "always" | "links" | "selected" | "never") => {
return ( return (
<Dropdown.Item <DropdownItem
className={`${key == "links" ? "hidden lg:flex" : ""}`} className={`${key == "links" ? "hidden lg:flex" : ""}`}
key={`navbar-titles-${key}`} key={`navbar-titles-${key}`}
onClick={() => onClick={() =>
@ -192,7 +196,7 @@ export const SettingsModal = (props: { isOpen: boolean; setIsOpen: any }) => {
} }
> >
{NavbarTitles[key]} {NavbarTitles[key]}
</Dropdown.Item> </DropdownItem>
); );
} }
)} )}
@ -211,7 +215,7 @@ export const SettingsModal = (props: { isOpen: boolean; setIsOpen: any }) => {
: "Нет" : "Нет"
} }
> >
<Dropdown.Item <DropdownItem
onClick={() => onClick={() =>
preferenceStore.setFlags({ preferenceStore.setFlags({
showFifthButton: null, showFifthButton: null,
@ -219,10 +223,10 @@ export const SettingsModal = (props: { isOpen: boolean; setIsOpen: any }) => {
} }
> >
Не показывать Не показывать
</Dropdown.Item> </DropdownItem>
{Object.keys(FifthButton).map((key) => { {Object.keys(FifthButton).map((key) => {
return ( return (
<Dropdown.Item <DropdownItem
key={`navbar-fifthbutton-${key}`} key={`navbar-fifthbutton-${key}`}
onClick={() => onClick={() =>
preferenceStore.setFlags({ preferenceStore.setFlags({
@ -231,7 +235,7 @@ export const SettingsModal = (props: { isOpen: boolean; setIsOpen: any }) => {
} }
> >
{FifthButton[key]} {FifthButton[key]}
</Dropdown.Item> </DropdownItem>
); );
})} })}
</Dropdown> </Dropdown>
@ -340,7 +344,7 @@ export const SettingsModal = (props: { isOpen: boolean; setIsOpen: any }) => {
</div> </div>
</Link> </Link>
</div> </div>
</Modal.Body> </ModalBody>
</Modal> </Modal>
); );
}; };

View file

@ -5,7 +5,7 @@ import { Spinner } from "#/components/Spinner/Spinner";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { useScrollPosition } from "#/hooks/useScrollPosition"; import { useScrollPosition } from "#/hooks/useScrollPosition";
import { useUserStore } from "../store/auth"; import { useUserStore } from "../store/auth";
import { Dropdown, Button } from "flowbite-react"; import { Button, ButtonGroup, Dropdown, DropdownItem } from "flowbite-react";
import { sort } from "./common"; import { sort } from "./common";
import { ENDPOINTS } from "#/api/config"; import { ENDPOINTS } from "#/api/config";
import { BookmarksList, useSWRfetcher } from "#/api/utils"; import { BookmarksList, useSWRfetcher } from "#/api/utils";
@ -151,7 +151,7 @@ export function BookmarksCategoryPage(props: any) {
</form> </form>
: ""} : ""}
<div className="m-4 overflow-auto"> <div className="m-4 overflow-auto">
<Button.Group> <ButtonGroup>
<Button <Button
className="whitespace-nowrap" className="whitespace-nowrap"
disabled={props.slug == "watching"} disabled={props.slug == "watching"}
@ -222,7 +222,7 @@ export function BookmarksCategoryPage(props: any) {
> >
{props.SectionTitleMapping["abandoned"]} {props.SectionTitleMapping["abandoned"]}
</Button> </Button>
</Button.Group> </ButtonGroup>
</div> </div>
<div className="flex items-center justify-between px-4 py-2 border-b-2 border-black dark:border-white"> <div className="flex items-center justify-between px-4 py-2 border-b-2 border-black dark:border-white">
<h1 className="font-bold text-md sm:text-xl md:text-lg xl:text-xl"> <h1 className="font-bold text-md sm:text-xl md:text-lg xl:text-xl">
@ -237,7 +237,7 @@ export function BookmarksCategoryPage(props: any) {
theme={DropdownTheme} theme={DropdownTheme}
> >
{sort.values.map((item, index) => ( {sort.values.map((item, index) => (
<Dropdown.Item key={index} onClick={() => setSelectedSort(index)}> <DropdownItem key={index} onClick={() => setSelectedSort(index)}>
<span <span
className={`w-6 h-6 iconify ${ className={`w-6 h-6 iconify ${
sort.values[index].value.split("_")[1] == "descending" ? sort.values[index].value.split("_")[1] == "descending" ?
@ -246,7 +246,7 @@ export function BookmarksCategoryPage(props: any) {
}`} }`}
></span> ></span>
{item.name} {item.name}
</Dropdown.Item> </DropdownItem>
))} ))}
</Dropdown> </Dropdown>
</div> </div>

View file

@ -5,14 +5,15 @@ import { useEffect, useState, useCallback } from "react";
import { useSearchParams, useRouter } from "next/navigation"; import { useSearchParams, useRouter } from "next/navigation";
import { ENDPOINTS } from "#/api/config"; import { ENDPOINTS } from "#/api/config";
import { import {
Card,
Button, Button,
Card,
Checkbox, Checkbox,
TextInput,
Textarea,
FileInput, FileInput,
Label, Label,
Modal, Modal,
ModalHeader,
Textarea,
TextInput,
useThemeMode, useThemeMode,
} from "flowbite-react"; } from "flowbite-react";
import { PosterWithStuff } from "#/components/ReleasePoster/PosterWithStuff"; import { PosterWithStuff } from "#/components/ReleasePoster/PosterWithStuff";
@ -388,10 +389,9 @@ export const CreateCollectionPage = () => {
</Label> </Label>
<div className="flex-1"> <div className="flex-1">
<div className="block mb-2"> <div className="block mb-2">
<Label <Label htmlFor="title">
htmlFor="title" Название (минимум 10, максимум 60 символов)
value="Название (минимум 10, максимум 60 символов)" </Label>
/>
</div> </div>
<TextInput <TextInput
id="title" id="title"
@ -408,10 +408,9 @@ export const CreateCollectionPage = () => {
{stringLength.title}/60 {stringLength.title}/60
</p> </p>
<div className="block mt-2 mb-2"> <div className="block mt-2 mb-2">
<Label <Label htmlFor="description">
htmlFor="description" Описание (максимум 1000 символов)
value="Описание (максимум 1000 символов)" </Label>
/>
</div> </div>
<Textarea <Textarea
rows={4} rows={4}
@ -434,7 +433,7 @@ export const CreateCollectionPage = () => {
checked={isPrivate} checked={isPrivate}
onChange={(e) => setIsPrivate(e.target.checked)} onChange={(e) => setIsPrivate(e.target.checked)}
/> />
<Label htmlFor="private" value="Приватная коллекция" /> <Label htmlFor="private">Приватная коллекция</Label>
</div> </div>
</div> </div>
<Button <Button
@ -603,7 +602,7 @@ export const ReleasesEditModal = (props: {
onClose={() => props.setIsOpen(false)} onClose={() => props.setIsOpen(false)}
size={"7xl"} size={"7xl"}
> >
<Modal.Header>Изменить релизы в коллекции</Modal.Header> <ModalHeader>Изменить релизы в коллекции</ModalHeader>
<div <div
onScroll={handleScroll} onScroll={handleScroll}
ref={modalRef} ref={modalRef}

View file

@ -5,7 +5,7 @@ import { Spinner } from "#/components/Spinner/Spinner";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { useScrollPosition } from "#/hooks/useScrollPosition"; import { useScrollPosition } from "#/hooks/useScrollPosition";
import { useUserStore } from "../store/auth"; import { useUserStore } from "../store/auth";
import { Dropdown, Button } from "flowbite-react"; import { Button, Dropdown, DropdownItem } from "flowbite-react";
import { sort } from "./common"; import { sort } from "./common";
import { ENDPOINTS } from "#/api/config"; import { ENDPOINTS } from "#/api/config";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
@ -126,7 +126,7 @@ export function FavoritesPage() {
theme={DropdownTheme} theme={DropdownTheme}
> >
{sort.values.map((item, index) => ( {sort.values.map((item, index) => (
<Dropdown.Item key={index} onClick={() => setSelectedSort(index)}> <DropdownItem key={index} onClick={() => setSelectedSort(index)}>
<span <span
className={`w-6 h-6 iconify ${ className={`w-6 h-6 iconify ${
sort.values[index].value.split("_")[1] == "descending" sort.values[index].value.split("_")[1] == "descending"
@ -135,7 +135,7 @@ export function FavoritesPage() {
}`} }`}
></span> ></span>
{item.name} {item.name}
</Dropdown.Item> </DropdownItem>
))} ))}
</Dropdown> </Dropdown>
</div> </div>

View file

@ -5,7 +5,7 @@ import { useState, useEffect } from "react";
import { useScrollPosition } from "#/hooks/useScrollPosition"; import { useScrollPosition } from "#/hooks/useScrollPosition";
import { useUserStore } from "../store/auth"; import { useUserStore } from "../store/auth";
import { _FetchHomePageReleases } from "#/api/utils"; import { _FetchHomePageReleases } from "#/api/utils";
import { Button } from "flowbite-react"; import { Button, ButtonGroup } from "flowbite-react";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
export function IndexCategoryPage(props) { export function IndexCategoryPage(props) {
@ -53,13 +53,13 @@ export function IndexCategoryPage(props) {
return ( return (
<> <>
<div className="mb-4 overflow-auto"> <div className="mb-4 overflow-auto">
<Button.Group> <ButtonGroup>
<Button className="whitespace-nowrap" disabled={props.slug == "last"} color="light" onClick={() => router.push("/home/last")}>{props.SectionTitleMapping["last"]}</Button> <Button className="whitespace-nowrap" disabled={props.slug == "last"} color="light" onClick={() => router.push("/home/last")}>{props.SectionTitleMapping["last"]}</Button>
<Button className="whitespace-nowrap" disabled={props.slug == "finished"} color="light" onClick={() => router.push("/home/finished")}>{props.SectionTitleMapping["finished"]}</Button> <Button className="whitespace-nowrap" disabled={props.slug == "finished"} color="light" onClick={() => router.push("/home/finished")}>{props.SectionTitleMapping["finished"]}</Button>
<Button className="whitespace-nowrap" disabled={props.slug == "ongoing"} color="light" onClick={() => router.push("/home/ongoing")}>{props.SectionTitleMapping["ongoing"]}</Button> <Button className="whitespace-nowrap" disabled={props.slug == "ongoing"} color="light" onClick={() => router.push("/home/ongoing")}>{props.SectionTitleMapping["ongoing"]}</Button>
<Button className="whitespace-nowrap" disabled={props.slug == "announce"} color="light" onClick={() => router.push("/home/announce")}>{props.SectionTitleMapping["announce"]}</Button> <Button className="whitespace-nowrap" disabled={props.slug == "announce"} color="light" onClick={() => router.push("/home/announce")}>{props.SectionTitleMapping["announce"]}</Button>
<Button className="whitespace-nowrap" disabled={props.slug == "films"} color="light" onClick={() => router.push("/home/films")}>{props.SectionTitleMapping["films"]}</Button> <Button className="whitespace-nowrap" disabled={props.slug == "films"} color="light" onClick={() => router.push("/home/films")}>{props.SectionTitleMapping["films"]}</Button>
</Button.Group> </ButtonGroup>
</div> </div>
{content && content.length > 0 ? ( {content && content.length > 0 ? (
<ReleaseSection <ReleaseSection

View file

@ -8,7 +8,7 @@ import { useScrollPosition } from "#/hooks/useScrollPosition";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { useSearchParams } from "next/navigation"; import { useSearchParams } from "next/navigation";
import { useUserStore } from "../store/auth"; import { useUserStore } from "../store/auth";
import { Button, Dropdown, Modal } from "flowbite-react"; import { Button, Dropdown, DropdownItem, Modal, ModalBody, ModalFooter, ModalHeader } from "flowbite-react";
import { CollectionsSection } from "#/components/CollectionsSection/CollectionsSection"; import { CollectionsSection } from "#/components/CollectionsSection/CollectionsSection";
import { UserSection } from "#/components/UserSection/UserSection"; import { UserSection } from "#/components/UserSection/UserSection";
import { useSWRfetcher } from "#/api/utils"; import { useSWRfetcher } from "#/api/utils";
@ -360,8 +360,8 @@ const FiltersModal = (props: {
return ( return (
<Modal show={props.isOpen} onClose={() => _cancel()}> <Modal show={props.isOpen} onClose={() => _cancel()}>
<Modal.Header>Фильтры</Modal.Header> <ModalHeader>Фильтры</ModalHeader>
<Modal.Body> <ModalBody>
<div className="my-4"> <div className="my-4">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<p className="font-bold dark:text-white">Искать в</p> <p className="font-bold dark:text-white">Искать в</p>
@ -376,12 +376,12 @@ const FiltersModal = (props: {
return <></>; return <></>;
} else { } else {
return ( return (
<Dropdown.Item <DropdownItem
onClick={() => setWhere(item)} onClick={() => setWhere(item)}
key={`where--${item}`} key={`where--${item}`}
> >
{WhereMapping[item]} {WhereMapping[item]}
</Dropdown.Item> </DropdownItem>
); );
} }
})} })}
@ -395,12 +395,12 @@ const FiltersModal = (props: {
<Dropdown label={ListsMapping[list].name} color="blue"> <Dropdown label={ListsMapping[list].name} color="blue">
{Object.keys(ListsMapping).map((item) => { {Object.keys(ListsMapping).map((item) => {
return ( return (
<Dropdown.Item <DropdownItem
onClick={() => setList(item)} onClick={() => setList(item)}
key={`list--${item}`} key={`list--${item}`}
> >
{ListsMapping[item].name} {ListsMapping[item].name}
</Dropdown.Item> </DropdownItem>
); );
})} })}
</Dropdown> </Dropdown>
@ -414,20 +414,20 @@ const FiltersModal = (props: {
<Dropdown label={TagMapping[searchBy].name} color="blue"> <Dropdown label={TagMapping[searchBy].name} color="blue">
{Object.keys(TagMapping).map((item) => { {Object.keys(TagMapping).map((item) => {
return ( return (
<Dropdown.Item <DropdownItem
onClick={() => setSearchBy(item)} onClick={() => setSearchBy(item)}
key={`tag--${item}`} key={`tag--${item}`}
> >
{TagMapping[item].name} {TagMapping[item].name}
</Dropdown.Item> </DropdownItem>
); );
})} })}
</Dropdown> </Dropdown>
</div> </div>
</div> </div>
: ""} : ""}
</Modal.Body> </ModalBody>
<Modal.Footer> <ModalFooter>
<div className="flex justify-end w-full gap-2"> <div className="flex justify-end w-full gap-2">
<Button color="red" onClick={() => _cancel()}> <Button color="red" onClick={() => _cancel()}>
Отменить Отменить
@ -436,7 +436,7 @@ const FiltersModal = (props: {
Применить Применить
</Button> </Button>
</div> </div>
</Modal.Footer> </ModalFooter>
</Modal> </Modal>
); );
}; };

View file

@ -1,8 +1,7 @@
const { withPlausibleProxy } = require("next-plausible"); const { withPlausibleProxy } = require("next-plausible");
const withFlowbiteReact = require("flowbite-react/plugin/nextjs");
module.exports = withPlausibleProxy({ /** @type {import('next').NextConfig} */
customDomain: "https://analytics.wah.su", const NextConfig = {
})({
reactStrictMode: false, reactStrictMode: false,
images: { images: {
unoptimized: true, unoptimized: true,
@ -10,68 +9,88 @@ module.exports = withPlausibleProxy({
async headers() { async headers() {
return [ return [
{ {
source: '/bookmarks/:slug*', source: "/bookmarks/:slug*",
headers: [ headers: [
{ {
key: 'Cache-Control', key: "Cache-Control",
value: 's-maxage=2592000, stale-while-revalidate=86400', value: "s-maxage=2592000, stale-while-revalidate=86400",
}, },
], ],
}, },
{ {
source: '/collection/:slug*', source: "/collection/:slug*",
headers: [ headers: [
{ {
key: 'Cache-Control', key: "Cache-Control",
value: 's-maxage=2592000, stale-while-revalidate=86400', value: "s-maxage=2592000, stale-while-revalidate=86400",
}, },
], ],
}, },
{ {
source: '/home/:slug*', source: "/home/:slug*",
headers: [ headers: [
{ {
key: 'Cache-Control', key: "Cache-Control",
value: 's-maxage=2592000, stale-while-revalidate=86400', value: "s-maxage=2592000, stale-while-revalidate=86400",
}, },
], ],
}, },
{ {
source: '/profile/:slug*', source: "/profile/:slug*",
headers: [ headers: [
{ {
key: 'Cache-Control', key: "Cache-Control",
value: 's-maxage=2592000, stale-while-revalidate=86400', value: "s-maxage=2592000, stale-while-revalidate=86400",
}, },
], ],
}, },
{ {
source: '/release/:slug*', source: "/release/:slug*",
headers: [ headers: [
{ {
key: 'Cache-Control', key: "Cache-Control",
value: 's-maxage=2592000, stale-while-revalidate=86400', value: "s-maxage=2592000, stale-while-revalidate=86400",
}, },
], ],
}, },
{ {
source: '/related/:slug*', source: "/related/:slug*",
headers: [ headers: [
{ {
key: 'Cache-Control', key: "Cache-Control",
value: 's-maxage=2592000, stale-while-revalidate=86400', value: "s-maxage=2592000, stale-while-revalidate=86400",
}, },
], ],
}, },
{ {
source: '/search', source: "/search",
headers: [ headers: [
{ {
key: 'Cache-Control', key: "Cache-Control",
value: 's-maxage=2592000, stale-while-revalidate=86400', value: "s-maxage=2592000, stale-while-revalidate=86400",
}, },
], ],
}, },
]; ];
}, },
}); };
const config = () => {
const plugins = [withPlausibleProxy, withFlowbiteReact];
return (
plugins.reduce((acc, next) => {
console.log(`INIT: ${next.name}`);
if (next.name === "withPlausibleProxy") {
return next(acc, {
customDomain: "https://analytics.wah.su",
});
}
return next(acc);
}),
{ ...NextConfig }
);
};
console.log(config());
module.exports = config();

357
package-lock.json generated
View file

@ -11,7 +11,7 @@
"apexcharts": "^3.52.0", "apexcharts": "^3.52.0",
"deepmerge-ts": "^7.1.0", "deepmerge-ts": "^7.1.0",
"flowbite": "^2.4.1", "flowbite": "^2.4.1",
"flowbite-react": "^0.10.1", "flowbite-react": "^0.11.7",
"hls-video-element": "^1.5.0", "hls-video-element": "^1.5.0",
"markdown-to-jsx": "^7.4.7", "markdown-to-jsx": "^7.4.7",
"media-chrome": "^4.8.0", "media-chrome": "^4.8.0",
@ -153,12 +153,12 @@
} }
}, },
"node_modules/@floating-ui/core": { "node_modules/@floating-ui/core": {
"version": "1.6.6", "version": "1.6.9",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.6.tgz", "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz",
"integrity": "sha512-Vkvsw6EcpMHjvZZdMkSY+djMGFbt7CRssW99Ne8tar2WLnZ/l3dbxeTShbLQj+/s35h+Qb4cmnob+EzwtjrXGQ==", "integrity": "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@floating-ui/utils": "^0.2.6" "@floating-ui/utils": "^0.2.9"
} }
}, },
"node_modules/@floating-ui/dom": { "node_modules/@floating-ui/dom": {
@ -172,18 +172,18 @@
} }
}, },
"node_modules/@floating-ui/react": { "node_modules/@floating-ui/react": {
"version": "0.26.21", "version": "0.27.3",
"resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.21.tgz", "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.3.tgz",
"integrity": "sha512-7P5ncDIiYd6RrwpCDbKyFzvabM014QlzlumtDbK3Bck0UueC+Rp8BLS34qcGBcN1pZCTodl4QNnCVmKv4tSxfQ==", "integrity": "sha512-CLHnes3ixIFFKVQDdICjel8muhFLOBdQH7fgtHNPY8UbCNqbeKZ262G7K66lGQOUQWWnYocf7ZbUsLJgGfsLHg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@floating-ui/react-dom": "^2.1.1", "@floating-ui/react-dom": "^2.1.2",
"@floating-ui/utils": "^0.2.6", "@floating-ui/utils": "^0.2.9",
"tabbable": "^6.0.0" "tabbable": "^6.0.0"
}, },
"peerDependencies": { "peerDependencies": {
"react": ">=16.8.0", "react": ">=17.0.0",
"react-dom": ">=16.8.0" "react-dom": ">=17.0.0"
} }
}, },
"node_modules/@floating-ui/react-dom": { "node_modules/@floating-ui/react-dom": {
@ -243,6 +243,12 @@
"dev": true, "dev": true,
"license": "BSD-3-Clause" "license": "BSD-3-Clause"
}, },
"node_modules/@iarna/toml": {
"version": "2.2.5",
"resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz",
"integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==",
"license": "ISC"
},
"node_modules/@iconify-json/fa6-brands": { "node_modules/@iconify-json/fa6-brands": {
"version": "1.2.5", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/@iconify-json/fa6-brands/-/fa6-brands-1.2.5.tgz", "resolved": "https://registry.npmjs.org/@iconify-json/fa6-brands/-/fa6-brands-1.2.5.tgz",
@ -1619,6 +1625,12 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/array-timsort": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz",
"integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==",
"license": "MIT"
},
"node_modules/array-union": { "node_modules/array-union": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
@ -1749,6 +1761,18 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/ast-types": {
"version": "0.16.1",
"resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz",
"integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==",
"license": "MIT",
"dependencies": {
"tslib": "^2.0.1"
},
"engines": {
"node": ">=4"
}
},
"node_modules/ast-types-flow": { "node_modules/ast-types-flow": {
"version": "0.0.8", "version": "0.0.8",
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz",
@ -2106,6 +2130,22 @@
"node": ">= 6" "node": ">= 6"
} }
}, },
"node_modules/comment-json": {
"version": "4.2.5",
"resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.2.5.tgz",
"integrity": "sha512-bKw/r35jR3HGt5PEPm1ljsQQGyCrR8sFGNiN5L+ykDHdpO8Smxkrkla9Yi6NkQyUrb8V54PGhfMs6NrIwtxtdw==",
"license": "MIT",
"dependencies": {
"array-timsort": "^1.0.3",
"core-util-is": "^1.0.3",
"esprima": "^4.0.1",
"has-own-prop": "^2.0.0",
"repeat-string": "^1.6.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/concat-map": { "node_modules/concat-map": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@ -2138,6 +2178,12 @@
"webpack": "^5.1.0" "webpack": "^5.1.0"
} }
}, },
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
"license": "MIT"
},
"node_modules/cropperjs": { "node_modules/cropperjs": {
"version": "1.6.2", "version": "1.6.2",
"resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-1.6.2.tgz", "resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-1.6.2.tgz",
@ -2245,9 +2291,9 @@
} }
}, },
"node_modules/debounce": { "node_modules/debounce": {
"version": "2.1.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/debounce/-/debounce-2.1.0.tgz", "resolved": "https://registry.npmjs.org/debounce/-/debounce-2.2.0.tgz",
"integrity": "sha512-OkL3+0pPWCqoBc/nhO9u6TIQNTK44fnBnzuVtJAbp13Naxw9R6u21x+8tVTka87AhDZ3htqZ2pSSsZl9fqL2Wg==", "integrity": "sha512-Xks6RUDLZFdz8LIdR6q0MTH44k7FikOmnh5xkSjMig6ch45afc8sjTjRQf3P6ax8dMgcQrYO/AR2RGWURrruqw==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=18" "node": ">=18"
@ -2260,7 +2306,6 @@
"version": "4.4.0", "version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"ms": "^2.1.3" "ms": "^2.1.3"
@ -3049,6 +3094,19 @@
"url": "https://opencollective.com/eslint" "url": "https://opencollective.com/eslint"
} }
}, },
"node_modules/esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
"license": "BSD-2-Clause",
"bin": {
"esparse": "bin/esparse.js",
"esvalidate": "bin/esvalidate.js"
},
"engines": {
"node": ">=4"
}
},
"node_modules/esquery": { "node_modules/esquery": {
"version": "1.6.0", "version": "1.6.0",
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
@ -3288,34 +3346,174 @@
} }
}, },
"node_modules/flowbite-react": { "node_modules/flowbite-react": {
"version": "0.10.2", "version": "0.11.7",
"resolved": "https://registry.npmjs.org/flowbite-react/-/flowbite-react-0.10.2.tgz", "resolved": "https://registry.npmjs.org/flowbite-react/-/flowbite-react-0.11.7.tgz",
"integrity": "sha512-qkayK6IFmfH7zuuDnHmS0hJxLtL0KpW4vo4i/VQfZ6ZfaNlUsNLQxCGcmXwbZZtUm2WVw8x71aaDOAxftG9tmg==", "integrity": "sha512-Z8m+ycHEsXPacSAi8P4yYDeff7LvcHNwbGAnL/+Fpiv+6ZWDEAGY/YPKhUofZsZa837JTYrbcbmgjqQ1bpt51g==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@floating-ui/core": "1.6.6", "@floating-ui/core": "1.6.9",
"@floating-ui/react": "0.26.21", "@floating-ui/react": "0.27.3",
"@iarna/toml": "2.2.5",
"@typescript-eslint/typescript-estree": "8.26.0",
"chokidar": "4.0.3",
"classnames": "2.5.1", "classnames": "2.5.1",
"debounce": "2.1.0", "comment-json": "4.2.5",
"flowbite": "2.5.1", "debounce": "2.2.0",
"react-icons": "5.2.1", "deepmerge-ts": "7.1.4",
"tailwind-merge": "2.4.0" "klona": "2.0.6",
"package-manager-detector": "0.2.9",
"recast": "0.23.11",
"tailwind-merge-v2": "npm:tailwind-merge@2.6.0",
"tailwind-merge-v3": "npm:tailwind-merge@3.0.1"
},
"bin": {
"flowbite-react": "dist/cli/bin.js"
}, },
"peerDependencies": { "peerDependencies": {
"react": ">=18", "react": "^18 || ^19",
"react-dom": ">=18", "react-dom": "^18 || ^19",
"tailwindcss": "^3" "tailwindcss": "^3 || ^4"
} }
}, },
"node_modules/flowbite-react/node_modules/flowbite": { "node_modules/flowbite-react/node_modules/@typescript-eslint/types": {
"version": "2.5.1", "version": "8.26.0",
"resolved": "https://registry.npmjs.org/flowbite/-/flowbite-2.5.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.26.0.tgz",
"integrity": "sha512-7jP1jy9c3QP7y+KU9lc8ueMkTyUdMDvRP+lteSWgY5TigSZjf9K1kqZxmqjhbx2gBnFQxMl1GAjVThCa8cEpKA==", "integrity": "sha512-89B1eP3tnpr9A8L6PZlSjBvnJhWXtYfZhECqlBl1D9Lme9mHO6iWlsprBtVenQvY1HMhax1mWOjhtL3fh/u+pA==",
"license": "MIT",
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/flowbite-react/node_modules/@typescript-eslint/typescript-estree": {
"version": "8.26.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.26.0.tgz",
"integrity": "sha512-tiJ1Hvy/V/oMVRTbEOIeemA2XoylimlDQ03CgPPNaHYZbpsc78Hmngnt+WXZfJX1pjQ711V7g0H7cSJThGYfPQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@popperjs/core": "^2.9.3", "@typescript-eslint/types": "8.26.0",
"flowbite-datepicker": "^1.3.0", "@typescript-eslint/visitor-keys": "8.26.0",
"mini-svg-data-uri": "^1.4.3" "debug": "^4.3.4",
"fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
"minimatch": "^9.0.4",
"semver": "^7.6.0",
"ts-api-utils": "^2.0.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/flowbite-react/node_modules/@typescript-eslint/visitor-keys": {
"version": "8.26.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.26.0.tgz",
"integrity": "sha512-2z8JQJWAzPdDd51dRQ/oqIJxe99/hoLIqmf8RMCAJQtYDc535W/Jt2+RTP4bP0aKeBG1F65yjIZuczOXCmbWwg==",
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.26.0",
"eslint-visitor-keys": "^4.2.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/flowbite-react/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/flowbite-react/node_modules/chokidar": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
"license": "MIT",
"dependencies": {
"readdirp": "^4.0.1"
},
"engines": {
"node": ">= 14.16.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/flowbite-react/node_modules/deepmerge-ts": {
"version": "7.1.4",
"resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.4.tgz",
"integrity": "sha512-fxqo6nHGQ9zOVgI4KXqtWXJR/yCLtC7aXIVq+6jc8tHPFUxlFmuUcm2kC4vztQ+LJxQ3gER/XAWearGYQ8niGA==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/flowbite-react/node_modules/eslint-visitor-keys": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
"integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
"license": "Apache-2.0",
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"url": "https://opencollective.com/eslint"
}
},
"node_modules/flowbite-react/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/flowbite-react/node_modules/readdirp": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
"integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
"license": "MIT",
"engines": {
"node": ">= 14.18.0"
},
"funding": {
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/flowbite-react/node_modules/ts-api-utils": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
"integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==",
"license": "MIT",
"engines": {
"node": ">=18.12"
},
"peerDependencies": {
"typescript": ">=4.8.4"
} }
}, },
"node_modules/for-each": { "node_modules/for-each": {
@ -3660,6 +3858,15 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/has-own-prop": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/has-own-prop/-/has-own-prop-2.0.0.tgz",
"integrity": "sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/has-property-descriptors": { "node_modules/has-property-descriptors": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
@ -4417,6 +4624,15 @@
"json-buffer": "3.0.1" "json-buffer": "3.0.1"
} }
}, },
"node_modules/klona": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz",
"integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==",
"license": "MIT",
"engines": {
"node": ">= 8"
}
},
"node_modules/language-subtag-registry": { "node_modules/language-subtag-registry": {
"version": "0.3.23", "version": "0.3.23",
"resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz",
@ -4670,7 +4886,6 @@
"version": "2.1.3", "version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/mz": { "node_modules/mz": {
@ -5035,6 +5250,12 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/package-manager-detector": {
"version": "0.2.9",
"resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.9.tgz",
"integrity": "sha512-+vYvA/Y31l8Zk8dwxHhL3JfTuHPm6tlxM2A3GeQyl7ovYnSp1+mzAxClxaOr0qO1TtPxbQxetI7v5XqKLJZk7Q==",
"license": "MIT"
},
"node_modules/parent-module": { "node_modules/parent-module": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@ -5416,15 +5637,6 @@
"react": "^18.3.1" "react": "^18.3.1"
} }
}, },
"node_modules/react-icons": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.2.1.tgz",
"integrity": "sha512-zdbW5GstTzXaVKvGSyTaBalt7HSfuK5ovrzlpyiWHAFXndXTdd/1hdDHI4xBM1Mn7YriT6aqESucFl9kEXzrdw==",
"license": "MIT",
"peerDependencies": {
"react": "*"
}
},
"node_modules/react-is": { "node_modules/react-is": {
"version": "16.13.1", "version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
@ -5478,6 +5690,22 @@
"url": "https://github.com/sponsors/jonschlinkert" "url": "https://github.com/sponsors/jonschlinkert"
} }
}, },
"node_modules/recast": {
"version": "0.23.11",
"resolved": "https://registry.npmjs.org/recast/-/recast-0.23.11.tgz",
"integrity": "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==",
"license": "MIT",
"dependencies": {
"ast-types": "^0.16.1",
"esprima": "~4.0.0",
"source-map": "~0.6.1",
"tiny-invariant": "^1.3.3",
"tslib": "^2.0.1"
},
"engines": {
"node": ">= 4"
}
},
"node_modules/reflect.getprototypeof": { "node_modules/reflect.getprototypeof": {
"version": "1.0.10", "version": "1.0.10",
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
@ -5522,6 +5750,15 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/repeat-string": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
"integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==",
"license": "MIT",
"engines": {
"node": ">=0.10"
}
},
"node_modules/require-from-string": { "node_modules/require-from-string": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
@ -5790,7 +6027,6 @@
"version": "7.7.1", "version": "7.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
"dev": true,
"license": "ISC", "license": "ISC",
"bin": { "bin": {
"semver": "bin/semver.js" "semver": "bin/semver.js"
@ -5984,9 +6220,7 @@
"version": "0.6.1", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true,
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"peer": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@ -6458,10 +6692,22 @@
"integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/tailwind-merge": { "node_modules/tailwind-merge-v2": {
"version": "2.4.0", "name": "tailwind-merge",
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.4.0.tgz", "version": "2.6.0",
"integrity": "sha512-49AwoOQNKdqKPd9CViyH5wJoSKsCDjUlzL8DxuGp3P1FsGY36NJDAa18jLZcaHAUUuTj+JB8IAo8zWgBNvBF7A==", "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.0.tgz",
"integrity": "sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/dcastil"
}
},
"node_modules/tailwind-merge-v3": {
"name": "tailwind-merge",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.0.1.tgz",
"integrity": "sha512-AvzE8FmSoXC7nC+oU5GlQJbip2UO7tmOhOfQyOmPhrStOGXHU08j8mZEHZ4BmCqY5dWTCo4ClWkNyRNx1wpT0g==",
"license": "MIT", "license": "MIT",
"funding": { "funding": {
"type": "github", "type": "github",
@ -6621,6 +6867,12 @@
"node": ">=0.8" "node": ">=0.8"
} }
}, },
"node_modules/tiny-invariant": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
"integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==",
"license": "MIT"
},
"node_modules/tinyglobby": { "node_modules/tinyglobby": {
"version": "0.2.12", "version": "0.2.12",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz",
@ -6796,7 +7048,6 @@
"version": "5.8.2", "version": "5.8.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz",
"integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==",
"dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"peer": true, "peer": true,
"bin": { "bin": {

View file

@ -6,13 +6,14 @@
"dev": "next dev", "dev": "next dev",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
"lint": "next lint" "lint": "next lint",
"postinstall": "flowbite-react patch"
}, },
"dependencies": { "dependencies": {
"apexcharts": "^3.52.0", "apexcharts": "^3.52.0",
"deepmerge-ts": "^7.1.0", "deepmerge-ts": "^7.1.0",
"flowbite": "^2.4.1", "flowbite": "^2.4.1",
"flowbite-react": "^0.10.1", "flowbite-react": "^0.11.7",
"hls-video-element": "^1.5.0", "hls-video-element": "^1.5.0",
"markdown-to-jsx": "^7.4.7", "markdown-to-jsx": "^7.4.7",
"media-chrome": "^4.8.0", "media-chrome": "^4.8.0",

View file

@ -1,5 +1,9 @@
const { addIconSelectors } = require("@iconify/tailwind"); const { addIconSelectors } = require("@iconify/tailwind");
import flowbite from "flowbite-react/tailwind"; const flowbiteReact = require("flowbite-react/plugin/tailwindcss");
flowbiteReact.config = {
charts: true,
}
/** @type {import('tailwindcss').Config} */ /** @type {import('tailwindcss').Config} */
module.exports = { module.exports = {
@ -7,14 +11,12 @@ module.exports = {
"./pages/**/*.{js,ts,jsx,tsx,mdx}", "./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}", "./components/**/*.{js,ts,jsx,tsx,mdx}",
"./app/**/*.{js,ts,jsx,tsx,mdx}", "./app/**/*.{js,ts,jsx,tsx,mdx}",
flowbite.content(), ".flowbite-react\\class-list.json"
], ],
plugins: [ plugins: [
addIconSelectors(["mdi", "material-symbols", "twemoji", "fa6-brands"]), addIconSelectors(["mdi", "material-symbols", "twemoji", "fa6-brands"]),
require("tailwind-scrollbar"), require("tailwind-scrollbar"),
flowbite.plugin()({ flowbiteReact
charts: true,
}),
], ],
darkMode: "selector", darkMode: "selector",
theme: { theme: {