diff --git a/.github/workflows/backend_test.yml b/.github/workflows/backend_test.yml
index 3be87b4bb..2f79256ab 100644
--- a/.github/workflows/backend_test.yml
+++ b/.github/workflows/backend_test.yml
@@ -17,18 +17,18 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: ["3.10"]
+ python-version: ["3.12"]
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install Poetry
run: pip install poetry
- name: Install dependencies
- working-directory: backend/src
- run: poetry install
+ working-directory: backend
+ run: poetry install --with dev,docs
- name: Start MySQL
run: |
sudo systemctl enable mysql.service
@@ -48,6 +48,32 @@ jobs:
KWAI_EMAIL_PASSWORD: ${{ secrets.KWAI_EMAIL_PASSWORD }}
run: |
cat < .kwai.toml
+ [frontend]
+ test = true
+ path = ""
+ root_app = "portal"
+ [frontend.apps.portal]
+ base="/apps/portal"
+ base_dev="http://localhost:3000"
+ entries="/src/index.ts"
+ [frontend.apps.author]
+ base="/apps/author"
+ base_dev="http://localhost:3001"
+ entries="/src/index.ts"
+ [frontend.apps.auth]
+ base="/apps/auth"
+ base_dev="http://localhost:3002"
+ entries="/src/index.ts"
+ [frontend.apps.coach]
+ base="/apps/coach"
+ base_dev="http://localhost:3003"
+ entries="/src/index.ts"
+ [frontend.apps.club]
+ base="/apps/club"
+ base_dev="http://localhost:3004"
+ entries="/src/index.ts"
+ [files]
+ path = "/var/tmp/kwai"
[security]
jwt_secret="$KWAI_JWT_SECRET"
jwt_refresh_secret="$KWAI_JWT_SECRET"
@@ -87,18 +113,18 @@ jobs:
DBMATE_WAIT_TIMEOUT: "30s"
run: ./dbmate up
- name: Test with pytest
- working-directory: backend/src
+ working-directory: backend
env:
KWAI_SETTINGS_FILE: ${{github.workspace}}/.kwai.toml
run: poetry run pytest --cov=kwai --cov-report html
- name: Generate coverage badge
- working-directory: backend/src
+ working-directory: backend
run: poetry run coverage-badge -o ./htmlcov/coverage.svg
- name: Remove .gitignore from coverage report
- run: rm backend/src/htmlcov/.gitignore
+ run: rm backend/htmlcov/.gitignore
- name: Deploy coverage to github pages
uses: JamesIves/github-pages-deploy-action@4.1.0
with:
branch: gh-pages
target-folder: coverage
- folder: backend/src/htmlcov
+ folder: backend/htmlcov
diff --git a/.github/workflows/generate_docs.yml b/.github/workflows/generate_docs.yml
index af0859b8c..4624c0764 100644
--- a/.github/workflows/generate_docs.yml
+++ b/.github/workflows/generate_docs.yml
@@ -10,21 +10,21 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@master
+ uses: actions/checkout@v4
with:
fetch-depth: 0
- - uses: actions/setup-python@v3
+ - uses: actions/setup-python@v5
with:
- python-version: "3.10"
+ python-version: "3.12"
- name: Install Poetry
run: pip install poetry
- name: install
- working-directory: backend/src
- run: poetry install
+ working-directory: backend
+ run: poetry install --with docs
- name: Build documentation
- working-directory: backend/src
+ working-directory: backend
run: |
- poetry run mkdocs build -f ../../mkdocs.yml
+ poetry run mkdocs build -f ../mkdocs.yml
- name: Copy site
run: |
mkdir -p gh-pages
diff --git a/.github/workflows/mirror.yml b/.github/workflows/mirror.yml
new file mode 100644
index 000000000..c71f2e144
--- /dev/null
+++ b/.github/workflows/mirror.yml
@@ -0,0 +1,27 @@
+name: Mirror to Codeberg
+
+on:
+ push:
+ branches: ["**"]
+ tags: ["**"]
+ release:
+ types: ["published"]
+ workflow_dispatch:
+
+jobs:
+ mirror:
+ runs-on: ubuntu-latest
+ steps:
+ - name: "Checkout"
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: "Mirror to codeberg"
+ uses: cssnr/mirror-repository-action@master
+ with:
+ host: https://codeberg.org
+ owner: zumuta
+ repo: kwai
+ username: ${{ secrets.CODEBERG_USER }}
+ password: ${{ secrets.CODEBERG_TOKEN }}
diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml
index 913950c7a..344ac11bd 100644
--- a/.github/workflows/ruff.yml
+++ b/.github/workflows/ruff.yml
@@ -10,8 +10,8 @@ jobs:
ruff:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
- - uses: chartboost/ruff-action@v1
+ - uses: actions/checkout@v4
+ - uses: astral-sh/ruff-action@v1
with:
src: "${{ github.workspace }}/backend/src"
- args: --ignore D102
+ args: check --ignore D102
diff --git a/.gitignore b/.gitignore
index 757d13472..b51cc0fa0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,7 +9,6 @@
/_site/
/backend/src/.venv/
/backend/src/.coverage
-.turbo
dist
node_modules
public
@@ -24,3 +23,8 @@ __pycache__
/frontend/apps/portal/images/*.jpg
*.tsbuildinfo
stats.html
+/backend/.venv/
+/frontend/packages/kwai-config/src/config.production.toml
+.task
+/frontend/.env.test
+/backend/db/schema.sql
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 52df109fa..8e35a0967 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -22,11 +22,11 @@ repos:
language_version: python3.12
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
- rev: v0.3.2
+ rev: v0.7.3
hooks:
- id: ruff
types: [python]
- args: [--ignore=D102]
+ args: [--ignore=D102, --fix]
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.2
hooks:
diff --git a/Taskfile.yml b/Taskfile.yml
new file mode 100644
index 000000000..47b9c3696
--- /dev/null
+++ b/Taskfile.yml
@@ -0,0 +1,20 @@
+version: '3'
+
+tasks:
+ # build documentation
+ build_doc:
+ desc: Build the documentation
+ dir: backend
+ cmds:
+ - poetry run mkdocs build -f ../mkdocs.yml
+
+ serve_doc:
+ desc: Build the documentation and run the webserver
+ dir: backend
+ cmds:
+ - poetry run mkdocs serve -f ../mkdocs.yml
+
+includes:
+ frontend:
+ taskfile: ./frontend/Taskfile.yml
+ dir: ./frontend
diff --git a/backend/docs/api/api_auth.md b/backend/docs/api/api_auth.md
index 0c44c90bb..1b109081a 100644
--- a/backend/docs/api/api_auth.md
+++ b/backend/docs/api/api_auth.md
@@ -1,14 +1,57 @@
# Auth API's
-## ::: kwai.api.v1.auth.endpoints.login
- selection:
- members: no
-### ::: kwai.api.v1.auth.endpoints.login.login
-### ::: kwai.api.v1.auth.endpoints.login.logout
-### ::: kwai.api.v1.auth.endpoints.login.recover_user
-### ::: kwai.api.v1.auth.endpoints.login.renew_access_token
-### ::: kwai.api.v1.auth.endpoints.login.reset_password
+All API's used for authentication, authorization, users, ...
-# Auth Responses
+## /api/v1/auth
-### ::: kwai.api.v1.auth.endpoints.login.TokenSchema
+### Requests
+
+::: kwai.api.v1.auth.endpoints.login.renew_access_token
+ options:
+ heading_level: 4
+
+::: kwai.api.v1.auth.endpoints.login.login
+ options:
+ heading_level: 4
+
+::: kwai.api.v1.auth.endpoints.login.logout
+ options:
+ heading_level: 4
+
+::: kwai.api.v1.auth.endpoints.login.recover_user
+ options:
+ heading_level: 4
+
+::: kwai.api.v1.auth.endpoints.login.reset_password
+ options:
+ heading_level: 4
+
+::: kwai.api.v1.auth.endpoints.user.get
+ options:
+ heading_level: 4
+
+### Responses
+
+#### ::: kwai.api.v1.auth.endpoints.login.TokenSchema
+ options:
+ show_root_toc_entry: false
+
+## /api/v1/auth/users
+
+### Requests
+
+::: kwai.api.v1.auth.endpoints.user_invitations.create_user_invitation
+ options:
+ heading_level: 4
+
+::: kwai.api.v1.auth.endpoints.user_invitations.delete_user_invitation
+ options:
+ heading_level: 4
+
+::: kwai.api.v1.auth.endpoints.user_invitations.get_user_invitations
+ options:
+ heading_level: 4
+
+::: kwai.api.v1.auth.endpoints.user_invitations.get_user_invitation
+ options:
+ heading_level: 4
diff --git a/backend/docs/api/index.md b/backend/docs/api/index.md
new file mode 100644
index 000000000..88ad15bf9
--- /dev/null
+++ b/backend/docs/api/index.md
@@ -0,0 +1,13 @@
+# API
+
+## [Authentication](./api_auth.md)
+
+All API's related to authentication.
+
+!!! Note
+
+ Use [swagger](https://swagger.io/) UI from [FastAPI](https://fastapi.tiangolo.com) to get a list of
+ all available api's.
+
+ When the Kwai api backend is running in test mode, point your browser
+ to `http://localhost:/api/docs`.
diff --git a/backend/docs/architecture.md b/backend/docs/architecture.md
new file mode 100644
index 000000000..8b4dc28a9
--- /dev/null
+++ b/backend/docs/architecture.md
@@ -0,0 +1,60 @@
+Architecture
+============
+
+Kwai tries to follow the [clean architecture](http://cleancoder.com) principles. The [frontend]() is already a
+separated layer. The backend code is using the domain driven design (DDD) for modeling the software.
+
+One of the rules of clean architecture is that when you don't own or control something, then keep it on the
+outside of your design or wrap it. This means for example, that the domain code isn't allowed to contain FastAPI code
+or database related code. The code for the API is on the outside because it's the entry point of a call to the system.
+Presenters are used to transform domain objects into JSON:API documents. The repository pattern keeps the
+database code on the outside. And interfaces are used to protect the inside from the outside.
+
+The [pendulum](https://pendulum.eustace.io/) library is used for processing dates and timestamps. Because kwai doesn't
+own this code, the pendulum code is wrapped into value objects (Timestamp, Date, ...). If the pendulum package is
+outdated, we only need to change these value objects.
+
+> This is also the reason why [Pydantic](https://docs.pydantic.dev/latest/) isn't used for entities or value objects.
+> Pydantic is great for validation and serialization, but we don't want Pydantic to become a dependency of the kwai
+> domain.
+
+Dependency injection containers are only used on the outside. There should not be any magic code in the domain.
+So, dependency injection containers can only be used in the API entry code, the CLI entry code, ... From there on,
+the dependency should be passed as an argument (and passing it down should be done using an interface).
+
+Actors
+======
+
+Who are the actors in our application?
+
+Visitor
+-------
+
+A visitor is a person that visits our website. He/She does not have any permissions and is
+not known in the system.
+
+Member
+------
+
+A member is a person that is a member of the club.
+
+Coach
+-----
+
+A coach is a member of the club. A coach can create/view/update/delete trainings. A coach can also registers
+participants for a training. When participants are registered, a training can't be deleted anymore.
+
+````mermaid
+sequenceDiagram
+ actor Coach
+ Coach->>Trainings: View
+ Coach->>Trainings: Create
+ Coach->>Trainings: Update
+ Coach->>Trainings: Delete
+ Coach->>Trainings: Register participants
+````
+
+Admin
+-----
+
+An administrator is a person that manages the website.
diff --git a/backend/docs/cli.md b/backend/docs/cli.md
index fbc2aece0..466b642d8 100644
--- a/backend/docs/cli.md
+++ b/backend/docs/cli.md
@@ -1,10 +1,10 @@
# Command Line Interface
-A command line interface (CLI) is provided to help managing the kwai system. To run the cli, use the kwai_cli.py
+A command line interface (CLI) is provided to help managing the kwai system. To run the cli, use the kwai_cli.py
script:
`kwai_cli.py --help`
-::: kwai.cli.bus
+::: kwai.cli.commands.bus
options:
show_root_full_path: False
show_signature: False
@@ -12,7 +12,7 @@ script:
- show
- test
-::: kwai.cli.db
+::: kwai.cli.commands.db
options:
show_root_full_path: False
show_signature: False
@@ -20,10 +20,9 @@ script:
- show
- test
-::: kwai.cli.identity
+::: kwai.cli.commands.identity
options:
show_root_full_path: False
show_signature: False
members:
- create
-
diff --git a/backend/docs/deploy.md b/backend/docs/deploy.md
index e1c1cc446..06b979f4d 100644
--- a/backend/docs/deploy.md
+++ b/backend/docs/deploy.md
@@ -2,30 +2,32 @@
This page will describe how you can deploy the backend of kwai.
-## Step 1: Clone
+## Step 1: Build
First you need to get the latest version. The repository is a monorepo.
This means the backend code and the frontend code are in the same repository.
-We only need the backend here:
+We only need the backend. Set up the [development environment](./index.md) for kwai
+and build the wheel file.
````shell
-git clone --no-checkout https://codeberg.org/zumuta/kwai.git
-cd kwai
-git sparse-checkout init --cone
-git sparse-checkout set backend
-git checkout
+cd backend
+poetry build
````
-> When sparse-checkout is not available, you can safely remove the frontend directory.
+This command creates a dist folder where you find two files: a tar.gz with the source code and a .whl file
+that can used to install kwai.
+Transfer the .whl file to your host.
## Step 2: Python Environment
-Kwai needs a Python environment. [Poetry](https://python-poetry.org/) is used as Python packaging and
-dependency management tool. Make sure it is available.
+Kwai needs a Python environment. It is recommended to create a separate environment for kwai.
+Run the following command on your host:
````shell
-cd backend/src
-poetry install
+mkdir backend
+python3 -m venv .venv
+source .venv/bin/activate
+pip install kwai-x.x.x-py3-none-any.whl
````
## Step 3: Configuration
@@ -41,25 +43,67 @@ cp kwai.dist.toml .kwai.toml
Use an editor to change the configuration. Set the environment
variable `KWAI_SETTINGS_FILE` with the full path of this configuration file.
-## Step 4: Migration
+## Step 4: Templates
+
+kwai requires jinja2 templates. Copy the templates to a folder on the server
+and update the `path` setting in the `template` section of the configuration file.
+
+## Step 5: Migration
When there are database changes required, a migration must run before
-starting the backend.
+starting the backend. Copy the migrations folder to your server and use dbmate to upgrade.
> [dbmate](https://github.com/amacneil/dbmate) is used for database migrations. Make sure it is available.
````shell
-cd backend/migrations
+cd /migrations
dbmate -d . -u "" up
````
-## Step 4: Run
+## Step 6: Frontend
+
+The frontend is also served by the FastAPI backend.
+
+To build the frontend you need [Node](https://nodejs.org/en).
+
+````shell
+cd frontend
+npm install
+npm run build
+````
+
+!!! Note
+ You can also use [Task](https://taskfile.dev/) to build the frontend. Run the following
+ command from the kwai root folder:
+ `task frontend:build`
-To start the application use the following command:
+This will result in a folder `dist` in all the frontend applications.
+FastAPI will be used to render the frontend. Add all applications to the `.kwai.toml` configuration file:
+
+````toml
+[frontend]
+path = "/home/kwai/frontend"
+root_app = "portal"
+
+[frontend.apps]
+
+[frontend.apps.portal]
+base="/apps/portal"
+entries="/src/index.ts"
+````
+
+In this example there should be a `/home/kwai/frontend/apps/portal/dist` folder that contains the result of the
+build command.
+
+## Step 7: Run
+
+To start the backend application use the following command:
````shell
-cd backend/src
-poetry run python -m kwai.api
+cd backend
+
+source .venv/bin/activate
+python -m kwai
````
This python script will start an uvicorn server. The host
diff --git a/backend/docs/index.md b/backend/docs/index.md
index 79beafc87..041dbfa10 100644
--- a/backend/docs/index.md
+++ b/backend/docs/index.md
@@ -5,11 +5,17 @@
[![coverage](./tests/coverage/coverage.svg)](./tests/coverage/index.html)
-kwai API is the backend for the kwai sports club management system.
+This is the backend for the KWAI sports club management system. This system
+contains a [JSON:API](https://jsonapi.org/) REST API, a CLI and an event bus.
-All server side code is written with Python using [FastAPI](https://fastapi.tiangolo.com/) as web framework.
+All server side code is written with Python using [FastAPI](https://fastapi.tiangolo.com/) for the REST API
+and [Typer](https://typer.tiangolo.com/) for the CLI.
+Currently, the event bus is custom code and not in use yet.
-## Install
+!!! note
+ The frontend is also served by FastAPI.
+
+## Develop
### Prerequisites
@@ -18,12 +24,12 @@ Clone the repository to your system.
[Poetry](https://python-poetry.org/) is used as Python packaging and
dependency management tool. Make sure it is available.
-Use Poetry to install all the dependencies: Make `backend/src` the current directory
+Use Poetry to install all the dependencies: Make `backend` the current directory
and run:
`poetry install`
-This will only install the modules required to run kwai, for developing add `dev` and `docs` dependencies:
+This will only install the modules required to run KWAI, for developing add `dev` and `docs` dependencies:
`poetry install --with dev,docs`
@@ -40,7 +46,7 @@ available from the internet.
### Database
-kwai needs a database. Migration files are available in the folder migrations.
+KWAI needs a database. Migration files are available in the folder migrations.
[Dbmate](https://github.com/amacneil/dbmate) is used as migration tool.
```console
@@ -76,7 +82,7 @@ Use `kwai.dist.yaml` file to create `kwai.yaml` in each machine folder. This fil
> Don't add `kwai.yaml` to version control!
-## Develop
+### Tools
The backend is written in Python. The following tools are used to develop kwai:
+ [Poetry](https://python-poetry.org/) for managing dependencies.
@@ -87,39 +93,42 @@ The backend is written in Python. The following tools are used to develop kwai:
There are pre-commit hooks defined for formatting and linting the code. Use
Poetry to create the pre-commit hooks:
+> Use the backend folder as working directory for the poetry commands.
+
````
-poetry -C ./backend/src/pyproject.toml pre-commit install
+poetry run pre-commit install
````
-### Testing
-Use the development vagrant machine to run kwai while developing. Use the test machine to test all code before pushing
-code to the remote repository. In a development environment, poetry and pytest can be used to run the tests. On the
-test machine, a script `kwai_test.sh` is provided to run the tests. This script will also update the coverage
-documentation.
+There are several github actions defined:
+
++ backend_test: will run all pytest test when code is pushed in backend/src.
++ generate_docs: will generate this documentation.
++ mirror: will copy the repository to codeberg.
++ ruff: will check the code.
-## Project structure
+### Project structure
The kwai API code in the repository is located in the `backend` folder.
-### docs
+#### docs
This folder contains all files for creating this documentation site.
-### migrations
+#### migrations
This folder contains the database migrations.
[Dbmate](https://github.com/amacneil/dbmate) is used as migration tool.
-### src
+#### src
This folder contains the Python code. The system is written following DDD as software development philosophy.
Clean code should be the result of following this philosophy. The folder `kwai` contains the
program code, `tests` contains the [pytest](https://pytest.org) code for testing the program code.
-### templates
+#### templates
This folder contains all templates used by kwai.
-### vagrant
+#### vagrant
This folder contains two vagrant machines: one for development and one for testing.
diff --git a/backend/kwai.dist.toml b/backend/kwai.dist.toml
index caf0cb145..748a1a3b9 100644
--- a/backend/kwai.dist.toml
+++ b/backend/kwai.dist.toml
@@ -1,4 +1,36 @@
# Rename this file to kwai.toml and set the env KWAI_SETTINGS_FILE to the path of this file.
+[frontend]
+test = false
+path = "" # Where are the frontend applications deployed?
+root_app = "portal" # Which app should be used as default?
+
+[frontend.apps]
+
+[frontend.apps.portal]
+server="http://localhost:3000" # Only necessary in test mode
+base="/apps/portal" # Only necessary in test mode
+entries="src/index.ts"
+
+[frontend.apps.author]
+server="http://localhost:3001" # Only necessary in test mode
+base="/apps/author" # Only necessary in test mode
+entries="src/index.ts"
+
+[frontend.apps.auth]
+server="http://localhost:3002" # Only necessary in test mode
+base="/apps/auth" # Only necessary in test mode
+entries="src/index.ts"
+
+[frontend.apps.coach]
+server="http://localhost:3003" # Only necessary in test mode
+base="/apps/coach" # Only necessary in test mode
+entries="src/index.ts"
+
+[frontend.apps.club]
+server="http://localhost:3004" # Only necessary in test mode
+base="/apps/club" # Only necessary in test mode
+entries="src/index.ts"
+
[files]
path="/var/tmp/kwai"
diff --git a/backend/migrations/20240525191900_upload_preview.sql b/backend/migrations/20240525191900_upload_preview.sql
new file mode 100644
index 000000000..e7fa8796e
--- /dev/null
+++ b/backend/migrations/20240525191900_upload_preview.sql
@@ -0,0 +1,5 @@
+-- migrate:up
+
+alter table imports add column preview tinyint(1) default 0 not null;
+
+-- migrate:down
diff --git a/backend/migrations/20240601194900_member_id.sql b/backend/migrations/20240601194900_member_id.sql
new file mode 100644
index 000000000..b34822dda
--- /dev/null
+++ b/backend/migrations/20240601194900_member_id.sql
@@ -0,0 +1,6 @@
+-- migrate:up
+
+alter table coaches rename column person_id to member_id;
+alter table team_members rename column person_id to member_id;
+
+-- migrate:down
diff --git a/backend/migrations/db/schema.sql b/backend/migrations/db/schema.sql
index 9e96d8987..86c6afaa8 100644
--- a/backend/migrations/db/schema.sql
+++ b/backend/migrations/db/schema.sql
@@ -41,7 +41,7 @@ CREATE TABLE `applications` (
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `coaches` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
- `person_id` int NOT NULL,
+ `member_id` int NOT NULL,
`description` text,
`diploma` varchar(255) DEFAULT NULL,
`active` tinyint(1) NOT NULL DEFAULT '1',
@@ -108,6 +108,7 @@ CREATE TABLE `imports` (
`user_id` int NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NULL DEFAULT NULL,
+ `preview` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
/*!40101 SET character_set_client = @saved_cs_client */;
@@ -346,11 +347,11 @@ CREATE TABLE `team_categories` (
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `team_members` (
`team_id` int NOT NULL,
- `person_id` int NOT NULL,
+ `member_id` int NOT NULL,
`active` tinyint(1) NOT NULL DEFAULT '1',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NULL DEFAULT NULL,
- PRIMARY KEY (`team_id`,`person_id`)
+ PRIMARY KEY (`team_id`,`member_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
/*!40101 SET character_set_client = @saved_cs_client */;
@@ -554,7 +555,7 @@ CREATE TABLE `users` (
`uuid` varchar(255) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NULL DEFAULT NULL,
- `person_id` int DEFAULT NULL,
+ `member_id` int DEFAULT NULL,
`revoked` tinyint(1) NOT NULL DEFAULT '0',
`last_unsuccessful_login` datetime DEFAULT NULL,
`admin` tinyint(1) NOT NULL DEFAULT '0',
@@ -586,5 +587,7 @@ INSERT INTO `schema_migrations` (version) VALUES
('20230128205126'),
('20231110160912'),
('20240201192100'),
- ('20240502185700');
+ ('20240502185700'),
+ ('20240525191900'),
+ ('20240601194900');
UNLOCK TABLES;
diff --git a/backend/mkdocs.yml b/backend/mkdocs.yml
index 9c13b578d..303f34d4c 100644
--- a/backend/mkdocs.yml
+++ b/backend/mkdocs.yml
@@ -4,8 +4,8 @@ docs_dir: docs
nav:
- index.md
- - API:
- - auth: api/api_auth.md
+ - architecture.md
+ - api/index.md
- cli.md
- source.md
- deploy.md
diff --git a/backend/poetry.lock b/backend/poetry.lock
new file mode 100644
index 000000000..937d3874f
--- /dev/null
+++ b/backend/poetry.lock
@@ -0,0 +1,3221 @@
+# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
+
+[[package]]
+name = "aiohappyeyeballs"
+version = "2.4.3"
+description = "Happy Eyeballs for asyncio"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "aiohappyeyeballs-2.4.3-py3-none-any.whl", hash = "sha256:8a7a83727b2756f394ab2895ea0765a0a8c475e3c71e98d43d76f22b4b435572"},
+ {file = "aiohappyeyeballs-2.4.3.tar.gz", hash = "sha256:75cf88a15106a5002a8eb1dab212525c00d1f4c0fa96e551c9fbe6f09a621586"},
+]
+
+[[package]]
+name = "aiohttp"
+version = "3.11.7"
+description = "Async http client/server framework (asyncio)"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "aiohttp-3.11.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8bedb1f6cb919af3b6353921c71281b1491f948ca64408871465d889b4ee1b66"},
+ {file = "aiohttp-3.11.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f5022504adab881e2d801a88b748ea63f2a9d130e0b2c430824682a96f6534be"},
+ {file = "aiohttp-3.11.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e22d1721c978a6494adc824e0916f9d187fa57baeda34b55140315fa2f740184"},
+ {file = "aiohttp-3.11.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e993676c71288618eb07e20622572b1250d8713e7e00ab3aabae28cb70f3640d"},
+ {file = "aiohttp-3.11.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e13a05db87d3b241c186d0936808d0e4e12decc267c617d54e9c643807e968b6"},
+ {file = "aiohttp-3.11.7-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4ba8d043fed7ffa117024d7ba66fdea011c0e7602327c6d73cacaea38abe4491"},
+ {file = "aiohttp-3.11.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dda3ed0a7869d2fa16aa41f9961ade73aa2c2e3b2fcb0a352524e7b744881889"},
+ {file = "aiohttp-3.11.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43bfd25113c1e98aec6c70e26d5f4331efbf4aa9037ba9ad88f090853bf64d7f"},
+ {file = "aiohttp-3.11.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3dd3e7e7c9ef3e7214f014f1ae260892286647b3cf7c7f1b644a568fd410f8ca"},
+ {file = "aiohttp-3.11.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:78c657ece7a73b976905ab9ec8be9ef2df12ed8984c24598a1791c58ce3b4ce4"},
+ {file = "aiohttp-3.11.7-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:db70a47987e34494b451a334605bee57a126fe8d290511349e86810b4be53b01"},
+ {file = "aiohttp-3.11.7-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:9e67531370a3b07e49b280c1f8c2df67985c790ad2834d1b288a2f13cd341c5f"},
+ {file = "aiohttp-3.11.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9202f184cc0582b1db15056f2225ab4c1e3dac4d9ade50dd0613ac3c46352ac2"},
+ {file = "aiohttp-3.11.7-cp310-cp310-win32.whl", hash = "sha256:2257bdd5cf54a4039a4337162cd8048f05a724380a2283df34620f55d4e29341"},
+ {file = "aiohttp-3.11.7-cp310-cp310-win_amd64.whl", hash = "sha256:b7215bf2b53bc6cb35808149980c2ae80a4ae4e273890ac85459c014d5aa60ac"},
+ {file = "aiohttp-3.11.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:cea52d11e02123f125f9055dfe0ccf1c3857225fb879e4a944fae12989e2aef2"},
+ {file = "aiohttp-3.11.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3ce18f703b7298e7f7633efd6a90138d99a3f9a656cb52c1201e76cb5d79cf08"},
+ {file = "aiohttp-3.11.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:670847ee6aeb3a569cd7cdfbe0c3bec1d44828bbfbe78c5d305f7f804870ef9e"},
+ {file = "aiohttp-3.11.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4dda726f89bfa5c465ba45b76515135a3ece0088dfa2da49b8bb278f3bdeea12"},
+ {file = "aiohttp-3.11.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c25b74a811dba37c7ea6a14d99eb9402d89c8d739d50748a75f3cf994cf19c43"},
+ {file = "aiohttp-3.11.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5522ee72f95661e79db691310290c4618b86dff2d9b90baedf343fd7a08bf79"},
+ {file = "aiohttp-3.11.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1fbf41a6bbc319a7816ae0f0177c265b62f2a59ad301a0e49b395746eb2a9884"},
+ {file = "aiohttp-3.11.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:59ee1925b5a5efdf6c4e7be51deee93984d0ac14a6897bd521b498b9916f1544"},
+ {file = "aiohttp-3.11.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:24054fce8c6d6f33a3e35d1c603ef1b91bbcba73e3f04a22b4f2f27dac59b347"},
+ {file = "aiohttp-3.11.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:351849aca2c6f814575c1a485c01c17a4240413f960df1bf9f5deb0003c61a53"},
+ {file = "aiohttp-3.11.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:12724f3a211fa243570e601f65a8831372caf1a149d2f1859f68479f07efec3d"},
+ {file = "aiohttp-3.11.7-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:7ea4490360b605804bea8173d2d086b6c379d6bb22ac434de605a9cbce006e7d"},
+ {file = "aiohttp-3.11.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e0bf378db07df0a713a1e32381a1b277e62ad106d0dbe17b5479e76ec706d720"},
+ {file = "aiohttp-3.11.7-cp311-cp311-win32.whl", hash = "sha256:cd8d62cab363dfe713067027a5adb4907515861f1e4ce63e7be810b83668b847"},
+ {file = "aiohttp-3.11.7-cp311-cp311-win_amd64.whl", hash = "sha256:bf0e6cce113596377cadda4e3ac5fb89f095bd492226e46d91b4baef1dd16f60"},
+ {file = "aiohttp-3.11.7-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:4bb7493c3e3a36d3012b8564bd0e2783259ddd7ef3a81a74f0dbfa000fce48b7"},
+ {file = "aiohttp-3.11.7-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e143b0ef9cb1a2b4f74f56d4fbe50caa7c2bb93390aff52f9398d21d89bc73ea"},
+ {file = "aiohttp-3.11.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f7c58a240260822dc07f6ae32a0293dd5bccd618bb2d0f36d51c5dbd526f89c0"},
+ {file = "aiohttp-3.11.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d20cfe63a1c135d26bde8c1d0ea46fd1200884afbc523466d2f1cf517d1fe33"},
+ {file = "aiohttp-3.11.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12e4d45847a174f77b2b9919719203769f220058f642b08504cf8b1cf185dacf"},
+ {file = "aiohttp-3.11.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cf4efa2d01f697a7dbd0509891a286a4af0d86902fc594e20e3b1712c28c0106"},
+ {file = "aiohttp-3.11.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ee6a4cdcbf54b8083dc9723cdf5f41f722c00db40ccf9ec2616e27869151129"},
+ {file = "aiohttp-3.11.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c6095aaf852c34f42e1bd0cf0dc32d1e4b48a90bfb5054abdbb9d64b36acadcb"},
+ {file = "aiohttp-3.11.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1cf03d27885f8c5ebf3993a220cc84fc66375e1e6e812731f51aab2b2748f4a6"},
+ {file = "aiohttp-3.11.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:1a17f6a230f81eb53282503823f59d61dff14fb2a93847bf0399dc8e87817307"},
+ {file = "aiohttp-3.11.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:481f10a1a45c5f4c4a578bbd74cff22eb64460a6549819242a87a80788461fba"},
+ {file = "aiohttp-3.11.7-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:db37248535d1ae40735d15bdf26ad43be19e3d93ab3f3dad8507eb0f85bb8124"},
+ {file = "aiohttp-3.11.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9d18a8b44ec8502a7fde91446cd9c9b95ce7c49f1eacc1fb2358b8907d4369fd"},
+ {file = "aiohttp-3.11.7-cp312-cp312-win32.whl", hash = "sha256:3d1c9c15d3999107cbb9b2d76ca6172e6710a12fda22434ee8bd3f432b7b17e8"},
+ {file = "aiohttp-3.11.7-cp312-cp312-win_amd64.whl", hash = "sha256:018f1b04883a12e77e7fc161934c0f298865d3a484aea536a6a2ca8d909f0ba0"},
+ {file = "aiohttp-3.11.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:241a6ca732d2766836d62c58c49ca7a93d08251daef0c1e3c850df1d1ca0cbc4"},
+ {file = "aiohttp-3.11.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:aa3705a8d14de39898da0fbad920b2a37b7547c3afd2a18b9b81f0223b7d0f68"},
+ {file = "aiohttp-3.11.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9acfc7f652b31853eed3b92095b0acf06fd5597eeea42e939bd23a17137679d5"},
+ {file = "aiohttp-3.11.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcefcf2915a2dbdbce37e2fc1622129a1918abfe3d06721ce9f6cdac9b6d2eaa"},
+ {file = "aiohttp-3.11.7-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c1f6490dd1862af5aae6cfcf2a274bffa9a5b32a8f5acb519a7ecf5a99a88866"},
+ {file = "aiohttp-3.11.7-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1ac5462582d6561c1c1708853a9faf612ff4e5ea5e679e99be36143d6eabd8e"},
+ {file = "aiohttp-3.11.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c1a6309005acc4b2bcc577ba3b9169fea52638709ffacbd071f3503264620da"},
+ {file = "aiohttp-3.11.7-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f5b973cce96793725ef63eb449adfb74f99c043c718acb76e0d2a447ae369962"},
+ {file = "aiohttp-3.11.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ce91a24aac80de6be8512fb1c4838a9881aa713f44f4e91dd7bb3b34061b497d"},
+ {file = "aiohttp-3.11.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:875f7100ce0e74af51d4139495eec4025affa1a605280f23990b6434b81df1bd"},
+ {file = "aiohttp-3.11.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c171fc35d3174bbf4787381716564042a4cbc008824d8195eede3d9b938e29a8"},
+ {file = "aiohttp-3.11.7-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ee9afa1b0d2293c46954f47f33e150798ad68b78925e3710044e0d67a9487791"},
+ {file = "aiohttp-3.11.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8360c7cc620abb320e1b8d603c39095101391a82b1d0be05fb2225471c9c5c52"},
+ {file = "aiohttp-3.11.7-cp313-cp313-win32.whl", hash = "sha256:7a9318da4b4ada9a67c1dd84d1c0834123081e746bee311a16bb449f363d965e"},
+ {file = "aiohttp-3.11.7-cp313-cp313-win_amd64.whl", hash = "sha256:fc6da202068e0a268e298d7cd09b6e9f3997736cd9b060e2750963754552a0a9"},
+ {file = "aiohttp-3.11.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:17829f37c0d31d89aa6b8b010475a10233774771f9b6dc2cc352ea4f8ce95d9a"},
+ {file = "aiohttp-3.11.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d6177077a31b1aecfc3c9070bd2f11419dbb4a70f30f4c65b124714f525c2e48"},
+ {file = "aiohttp-3.11.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:badda65ac99555791eed75e234afb94686ed2317670c68bff8a4498acdaee935"},
+ {file = "aiohttp-3.11.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0de6466b9d742b4ee56fe1b2440706e225eb48c77c63152b1584864a236e7a50"},
+ {file = "aiohttp-3.11.7-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:04b0cc74d5a882c9dacaeeccc1444f0233212b6f5be8bc90833feef1e1ce14b9"},
+ {file = "aiohttp-3.11.7-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c7af3e50e5903d21d7b935aceed901cc2475463bc16ddd5587653548661fdb"},
+ {file = "aiohttp-3.11.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c63f898f683d1379b9be5afc3dd139e20b30b0b1e0bf69a3fc3681f364cf1629"},
+ {file = "aiohttp-3.11.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fdadc3f6a32d6eca45f9a900a254757fd7855dfb2d8f8dcf0e88f0fae3ff8eb1"},
+ {file = "aiohttp-3.11.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d329300fb23e14ed1f8c6d688dfd867d1dcc3b1d7cd49b7f8c5b44e797ce0932"},
+ {file = "aiohttp-3.11.7-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:5578cf40440eafcb054cf859964bc120ab52ebe0e0562d2b898126d868749629"},
+ {file = "aiohttp-3.11.7-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:7b2f8107a3c329789f3c00b2daad0e35f548d0a55cda6291579136622099a46e"},
+ {file = "aiohttp-3.11.7-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:43dd89a6194f6ab02a3fe36b09e42e2df19c211fc2050ce37374d96f39604997"},
+ {file = "aiohttp-3.11.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d2fa6fc7cc865d26ff42480ac9b52b8c9b7da30a10a6442a9cdf429de840e949"},
+ {file = "aiohttp-3.11.7-cp39-cp39-win32.whl", hash = "sha256:a7d9a606355655617fee25dd7e54d3af50804d002f1fd3118dd6312d26692d70"},
+ {file = "aiohttp-3.11.7-cp39-cp39-win_amd64.whl", hash = "sha256:53c921b58fdc6485d6b2603e0132bb01cd59b8f0620ffc0907f525e0ba071687"},
+ {file = "aiohttp-3.11.7.tar.gz", hash = "sha256:01a8aca4af3da85cea5c90141d23f4b0eee3cbecfd33b029a45a80f28c66c668"},
+]
+
+[package.dependencies]
+aiohappyeyeballs = ">=2.3.0"
+aiosignal = ">=1.1.2"
+attrs = ">=17.3.0"
+frozenlist = ">=1.1.1"
+multidict = ">=4.5,<7.0"
+propcache = ">=0.2.0"
+yarl = ">=1.17.0,<2.0"
+
+[package.extras]
+speedups = ["Brotli", "aiodns (>=3.2.0)", "brotlicffi"]
+
+[[package]]
+name = "aiosignal"
+version = "1.3.1"
+description = "aiosignal: a list of registered asynchronous callbacks"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"},
+ {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"},
+]
+
+[package.dependencies]
+frozenlist = ">=1.1.0"
+
+[[package]]
+name = "annotated-types"
+version = "0.7.0"
+description = "Reusable constraint types to use with typing.Annotated"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"},
+ {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"},
+]
+
+[[package]]
+name = "anyio"
+version = "4.6.2.post1"
+description = "High level compatibility layer for multiple asynchronous event loop implementations"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "anyio-4.6.2.post1-py3-none-any.whl", hash = "sha256:6d170c36fba3bdd840c73d3868c1e777e33676a69c3a72cf0a0d5d6d8009b61d"},
+ {file = "anyio-4.6.2.post1.tar.gz", hash = "sha256:4c8bc31ccdb51c7f7bd251f51c609e038d63e34219b44aa86e47576389880b4c"},
+]
+
+[package.dependencies]
+idna = ">=2.8"
+sniffio = ">=1.1"
+
+[package.extras]
+doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"]
+test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21.0b1)"]
+trio = ["trio (>=0.26.1)"]
+
+[[package]]
+name = "async-lru"
+version = "2.0.4"
+description = "Simple LRU cache for asyncio"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "async-lru-2.0.4.tar.gz", hash = "sha256:b8a59a5df60805ff63220b2a0c5b5393da5521b113cd5465a44eb037d81a5627"},
+ {file = "async_lru-2.0.4-py3-none-any.whl", hash = "sha256:ff02944ce3c288c5be660c42dbcca0742b32c3b279d6dceda655190240b99224"},
+]
+
+[[package]]
+name = "asyncmy"
+version = "0.2.9"
+description = "A fast asyncio MySQL driver"
+optional = false
+python-versions = ">=3.7,<4.0"
+files = [
+ {file = "asyncmy-0.2.9-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:d077eaee9a126f36bbe95e0412baa89e93172dd46193ef7bf7650a686e458e50"},
+ {file = "asyncmy-0.2.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83cf951a44294626df43c5a85cf328297c3bac63f25ede216f9706514dabb322"},
+ {file = "asyncmy-0.2.9-cp310-cp310-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:8a1d63c1bb8e3a09c90767199954fd423c48084a1f6c0d956217bc2e48d37d6d"},
+ {file = "asyncmy-0.2.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ecad6826086e47596c6aa65dcbe221305f3d9232f0d4de11b8562ee2c55464a"},
+ {file = "asyncmy-0.2.9-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4a664d58f9ebe4132f6cb3128206392be8ad71ad6fb09a5f4a990b04ec142024"},
+ {file = "asyncmy-0.2.9-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f2bbd7b75e2d751216f48c3b1b5092b812d70c2cd0053f8d2f50ec3f76a525a8"},
+ {file = "asyncmy-0.2.9-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:55e3bc41aa0d4ab410fc3a1d0c31b9cdb6688cd3b0cae6f2ee49c2e7f42968be"},
+ {file = "asyncmy-0.2.9-cp310-cp310-win32.whl", hash = "sha256:ea44eefc965c62bcfebf34e9ef00f6e807edf51046046767c56914243e0737e4"},
+ {file = "asyncmy-0.2.9-cp310-cp310-win_amd64.whl", hash = "sha256:2b4a2a7cf0bd5051931756e765fefef3c9f9561550e0dd8b1e79308d048b710a"},
+ {file = "asyncmy-0.2.9-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:e2b77f03a17a8db338d74311e38ca6dbd4ff9aacb07d2af6b9e0cac9cf1c7b87"},
+ {file = "asyncmy-0.2.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c19f27b7ff0e297f2981335a85599ffe1c9a8a35c97230203321d5d6e9e4cb30"},
+ {file = "asyncmy-0.2.9-cp311-cp311-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:bf18aef65ac98f5130ca588c55a83a56e74ae416cf0fe2c0757a2b597c4269d0"},
+ {file = "asyncmy-0.2.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ef02186cc02cb767ee5d5cf9ab002d5c7910a1a9f4c16a666867a9325c9ec5e"},
+ {file = "asyncmy-0.2.9-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:696da0f71db0fe11e62fa58cd5a27d7c9d9a90699d13d82640755d0061da0624"},
+ {file = "asyncmy-0.2.9-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:84d20745bb187ced05bd4072ae8b0bff4b4622efa23b79935519edb717174584"},
+ {file = "asyncmy-0.2.9-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ea242364523f6205c4426435272bd57cbf593c20d5e5551efb28d44cfbd595c2"},
+ {file = "asyncmy-0.2.9-cp311-cp311-win32.whl", hash = "sha256:47609d34e6b49fc5ad5bd2a2a593ca120e143e2a4f4206f27a543c5c598a18ca"},
+ {file = "asyncmy-0.2.9-cp311-cp311-win_amd64.whl", hash = "sha256:0d56df7342f7b5467a9d09a854f0e5602c8da09afdad8181ba40b0434d66d8a4"},
+ {file = "asyncmy-0.2.9-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63c2a98f225560f9a52d5bd0d2e58517639e209e5d996e9ab7470e661b39394d"},
+ {file = "asyncmy-0.2.9-cp37-cp37m-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:20ae3acc326b4b104949cc5e3a728a927e671f671c6f26266ad4a44f57ea9a5b"},
+ {file = "asyncmy-0.2.9-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8171a64888453423a17ae507cd97d256541ea880b314bba16376ab9deffef6e8"},
+ {file = "asyncmy-0.2.9-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c966de493928f26218e0bfaa284cfa609540e52841c423d7babf9ca97c9ff820"},
+ {file = "asyncmy-0.2.9-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4321c4cb4c691689aa26a56354e3fa723d89dc2cac82751e8671b2a4e6441778"},
+ {file = "asyncmy-0.2.9-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:cd7cde6759dbbfcc467c2af4ef3d75de0b756dde39a3d176383d8c6d9f8a34f3"},
+ {file = "asyncmy-0.2.9-cp37-cp37m-win32.whl", hash = "sha256:7678d3641d5a19f20e7e19220c83405fe8616a3b437efbc494f34ad186cedcf0"},
+ {file = "asyncmy-0.2.9-cp37-cp37m-win_amd64.whl", hash = "sha256:e8f48d09adf3426e7a59066eaae3c7c84c318ec56cc2f20732d652056c7a3f62"},
+ {file = "asyncmy-0.2.9-cp38-cp38-macosx_12_0_x86_64.whl", hash = "sha256:4c4f1dc0acbaac8c3f046215031bbf3ca3d2cd7716244365325496e4f6222b78"},
+ {file = "asyncmy-0.2.9-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:901aac048e5342acc62e1f68f6dec5aa3ed272cb2b138dca38d1c74fc414285d"},
+ {file = "asyncmy-0.2.9-cp38-cp38-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:c2d4ad8817f99d9734912c2ff91c42e419031441f512b4aecd7e40a167908c1c"},
+ {file = "asyncmy-0.2.9-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:544d3736fd6682f0201a123e4f49335420b6abf6c245abe0487f5967021f1436"},
+ {file = "asyncmy-0.2.9-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f0c606a55625146e189534cc39038540f7a8f2c680ea82845c1f4315a9ad2914"},
+ {file = "asyncmy-0.2.9-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:625f96371d64769b94f7f7f699cfa5be56e669828aef3698cbf4f5bb0014ccb3"},
+ {file = "asyncmy-0.2.9-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eeeb53fdd54eef54b9793a7a5c849c5f7a2fb2540a637f21585a996ef9dd8845"},
+ {file = "asyncmy-0.2.9-cp38-cp38-win32.whl", hash = "sha256:2136b749ac489c25ab3aab4a81ae6e9dfb18fd0a5ebda96cd72788c5e4d46927"},
+ {file = "asyncmy-0.2.9-cp38-cp38-win_amd64.whl", hash = "sha256:d08fb8722150a9c0645665cf777916335687bddb5f37a8e02af772e330be777b"},
+ {file = "asyncmy-0.2.9-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:dbee276a9c8750b522aaad86315a6ed1ffbcb9145ce89070db77831c00dd2da1"},
+ {file = "asyncmy-0.2.9-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a8755248429f9bd3d7768c71494c9943fced18f9f526f768e96f5b9b3c727c84"},
+ {file = "asyncmy-0.2.9-cp39-cp39-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:64bcd5110dca7a96cb411de85ab8f79fa867e864150939b8e76286a66eab28fc"},
+ {file = "asyncmy-0.2.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a83e3895bed6d44aa334deb1c343d4ffc64b0def2215149f8df2e0e13499250"},
+ {file = "asyncmy-0.2.9-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:beb3d0e434ce0bd9e609cf5341c3b82433ef544f89055d3792186e11fa2433d9"},
+ {file = "asyncmy-0.2.9-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:dc608ff331c5d1065e2d3566493d2d9e17f36e315bd5fad3c91c421eea306edb"},
+ {file = "asyncmy-0.2.9-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:02caedc00035b2bd0be5555ef61d83ee9cb356ab488ac40072630ba224af02b0"},
+ {file = "asyncmy-0.2.9-cp39-cp39-win32.whl", hash = "sha256:5b944d9cdf7ce25b396cd1e0c9319ba24c6583bde7a5dd31157614f3b9cc5b2f"},
+ {file = "asyncmy-0.2.9-cp39-cp39-win_amd64.whl", hash = "sha256:3ceb59b9307b5eb893f4d473fcbc43ac0321ffb0436e0115b20cc2e0baa44eb5"},
+ {file = "asyncmy-0.2.9-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9f1ca623517552a637900b90d65b5bafc9c67bebf96e3427eecb9359ffa24b1"},
+ {file = "asyncmy-0.2.9-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:49622dc4ec69b5a4cbddb3695a1e9249b31092c6f19604abb664b43dcb509b6f"},
+ {file = "asyncmy-0.2.9-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8412e825443ee876ef0d55ac4356b56173f5cb64ca8e4638974f8cf5c912a63"},
+ {file = "asyncmy-0.2.9-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:4025db2a27b1d84d3c68b5d5aacecac17258b69f25ec8a8c350c5f666003a778"},
+ {file = "asyncmy-0.2.9-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da7640f3357849b176364ed546908e28c8460701ddc0d23cc3fa7113ec52a076"},
+ {file = "asyncmy-0.2.9-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:d2593717fa7a92a7d361444726292ce34edea76d5aa67d469b5efeee1c9b729e"},
+ {file = "asyncmy-0.2.9-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9f22e13bd77277593b56de2e4b65c40c2e81b1a42c4845d062403c5c5bc52bc"},
+ {file = "asyncmy-0.2.9-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:a4aa17cc6ac0f7bc6b72e08d112566e69a36e2e1ebebad43d699757b7b4ff028"},
+ {file = "asyncmy-0.2.9-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7e6f5205722e67c910510e294ad483bdafa7e29d5cf455d49ffa4b819e55fd8"},
+ {file = "asyncmy-0.2.9-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:1021796f1910a0c2ab2d878f8f5d56f939ef0681f9c1fe925b78161cad2f8297"},
+ {file = "asyncmy-0.2.9-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b1dd463bb054138bd1fd3fec9911eb618e92f54f61abb476658f863340394d1"},
+ {file = "asyncmy-0.2.9-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ad06f3c02d455947e95087d29f7122411208f0eadaf8671772fe5bad97d9873a"},
+ {file = "asyncmy-0.2.9.tar.gz", hash = "sha256:da188be013291d1f831d63cdd3614567f4c63bfdcde73631ddff8df00c56d614"},
+]
+
+[[package]]
+name = "attrs"
+version = "24.2.0"
+description = "Classes Without Boilerplate"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"},
+ {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"},
+]
+
+[package.extras]
+benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
+cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
+dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
+docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"]
+tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
+tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"]
+
+[[package]]
+name = "babel"
+version = "2.16.0"
+description = "Internationalization utilities"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b"},
+ {file = "babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316"},
+]
+
+[package.extras]
+dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"]
+
+[[package]]
+name = "bcrypt"
+version = "4.2.1"
+description = "Modern password hashing for your software and your servers"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "bcrypt-4.2.1-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:1340411a0894b7d3ef562fb233e4b6ed58add185228650942bdc885362f32c17"},
+ {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1ee315739bc8387aa36ff127afc99120ee452924e0df517a8f3e4c0187a0f5f"},
+ {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8dbd0747208912b1e4ce730c6725cb56c07ac734b3629b60d4398f082ea718ad"},
+ {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:aaa2e285be097050dba798d537b6efd9b698aa88eef52ec98d23dcd6d7cf6fea"},
+ {file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:76d3e352b32f4eeb34703370e370997065d28a561e4a18afe4fef07249cb4396"},
+ {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:b7703ede632dc945ed1172d6f24e9f30f27b1b1a067f32f68bf169c5f08d0425"},
+ {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:89df2aea2c43be1e1fa066df5f86c8ce822ab70a30e4c210968669565c0f4685"},
+ {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:04e56e3fe8308a88b77e0afd20bec516f74aecf391cdd6e374f15cbed32783d6"},
+ {file = "bcrypt-4.2.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:cfdf3d7530c790432046c40cda41dfee8c83e29482e6a604f8930b9930e94139"},
+ {file = "bcrypt-4.2.1-cp37-abi3-win32.whl", hash = "sha256:adadd36274510a01f33e6dc08f5824b97c9580583bd4487c564fc4617b328005"},
+ {file = "bcrypt-4.2.1-cp37-abi3-win_amd64.whl", hash = "sha256:8c458cd103e6c5d1d85cf600e546a639f234964d0228909d8f8dbeebff82d526"},
+ {file = "bcrypt-4.2.1-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:8ad2f4528cbf0febe80e5a3a57d7a74e6635e41af1ea5675282a33d769fba413"},
+ {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:909faa1027900f2252a9ca5dfebd25fc0ef1417943824783d1c8418dd7d6df4a"},
+ {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cde78d385d5e93ece5479a0a87f73cd6fa26b171c786a884f955e165032b262c"},
+ {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:533e7f3bcf2f07caee7ad98124fab7499cb3333ba2274f7a36cf1daee7409d99"},
+ {file = "bcrypt-4.2.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:687cf30e6681eeda39548a93ce9bfbb300e48b4d445a43db4298d2474d2a1e54"},
+ {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:041fa0155c9004eb98a232d54da05c0b41d4b8e66b6fc3cb71b4b3f6144ba837"},
+ {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f85b1ffa09240c89aa2e1ae9f3b1c687104f7b2b9d2098da4e923f1b7082d331"},
+ {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c6f5fa3775966cca251848d4d5393ab016b3afed251163c1436fefdec3b02c84"},
+ {file = "bcrypt-4.2.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:807261df60a8b1ccd13e6599c779014a362ae4e795f5c59747f60208daddd96d"},
+ {file = "bcrypt-4.2.1-cp39-abi3-win32.whl", hash = "sha256:b588af02b89d9fad33e5f98f7838bf590d6d692df7153647724a7f20c186f6bf"},
+ {file = "bcrypt-4.2.1-cp39-abi3-win_amd64.whl", hash = "sha256:e84e0e6f8e40a242b11bce56c313edc2be121cec3e0ec2d76fce01f6af33c07c"},
+ {file = "bcrypt-4.2.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:76132c176a6d9953cdc83c296aeaed65e1a708485fd55abf163e0d9f8f16ce0e"},
+ {file = "bcrypt-4.2.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e158009a54c4c8bc91d5e0da80920d048f918c61a581f0a63e4e93bb556d362f"},
+ {file = "bcrypt-4.2.1.tar.gz", hash = "sha256:6765386e3ab87f569b276988742039baab087b2cdb01e809d74e74503c2faafe"},
+]
+
+[package.extras]
+tests = ["pytest (>=3.2.1,!=3.3.0)"]
+typecheck = ["mypy"]
+
+[[package]]
+name = "black"
+version = "24.10.0"
+description = "The uncompromising code formatter."
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "black-24.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6668650ea4b685440857138e5fe40cde4d652633b1bdffc62933d0db4ed9812"},
+ {file = "black-24.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1c536fcf674217e87b8cc3657b81809d3c085d7bf3ef262ead700da345bfa6ea"},
+ {file = "black-24.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:649fff99a20bd06c6f727d2a27f401331dc0cc861fb69cde910fe95b01b5928f"},
+ {file = "black-24.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:fe4d6476887de70546212c99ac9bd803d90b42fc4767f058a0baa895013fbb3e"},
+ {file = "black-24.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5a2221696a8224e335c28816a9d331a6c2ae15a2ee34ec857dcf3e45dbfa99ad"},
+ {file = "black-24.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f9da3333530dbcecc1be13e69c250ed8dfa67f43c4005fb537bb426e19200d50"},
+ {file = "black-24.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4007b1393d902b48b36958a216c20c4482f601569d19ed1df294a496eb366392"},
+ {file = "black-24.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:394d4ddc64782e51153eadcaaca95144ac4c35e27ef9b0a42e121ae7e57a9175"},
+ {file = "black-24.10.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b5e39e0fae001df40f95bd8cc36b9165c5e2ea88900167bddf258bacef9bbdc3"},
+ {file = "black-24.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d37d422772111794b26757c5b55a3eade028aa3fde43121ab7b673d050949d65"},
+ {file = "black-24.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14b3502784f09ce2443830e3133dacf2c0110d45191ed470ecb04d0f5f6fcb0f"},
+ {file = "black-24.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:30d2c30dc5139211dda799758559d1b049f7f14c580c409d6ad925b74a4208a8"},
+ {file = "black-24.10.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cbacacb19e922a1d75ef2b6ccaefcd6e93a2c05ede32f06a21386a04cedb981"},
+ {file = "black-24.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1f93102e0c5bb3907451063e08b9876dbeac810e7da5a8bfb7aeb5a9ef89066b"},
+ {file = "black-24.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ddacb691cdcdf77b96f549cf9591701d8db36b2f19519373d60d31746068dbf2"},
+ {file = "black-24.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:680359d932801c76d2e9c9068d05c6b107f2584b2a5b88831c83962eb9984c1b"},
+ {file = "black-24.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:17374989640fbca88b6a448129cd1745c5eb8d9547b464f281b251dd00155ccd"},
+ {file = "black-24.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:63f626344343083322233f175aaf372d326de8436f5928c042639a4afbbf1d3f"},
+ {file = "black-24.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfa1d0cb6200857f1923b602f978386a3a2758a65b52e0950299ea014be6800"},
+ {file = "black-24.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:2cd9c95431d94adc56600710f8813ee27eea544dd118d45896bb734e9d7a0dc7"},
+ {file = "black-24.10.0-py3-none-any.whl", hash = "sha256:3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d"},
+ {file = "black-24.10.0.tar.gz", hash = "sha256:846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875"},
+]
+
+[package.dependencies]
+aiohttp = {version = ">=3.10", optional = true, markers = "extra == \"d\""}
+click = ">=8.0.0"
+mypy-extensions = ">=0.4.3"
+packaging = ">=22.0"
+pathspec = ">=0.9.0"
+platformdirs = ">=2"
+
+[package.extras]
+colorama = ["colorama (>=0.4.3)"]
+d = ["aiohttp (>=3.10)"]
+jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
+uvloop = ["uvloop (>=0.15.2)"]
+
+[[package]]
+name = "certifi"
+version = "2024.8.30"
+description = "Python package for providing Mozilla's CA Bundle."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"},
+ {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"},
+]
+
+[[package]]
+name = "cffi"
+version = "1.17.1"
+description = "Foreign Function Interface for Python calling C code."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"},
+ {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"},
+ {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"},
+ {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"},
+ {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"},
+ {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"},
+ {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"},
+ {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"},
+ {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"},
+ {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"},
+ {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"},
+ {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"},
+ {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"},
+ {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"},
+ {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"},
+ {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"},
+ {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"},
+ {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"},
+ {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"},
+ {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"},
+ {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"},
+ {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"},
+ {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"},
+ {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"},
+ {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"},
+ {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"},
+ {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"},
+ {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"},
+ {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"},
+ {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"},
+ {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"},
+ {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"},
+ {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"},
+ {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"},
+ {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"},
+ {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"},
+ {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"},
+ {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"},
+ {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"},
+ {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"},
+ {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"},
+ {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"},
+ {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"},
+ {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"},
+ {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"},
+ {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"},
+ {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"},
+ {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"},
+ {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"},
+ {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"},
+ {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"},
+ {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"},
+ {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"},
+ {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"},
+ {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"},
+ {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"},
+ {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"},
+ {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"},
+ {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"},
+ {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"},
+ {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"},
+ {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"},
+ {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"},
+ {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"},
+ {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"},
+ {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"},
+ {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"},
+]
+
+[package.dependencies]
+pycparser = "*"
+
+[[package]]
+name = "cfgv"
+version = "3.4.0"
+description = "Validate configuration and produce human readable error messages."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"},
+ {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"},
+]
+
+[[package]]
+name = "charset-normalizer"
+version = "3.4.0"
+description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
+optional = false
+python-versions = ">=3.7.0"
+files = [
+ {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc"},
+ {file = "charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99"},
+ {file = "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"},
+ {file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"},
+ {file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149"},
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-win32.whl", hash = "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613"},
+ {file = "charset_normalizer-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2"},
+ {file = "charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca"},
+ {file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"},
+ {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"},
+]
+
+[[package]]
+name = "click"
+version = "8.1.7"
+description = "Composable command line interface toolkit"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
+ {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "platform_system == \"Windows\""}
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+description = "Cross-platform colored terminal text."
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+files = [
+ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
+ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
+]
+
+[[package]]
+name = "coverage"
+version = "7.6.7"
+description = "Code coverage measurement for Python"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "coverage-7.6.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:108bb458827765d538abcbf8288599fee07d2743357bdd9b9dad456c287e121e"},
+ {file = "coverage-7.6.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c973b2fe4dc445cb865ab369df7521df9c27bf40715c837a113edaa2aa9faf45"},
+ {file = "coverage-7.6.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c6b24007c4bcd0b19fac25763a7cac5035c735ae017e9a349b927cfc88f31c1"},
+ {file = "coverage-7.6.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:acbb8af78f8f91b3b51f58f288c0994ba63c646bc1a8a22ad072e4e7e0a49f1c"},
+ {file = "coverage-7.6.7-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad32a981bcdedb8d2ace03b05e4fd8dace8901eec64a532b00b15217d3677dd2"},
+ {file = "coverage-7.6.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:34d23e28ccb26236718a3a78ba72744212aa383141961dd6825f6595005c8b06"},
+ {file = "coverage-7.6.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e25bacb53a8c7325e34d45dddd2f2fbae0dbc230d0e2642e264a64e17322a777"},
+ {file = "coverage-7.6.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:af05bbba896c4472a29408455fe31b3797b4d8648ed0a2ccac03e074a77e2314"},
+ {file = "coverage-7.6.7-cp310-cp310-win32.whl", hash = "sha256:796c9b107d11d2d69e1849b2dfe41730134b526a49d3acb98ca02f4985eeff7a"},
+ {file = "coverage-7.6.7-cp310-cp310-win_amd64.whl", hash = "sha256:987a8e3da7da4eed10a20491cf790589a8e5e07656b6dc22d3814c4d88faf163"},
+ {file = "coverage-7.6.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7e61b0e77ff4dddebb35a0e8bb5a68bf0f8b872407d8d9f0c726b65dfabe2469"},
+ {file = "coverage-7.6.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1a5407a75ca4abc20d6252efeb238377a71ce7bda849c26c7a9bece8680a5d99"},
+ {file = "coverage-7.6.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df002e59f2d29e889c37abd0b9ee0d0e6e38c24f5f55d71ff0e09e3412a340ec"},
+ {file = "coverage-7.6.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:673184b3156cba06154825f25af33baa2671ddae6343f23175764e65a8c4c30b"},
+ {file = "coverage-7.6.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e69ad502f1a2243f739f5bd60565d14a278be58be4c137d90799f2c263e7049a"},
+ {file = "coverage-7.6.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:60dcf7605c50ea72a14490d0756daffef77a5be15ed1b9fea468b1c7bda1bc3b"},
+ {file = "coverage-7.6.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9c2eb378bebb2c8f65befcb5147877fc1c9fbc640fc0aad3add759b5df79d55d"},
+ {file = "coverage-7.6.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3c0317288f032221d35fa4cbc35d9f4923ff0dfd176c79c9b356e8ef8ef2dff4"},
+ {file = "coverage-7.6.7-cp311-cp311-win32.whl", hash = "sha256:951aade8297358f3618a6e0660dc74f6b52233c42089d28525749fc8267dccd2"},
+ {file = "coverage-7.6.7-cp311-cp311-win_amd64.whl", hash = "sha256:5e444b8e88339a2a67ce07d41faabb1d60d1004820cee5a2c2b54e2d8e429a0f"},
+ {file = "coverage-7.6.7-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f07ff574986bc3edb80e2c36391678a271d555f91fd1d332a1e0f4b5ea4b6ea9"},
+ {file = "coverage-7.6.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:49ed5ee4109258973630c1f9d099c7e72c5c36605029f3a91fe9982c6076c82b"},
+ {file = "coverage-7.6.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3e8796434a8106b3ac025fd15417315d7a58ee3e600ad4dbcfddc3f4b14342c"},
+ {file = "coverage-7.6.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3b925300484a3294d1c70f6b2b810d6526f2929de954e5b6be2bf8caa1f12c1"},
+ {file = "coverage-7.6.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c42ec2c522e3ddd683dec5cdce8e62817afb648caedad9da725001fa530d354"},
+ {file = "coverage-7.6.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0266b62cbea568bd5e93a4da364d05de422110cbed5056d69339bd5af5685433"},
+ {file = "coverage-7.6.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e5f2a0f161d126ccc7038f1f3029184dbdf8f018230af17ef6fd6a707a5b881f"},
+ {file = "coverage-7.6.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c132b5a22821f9b143f87446805e13580b67c670a548b96da945a8f6b4f2efbb"},
+ {file = "coverage-7.6.7-cp312-cp312-win32.whl", hash = "sha256:7c07de0d2a110f02af30883cd7dddbe704887617d5c27cf373362667445a4c76"},
+ {file = "coverage-7.6.7-cp312-cp312-win_amd64.whl", hash = "sha256:fd49c01e5057a451c30c9b892948976f5d38f2cbd04dc556a82743ba8e27ed8c"},
+ {file = "coverage-7.6.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:46f21663e358beae6b368429ffadf14ed0a329996248a847a4322fb2e35d64d3"},
+ {file = "coverage-7.6.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:40cca284c7c310d622a1677f105e8507441d1bb7c226f41978ba7c86979609ab"},
+ {file = "coverage-7.6.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77256ad2345c29fe59ae861aa11cfc74579c88d4e8dbf121cbe46b8e32aec808"},
+ {file = "coverage-7.6.7-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87ea64b9fa52bf395272e54020537990a28078478167ade6c61da7ac04dc14bc"},
+ {file = "coverage-7.6.7-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d608a7808793e3615e54e9267519351c3ae204a6d85764d8337bd95993581a8"},
+ {file = "coverage-7.6.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdd94501d65adc5c24f8a1a0eda110452ba62b3f4aeaba01e021c1ed9cb8f34a"},
+ {file = "coverage-7.6.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:82c809a62e953867cf57e0548c2b8464207f5f3a6ff0e1e961683e79b89f2c55"},
+ {file = "coverage-7.6.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bb684694e99d0b791a43e9fc0fa58efc15ec357ac48d25b619f207c41f2fd384"},
+ {file = "coverage-7.6.7-cp313-cp313-win32.whl", hash = "sha256:963e4a08cbb0af6623e61492c0ec4c0ec5c5cf74db5f6564f98248d27ee57d30"},
+ {file = "coverage-7.6.7-cp313-cp313-win_amd64.whl", hash = "sha256:14045b8bfd5909196a90da145a37f9d335a5d988a83db34e80f41e965fb7cb42"},
+ {file = "coverage-7.6.7-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:f2c7a045eef561e9544359a0bf5784b44e55cefc7261a20e730baa9220c83413"},
+ {file = "coverage-7.6.7-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5dd4e4a49d9c72a38d18d641135d2fb0bdf7b726ca60a103836b3d00a1182acd"},
+ {file = "coverage-7.6.7-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c95e0fa3d1547cb6f021ab72f5c23402da2358beec0a8e6d19a368bd7b0fb37"},
+ {file = "coverage-7.6.7-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f63e21ed474edd23f7501f89b53280014436e383a14b9bd77a648366c81dce7b"},
+ {file = "coverage-7.6.7-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ead9b9605c54d15be228687552916c89c9683c215370c4a44f1f217d2adcc34d"},
+ {file = "coverage-7.6.7-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:0573f5cbf39114270842d01872952d301027d2d6e2d84013f30966313cadb529"},
+ {file = "coverage-7.6.7-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:e2c8e3384c12dfa19fa9a52f23eb091a8fad93b5b81a41b14c17c78e23dd1d8b"},
+ {file = "coverage-7.6.7-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:70a56a2ec1869e6e9fa69ef6b76b1a8a7ef709972b9cc473f9ce9d26b5997ce3"},
+ {file = "coverage-7.6.7-cp313-cp313t-win32.whl", hash = "sha256:dbba8210f5067398b2c4d96b4e64d8fb943644d5eb70be0d989067c8ca40c0f8"},
+ {file = "coverage-7.6.7-cp313-cp313t-win_amd64.whl", hash = "sha256:dfd14bcae0c94004baba5184d1c935ae0d1231b8409eb6c103a5fd75e8ecdc56"},
+ {file = "coverage-7.6.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:37a15573f988b67f7348916077c6d8ad43adb75e478d0910957394df397d2874"},
+ {file = "coverage-7.6.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b6cce5c76985f81da3769c52203ee94722cd5d5889731cd70d31fee939b74bf0"},
+ {file = "coverage-7.6.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ab9763d291a17b527ac6fd11d1a9a9c358280adb320e9c2672a97af346ac2c"},
+ {file = "coverage-7.6.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6cf96ceaa275f071f1bea3067f8fd43bec184a25a962c754024c973af871e1b7"},
+ {file = "coverage-7.6.7-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aee9cf6b0134d6f932d219ce253ef0e624f4fa588ee64830fcba193269e4daa3"},
+ {file = "coverage-7.6.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2bc3e45c16564cc72de09e37413262b9f99167803e5e48c6156bccdfb22c8327"},
+ {file = "coverage-7.6.7-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:623e6965dcf4e28a3debaa6fcf4b99ee06d27218f46d43befe4db1c70841551c"},
+ {file = "coverage-7.6.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:850cfd2d6fc26f8346f422920ac204e1d28814e32e3a58c19c91980fa74d8289"},
+ {file = "coverage-7.6.7-cp39-cp39-win32.whl", hash = "sha256:c296263093f099da4f51b3dff1eff5d4959b527d4f2f419e16508c5da9e15e8c"},
+ {file = "coverage-7.6.7-cp39-cp39-win_amd64.whl", hash = "sha256:90746521206c88bdb305a4bf3342b1b7316ab80f804d40c536fc7d329301ee13"},
+ {file = "coverage-7.6.7-pp39.pp310-none-any.whl", hash = "sha256:0ddcb70b3a3a57581b450571b31cb774f23eb9519c2aaa6176d3a84c9fc57671"},
+ {file = "coverage-7.6.7.tar.gz", hash = "sha256:d79d4826e41441c9a118ff045e4bccb9fdbdcb1d02413e7ea6eb5c87b5439d24"},
+]
+
+[package.extras]
+toml = ["tomli"]
+
+[[package]]
+name = "coverage-badge"
+version = "1.1.2"
+description = "Generate coverage badges for Coverage.py."
+optional = false
+python-versions = "*"
+files = [
+ {file = "coverage_badge-1.1.2-py2.py3-none-any.whl", hash = "sha256:d8413ce51c91043a1692b943616b450868cbeeb0ea6a0c54a32f8318c9c96ff7"},
+ {file = "coverage_badge-1.1.2.tar.gz", hash = "sha256:fe7ed58a3b72dad85a553b64a99e963dea3847dcd0b8ddd2b38a00333618642c"},
+]
+
+[package.dependencies]
+coverage = "*"
+setuptools = "*"
+
+[[package]]
+name = "cryptography"
+version = "42.0.8"
+description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e"},
+ {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d"},
+ {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902"},
+ {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801"},
+ {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949"},
+ {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9"},
+ {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583"},
+ {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7"},
+ {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b"},
+ {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7"},
+ {file = "cryptography-42.0.8-cp37-abi3-win32.whl", hash = "sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2"},
+ {file = "cryptography-42.0.8-cp37-abi3-win_amd64.whl", hash = "sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba"},
+ {file = "cryptography-42.0.8-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28"},
+ {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e"},
+ {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70"},
+ {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c"},
+ {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7"},
+ {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e"},
+ {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961"},
+ {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1"},
+ {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14"},
+ {file = "cryptography-42.0.8-cp39-abi3-win32.whl", hash = "sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c"},
+ {file = "cryptography-42.0.8-cp39-abi3-win_amd64.whl", hash = "sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a"},
+ {file = "cryptography-42.0.8-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe"},
+ {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c"},
+ {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71"},
+ {file = "cryptography-42.0.8-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d"},
+ {file = "cryptography-42.0.8-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c"},
+ {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842"},
+ {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648"},
+ {file = "cryptography-42.0.8-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad"},
+ {file = "cryptography-42.0.8.tar.gz", hash = "sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2"},
+]
+
+[package.dependencies]
+cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""}
+
+[package.extras]
+docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"]
+docstest = ["pyenchant (>=1.6.11)", "readme-renderer", "sphinxcontrib-spelling (>=4.0.1)"]
+nox = ["nox"]
+pep8test = ["check-sdist", "click", "mypy", "ruff"]
+sdist = ["build"]
+ssh = ["bcrypt (>=3.1.5)"]
+test = ["certifi", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"]
+test-randomorder = ["pytest-randomly"]
+
+[[package]]
+name = "deepdiff"
+version = "6.7.1"
+description = "Deep Difference and Search of any Python object/data. Recreate objects by adding adding deltas to each other."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "deepdiff-6.7.1-py3-none-any.whl", hash = "sha256:58396bb7a863cbb4ed5193f548c56f18218060362311aa1dc36397b2f25108bd"},
+ {file = "deepdiff-6.7.1.tar.gz", hash = "sha256:b367e6fa6caac1c9f500adc79ada1b5b1242c50d5f716a1a4362030197847d30"},
+]
+
+[package.dependencies]
+ordered-set = ">=4.0.2,<4.2.0"
+
+[package.extras]
+cli = ["click (==8.1.3)", "pyyaml (==6.0.1)"]
+optimize = ["orjson"]
+
+[[package]]
+name = "distlib"
+version = "0.3.9"
+description = "Distribution utilities"
+optional = false
+python-versions = "*"
+files = [
+ {file = "distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87"},
+ {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"},
+]
+
+[[package]]
+name = "dnspython"
+version = "2.7.0"
+description = "DNS toolkit"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "dnspython-2.7.0-py3-none-any.whl", hash = "sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86"},
+ {file = "dnspython-2.7.0.tar.gz", hash = "sha256:ce9c432eda0dc91cf618a5cedf1a4e142651196bbcd2c80e89ed5a907e5cfaf1"},
+]
+
+[package.extras]
+dev = ["black (>=23.1.0)", "coverage (>=7.0)", "flake8 (>=7)", "hypercorn (>=0.16.0)", "mypy (>=1.8)", "pylint (>=3)", "pytest (>=7.4)", "pytest-cov (>=4.1.0)", "quart-trio (>=0.11.0)", "sphinx (>=7.2.0)", "sphinx-rtd-theme (>=2.0.0)", "twine (>=4.0.0)", "wheel (>=0.42.0)"]
+dnssec = ["cryptography (>=43)"]
+doh = ["h2 (>=4.1.0)", "httpcore (>=1.0.0)", "httpx (>=0.26.0)"]
+doq = ["aioquic (>=1.0.0)"]
+idna = ["idna (>=3.7)"]
+trio = ["trio (>=0.23)"]
+wmi = ["wmi (>=1.5.1)"]
+
+[[package]]
+name = "fastapi"
+version = "0.110.3"
+description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "fastapi-0.110.3-py3-none-any.whl", hash = "sha256:fd7600612f755e4050beb74001310b5a7e1796d149c2ee363124abdfa0289d32"},
+ {file = "fastapi-0.110.3.tar.gz", hash = "sha256:555700b0159379e94fdbfc6bb66a0f1c43f4cf7060f25239af3d84b63a656626"},
+]
+
+[package.dependencies]
+pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0"
+starlette = ">=0.37.2,<0.38.0"
+typing-extensions = ">=4.8.0"
+
+[package.extras]
+all = ["email_validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
+
+[[package]]
+name = "filelock"
+version = "3.16.1"
+description = "A platform independent file lock."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"},
+ {file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"},
+]
+
+[package.extras]
+docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4.1)"]
+testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.2)", "pytest (>=8.3.3)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.4)"]
+typing = ["typing-extensions (>=4.12.2)"]
+
+[[package]]
+name = "frozenlist"
+version = "1.5.0"
+description = "A list-like structure which implements collections.abc.MutableSequence"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5b6a66c18b5b9dd261ca98dffcb826a525334b2f29e7caa54e182255c5f6a65a"},
+ {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d1b3eb7b05ea246510b43a7e53ed1653e55c2121019a97e60cad7efb881a97bb"},
+ {file = "frozenlist-1.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:15538c0cbf0e4fa11d1e3a71f823524b0c46299aed6e10ebb4c2089abd8c3bec"},
+ {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e79225373c317ff1e35f210dd5f1344ff31066ba8067c307ab60254cd3a78ad5"},
+ {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9272fa73ca71266702c4c3e2d4a28553ea03418e591e377a03b8e3659d94fa76"},
+ {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:498524025a5b8ba81695761d78c8dd7382ac0b052f34e66939c42df860b8ff17"},
+ {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92b5278ed9d50fe610185ecd23c55d8b307d75ca18e94c0e7de328089ac5dcba"},
+ {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f3c8c1dacd037df16e85227bac13cca58c30da836c6f936ba1df0c05d046d8d"},
+ {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f2ac49a9bedb996086057b75bf93538240538c6d9b38e57c82d51f75a73409d2"},
+ {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e66cc454f97053b79c2ab09c17fbe3c825ea6b4de20baf1be28919460dd7877f"},
+ {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:5a3ba5f9a0dfed20337d3e966dc359784c9f96503674c2faf015f7fe8e96798c"},
+ {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6321899477db90bdeb9299ac3627a6a53c7399c8cd58d25da094007402b039ab"},
+ {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:76e4753701248476e6286f2ef492af900ea67d9706a0155335a40ea21bf3b2f5"},
+ {file = "frozenlist-1.5.0-cp310-cp310-win32.whl", hash = "sha256:977701c081c0241d0955c9586ffdd9ce44f7a7795df39b9151cd9a6fd0ce4cfb"},
+ {file = "frozenlist-1.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:189f03b53e64144f90990d29a27ec4f7997d91ed3d01b51fa39d2dbe77540fd4"},
+ {file = "frozenlist-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:fd74520371c3c4175142d02a976aee0b4cb4a7cc912a60586ffd8d5929979b30"},
+ {file = "frozenlist-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2f3f7a0fbc219fb4455264cae4d9f01ad41ae6ee8524500f381de64ffaa077d5"},
+ {file = "frozenlist-1.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f47c9c9028f55a04ac254346e92977bf0f166c483c74b4232bee19a6697e4778"},
+ {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0996c66760924da6e88922756d99b47512a71cfd45215f3570bf1e0b694c206a"},
+ {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2fe128eb4edeabe11896cb6af88fca5346059f6c8d807e3b910069f39157869"},
+ {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a8ea951bbb6cacd492e3948b8da8c502a3f814f5d20935aae74b5df2b19cf3d"},
+ {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de537c11e4aa01d37db0d403b57bd6f0546e71a82347a97c6a9f0dcc532b3a45"},
+ {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c2623347b933fcb9095841f1cc5d4ff0b278addd743e0e966cb3d460278840d"},
+ {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cee6798eaf8b1416ef6909b06f7dc04b60755206bddc599f52232606e18179d3"},
+ {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f5f9da7f5dbc00a604fe74aa02ae7c98bcede8a3b8b9666f9f86fc13993bc71a"},
+ {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:90646abbc7a5d5c7c19461d2e3eeb76eb0b204919e6ece342feb6032c9325ae9"},
+ {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:bdac3c7d9b705d253b2ce370fde941836a5f8b3c5c2b8fd70940a3ea3af7f4f2"},
+ {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:03d33c2ddbc1816237a67f66336616416e2bbb6beb306e5f890f2eb22b959cdf"},
+ {file = "frozenlist-1.5.0-cp311-cp311-win32.whl", hash = "sha256:237f6b23ee0f44066219dae14c70ae38a63f0440ce6750f868ee08775073f942"},
+ {file = "frozenlist-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:0cc974cc93d32c42e7b0f6cf242a6bd941c57c61b618e78b6c0a96cb72788c1d"},
+ {file = "frozenlist-1.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21"},
+ {file = "frozenlist-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d"},
+ {file = "frozenlist-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e"},
+ {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a"},
+ {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a"},
+ {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee"},
+ {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6"},
+ {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e"},
+ {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9"},
+ {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039"},
+ {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784"},
+ {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631"},
+ {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f"},
+ {file = "frozenlist-1.5.0-cp312-cp312-win32.whl", hash = "sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8"},
+ {file = "frozenlist-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f"},
+ {file = "frozenlist-1.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7a1a048f9215c90973402e26c01d1cff8a209e1f1b53f72b95c13db61b00f953"},
+ {file = "frozenlist-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dd47a5181ce5fcb463b5d9e17ecfdb02b678cca31280639255ce9d0e5aa67af0"},
+ {file = "frozenlist-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1431d60b36d15cda188ea222033eec8e0eab488f39a272461f2e6d9e1a8e63c2"},
+ {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6482a5851f5d72767fbd0e507e80737f9c8646ae7fd303def99bfe813f76cf7f"},
+ {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44c49271a937625619e862baacbd037a7ef86dd1ee215afc298a417ff3270608"},
+ {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:12f78f98c2f1c2429d42e6a485f433722b0061d5c0b0139efa64f396efb5886b"},
+ {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce3aa154c452d2467487765e3adc730a8c153af77ad84096bc19ce19a2400840"},
+ {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b7dc0c4338e6b8b091e8faf0db3168a37101943e687f373dce00959583f7439"},
+ {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:45e0896250900b5aa25180f9aec243e84e92ac84bd4a74d9ad4138ef3f5c97de"},
+ {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:561eb1c9579d495fddb6da8959fd2a1fca2c6d060d4113f5844b433fc02f2641"},
+ {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:df6e2f325bfee1f49f81aaac97d2aa757c7646534a06f8f577ce184afe2f0a9e"},
+ {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:140228863501b44b809fb39ec56b5d4071f4d0aa6d216c19cbb08b8c5a7eadb9"},
+ {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7707a25d6a77f5d27ea7dc7d1fc608aa0a478193823f88511ef5e6b8a48f9d03"},
+ {file = "frozenlist-1.5.0-cp313-cp313-win32.whl", hash = "sha256:31a9ac2b38ab9b5a8933b693db4939764ad3f299fcaa931a3e605bc3460e693c"},
+ {file = "frozenlist-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:11aabdd62b8b9c4b84081a3c246506d1cddd2dd93ff0ad53ede5defec7886b28"},
+ {file = "frozenlist-1.5.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:dd94994fc91a6177bfaafd7d9fd951bc8689b0a98168aa26b5f543868548d3ca"},
+ {file = "frozenlist-1.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0da8bbec082bf6bf18345b180958775363588678f64998c2b7609e34719b10"},
+ {file = "frozenlist-1.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:73f2e31ea8dd7df61a359b731716018c2be196e5bb3b74ddba107f694fbd7604"},
+ {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:828afae9f17e6de596825cf4228ff28fbdf6065974e5ac1410cecc22f699d2b3"},
+ {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1577515d35ed5649d52ab4319db757bb881ce3b2b796d7283e6634d99ace307"},
+ {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2150cc6305a2c2ab33299453e2968611dacb970d2283a14955923062c8d00b10"},
+ {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a72b7a6e3cd2725eff67cd64c8f13335ee18fc3c7befc05aed043d24c7b9ccb9"},
+ {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c16d2fa63e0800723139137d667e1056bee1a1cf7965153d2d104b62855e9b99"},
+ {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:17dcc32fc7bda7ce5875435003220a457bcfa34ab7924a49a1c19f55b6ee185c"},
+ {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:97160e245ea33d8609cd2b8fd997c850b56db147a304a262abc2b3be021a9171"},
+ {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:f1e6540b7fa044eee0bb5111ada694cf3dc15f2b0347ca125ee9ca984d5e9e6e"},
+ {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:91d6c171862df0a6c61479d9724f22efb6109111017c87567cfeb7b5d1449fdf"},
+ {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c1fac3e2ace2eb1052e9f7c7db480818371134410e1f5c55d65e8f3ac6d1407e"},
+ {file = "frozenlist-1.5.0-cp38-cp38-win32.whl", hash = "sha256:b97f7b575ab4a8af9b7bc1d2ef7f29d3afee2226bd03ca3875c16451ad5a7723"},
+ {file = "frozenlist-1.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:374ca2dabdccad8e2a76d40b1d037f5bd16824933bf7bcea3e59c891fd4a0923"},
+ {file = "frozenlist-1.5.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9bbcdfaf4af7ce002694a4e10a0159d5a8d20056a12b05b45cea944a4953f972"},
+ {file = "frozenlist-1.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1893f948bf6681733aaccf36c5232c231e3b5166d607c5fa77773611df6dc336"},
+ {file = "frozenlist-1.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2b5e23253bb709ef57a8e95e6ae48daa9ac5f265637529e4ce6b003a37b2621f"},
+ {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f253985bb515ecd89629db13cb58d702035ecd8cfbca7d7a7e29a0e6d39af5f"},
+ {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:04a5c6babd5e8fb7d3c871dc8b321166b80e41b637c31a995ed844a6139942b6"},
+ {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9fe0f1c29ba24ba6ff6abf688cb0b7cf1efab6b6aa6adc55441773c252f7411"},
+ {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:226d72559fa19babe2ccd920273e767c96a49b9d3d38badd7c91a0fdeda8ea08"},
+ {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15b731db116ab3aedec558573c1a5eec78822b32292fe4f2f0345b7f697745c2"},
+ {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:366d8f93e3edfe5a918c874702f78faac300209a4d5bf38352b2c1bdc07a766d"},
+ {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1b96af8c582b94d381a1c1f51ffaedeb77c821c690ea5f01da3d70a487dd0a9b"},
+ {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c03eff4a41bd4e38415cbed054bbaff4a075b093e2394b6915dca34a40d1e38b"},
+ {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:50cf5e7ee9b98f22bdecbabf3800ae78ddcc26e4a435515fc72d97903e8488e0"},
+ {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1e76bfbc72353269c44e0bc2cfe171900fbf7f722ad74c9a7b638052afe6a00c"},
+ {file = "frozenlist-1.5.0-cp39-cp39-win32.whl", hash = "sha256:666534d15ba8f0fda3f53969117383d5dc021266b3c1a42c9ec4855e4b58b9d3"},
+ {file = "frozenlist-1.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:5c28f4b5dbef8a0d8aad0d4de24d1e9e981728628afaf4ea0792f5d0939372f0"},
+ {file = "frozenlist-1.5.0-py3-none-any.whl", hash = "sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3"},
+ {file = "frozenlist-1.5.0.tar.gz", hash = "sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817"},
+]
+
+[[package]]
+name = "ghp-import"
+version = "2.1.0"
+description = "Copy your docs directly to the gh-pages branch."
+optional = false
+python-versions = "*"
+files = [
+ {file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"},
+ {file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"},
+]
+
+[package.dependencies]
+python-dateutil = ">=2.8.1"
+
+[package.extras]
+dev = ["flake8", "markdown", "twine", "wheel"]
+
+[[package]]
+name = "griffe"
+version = "1.5.1"
+description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API."
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "griffe-1.5.1-py3-none-any.whl", hash = "sha256:ad6a7980f8c424c9102160aafa3bcdf799df0e75f7829d75af9ee5aef656f860"},
+ {file = "griffe-1.5.1.tar.gz", hash = "sha256:72964f93e08c553257706d6cd2c42d1c172213feb48b2be386f243380b405d4b"},
+]
+
+[package.dependencies]
+colorama = ">=0.4"
+
+[[package]]
+name = "griffe-fastapi"
+version = "0.1.5"
+description = "Griffe extension for FastAPI."
+optional = false
+python-versions = "<4.0,>=3.12"
+files = [
+ {file = "griffe_fastapi-0.1.5-py3-none-any.whl", hash = "sha256:d53b23d524c7ace0a1f85f477f7b58de995b0834bc440ccd851e758b825626c8"},
+ {file = "griffe_fastapi-0.1.5.tar.gz", hash = "sha256:d1534dd0ad9f12e34d66cfce5d797b93129b4d3b174c79fcaeb3d2d1723c71d5"},
+]
+
+[package.dependencies]
+griffe = ">=1.5.1,<2.0.0"
+
+[[package]]
+name = "h11"
+version = "0.14.0"
+description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
+ {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
+]
+
+[[package]]
+name = "httpcore"
+version = "1.0.7"
+description = "A minimal low-level HTTP client."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd"},
+ {file = "httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c"},
+]
+
+[package.dependencies]
+certifi = "*"
+h11 = ">=0.13,<0.15"
+
+[package.extras]
+asyncio = ["anyio (>=4.0,<5.0)"]
+http2 = ["h2 (>=3,<5)"]
+socks = ["socksio (==1.*)"]
+trio = ["trio (>=0.22.0,<1.0)"]
+
+[[package]]
+name = "httptools"
+version = "0.6.4"
+description = "A collection of framework independent HTTP protocol utils."
+optional = false
+python-versions = ">=3.8.0"
+files = [
+ {file = "httptools-0.6.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3c73ce323711a6ffb0d247dcd5a550b8babf0f757e86a52558fe5b86d6fefcc0"},
+ {file = "httptools-0.6.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:345c288418f0944a6fe67be8e6afa9262b18c7626c3ef3c28adc5eabc06a68da"},
+ {file = "httptools-0.6.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deee0e3343f98ee8047e9f4c5bc7cedbf69f5734454a94c38ee829fb2d5fa3c1"},
+ {file = "httptools-0.6.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca80b7485c76f768a3bc83ea58373f8db7b015551117375e4918e2aa77ea9b50"},
+ {file = "httptools-0.6.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:90d96a385fa941283ebd231464045187a31ad932ebfa541be8edf5b3c2328959"},
+ {file = "httptools-0.6.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:59e724f8b332319e2875efd360e61ac07f33b492889284a3e05e6d13746876f4"},
+ {file = "httptools-0.6.4-cp310-cp310-win_amd64.whl", hash = "sha256:c26f313951f6e26147833fc923f78f95604bbec812a43e5ee37f26dc9e5a686c"},
+ {file = "httptools-0.6.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f47f8ed67cc0ff862b84a1189831d1d33c963fb3ce1ee0c65d3b0cbe7b711069"},
+ {file = "httptools-0.6.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0614154d5454c21b6410fdf5262b4a3ddb0f53f1e1721cfd59d55f32138c578a"},
+ {file = "httptools-0.6.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8787367fbdfccae38e35abf7641dafc5310310a5987b689f4c32cc8cc3ee975"},
+ {file = "httptools-0.6.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40b0f7fe4fd38e6a507bdb751db0379df1e99120c65fbdc8ee6c1d044897a636"},
+ {file = "httptools-0.6.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:40a5ec98d3f49904b9fe36827dcf1aadfef3b89e2bd05b0e35e94f97c2b14721"},
+ {file = "httptools-0.6.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dacdd3d10ea1b4ca9df97a0a303cbacafc04b5cd375fa98732678151643d4988"},
+ {file = "httptools-0.6.4-cp311-cp311-win_amd64.whl", hash = "sha256:288cd628406cc53f9a541cfaf06041b4c71d751856bab45e3702191f931ccd17"},
+ {file = "httptools-0.6.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:df017d6c780287d5c80601dafa31f17bddb170232d85c066604d8558683711a2"},
+ {file = "httptools-0.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:85071a1e8c2d051b507161f6c3e26155b5c790e4e28d7f236422dbacc2a9cc44"},
+ {file = "httptools-0.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69422b7f458c5af875922cdb5bd586cc1f1033295aa9ff63ee196a87519ac8e1"},
+ {file = "httptools-0.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16e603a3bff50db08cd578d54f07032ca1631450ceb972c2f834c2b860c28ea2"},
+ {file = "httptools-0.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ec4f178901fa1834d4a060320d2f3abc5c9e39766953d038f1458cb885f47e81"},
+ {file = "httptools-0.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f9eb89ecf8b290f2e293325c646a211ff1c2493222798bb80a530c5e7502494f"},
+ {file = "httptools-0.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:db78cb9ca56b59b016e64b6031eda5653be0589dba2b1b43453f6e8b405a0970"},
+ {file = "httptools-0.6.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ade273d7e767d5fae13fa637f4d53b6e961fb7fd93c7797562663f0171c26660"},
+ {file = "httptools-0.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:856f4bc0478ae143bad54a4242fccb1f3f86a6e1be5548fecfd4102061b3a083"},
+ {file = "httptools-0.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:322d20ea9cdd1fa98bd6a74b77e2ec5b818abdc3d36695ab402a0de8ef2865a3"},
+ {file = "httptools-0.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d87b29bd4486c0093fc64dea80231f7c7f7eb4dc70ae394d70a495ab8436071"},
+ {file = "httptools-0.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:342dd6946aa6bda4b8f18c734576106b8a31f2fe31492881a9a160ec84ff4bd5"},
+ {file = "httptools-0.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b36913ba52008249223042dca46e69967985fb4051951f94357ea681e1f5dc0"},
+ {file = "httptools-0.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:28908df1b9bb8187393d5b5db91435ccc9c8e891657f9cbb42a2541b44c82fc8"},
+ {file = "httptools-0.6.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:d3f0d369e7ffbe59c4b6116a44d6a8eb4783aae027f2c0b366cf0aa964185dba"},
+ {file = "httptools-0.6.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:94978a49b8f4569ad607cd4946b759d90b285e39c0d4640c6b36ca7a3ddf2efc"},
+ {file = "httptools-0.6.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40dc6a8e399e15ea525305a2ddba998b0af5caa2566bcd79dcbe8948181eeaff"},
+ {file = "httptools-0.6.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab9ba8dcf59de5181f6be44a77458e45a578fc99c31510b8c65b7d5acc3cf490"},
+ {file = "httptools-0.6.4-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:fc411e1c0a7dcd2f902c7c48cf079947a7e65b5485dea9decb82b9105ca71a43"},
+ {file = "httptools-0.6.4-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:d54efd20338ac52ba31e7da78e4a72570cf729fac82bc31ff9199bedf1dc7440"},
+ {file = "httptools-0.6.4-cp38-cp38-win_amd64.whl", hash = "sha256:df959752a0c2748a65ab5387d08287abf6779ae9165916fe053e68ae1fbdc47f"},
+ {file = "httptools-0.6.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:85797e37e8eeaa5439d33e556662cc370e474445d5fab24dcadc65a8ffb04003"},
+ {file = "httptools-0.6.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:db353d22843cf1028f43c3651581e4bb49374d85692a85f95f7b9a130e1b2cab"},
+ {file = "httptools-0.6.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1ffd262a73d7c28424252381a5b854c19d9de5f56f075445d33919a637e3547"},
+ {file = "httptools-0.6.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:703c346571fa50d2e9856a37d7cd9435a25e7fd15e236c397bf224afaa355fe9"},
+ {file = "httptools-0.6.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:aafe0f1918ed07b67c1e838f950b1c1fabc683030477e60b335649b8020e1076"},
+ {file = "httptools-0.6.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0e563e54979e97b6d13f1bbc05a96109923e76b901f786a5eae36e99c01237bd"},
+ {file = "httptools-0.6.4-cp39-cp39-win_amd64.whl", hash = "sha256:b799de31416ecc589ad79dd85a0b2657a8fe39327944998dea368c1d4c9e55e6"},
+ {file = "httptools-0.6.4.tar.gz", hash = "sha256:4e93eee4add6493b59a5c514da98c939b244fce4a0d8879cd3f466562f4b7d5c"},
+]
+
+[package.extras]
+test = ["Cython (>=0.29.24)"]
+
+[[package]]
+name = "httpx"
+version = "0.26.0"
+description = "The next generation HTTP client."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "httpx-0.26.0-py3-none-any.whl", hash = "sha256:8915f5a3627c4d47b73e8202457cb28f1266982d1159bd5779d86a80c0eab1cd"},
+ {file = "httpx-0.26.0.tar.gz", hash = "sha256:451b55c30d5185ea6b23c2c793abf9bb237d2a7dfb901ced6ff69ad37ec1dfaf"},
+]
+
+[package.dependencies]
+anyio = "*"
+certifi = "*"
+httpcore = "==1.*"
+idna = "*"
+sniffio = "*"
+
+[package.extras]
+brotli = ["brotli", "brotlicffi"]
+cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"]
+http2 = ["h2 (>=3,<5)"]
+socks = ["socksio (==1.*)"]
+
+[[package]]
+name = "identify"
+version = "2.6.2"
+description = "File identification library for Python"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "identify-2.6.2-py2.py3-none-any.whl", hash = "sha256:c097384259f49e372f4ea00a19719d95ae27dd5ff0fd77ad630aa891306b82f3"},
+ {file = "identify-2.6.2.tar.gz", hash = "sha256:fab5c716c24d7a789775228823797296a2994b075fb6080ac83a102772a98cbd"},
+]
+
+[package.extras]
+license = ["ukkonen"]
+
+[[package]]
+name = "idna"
+version = "3.10"
+description = "Internationalized Domain Names in Applications (IDNA)"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"},
+ {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"},
+]
+
+[package.extras]
+all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"]
+
+[[package]]
+name = "iniconfig"
+version = "2.0.0"
+description = "brain-dead simple config-ini parsing"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
+ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
+]
+
+[[package]]
+name = "inject"
+version = "5.2.1"
+description = "Python dependency injection framework."
+optional = false
+python-versions = "*"
+files = [
+ {file = "inject-5.2.1-py2.py3-none-any.whl", hash = "sha256:e40a5b1bebd8a4050b6f98f3396f3de6e9e2e411ad2a2145f16f351cb6f54e51"},
+ {file = "inject-5.2.1.tar.gz", hash = "sha256:f7c305a75cc4e3a331d248e996f25783ba784b88d5a9b9f73c53eacaa6d76985"},
+]
+
+[[package]]
+name = "jinja2"
+version = "3.1.4"
+description = "A very fast and expressive template engine."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"},
+ {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"},
+]
+
+[package.dependencies]
+MarkupSafe = ">=2.0"
+
+[package.extras]
+i18n = ["Babel (>=2.7)"]
+
+[[package]]
+name = "loguru"
+version = "0.7.2"
+description = "Python logging made (stupidly) simple"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "loguru-0.7.2-py3-none-any.whl", hash = "sha256:003d71e3d3ed35f0f8984898359d65b79e5b21943f78af86aa5491210429b8eb"},
+ {file = "loguru-0.7.2.tar.gz", hash = "sha256:e671a53522515f34fd406340ee968cb9ecafbc4b36c679da03c18fd8d0bd51ac"},
+]
+
+[package.dependencies]
+colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""}
+win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""}
+
+[package.extras]
+dev = ["Sphinx (==7.2.5)", "colorama (==0.4.5)", "colorama (==0.4.6)", "exceptiongroup (==1.1.3)", "freezegun (==1.1.0)", "freezegun (==1.2.2)", "mypy (==v0.910)", "mypy (==v0.971)", "mypy (==v1.4.1)", "mypy (==v1.5.1)", "pre-commit (==3.4.0)", "pytest (==6.1.2)", "pytest (==7.4.0)", "pytest-cov (==2.12.1)", "pytest-cov (==4.1.0)", "pytest-mypy-plugins (==1.9.3)", "pytest-mypy-plugins (==3.0.0)", "sphinx-autobuild (==2021.3.14)", "sphinx-rtd-theme (==1.3.0)", "tox (==3.27.1)", "tox (==4.11.0)"]
+
+[[package]]
+name = "markdown"
+version = "3.7"
+description = "Python implementation of John Gruber's Markdown."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "Markdown-3.7-py3-none-any.whl", hash = "sha256:7eb6df5690b81a1d7942992c97fad2938e956e79df20cbc6186e9c3a77b1c803"},
+ {file = "markdown-3.7.tar.gz", hash = "sha256:2ae2471477cfd02dbbf038d5d9bc226d40def84b4fe2986e49b59b6b472bbed2"},
+]
+
+[package.extras]
+docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"]
+testing = ["coverage", "pyyaml"]
+
+[[package]]
+name = "markdown-it-py"
+version = "3.0.0"
+description = "Python port of markdown-it. Markdown parsing, done right!"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"},
+ {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"},
+]
+
+[package.dependencies]
+mdurl = ">=0.1,<1.0"
+
+[package.extras]
+benchmarking = ["psutil", "pytest", "pytest-benchmark"]
+code-style = ["pre-commit (>=3.0,<4.0)"]
+compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"]
+linkify = ["linkify-it-py (>=1,<3)"]
+plugins = ["mdit-py-plugins"]
+profiling = ["gprof2dot"]
+rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"]
+testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
+
+[[package]]
+name = "markupsafe"
+version = "3.0.2"
+description = "Safely add untrusted strings to HTML/XML markup."
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"},
+ {file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"},
+ {file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"},
+ {file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"},
+ {file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"},
+ {file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"},
+ {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"},
+]
+
+[[package]]
+name = "mdurl"
+version = "0.1.2"
+description = "Markdown URL utilities"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"},
+ {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"},
+]
+
+[[package]]
+name = "mergedeep"
+version = "1.3.4"
+description = "A deep merge function for 🐍."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"},
+ {file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"},
+]
+
+[[package]]
+name = "mkdocs"
+version = "1.6.1"
+description = "Project documentation with Markdown."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "mkdocs-1.6.1-py3-none-any.whl", hash = "sha256:db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e"},
+ {file = "mkdocs-1.6.1.tar.gz", hash = "sha256:7b432f01d928c084353ab39c57282f29f92136665bdd6abf7c1ec8d822ef86f2"},
+]
+
+[package.dependencies]
+click = ">=7.0"
+colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""}
+ghp-import = ">=1.0"
+jinja2 = ">=2.11.1"
+markdown = ">=3.3.6"
+markupsafe = ">=2.0.1"
+mergedeep = ">=1.3.4"
+mkdocs-get-deps = ">=0.2.0"
+packaging = ">=20.5"
+pathspec = ">=0.11.1"
+pyyaml = ">=5.1"
+pyyaml-env-tag = ">=0.1"
+watchdog = ">=2.0"
+
+[package.extras]
+i18n = ["babel (>=2.9.0)"]
+min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.4)", "jinja2 (==2.11.1)", "markdown (==3.3.6)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "mkdocs-get-deps (==0.2.0)", "packaging (==20.5)", "pathspec (==0.11.1)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "watchdog (==2.0)"]
+
+[[package]]
+name = "mkdocs-autorefs"
+version = "1.2.0"
+description = "Automatically link across pages in MkDocs."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "mkdocs_autorefs-1.2.0-py3-none-any.whl", hash = "sha256:d588754ae89bd0ced0c70c06f58566a4ee43471eeeee5202427da7de9ef85a2f"},
+ {file = "mkdocs_autorefs-1.2.0.tar.gz", hash = "sha256:a86b93abff653521bda71cf3fc5596342b7a23982093915cb74273f67522190f"},
+]
+
+[package.dependencies]
+Markdown = ">=3.3"
+markupsafe = ">=2.0.1"
+mkdocs = ">=1.1"
+
+[[package]]
+name = "mkdocs-get-deps"
+version = "0.2.0"
+description = "MkDocs extension that lists all dependencies according to a mkdocs.yml file"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134"},
+ {file = "mkdocs_get_deps-0.2.0.tar.gz", hash = "sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c"},
+]
+
+[package.dependencies]
+mergedeep = ">=1.3.4"
+platformdirs = ">=2.2.0"
+pyyaml = ">=5.1"
+
+[[package]]
+name = "mkdocs-material"
+version = "9.5.45"
+description = "Documentation that simply works"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "mkdocs_material-9.5.45-py3-none-any.whl", hash = "sha256:a9be237cfd0be14be75f40f1726d83aa3a81ce44808dc3594d47a7a592f44547"},
+ {file = "mkdocs_material-9.5.45.tar.gz", hash = "sha256:286489cf0beca4a129d91d59d6417419c63bceed1ce5cd0ec1fc7e1ebffb8189"},
+]
+
+[package.dependencies]
+babel = ">=2.10,<3.0"
+colorama = ">=0.4,<1.0"
+jinja2 = ">=3.0,<4.0"
+markdown = ">=3.2,<4.0"
+mkdocs = ">=1.6,<2.0"
+mkdocs-material-extensions = ">=1.3,<2.0"
+paginate = ">=0.5,<1.0"
+pygments = ">=2.16,<3.0"
+pymdown-extensions = ">=10.2,<11.0"
+regex = ">=2022.4"
+requests = ">=2.26,<3.0"
+
+[package.extras]
+git = ["mkdocs-git-committers-plugin-2 (>=1.1,<2.0)", "mkdocs-git-revision-date-localized-plugin (>=1.2.4,<2.0)"]
+imaging = ["cairosvg (>=2.6,<3.0)", "pillow (>=10.2,<11.0)"]
+recommended = ["mkdocs-minify-plugin (>=0.7,<1.0)", "mkdocs-redirects (>=1.2,<2.0)", "mkdocs-rss-plugin (>=1.6,<2.0)"]
+
+[[package]]
+name = "mkdocs-material-extensions"
+version = "1.3.1"
+description = "Extension pack for Python Markdown and MkDocs Material."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31"},
+ {file = "mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443"},
+]
+
+[[package]]
+name = "mkdocs-monorepo-plugin"
+version = "1.1.0"
+description = "Plugin for adding monorepository support in Mkdocs."
+optional = false
+python-versions = ">=3"
+files = [
+ {file = "mkdocs-monorepo-plugin-1.1.0.tar.gz", hash = "sha256:ccc566e166aac5ae7fade498c15c4a337a4892d238629b51aba8ef3fc7099034"},
+ {file = "mkdocs_monorepo_plugin-1.1.0-py3-none-any.whl", hash = "sha256:7bbfd9756a7fdecf64d6105dad96cce7e7bb5f0d6cfc2bfda31a1919c77cc3b9"},
+]
+
+[package.dependencies]
+mkdocs = ">=1.0.4"
+python-slugify = ">=4.0.1"
+
+[[package]]
+name = "mkdocstrings"
+version = "0.27.0"
+description = "Automatic documentation from sources, for MkDocs."
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "mkdocstrings-0.27.0-py3-none-any.whl", hash = "sha256:6ceaa7ea830770959b55a16203ac63da24badd71325b96af950e59fd37366332"},
+ {file = "mkdocstrings-0.27.0.tar.gz", hash = "sha256:16adca6d6b0a1f9e0c07ff0b02ced8e16f228a9d65a37c063ec4c14d7b76a657"},
+]
+
+[package.dependencies]
+click = ">=7.0"
+Jinja2 = ">=2.11.1"
+Markdown = ">=3.6"
+MarkupSafe = ">=1.1"
+mkdocs = ">=1.4"
+mkdocs-autorefs = ">=1.2"
+platformdirs = ">=2.2"
+pymdown-extensions = ">=6.3"
+
+[package.extras]
+crystal = ["mkdocstrings-crystal (>=0.3.4)"]
+python = ["mkdocstrings-python (>=0.5.2)"]
+python-legacy = ["mkdocstrings-python-legacy (>=0.2.1)"]
+
+[[package]]
+name = "mkdocstrings-python"
+version = "1.12.2"
+description = "A Python handler for mkdocstrings."
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "mkdocstrings_python-1.12.2-py3-none-any.whl", hash = "sha256:7f7d40d6db3cb1f5d19dbcd80e3efe4d0ba32b073272c0c0de9de2e604eda62a"},
+ {file = "mkdocstrings_python-1.12.2.tar.gz", hash = "sha256:7a1760941c0b52a2cd87b960a9e21112ffe52e7df9d0b9583d04d47ed2e186f3"},
+]
+
+[package.dependencies]
+griffe = ">=0.49"
+mkdocs-autorefs = ">=1.2"
+mkdocstrings = ">=0.26"
+
+[[package]]
+name = "multidict"
+version = "6.1.0"
+description = "multidict implementation"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60"},
+ {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1"},
+ {file = "multidict-6.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a114d03b938376557927ab23f1e950827c3b893ccb94b62fd95d430fd0e5cf53"},
+ {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1c416351ee6271b2f49b56ad7f308072f6f44b37118d69c2cad94f3fa8a40d5"},
+ {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b5d83030255983181005e6cfbac1617ce9746b219bc2aad52201ad121226581"},
+ {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3e97b5e938051226dc025ec80980c285b053ffb1e25a3db2a3aa3bc046bf7f56"},
+ {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d618649d4e70ac6efcbba75be98b26ef5078faad23592f9b51ca492953012429"},
+ {file = "multidict-6.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10524ebd769727ac77ef2278390fb0068d83f3acb7773792a5080f2b0abf7748"},
+ {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ff3827aef427c89a25cc96ded1759271a93603aba9fb977a6d264648ebf989db"},
+ {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056"},
+ {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f179dee3b863ab1c59580ff60f9d99f632f34ccb38bf67a33ec6b3ecadd0fd76"},
+ {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:aaed8b0562be4a0876ee3b6946f6869b7bcdb571a5d1496683505944e268b160"},
+ {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3c8b88a2ccf5493b6c8da9076fb151ba106960a2df90c2633f342f120751a9e7"},
+ {file = "multidict-6.1.0-cp310-cp310-win32.whl", hash = "sha256:4a9cb68166a34117d6646c0023c7b759bf197bee5ad4272f420a0141d7eb03a0"},
+ {file = "multidict-6.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:20b9b5fbe0b88d0bdef2012ef7dee867f874b72528cf1d08f1d59b0e3850129d"},
+ {file = "multidict-6.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6"},
+ {file = "multidict-6.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156"},
+ {file = "multidict-6.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb"},
+ {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b"},
+ {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72"},
+ {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304"},
+ {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351"},
+ {file = "multidict-6.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb"},
+ {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3"},
+ {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399"},
+ {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423"},
+ {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3"},
+ {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753"},
+ {file = "multidict-6.1.0-cp311-cp311-win32.whl", hash = "sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80"},
+ {file = "multidict-6.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926"},
+ {file = "multidict-6.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa"},
+ {file = "multidict-6.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436"},
+ {file = "multidict-6.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761"},
+ {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e"},
+ {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef"},
+ {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95"},
+ {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925"},
+ {file = "multidict-6.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966"},
+ {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305"},
+ {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2"},
+ {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2"},
+ {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6"},
+ {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3"},
+ {file = "multidict-6.1.0-cp312-cp312-win32.whl", hash = "sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133"},
+ {file = "multidict-6.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1"},
+ {file = "multidict-6.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008"},
+ {file = "multidict-6.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f"},
+ {file = "multidict-6.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28"},
+ {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b"},
+ {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c"},
+ {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3"},
+ {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44"},
+ {file = "multidict-6.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2"},
+ {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3"},
+ {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa"},
+ {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa"},
+ {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4"},
+ {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6"},
+ {file = "multidict-6.1.0-cp313-cp313-win32.whl", hash = "sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81"},
+ {file = "multidict-6.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774"},
+ {file = "multidict-6.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:db7457bac39421addd0c8449933ac32d8042aae84a14911a757ae6ca3eef1392"},
+ {file = "multidict-6.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d094ddec350a2fb899fec68d8353c78233debde9b7d8b4beeafa70825f1c281a"},
+ {file = "multidict-6.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5845c1fd4866bb5dd3125d89b90e57ed3138241540897de748cdf19de8a2fca2"},
+ {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9079dfc6a70abe341f521f78405b8949f96db48da98aeb43f9907f342f627cdc"},
+ {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3914f5aaa0f36d5d60e8ece6a308ee1c9784cd75ec8151062614657a114c4478"},
+ {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c08be4f460903e5a9d0f76818db3250f12e9c344e79314d1d570fc69d7f4eae4"},
+ {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d093be959277cb7dee84b801eb1af388b6ad3ca6a6b6bf1ed7585895789d027d"},
+ {file = "multidict-6.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3702ea6872c5a2a4eeefa6ffd36b042e9773f05b1f37ae3ef7264b1163c2dcf6"},
+ {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2090f6a85cafc5b2db085124d752757c9d251548cedabe9bd31afe6363e0aff2"},
+ {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:f67f217af4b1ff66c68a87318012de788dd95fcfeb24cc889011f4e1c7454dfd"},
+ {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:189f652a87e876098bbc67b4da1049afb5f5dfbaa310dd67c594b01c10388db6"},
+ {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:6bb5992037f7a9eff7991ebe4273ea7f51f1c1c511e6a2ce511d0e7bdb754492"},
+ {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:ac10f4c2b9e770c4e393876e35a7046879d195cd123b4f116d299d442b335bcd"},
+ {file = "multidict-6.1.0-cp38-cp38-win32.whl", hash = "sha256:e27bbb6d14416713a8bd7aaa1313c0fc8d44ee48d74497a0ff4c3a1b6ccb5167"},
+ {file = "multidict-6.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:22f3105d4fb15c8f57ff3959a58fcab6ce36814486500cd7485651230ad4d4ef"},
+ {file = "multidict-6.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:4e18b656c5e844539d506a0a06432274d7bd52a7487e6828c63a63d69185626c"},
+ {file = "multidict-6.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a185f876e69897a6f3325c3f19f26a297fa058c5e456bfcff8015e9a27e83ae1"},
+ {file = "multidict-6.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ab7c4ceb38d91570a650dba194e1ca87c2b543488fe9309b4212694174fd539c"},
+ {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e617fb6b0b6953fffd762669610c1c4ffd05632c138d61ac7e14ad187870669c"},
+ {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16e5f4bf4e603eb1fdd5d8180f1a25f30056f22e55ce51fb3d6ad4ab29f7d96f"},
+ {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4c035da3f544b1882bac24115f3e2e8760f10a0107614fc9839fd232200b875"},
+ {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:957cf8e4b6e123a9eea554fa7ebc85674674b713551de587eb318a2df3e00255"},
+ {file = "multidict-6.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:483a6aea59cb89904e1ceabd2b47368b5600fb7de78a6e4a2c2987b2d256cf30"},
+ {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:87701f25a2352e5bf7454caa64757642734da9f6b11384c1f9d1a8e699758057"},
+ {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:682b987361e5fd7a139ed565e30d81fd81e9629acc7d925a205366877d8c8657"},
+ {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ce2186a7df133a9c895dea3331ddc5ddad42cdd0d1ea2f0a51e5d161e4762f28"},
+ {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9f636b730f7e8cb19feb87094949ba54ee5357440b9658b2a32a5ce4bce53972"},
+ {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:73eae06aa53af2ea5270cc066dcaf02cc60d2994bbb2c4ef5764949257d10f43"},
+ {file = "multidict-6.1.0-cp39-cp39-win32.whl", hash = "sha256:1ca0083e80e791cffc6efce7660ad24af66c8d4079d2a750b29001b53ff59ada"},
+ {file = "multidict-6.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:aa466da5b15ccea564bdab9c89175c762bc12825f4659c11227f515cee76fa4a"},
+ {file = "multidict-6.1.0-py3-none-any.whl", hash = "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506"},
+ {file = "multidict-6.1.0.tar.gz", hash = "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a"},
+]
+
+[[package]]
+name = "mypy"
+version = "1.13.0"
+description = "Optional static typing for Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "mypy-1.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6607e0f1dd1fb7f0aca14d936d13fd19eba5e17e1cd2a14f808fa5f8f6d8f60a"},
+ {file = "mypy-1.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8a21be69bd26fa81b1f80a61ee7ab05b076c674d9b18fb56239d72e21d9f4c80"},
+ {file = "mypy-1.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7b2353a44d2179846a096e25691d54d59904559f4232519d420d64da6828a3a7"},
+ {file = "mypy-1.13.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0730d1c6a2739d4511dc4253f8274cdd140c55c32dfb0a4cf8b7a43f40abfa6f"},
+ {file = "mypy-1.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:c5fc54dbb712ff5e5a0fca797e6e0aa25726c7e72c6a5850cfd2adbc1eb0a372"},
+ {file = "mypy-1.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:581665e6f3a8a9078f28d5502f4c334c0c8d802ef55ea0e7276a6e409bc0d82d"},
+ {file = "mypy-1.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3ddb5b9bf82e05cc9a627e84707b528e5c7caaa1c55c69e175abb15a761cec2d"},
+ {file = "mypy-1.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20c7ee0bc0d5a9595c46f38beb04201f2620065a93755704e141fcac9f59db2b"},
+ {file = "mypy-1.13.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3790ded76f0b34bc9c8ba4def8f919dd6a46db0f5a6610fb994fe8efdd447f73"},
+ {file = "mypy-1.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:51f869f4b6b538229c1d1bcc1dd7d119817206e2bc54e8e374b3dfa202defcca"},
+ {file = "mypy-1.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5c7051a3461ae84dfb5dd15eff5094640c61c5f22257c8b766794e6dd85e72d5"},
+ {file = "mypy-1.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:39bb21c69a5d6342f4ce526e4584bc5c197fd20a60d14a8624d8743fffb9472e"},
+ {file = "mypy-1.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:164f28cb9d6367439031f4c81e84d3ccaa1e19232d9d05d37cb0bd880d3f93c2"},
+ {file = "mypy-1.13.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a4c1bfcdbce96ff5d96fc9b08e3831acb30dc44ab02671eca5953eadad07d6d0"},
+ {file = "mypy-1.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:a0affb3a79a256b4183ba09811e3577c5163ed06685e4d4b46429a271ba174d2"},
+ {file = "mypy-1.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a7b44178c9760ce1a43f544e595d35ed61ac2c3de306599fa59b38a6048e1aa7"},
+ {file = "mypy-1.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5d5092efb8516d08440e36626f0153b5006d4088c1d663d88bf79625af3d1d62"},
+ {file = "mypy-1.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de2904956dac40ced10931ac967ae63c5089bd498542194b436eb097a9f77bc8"},
+ {file = "mypy-1.13.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:7bfd8836970d33c2105562650656b6846149374dc8ed77d98424b40b09340ba7"},
+ {file = "mypy-1.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:9f73dba9ec77acb86457a8fc04b5239822df0c14a082564737833d2963677dbc"},
+ {file = "mypy-1.13.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:100fac22ce82925f676a734af0db922ecfea991e1d7ec0ceb1e115ebe501301a"},
+ {file = "mypy-1.13.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7bcb0bb7f42a978bb323a7c88f1081d1b5dee77ca86f4100735a6f541299d8fb"},
+ {file = "mypy-1.13.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bde31fc887c213e223bbfc34328070996061b0833b0a4cfec53745ed61f3519b"},
+ {file = "mypy-1.13.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:07de989f89786f62b937851295ed62e51774722e5444a27cecca993fc3f9cd74"},
+ {file = "mypy-1.13.0-cp38-cp38-win_amd64.whl", hash = "sha256:4bde84334fbe19bad704b3f5b78c4abd35ff1026f8ba72b29de70dda0916beb6"},
+ {file = "mypy-1.13.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0246bcb1b5de7f08f2826451abd947bf656945209b140d16ed317f65a17dc7dc"},
+ {file = "mypy-1.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7f5b7deae912cf8b77e990b9280f170381fdfbddf61b4ef80927edd813163732"},
+ {file = "mypy-1.13.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7029881ec6ffb8bc233a4fa364736789582c738217b133f1b55967115288a2bc"},
+ {file = "mypy-1.13.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3e38b980e5681f28f033f3be86b099a247b13c491f14bb8b1e1e134d23bb599d"},
+ {file = "mypy-1.13.0-cp39-cp39-win_amd64.whl", hash = "sha256:a6789be98a2017c912ae6ccb77ea553bbaf13d27605d2ca20a76dfbced631b24"},
+ {file = "mypy-1.13.0-py3-none-any.whl", hash = "sha256:9c250883f9fd81d212e0952c92dbfcc96fc237f4b7c92f56ac81fd48460b3e5a"},
+ {file = "mypy-1.13.0.tar.gz", hash = "sha256:0291a61b6fbf3e6673e3405cfcc0e7650bebc7939659fdca2702958038bd835e"},
+]
+
+[package.dependencies]
+mypy-extensions = ">=1.0.0"
+typing-extensions = ">=4.6.0"
+
+[package.extras]
+dmypy = ["psutil (>=4.0)"]
+faster-cache = ["orjson"]
+install-types = ["pip"]
+mypyc = ["setuptools (>=50)"]
+reports = ["lxml"]
+
+[[package]]
+name = "mypy-extensions"
+version = "1.0.0"
+description = "Type system extensions for programs checked with the mypy type checker."
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
+ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
+]
+
+[[package]]
+name = "mysql-connector-python"
+version = "8.4.0"
+description = "MySQL driver written in Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "mysql-connector-python-8.4.0.tar.gz", hash = "sha256:42542d131d63c78416d410fdc9e84b9acb960d715c2e7b28c57ac9577c6d8165"},
+ {file = "mysql_connector_python-8.4.0-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:c0a2688d95d53cfbea9352ed61926b47bc9042570570fb8fe0a8d19b1e20f1c4"},
+ {file = "mysql_connector_python-8.4.0-cp310-cp310-macosx_13_0_x86_64.whl", hash = "sha256:276bae0d5d44abb7ba1205003b55628e4e6f1d399f1825d518bc607320997b1f"},
+ {file = "mysql_connector_python-8.4.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:a6d24ea29b3c2bdbba6861590de557665420bfb938f74b5cecc630bac5457d35"},
+ {file = "mysql_connector_python-8.4.0-cp310-cp310-manylinux_2_17_x86_64.whl", hash = "sha256:b7876358d9e51f25edc492088c4ce16cd14c2db87c279a965b0f9c327723359c"},
+ {file = "mysql_connector_python-8.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:085024bf12d15f9b428938fdbeb50bd9b15dda9c4d3a474e6df061cb08713e6a"},
+ {file = "mysql_connector_python-8.4.0-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:4e83fc8ed95005b171ffa36a289dac48625048263b09b56718e8395539ea07d9"},
+ {file = "mysql_connector_python-8.4.0-cp311-cp311-macosx_13_0_x86_64.whl", hash = "sha256:cd89d1c8c2d1e33e5ac2d4eac5813422c150a8427fb60a16c59be18c29dd9a94"},
+ {file = "mysql_connector_python-8.4.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:76c13fde35a038afe50550a9af7b31b28ca3a04cce06f3030980afb20460d28c"},
+ {file = "mysql_connector_python-8.4.0-cp311-cp311-manylinux_2_17_x86_64.whl", hash = "sha256:accf10425c6af39a9595a47e7119ebcbcd7351f7df28755dbee01bca5a605b7c"},
+ {file = "mysql_connector_python-8.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cda868bb4e1641362d148f5b0d2a86188cffa2f7188831589781b13f2df6f51a"},
+ {file = "mysql_connector_python-8.4.0-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:3ae951f2e16d089975cb9f05b3f3e58807dc33a2e5a627047bba1c8ad5439d82"},
+ {file = "mysql_connector_python-8.4.0-cp312-cp312-macosx_13_0_x86_64.whl", hash = "sha256:af40b5bdd91547d3dbf5fa62bde37e9e840bd7cba3b9246b55c09e6a1cde536f"},
+ {file = "mysql_connector_python-8.4.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:bb4f3edab78f3fd6f80c6c0a9e5a533704044fc01bfb9e8736e1a993f74aa42d"},
+ {file = "mysql_connector_python-8.4.0-cp312-cp312-manylinux_2_17_x86_64.whl", hash = "sha256:e549674c72b596a7386f4a76bbac2ee9581f6632e6713618a70468713b162964"},
+ {file = "mysql_connector_python-8.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:aed505adc76b58282c76e6cbf3da195be0f84029a41f05c470be977481896074"},
+ {file = "mysql_connector_python-8.4.0-cp38-cp38-macosx_13_0_x86_64.whl", hash = "sha256:d343a4a8133ae9561bd537fc8cdbcab74a0607a5f40698569010fa3c7d4a048f"},
+ {file = "mysql_connector_python-8.4.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:74b1759d8bd9ccd4296dc2e5abe22ec7efbd1ad12a9032c2cb4d17fa5d0ca6e0"},
+ {file = "mysql_connector_python-8.4.0-cp38-cp38-manylinux_2_17_x86_64.whl", hash = "sha256:e6d5a418ef124dd1b18a73fd89431a1862ce7bf68f61275c7d006e8e2f8afcd2"},
+ {file = "mysql_connector_python-8.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:427a84027b8314c73f5ff3eb1abdc709a8201b44a491d7b580bdf430b4820a16"},
+ {file = "mysql_connector_python-8.4.0-cp39-cp39-macosx_13_0_arm64.whl", hash = "sha256:44a99d44a925ea29c2e423e6d8b1d97ce740c3078d8b41923a81bbcd0a821972"},
+ {file = "mysql_connector_python-8.4.0-cp39-cp39-macosx_13_0_x86_64.whl", hash = "sha256:ed276c4e7907da0ad95a9ad122004294d6fb425127064af2ae880033b8e72166"},
+ {file = "mysql_connector_python-8.4.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:2b5c6fea6513cf208c7116a4a5e36b3ae54e0d37f324a7cfe43fb01cfdf03be6"},
+ {file = "mysql_connector_python-8.4.0-cp39-cp39-manylinux_2_17_x86_64.whl", hash = "sha256:651c7824af57eb50f4a79ea04bf6f453b24381e1bb56eee45c0035b4c0c624c0"},
+ {file = "mysql_connector_python-8.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:655dccbdc0e2943e62cf69e10a024329248b17b58bfac59c60fd2103db3ba0b0"},
+ {file = "mysql_connector_python-8.4.0-py2.py3-none-any.whl", hash = "sha256:35939c4ff28f395a5550bae67bafa4d1658ea72ea3206f457fff64a0fbec17e4"},
+]
+
+[package.extras]
+dns-srv = ["dnspython (>=1.16.0,<=2.3.0)"]
+fido2 = ["fido2 (==1.1.2)"]
+gssapi = ["gssapi (>=1.6.9,<=1.8.2)"]
+opentelemetry = ["Deprecated (>=1.2.6)", "typing-extensions (>=3.7.4)", "zipp (>=0.5)"]
+
+[[package]]
+name = "nodeenv"
+version = "1.9.1"
+description = "Node.js virtual environment builder"
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+files = [
+ {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"},
+ {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"},
+]
+
+[[package]]
+name = "ordered-set"
+version = "4.1.0"
+description = "An OrderedSet is a custom MutableSet that remembers its order, so that every"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "ordered-set-4.1.0.tar.gz", hash = "sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8"},
+ {file = "ordered_set-4.1.0-py3-none-any.whl", hash = "sha256:046e1132c71fcf3330438a539928932caf51ddbc582496833e23de611de14562"},
+]
+
+[package.extras]
+dev = ["black", "mypy", "pytest"]
+
+[[package]]
+name = "packaging"
+version = "24.2"
+description = "Core utilities for Python packages"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"},
+ {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"},
+]
+
+[[package]]
+name = "paginate"
+version = "0.5.7"
+description = "Divides large result sets into pages for easier browsing"
+optional = false
+python-versions = "*"
+files = [
+ {file = "paginate-0.5.7-py2.py3-none-any.whl", hash = "sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591"},
+ {file = "paginate-0.5.7.tar.gz", hash = "sha256:22bd083ab41e1a8b4f3690544afb2c60c25e5c9a63a30fa2f483f6c60c8e5945"},
+]
+
+[package.extras]
+dev = ["pytest", "tox"]
+lint = ["black"]
+
+[[package]]
+name = "pathspec"
+version = "0.12.1"
+description = "Utility library for gitignore style pattern matching of file paths."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"},
+ {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"},
+]
+
+[[package]]
+name = "pendulum"
+version = "3.0.0"
+description = "Python datetimes made easy"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pendulum-3.0.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2cf9e53ef11668e07f73190c805dbdf07a1939c3298b78d5a9203a86775d1bfd"},
+ {file = "pendulum-3.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fb551b9b5e6059377889d2d878d940fd0bbb80ae4810543db18e6f77b02c5ef6"},
+ {file = "pendulum-3.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c58227ac260d5b01fc1025176d7b31858c9f62595737f350d22124a9a3ad82d"},
+ {file = "pendulum-3.0.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60fb6f415fea93a11c52578eaa10594568a6716602be8430b167eb0d730f3332"},
+ {file = "pendulum-3.0.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b69f6b4dbcb86f2c2fe696ba991e67347bcf87fe601362a1aba6431454b46bde"},
+ {file = "pendulum-3.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:138afa9c373ee450ede206db5a5e9004fd3011b3c6bbe1e57015395cd076a09f"},
+ {file = "pendulum-3.0.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:83d9031f39c6da9677164241fd0d37fbfc9dc8ade7043b5d6d62f56e81af8ad2"},
+ {file = "pendulum-3.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0c2308af4033fa534f089595bcd40a95a39988ce4059ccd3dc6acb9ef14ca44a"},
+ {file = "pendulum-3.0.0-cp310-none-win_amd64.whl", hash = "sha256:9a59637cdb8462bdf2dbcb9d389518c0263799189d773ad5c11db6b13064fa79"},
+ {file = "pendulum-3.0.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3725245c0352c95d6ca297193192020d1b0c0f83d5ee6bb09964edc2b5a2d508"},
+ {file = "pendulum-3.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6c035f03a3e565ed132927e2c1b691de0dbf4eb53b02a5a3c5a97e1a64e17bec"},
+ {file = "pendulum-3.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:597e66e63cbd68dd6d58ac46cb7a92363d2088d37ccde2dae4332ef23e95cd00"},
+ {file = "pendulum-3.0.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99a0f8172e19f3f0c0e4ace0ad1595134d5243cf75985dc2233e8f9e8de263ca"},
+ {file = "pendulum-3.0.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:77d8839e20f54706aed425bec82a83b4aec74db07f26acd039905d1237a5e1d4"},
+ {file = "pendulum-3.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afde30e8146292b059020fbc8b6f8fd4a60ae7c5e6f0afef937bbb24880bdf01"},
+ {file = "pendulum-3.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:660434a6fcf6303c4efd36713ca9212c753140107ee169a3fc6c49c4711c2a05"},
+ {file = "pendulum-3.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dee9e5a48c6999dc1106eb7eea3e3a50e98a50651b72c08a87ee2154e544b33e"},
+ {file = "pendulum-3.0.0-cp311-none-win_amd64.whl", hash = "sha256:d4cdecde90aec2d67cebe4042fd2a87a4441cc02152ed7ed8fb3ebb110b94ec4"},
+ {file = "pendulum-3.0.0-cp311-none-win_arm64.whl", hash = "sha256:773c3bc4ddda2dda9f1b9d51fe06762f9200f3293d75c4660c19b2614b991d83"},
+ {file = "pendulum-3.0.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:409e64e41418c49f973d43a28afe5df1df4f1dd87c41c7c90f1a63f61ae0f1f7"},
+ {file = "pendulum-3.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a38ad2121c5ec7c4c190c7334e789c3b4624798859156b138fcc4d92295835dc"},
+ {file = "pendulum-3.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fde4d0b2024b9785f66b7f30ed59281bd60d63d9213cda0eb0910ead777f6d37"},
+ {file = "pendulum-3.0.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b2c5675769fb6d4c11238132962939b960fcb365436b6d623c5864287faa319"},
+ {file = "pendulum-3.0.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8af95e03e066826f0f4c65811cbee1b3123d4a45a1c3a2b4fc23c4b0dff893b5"},
+ {file = "pendulum-3.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2165a8f33cb15e06c67070b8afc87a62b85c5a273e3aaa6bc9d15c93a4920d6f"},
+ {file = "pendulum-3.0.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ad5e65b874b5e56bd942546ea7ba9dd1d6a25121db1c517700f1c9de91b28518"},
+ {file = "pendulum-3.0.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:17fe4b2c844bbf5f0ece69cfd959fa02957c61317b2161763950d88fed8e13b9"},
+ {file = "pendulum-3.0.0-cp312-none-win_amd64.whl", hash = "sha256:78f8f4e7efe5066aca24a7a57511b9c2119f5c2b5eb81c46ff9222ce11e0a7a5"},
+ {file = "pendulum-3.0.0-cp312-none-win_arm64.whl", hash = "sha256:28f49d8d1e32aae9c284a90b6bb3873eee15ec6e1d9042edd611b22a94ac462f"},
+ {file = "pendulum-3.0.0-cp37-cp37m-macosx_10_12_x86_64.whl", hash = "sha256:d4e2512f4e1a4670284a153b214db9719eb5d14ac55ada5b76cbdb8c5c00399d"},
+ {file = "pendulum-3.0.0-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:3d897eb50883cc58d9b92f6405245f84b9286cd2de6e8694cb9ea5cb15195a32"},
+ {file = "pendulum-3.0.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e169cc2ca419517f397811bbe4589cf3cd13fca6dc38bb352ba15ea90739ebb"},
+ {file = "pendulum-3.0.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f17c3084a4524ebefd9255513692f7e7360e23c8853dc6f10c64cc184e1217ab"},
+ {file = "pendulum-3.0.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:826d6e258052715f64d05ae0fc9040c0151e6a87aae7c109ba9a0ed930ce4000"},
+ {file = "pendulum-3.0.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2aae97087872ef152a0c40e06100b3665d8cb86b59bc8471ca7c26132fccd0f"},
+ {file = "pendulum-3.0.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ac65eeec2250d03106b5e81284ad47f0d417ca299a45e89ccc69e36130ca8bc7"},
+ {file = "pendulum-3.0.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a5346d08f3f4a6e9e672187faa179c7bf9227897081d7121866358af369f44f9"},
+ {file = "pendulum-3.0.0-cp37-none-win_amd64.whl", hash = "sha256:235d64e87946d8f95c796af34818c76e0f88c94d624c268693c85b723b698aa9"},
+ {file = "pendulum-3.0.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:6a881d9c2a7f85bc9adafcfe671df5207f51f5715ae61f5d838b77a1356e8b7b"},
+ {file = "pendulum-3.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d7762d2076b9b1cb718a6631ad6c16c23fc3fac76cbb8c454e81e80be98daa34"},
+ {file = "pendulum-3.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e8e36a8130819d97a479a0e7bf379b66b3b1b520e5dc46bd7eb14634338df8c"},
+ {file = "pendulum-3.0.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7dc843253ac373358ffc0711960e2dd5b94ab67530a3e204d85c6e8cb2c5fa10"},
+ {file = "pendulum-3.0.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0a78ad3635d609ceb1e97d6aedef6a6a6f93433ddb2312888e668365908c7120"},
+ {file = "pendulum-3.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b30a137e9e0d1f751e60e67d11fc67781a572db76b2296f7b4d44554761049d6"},
+ {file = "pendulum-3.0.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c95984037987f4a457bb760455d9ca80467be792236b69d0084f228a8ada0162"},
+ {file = "pendulum-3.0.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d29c6e578fe0f893766c0d286adbf0b3c726a4e2341eba0917ec79c50274ec16"},
+ {file = "pendulum-3.0.0-cp38-none-win_amd64.whl", hash = "sha256:deaba8e16dbfcb3d7a6b5fabdd5a38b7c982809567479987b9c89572df62e027"},
+ {file = "pendulum-3.0.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b11aceea5b20b4b5382962b321dbc354af0defe35daa84e9ff3aae3c230df694"},
+ {file = "pendulum-3.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a90d4d504e82ad236afac9adca4d6a19e4865f717034fc69bafb112c320dcc8f"},
+ {file = "pendulum-3.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:825799c6b66e3734227756fa746cc34b3549c48693325b8b9f823cb7d21b19ac"},
+ {file = "pendulum-3.0.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad769e98dc07972e24afe0cff8d365cb6f0ebc7e65620aa1976fcfbcadc4c6f3"},
+ {file = "pendulum-3.0.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6fc26907eb5fb8cc6188cc620bc2075a6c534d981a2f045daa5f79dfe50d512"},
+ {file = "pendulum-3.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c717eab1b6d898c00a3e0fa7781d615b5c5136bbd40abe82be100bb06df7a56"},
+ {file = "pendulum-3.0.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3ddd1d66d1a714ce43acfe337190be055cdc221d911fc886d5a3aae28e14b76d"},
+ {file = "pendulum-3.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:822172853d7a9cf6da95d7b66a16c7160cb99ae6df55d44373888181d7a06edc"},
+ {file = "pendulum-3.0.0-cp39-none-win_amd64.whl", hash = "sha256:840de1b49cf1ec54c225a2a6f4f0784d50bd47f68e41dc005b7f67c7d5b5f3ae"},
+ {file = "pendulum-3.0.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3b1f74d1e6ffe5d01d6023870e2ce5c2191486928823196f8575dcc786e107b1"},
+ {file = "pendulum-3.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:729e9f93756a2cdfa77d0fc82068346e9731c7e884097160603872686e570f07"},
+ {file = "pendulum-3.0.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e586acc0b450cd21cbf0db6bae386237011b75260a3adceddc4be15334689a9a"},
+ {file = "pendulum-3.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22e7944ffc1f0099a79ff468ee9630c73f8c7835cd76fdb57ef7320e6a409df4"},
+ {file = "pendulum-3.0.0-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:fa30af36bd8e50686846bdace37cf6707bdd044e5cb6e1109acbad3277232e04"},
+ {file = "pendulum-3.0.0-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:440215347b11914ae707981b9a57ab9c7b6983ab0babde07063c6ee75c0dc6e7"},
+ {file = "pendulum-3.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:314c4038dc5e6a52991570f50edb2f08c339debdf8cea68ac355b32c4174e820"},
+ {file = "pendulum-3.0.0-pp37-pypy37_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5acb1d386337415f74f4d1955c4ce8d0201978c162927d07df8eb0692b2d8533"},
+ {file = "pendulum-3.0.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a789e12fbdefaffb7b8ac67f9d8f22ba17a3050ceaaa635cd1cc4645773a4b1e"},
+ {file = "pendulum-3.0.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:860aa9b8a888e5913bd70d819306749e5eb488e6b99cd6c47beb701b22bdecf5"},
+ {file = "pendulum-3.0.0-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:5ebc65ea033ef0281368217fbf59f5cb05b338ac4dd23d60959c7afcd79a60a0"},
+ {file = "pendulum-3.0.0-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:d9fef18ab0386ef6a9ac7bad7e43ded42c83ff7ad412f950633854f90d59afa8"},
+ {file = "pendulum-3.0.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:1c134ba2f0571d0b68b83f6972e2307a55a5a849e7dac8505c715c531d2a8795"},
+ {file = "pendulum-3.0.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:385680812e7e18af200bb9b4a49777418c32422d05ad5a8eb85144c4a285907b"},
+ {file = "pendulum-3.0.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9eec91cd87c59fb32ec49eb722f375bd58f4be790cae11c1b70fac3ee4f00da0"},
+ {file = "pendulum-3.0.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4386bffeca23c4b69ad50a36211f75b35a4deb6210bdca112ac3043deb7e494a"},
+ {file = "pendulum-3.0.0-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:dfbcf1661d7146d7698da4b86e7f04814221081e9fe154183e34f4c5f5fa3bf8"},
+ {file = "pendulum-3.0.0-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:04a1094a5aa1daa34a6b57c865b25f691848c61583fb22722a4df5699f6bf74c"},
+ {file = "pendulum-3.0.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5b0ec85b9045bd49dd3a3493a5e7ddfd31c36a2a60da387c419fa04abcaecb23"},
+ {file = "pendulum-3.0.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0a15b90129765b705eb2039062a6daf4d22c4e28d1a54fa260892e8c3ae6e157"},
+ {file = "pendulum-3.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:bb8f6d7acd67a67d6fedd361ad2958ff0539445ef51cbe8cd288db4306503cd0"},
+ {file = "pendulum-3.0.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd69b15374bef7e4b4440612915315cc42e8575fcda2a3d7586a0d88192d0c88"},
+ {file = "pendulum-3.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc00f8110db6898360c53c812872662e077eaf9c75515d53ecc65d886eec209a"},
+ {file = "pendulum-3.0.0-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:83a44e8b40655d0ba565a5c3d1365d27e3e6778ae2a05b69124db9e471255c4a"},
+ {file = "pendulum-3.0.0-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:1a3604e9fbc06b788041b2a8b78f75c243021e0f512447806a6d37ee5214905d"},
+ {file = "pendulum-3.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:92c307ae7accebd06cbae4729f0ba9fa724df5f7d91a0964b1b972a22baa482b"},
+ {file = "pendulum-3.0.0.tar.gz", hash = "sha256:5d034998dea404ec31fae27af6b22cff1708f830a1ed7353be4d1019bb9f584e"},
+]
+
+[package.dependencies]
+python-dateutil = ">=2.6"
+time-machine = {version = ">=2.6.0", optional = true, markers = "implementation_name != \"pypy\" and extra == \"test\""}
+tzdata = ">=2020.1"
+
+[package.extras]
+test = ["time-machine (>=2.6.0)"]
+
+[[package]]
+name = "platformdirs"
+version = "4.3.6"
+description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"},
+ {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"},
+]
+
+[package.extras]
+docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"]
+test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"]
+type = ["mypy (>=1.11.2)"]
+
+[[package]]
+name = "pluggy"
+version = "1.5.0"
+description = "plugin and hook calling mechanisms for python"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"},
+ {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"},
+]
+
+[package.extras]
+dev = ["pre-commit", "tox"]
+testing = ["pytest", "pytest-benchmark"]
+
+[[package]]
+name = "pre-commit"
+version = "3.8.0"
+description = "A framework for managing and maintaining multi-language pre-commit hooks."
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "pre_commit-3.8.0-py2.py3-none-any.whl", hash = "sha256:9a90a53bf82fdd8778d58085faf8d83df56e40dfe18f45b19446e26bf1b3a63f"},
+ {file = "pre_commit-3.8.0.tar.gz", hash = "sha256:8bb6494d4a20423842e198980c9ecf9f96607a07ea29549e180eef9ae80fe7af"},
+]
+
+[package.dependencies]
+cfgv = ">=2.0.0"
+identify = ">=1.0.0"
+nodeenv = ">=0.11.1"
+pyyaml = ">=5.1"
+virtualenv = ">=20.10.0"
+
+[[package]]
+name = "propcache"
+version = "0.2.0"
+description = "Accelerated property cache"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c5869b8fd70b81835a6f187c5fdbe67917a04d7e52b6e7cc4e5fe39d55c39d58"},
+ {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:952e0d9d07609d9c5be361f33b0d6d650cd2bae393aabb11d9b719364521984b"},
+ {file = "propcache-0.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:33ac8f098df0585c0b53009f039dfd913b38c1d2edafed0cedcc0c32a05aa110"},
+ {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97e48e8875e6c13909c800fa344cd54cc4b2b0db1d5f911f840458a500fde2c2"},
+ {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:388f3217649d6d59292b722d940d4d2e1e6a7003259eb835724092a1cca0203a"},
+ {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f571aea50ba5623c308aa146eb650eebf7dbe0fd8c5d946e28343cb3b5aad577"},
+ {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3dfafb44f7bb35c0c06eda6b2ab4bfd58f02729e7c4045e179f9a861b07c9850"},
+ {file = "propcache-0.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3ebe9a75be7ab0b7da2464a77bb27febcb4fab46a34f9288f39d74833db7f61"},
+ {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d2f0d0f976985f85dfb5f3d685697ef769faa6b71993b46b295cdbbd6be8cc37"},
+ {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a3dc1a4b165283bd865e8f8cb5f0c64c05001e0718ed06250d8cac9bec115b48"},
+ {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9e0f07b42d2a50c7dd2d8675d50f7343d998c64008f1da5fef888396b7f84630"},
+ {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e63e3e1e0271f374ed489ff5ee73d4b6e7c60710e1f76af5f0e1a6117cd26394"},
+ {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:56bb5c98f058a41bb58eead194b4db8c05b088c93d94d5161728515bd52b052b"},
+ {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7665f04d0c7f26ff8bb534e1c65068409bf4687aa2534faf7104d7182debb336"},
+ {file = "propcache-0.2.0-cp310-cp310-win32.whl", hash = "sha256:7cf18abf9764746b9c8704774d8b06714bcb0a63641518a3a89c7f85cc02c2ad"},
+ {file = "propcache-0.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:cfac69017ef97db2438efb854edf24f5a29fd09a536ff3a992b75990720cdc99"},
+ {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:63f13bf09cc3336eb04a837490b8f332e0db41da66995c9fd1ba04552e516354"},
+ {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608cce1da6f2672a56b24a015b42db4ac612ee709f3d29f27a00c943d9e851de"},
+ {file = "propcache-0.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:466c219deee4536fbc83c08d09115249db301550625c7fef1c5563a584c9bc87"},
+ {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc2db02409338bf36590aa985a461b2c96fce91f8e7e0f14c50c5fcc4f229016"},
+ {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a6ed8db0a556343d566a5c124ee483ae113acc9a557a807d439bcecc44e7dfbb"},
+ {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:91997d9cb4a325b60d4e3f20967f8eb08dfcb32b22554d5ef78e6fd1dda743a2"},
+ {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c7dde9e533c0a49d802b4f3f218fa9ad0a1ce21f2c2eb80d5216565202acab4"},
+ {file = "propcache-0.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffcad6c564fe6b9b8916c1aefbb37a362deebf9394bd2974e9d84232e3e08504"},
+ {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:97a58a28bcf63284e8b4d7b460cbee1edaab24634e82059c7b8c09e65284f178"},
+ {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:945db8ee295d3af9dbdbb698cce9bbc5c59b5c3fe328bbc4387f59a8a35f998d"},
+ {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:39e104da444a34830751715f45ef9fc537475ba21b7f1f5b0f4d71a3b60d7fe2"},
+ {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c5ecca8f9bab618340c8e848d340baf68bcd8ad90a8ecd7a4524a81c1764b3db"},
+ {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c436130cc779806bdf5d5fae0d848713105472b8566b75ff70048c47d3961c5b"},
+ {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:191db28dc6dcd29d1a3e063c3be0b40688ed76434622c53a284e5427565bbd9b"},
+ {file = "propcache-0.2.0-cp311-cp311-win32.whl", hash = "sha256:5f2564ec89058ee7c7989a7b719115bdfe2a2fb8e7a4543b8d1c0cc4cf6478c1"},
+ {file = "propcache-0.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e2e54267980349b723cff366d1e29b138b9a60fa376664a157a342689553f71"},
+ {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2ee7606193fb267be4b2e3b32714f2d58cad27217638db98a60f9efb5efeccc2"},
+ {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:91ee8fc02ca52e24bcb77b234f22afc03288e1dafbb1f88fe24db308910c4ac7"},
+ {file = "propcache-0.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e900bad2a8456d00a113cad8c13343f3b1f327534e3589acc2219729237a2e8"},
+ {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f52a68c21363c45297aca15561812d542f8fc683c85201df0bebe209e349f793"},
+ {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e41d67757ff4fbc8ef2af99b338bfb955010444b92929e9e55a6d4dcc3c4f09"},
+ {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a64e32f8bd94c105cc27f42d3b658902b5bcc947ece3c8fe7bc1b05982f60e89"},
+ {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55346705687dbd7ef0d77883ab4f6fabc48232f587925bdaf95219bae072491e"},
+ {file = "propcache-0.2.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00181262b17e517df2cd85656fcd6b4e70946fe62cd625b9d74ac9977b64d8d9"},
+ {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6994984550eaf25dd7fc7bd1b700ff45c894149341725bb4edc67f0ffa94efa4"},
+ {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:56295eb1e5f3aecd516d91b00cfd8bf3a13991de5a479df9e27dd569ea23959c"},
+ {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:439e76255daa0f8151d3cb325f6dd4a3e93043e6403e6491813bcaaaa8733887"},
+ {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f6475a1b2ecb310c98c28d271a30df74f9dd436ee46d09236a6b750a7599ce57"},
+ {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3444cdba6628accf384e349014084b1cacd866fbb88433cd9d279d90a54e0b23"},
+ {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4a9d9b4d0a9b38d1c391bb4ad24aa65f306c6f01b512e10a8a34a2dc5675d348"},
+ {file = "propcache-0.2.0-cp312-cp312-win32.whl", hash = "sha256:69d3a98eebae99a420d4b28756c8ce6ea5a29291baf2dc9ff9414b42676f61d5"},
+ {file = "propcache-0.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:ad9c9b99b05f163109466638bd30ada1722abb01bbb85c739c50b6dc11f92dc3"},
+ {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ecddc221a077a8132cf7c747d5352a15ed763b674c0448d811f408bf803d9ad7"},
+ {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0e53cb83fdd61cbd67202735e6a6687a7b491c8742dfc39c9e01e80354956763"},
+ {file = "propcache-0.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92fe151145a990c22cbccf9ae15cae8ae9eddabfc949a219c9f667877e40853d"},
+ {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a21ef516d36909931a2967621eecb256018aeb11fc48656e3257e73e2e247a"},
+ {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f88a4095e913f98988f5b338c1d4d5d07dbb0b6bad19892fd447484e483ba6b"},
+ {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a5b3bb545ead161be780ee85a2b54fdf7092815995661947812dde94a40f6fb"},
+ {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67aeb72e0f482709991aa91345a831d0b707d16b0257e8ef88a2ad246a7280bf"},
+ {file = "propcache-0.2.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c997f8c44ec9b9b0bcbf2d422cc00a1d9b9c681f56efa6ca149a941e5560da2"},
+ {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a66df3d4992bc1d725b9aa803e8c5a66c010c65c741ad901e260ece77f58d2f"},
+ {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:3ebbcf2a07621f29638799828b8d8668c421bfb94c6cb04269130d8de4fb7136"},
+ {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1235c01ddaa80da8235741e80815ce381c5267f96cc49b1477fdcf8c047ef325"},
+ {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3947483a381259c06921612550867b37d22e1df6d6d7e8361264b6d037595f44"},
+ {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d5bed7f9805cc29c780f3aee05de3262ee7ce1f47083cfe9f77471e9d6777e83"},
+ {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4a91d44379f45f5e540971d41e4626dacd7f01004826a18cb048e7da7e96544"},
+ {file = "propcache-0.2.0-cp313-cp313-win32.whl", hash = "sha256:f902804113e032e2cdf8c71015651c97af6418363bea8d78dc0911d56c335032"},
+ {file = "propcache-0.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:8f188cfcc64fb1266f4684206c9de0e80f54622c3f22a910cbd200478aeae61e"},
+ {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:53d1bd3f979ed529f0805dd35ddaca330f80a9a6d90bc0121d2ff398f8ed8861"},
+ {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:83928404adf8fb3d26793665633ea79b7361efa0287dfbd372a7e74311d51ee6"},
+ {file = "propcache-0.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:77a86c261679ea5f3896ec060be9dc8e365788248cc1e049632a1be682442063"},
+ {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:218db2a3c297a3768c11a34812e63b3ac1c3234c3a086def9c0fee50d35add1f"},
+ {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7735e82e3498c27bcb2d17cb65d62c14f1100b71723b68362872bca7d0913d90"},
+ {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:20a617c776f520c3875cf4511e0d1db847a076d720714ae35ffe0df3e440be68"},
+ {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67b69535c870670c9f9b14a75d28baa32221d06f6b6fa6f77a0a13c5a7b0a5b9"},
+ {file = "propcache-0.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4569158070180c3855e9c0791c56be3ceeb192defa2cdf6a3f39e54319e56b89"},
+ {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:db47514ffdbd91ccdc7e6f8407aac4ee94cc871b15b577c1c324236b013ddd04"},
+ {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:2a60ad3e2553a74168d275a0ef35e8c0a965448ffbc3b300ab3a5bb9956c2162"},
+ {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:662dd62358bdeaca0aee5761de8727cfd6861432e3bb828dc2a693aa0471a563"},
+ {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:25a1f88b471b3bc911d18b935ecb7115dff3a192b6fef46f0bfaf71ff4f12418"},
+ {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:f60f0ac7005b9f5a6091009b09a419ace1610e163fa5deaba5ce3484341840e7"},
+ {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:74acd6e291f885678631b7ebc85d2d4aec458dd849b8c841b57ef04047833bed"},
+ {file = "propcache-0.2.0-cp38-cp38-win32.whl", hash = "sha256:d9b6ddac6408194e934002a69bcaadbc88c10b5f38fb9307779d1c629181815d"},
+ {file = "propcache-0.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:676135dcf3262c9c5081cc8f19ad55c8a64e3f7282a21266d05544450bffc3a5"},
+ {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:25c8d773a62ce0451b020c7b29a35cfbc05de8b291163a7a0f3b7904f27253e6"},
+ {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:375a12d7556d462dc64d70475a9ee5982465fbb3d2b364f16b86ba9135793638"},
+ {file = "propcache-0.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1ec43d76b9677637a89d6ab86e1fef70d739217fefa208c65352ecf0282be957"},
+ {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f45eec587dafd4b2d41ac189c2156461ebd0c1082d2fe7013571598abb8505d1"},
+ {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc092ba439d91df90aea38168e11f75c655880c12782facf5cf9c00f3d42b562"},
+ {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa1076244f54bb76e65e22cb6910365779d5c3d71d1f18b275f1dfc7b0d71b4d"},
+ {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:682a7c79a2fbf40f5dbb1eb6bfe2cd865376deeac65acf9beb607505dced9e12"},
+ {file = "propcache-0.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e40876731f99b6f3c897b66b803c9e1c07a989b366c6b5b475fafd1f7ba3fb8"},
+ {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:363ea8cd3c5cb6679f1c2f5f1f9669587361c062e4899fce56758efa928728f8"},
+ {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:140fbf08ab3588b3468932974a9331aff43c0ab8a2ec2c608b6d7d1756dbb6cb"},
+ {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e70fac33e8b4ac63dfc4c956fd7d85a0b1139adcfc0d964ce288b7c527537fea"},
+ {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b33d7a286c0dc1a15f5fc864cc48ae92a846df287ceac2dd499926c3801054a6"},
+ {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:f6d5749fdd33d90e34c2efb174c7e236829147a2713334d708746e94c4bde40d"},
+ {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:22aa8f2272d81d9317ff5756bb108021a056805ce63dd3630e27d042c8092798"},
+ {file = "propcache-0.2.0-cp39-cp39-win32.whl", hash = "sha256:73e4b40ea0eda421b115248d7e79b59214411109a5bc47d0d48e4c73e3b8fcf9"},
+ {file = "propcache-0.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:9517d5e9e0731957468c29dbfd0f976736a0e55afaea843726e887f36fe017df"},
+ {file = "propcache-0.2.0-py3-none-any.whl", hash = "sha256:2ccc28197af5313706511fab3a8b66dcd6da067a1331372c82ea1cb74285e036"},
+ {file = "propcache-0.2.0.tar.gz", hash = "sha256:df81779732feb9d01e5d513fad0122efb3d53bbc75f61b2a4f29a020bc985e70"},
+]
+
+[[package]]
+name = "pycparser"
+version = "2.22"
+description = "C parser in Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"},
+ {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"},
+]
+
+[[package]]
+name = "pydantic"
+version = "2.6.3"
+description = "Data validation using Python type hints"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pydantic-2.6.3-py3-none-any.whl", hash = "sha256:72c6034df47f46ccdf81869fddb81aade68056003900a8724a4f160700016a2a"},
+ {file = "pydantic-2.6.3.tar.gz", hash = "sha256:e07805c4c7f5c6826e33a1d4c9d47950d7eaf34868e2690f8594d2e30241f11f"},
+]
+
+[package.dependencies]
+annotated-types = ">=0.4.0"
+pydantic-core = "2.16.3"
+typing-extensions = ">=4.6.1"
+
+[package.extras]
+email = ["email-validator (>=2.0.0)"]
+
+[[package]]
+name = "pydantic-core"
+version = "2.16.3"
+description = ""
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pydantic_core-2.16.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:75b81e678d1c1ede0785c7f46690621e4c6e63ccd9192af1f0bd9d504bbb6bf4"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9c865a7ee6f93783bd5d781af5a4c43dadc37053a5b42f7d18dc019f8c9d2bd1"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:162e498303d2b1c036b957a1278fa0899d02b2842f1ff901b6395104c5554a45"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f583bd01bbfbff4eaee0868e6fc607efdfcc2b03c1c766b06a707abbc856187"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b926dd38db1519ed3043a4de50214e0d600d404099c3392f098a7f9d75029ff8"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:716b542728d4c742353448765aa7cdaa519a7b82f9564130e2b3f6766018c9ec"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4ad7f7ee1a13d9cb49d8198cd7d7e3aa93e425f371a68235f784e99741561f"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd87f48924f360e5d1c5f770d6155ce0e7d83f7b4e10c2f9ec001c73cf475c99"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0df446663464884297c793874573549229f9eca73b59360878f382a0fc085979"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4df8a199d9f6afc5ae9a65f8f95ee52cae389a8c6b20163762bde0426275b7db"},
+ {file = "pydantic_core-2.16.3-cp310-none-win32.whl", hash = "sha256:456855f57b413f077dff513a5a28ed838dbbb15082ba00f80750377eed23d132"},
+ {file = "pydantic_core-2.16.3-cp310-none-win_amd64.whl", hash = "sha256:732da3243e1b8d3eab8c6ae23ae6a58548849d2e4a4e03a1924c8ddf71a387cb"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:519ae0312616026bf4cedc0fe459e982734f3ca82ee8c7246c19b650b60a5ee4"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b3992a322a5617ded0a9f23fd06dbc1e4bd7cf39bc4ccf344b10f80af58beacd"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d62da299c6ecb04df729e4b5c52dc0d53f4f8430b4492b93aa8de1f541c4aac"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2acca2be4bb2f2147ada8cac612f8a98fc09f41c89f87add7256ad27332c2fda"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b662180108c55dfbf1280d865b2d116633d436cfc0bba82323554873967b340"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e7c6ed0dc9d8e65f24f5824291550139fe6f37fac03788d4580da0d33bc00c97"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1bb0827f56654b4437955555dc3aeeebeddc47c2d7ed575477f082622c49e"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e56f8186d6210ac7ece503193ec84104da7ceb98f68ce18c07282fcc2452e76f"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:936e5db01dd49476fa8f4383c259b8b1303d5dd5fb34c97de194560698cc2c5e"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:33809aebac276089b78db106ee692bdc9044710e26f24a9a2eaa35a0f9fa70ba"},
+ {file = "pydantic_core-2.16.3-cp311-none-win32.whl", hash = "sha256:ded1c35f15c9dea16ead9bffcde9bb5c7c031bff076355dc58dcb1cb436c4721"},
+ {file = "pydantic_core-2.16.3-cp311-none-win_amd64.whl", hash = "sha256:d89ca19cdd0dd5f31606a9329e309d4fcbb3df860960acec32630297d61820df"},
+ {file = "pydantic_core-2.16.3-cp311-none-win_arm64.whl", hash = "sha256:6162f8d2dc27ba21027f261e4fa26f8bcb3cf9784b7f9499466a311ac284b5b9"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0f56ae86b60ea987ae8bcd6654a887238fd53d1384f9b222ac457070b7ac4cff"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9bd22a2a639e26171068f8ebb5400ce2c1bc7d17959f60a3b753ae13c632975"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4204e773b4b408062960e65468d5346bdfe139247ee5f1ca2a378983e11388a2"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f651dd19363c632f4abe3480a7c87a9773be27cfe1341aef06e8759599454120"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aaf09e615a0bf98d406657e0008e4a8701b11481840be7d31755dc9f97c44053"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8e47755d8152c1ab5b55928ab422a76e2e7b22b5ed8e90a7d584268dd49e9c6b"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:500960cb3a0543a724a81ba859da816e8cf01b0e6aaeedf2c3775d12ee49cade"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cf6204fe865da605285c34cf1172879d0314ff267b1c35ff59de7154f35fdc2e"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d33dd21f572545649f90c38c227cc8631268ba25c460b5569abebdd0ec5974ca"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:49d5d58abd4b83fb8ce763be7794d09b2f50f10aa65c0f0c1696c677edeb7cbf"},
+ {file = "pydantic_core-2.16.3-cp312-none-win32.whl", hash = "sha256:f53aace168a2a10582e570b7736cc5bef12cae9cf21775e3eafac597e8551fbe"},
+ {file = "pydantic_core-2.16.3-cp312-none-win_amd64.whl", hash = "sha256:0d32576b1de5a30d9a97f300cc6a3f4694c428d956adbc7e6e2f9cad279e45ed"},
+ {file = "pydantic_core-2.16.3-cp312-none-win_arm64.whl", hash = "sha256:ec08be75bb268473677edb83ba71e7e74b43c008e4a7b1907c6d57e940bf34b6"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b1f6f5938d63c6139860f044e2538baeee6f0b251a1816e7adb6cbce106a1f01"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2a1ef6a36fdbf71538142ed604ad19b82f67b05749512e47f247a6ddd06afdc7"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:704d35ecc7e9c31d48926150afada60401c55efa3b46cd1ded5a01bdffaf1d48"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d937653a696465677ed583124b94a4b2d79f5e30b2c46115a68e482c6a591c8a"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9803edf8e29bd825f43481f19c37f50d2b01899448273b3a7758441b512acf8"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72282ad4892a9fb2da25defeac8c2e84352c108705c972db82ab121d15f14e6d"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f752826b5b8361193df55afcdf8ca6a57d0232653494ba473630a83ba50d8c9"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4384a8f68ddb31a0b0c3deae88765f5868a1b9148939c3f4121233314ad5532c"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a4b2bf78342c40b3dc830880106f54328928ff03e357935ad26c7128bbd66ce8"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:13dcc4802961b5f843a9385fc821a0b0135e8c07fc3d9949fd49627c1a5e6ae5"},
+ {file = "pydantic_core-2.16.3-cp38-none-win32.whl", hash = "sha256:e3e70c94a0c3841e6aa831edab1619ad5c511199be94d0c11ba75fe06efe107a"},
+ {file = "pydantic_core-2.16.3-cp38-none-win_amd64.whl", hash = "sha256:ecdf6bf5f578615f2e985a5e1f6572e23aa632c4bd1dc67f8f406d445ac115ed"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:bda1ee3e08252b8d41fa5537413ffdddd58fa73107171a126d3b9ff001b9b820"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:21b888c973e4f26b7a96491c0965a8a312e13be108022ee510248fe379a5fa23"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be0ec334369316fa73448cc8c982c01e5d2a81c95969d58b8f6e272884df0074"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5b6079cc452a7c53dd378c6f881ac528246b3ac9aae0f8eef98498a75657805"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee8d5f878dccb6d499ba4d30d757111847b6849ae07acdd1205fffa1fc1253c"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7233d65d9d651242a68801159763d09e9ec96e8a158dbf118dc090cd77a104c9"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6119dc90483a5cb50a1306adb8d52c66e447da88ea44f323e0ae1a5fcb14256"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:578114bc803a4c1ff9946d977c221e4376620a46cf78da267d946397dc9514a8"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d8f99b147ff3fcf6b3cc60cb0c39ea443884d5559a30b1481e92495f2310ff2b"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4ac6b4ce1e7283d715c4b729d8f9dab9627586dafce81d9eaa009dd7f25dd972"},
+ {file = "pydantic_core-2.16.3-cp39-none-win32.whl", hash = "sha256:e7774b570e61cb998490c5235740d475413a1f6de823169b4cf94e2fe9e9f6b2"},
+ {file = "pydantic_core-2.16.3-cp39-none-win_amd64.whl", hash = "sha256:9091632a25b8b87b9a605ec0e61f241c456e9248bfdcf7abdf344fdb169c81cf"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:36fa178aacbc277bc6b62a2c3da95226520da4f4e9e206fdf076484363895d2c"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:dcca5d2bf65c6fb591fff92da03f94cd4f315972f97c21975398bd4bd046854a"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a72fb9963cba4cd5793854fd12f4cfee731e86df140f59ff52a49b3552db241"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b60cc1a081f80a2105a59385b92d82278b15d80ebb3adb200542ae165cd7d183"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cbcc558401de90a746d02ef330c528f2e668c83350f045833543cd57ecead1ad"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:fee427241c2d9fb7192b658190f9f5fd6dfe41e02f3c1489d2ec1e6a5ab1e04a"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f4cb85f693044e0f71f394ff76c98ddc1bc0953e48c061725e540396d5c8a2e1"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b29eeb887aa931c2fcef5aa515d9d176d25006794610c264ddc114c053bf96fe"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a425479ee40ff021f8216c9d07a6a3b54b31c8267c6e17aa88b70d7ebd0e5e5b"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5c5cbc703168d1b7a838668998308018a2718c2130595e8e190220238addc96f"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99b6add4c0b39a513d323d3b93bc173dac663c27b99860dd5bf491b240d26137"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f76ee558751746d6a38f89d60b6228fa174e5172d143886af0f85aa306fd89"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:00ee1c97b5364b84cb0bd82e9bbf645d5e2871fb8c58059d158412fee2d33d8a"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:287073c66748f624be4cef893ef9174e3eb88fe0b8a78dc22e88eca4bc357ca6"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ed25e1835c00a332cb10c683cd39da96a719ab1dfc08427d476bce41b92531fc"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:86b3d0033580bd6bbe07590152007275bd7af95f98eaa5bd36f3da219dcd93da"},
+ {file = "pydantic_core-2.16.3.tar.gz", hash = "sha256:1cac689f80a3abab2d3c0048b29eea5751114054f032a941a32de4c852c59cad"},
+]
+
+[package.dependencies]
+typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
+
+[[package]]
+name = "pygments"
+version = "2.18.0"
+description = "Pygments is a syntax highlighting package written in Python."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"},
+ {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"},
+]
+
+[package.extras]
+windows-terminal = ["colorama (>=0.4.6)"]
+
+[[package]]
+name = "pyisemail"
+version = "2.0.1"
+description = "Simple, robust email validation"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pyisemail-2.0.1-py3-none-any.whl", hash = "sha256:3d2bebd159f436673219d024a3f02bed1b468c793df9a5fa08d72b7d4b4f6cb4"},
+ {file = "pyisemail-2.0.1.tar.gz", hash = "sha256:daf4b3fb2150a38f406b0aaba729e19fcd638a6d1c0549c25ff54c7b804618f8"},
+]
+
+[package.dependencies]
+dnspython = ">=2.0.0"
+
+[[package]]
+name = "pyjwt"
+version = "2.10.0"
+description = "JSON Web Token implementation in Python"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "PyJWT-2.10.0-py3-none-any.whl", hash = "sha256:543b77207db656de204372350926bed5a86201c4cbff159f623f79c7bb487a15"},
+ {file = "pyjwt-2.10.0.tar.gz", hash = "sha256:7628a7eb7938959ac1b26e819a1df0fd3259505627b575e4bad6d08f76db695c"},
+]
+
+[package.extras]
+crypto = ["cryptography (>=3.4.0)"]
+dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx", "sphinx-rtd-theme", "zope.interface"]
+docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"]
+tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"]
+
+[[package]]
+name = "pymdown-extensions"
+version = "10.12"
+description = "Extension pack for Python Markdown."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pymdown_extensions-10.12-py3-none-any.whl", hash = "sha256:49f81412242d3527b8b4967b990df395c89563043bc51a3d2d7d500e52123b77"},
+ {file = "pymdown_extensions-10.12.tar.gz", hash = "sha256:b0ee1e0b2bef1071a47891ab17003bfe5bf824a398e13f49f8ed653b699369a7"},
+]
+
+[package.dependencies]
+markdown = ">=3.6"
+pyyaml = "*"
+
+[package.extras]
+extra = ["pygments (>=2.12)"]
+
+[[package]]
+name = "pytest"
+version = "8.3.3"
+description = "pytest: simple powerful testing with Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"},
+ {file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+iniconfig = "*"
+packaging = "*"
+pluggy = ">=1.5,<2"
+
+[package.extras]
+dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
+
+[[package]]
+name = "pytest-asyncio"
+version = "0.21.2"
+description = "Pytest support for asyncio"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pytest_asyncio-0.21.2-py3-none-any.whl", hash = "sha256:ab664c88bb7998f711d8039cacd4884da6430886ae8bbd4eded552ed2004f16b"},
+ {file = "pytest_asyncio-0.21.2.tar.gz", hash = "sha256:d67738fc232b94b326b9d060750beb16e0074210b98dd8b58a5239fa2a154f45"},
+]
+
+[package.dependencies]
+pytest = ">=7.0.0"
+
+[package.extras]
+docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"]
+testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"]
+
+[[package]]
+name = "pytest-cov"
+version = "5.0.0"
+description = "Pytest plugin for measuring coverage."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pytest-cov-5.0.0.tar.gz", hash = "sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857"},
+ {file = "pytest_cov-5.0.0-py3-none-any.whl", hash = "sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652"},
+]
+
+[package.dependencies]
+coverage = {version = ">=5.2.1", extras = ["toml"]}
+pytest = ">=4.6"
+
+[package.extras]
+testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"]
+
+[[package]]
+name = "pytest-sugar"
+version = "1.0.0"
+description = "pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly)."
+optional = false
+python-versions = "*"
+files = [
+ {file = "pytest-sugar-1.0.0.tar.gz", hash = "sha256:6422e83258f5b0c04ce7c632176c7732cab5fdb909cb39cca5c9139f81276c0a"},
+ {file = "pytest_sugar-1.0.0-py3-none-any.whl", hash = "sha256:70ebcd8fc5795dc457ff8b69d266a4e2e8a74ae0c3edc749381c64b5246c8dfd"},
+]
+
+[package.dependencies]
+packaging = ">=21.3"
+pytest = ">=6.2.0"
+termcolor = ">=2.1.0"
+
+[package.extras]
+dev = ["black", "flake8", "pre-commit"]
+
+[[package]]
+name = "python-dateutil"
+version = "2.9.0.post0"
+description = "Extensions to the standard Python datetime module"
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
+files = [
+ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"},
+ {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"},
+]
+
+[package.dependencies]
+six = ">=1.5"
+
+[[package]]
+name = "python-dotenv"
+version = "1.0.1"
+description = "Read key-value pairs from a .env file and set them as environment variables"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"},
+ {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"},
+]
+
+[package.extras]
+cli = ["click (>=5.0)"]
+
+[[package]]
+name = "python-multipart"
+version = "0.0.9"
+description = "A streaming multipart parser for Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "python_multipart-0.0.9-py3-none-any.whl", hash = "sha256:97ca7b8ea7b05f977dc3849c3ba99d51689822fab725c3703af7c866a0c2b215"},
+ {file = "python_multipart-0.0.9.tar.gz", hash = "sha256:03f54688c663f1b7977105f021043b0793151e4cb1c1a9d4a11fc13d622c4026"},
+]
+
+[package.extras]
+dev = ["atomicwrites (==1.4.1)", "attrs (==23.2.0)", "coverage (==7.4.1)", "hatch", "invoke (==2.2.0)", "more-itertools (==10.2.0)", "pbr (==6.0.0)", "pluggy (==1.4.0)", "py (==1.11.0)", "pytest (==8.0.0)", "pytest-cov (==4.1.0)", "pytest-timeout (==2.2.0)", "pyyaml (==6.0.1)", "ruff (==0.2.1)"]
+
+[[package]]
+name = "python-slugify"
+version = "8.0.4"
+description = "A Python slugify application that also handles Unicode"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "python-slugify-8.0.4.tar.gz", hash = "sha256:59202371d1d05b54a9e7720c5e038f928f45daaffe41dd10822f3907b937c856"},
+ {file = "python_slugify-8.0.4-py2.py3-none-any.whl", hash = "sha256:276540b79961052b66b7d116620b36518847f52d5fd9e3a70164fc8c50faa6b8"},
+]
+
+[package.dependencies]
+text-unidecode = ">=1.3"
+
+[package.extras]
+unidecode = ["Unidecode (>=1.1.1)"]
+
+[[package]]
+name = "pyyaml"
+version = "6.0.2"
+description = "YAML parser and emitter for Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"},
+ {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"},
+ {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"},
+ {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"},
+ {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"},
+ {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"},
+ {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"},
+ {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"},
+ {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"},
+ {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"},
+ {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"},
+ {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"},
+ {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"},
+ {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"},
+ {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"},
+ {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"},
+ {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"},
+ {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"},
+ {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"},
+ {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"},
+ {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"},
+ {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"},
+ {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"},
+ {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"},
+ {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"},
+ {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"},
+ {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"},
+ {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"},
+ {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"},
+ {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"},
+ {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"},
+ {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"},
+ {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"},
+ {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"},
+ {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"},
+ {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"},
+ {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"},
+ {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"},
+ {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"},
+ {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"},
+ {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"},
+ {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"},
+ {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"},
+ {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"},
+ {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"},
+ {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"},
+ {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"},
+ {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"},
+ {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"},
+ {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"},
+ {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"},
+ {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"},
+ {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"},
+]
+
+[[package]]
+name = "pyyaml-env-tag"
+version = "0.1"
+description = "A custom YAML tag for referencing environment variables in YAML files. "
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"},
+ {file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"},
+]
+
+[package.dependencies]
+pyyaml = "*"
+
+[[package]]
+name = "redis"
+version = "5.2.0"
+description = "Python client for Redis database and key-value store"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "redis-5.2.0-py3-none-any.whl", hash = "sha256:ae174f2bb3b1bf2b09d54bf3e51fbc1469cf6c10aa03e21141f51969801a7897"},
+ {file = "redis-5.2.0.tar.gz", hash = "sha256:0b1087665a771b1ff2e003aa5bdd354f15a70c9e25d5a7dbf9c722c16528a7b0"},
+]
+
+[package.extras]
+hiredis = ["hiredis (>=3.0.0)"]
+ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==23.2.1)", "requests (>=2.31.0)"]
+
+[[package]]
+name = "regex"
+version = "2024.11.6"
+description = "Alternative regular expression module, to replace re."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff590880083d60acc0433f9c3f713c51f7ac6ebb9adf889c79a261ecf541aa91"},
+ {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:658f90550f38270639e83ce492f27d2c8d2cd63805c65a13a14d36ca126753f0"},
+ {file = "regex-2024.11.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:164d8b7b3b4bcb2068b97428060b2a53be050085ef94eca7f240e7947f1b080e"},
+ {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3660c82f209655a06b587d55e723f0b813d3a7db2e32e5e7dc64ac2a9e86fde"},
+ {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d22326fcdef5e08c154280b71163ced384b428343ae16a5ab2b3354aed12436e"},
+ {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1ac758ef6aebfc8943560194e9fd0fa18bcb34d89fd8bd2af18183afd8da3a2"},
+ {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:997d6a487ff00807ba810e0f8332c18b4eb8d29463cfb7c820dc4b6e7562d0cf"},
+ {file = "regex-2024.11.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:02a02d2bb04fec86ad61f3ea7f49c015a0681bf76abb9857f945d26159d2968c"},
+ {file = "regex-2024.11.6-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f02f93b92358ee3f78660e43b4b0091229260c5d5c408d17d60bf26b6c900e86"},
+ {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:06eb1be98df10e81ebaded73fcd51989dcf534e3c753466e4b60c4697a003b67"},
+ {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:040df6fe1a5504eb0f04f048e6d09cd7c7110fef851d7c567a6b6e09942feb7d"},
+ {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabbfc59f2c6edba2a6622c647b716e34e8e3867e0ab975412c5c2f79b82da2"},
+ {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8447d2d39b5abe381419319f942de20b7ecd60ce86f16a23b0698f22e1b70008"},
+ {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:da8f5fc57d1933de22a9e23eec290a0d8a5927a5370d24bda9a6abe50683fe62"},
+ {file = "regex-2024.11.6-cp310-cp310-win32.whl", hash = "sha256:b489578720afb782f6ccf2840920f3a32e31ba28a4b162e13900c3e6bd3f930e"},
+ {file = "regex-2024.11.6-cp310-cp310-win_amd64.whl", hash = "sha256:5071b2093e793357c9d8b2929dfc13ac5f0a6c650559503bb81189d0a3814519"},
+ {file = "regex-2024.11.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5478c6962ad548b54a591778e93cd7c456a7a29f8eca9c49e4f9a806dcc5d638"},
+ {file = "regex-2024.11.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c89a8cc122b25ce6945f0423dc1352cb9593c68abd19223eebbd4e56612c5b7"},
+ {file = "regex-2024.11.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:94d87b689cdd831934fa3ce16cc15cd65748e6d689f5d2b8f4f4df2065c9fa20"},
+ {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1062b39a0a2b75a9c694f7a08e7183a80c63c0d62b301418ffd9c35f55aaa114"},
+ {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:167ed4852351d8a750da48712c3930b031f6efdaa0f22fa1933716bfcd6bf4a3"},
+ {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d548dafee61f06ebdb584080621f3e0c23fff312f0de1afc776e2a2ba99a74f"},
+ {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2a19f302cd1ce5dd01a9099aaa19cae6173306d1302a43b627f62e21cf18ac0"},
+ {file = "regex-2024.11.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bec9931dfb61ddd8ef2ebc05646293812cb6b16b60cf7c9511a832b6f1854b55"},
+ {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9714398225f299aa85267fd222f7142fcb5c769e73d7733344efc46f2ef5cf89"},
+ {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:202eb32e89f60fc147a41e55cb086db2a3f8cb82f9a9a88440dcfc5d37faae8d"},
+ {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:4181b814e56078e9b00427ca358ec44333765f5ca1b45597ec7446d3a1ef6e34"},
+ {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:068376da5a7e4da51968ce4c122a7cd31afaaec4fccc7856c92f63876e57b51d"},
+ {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ac10f2c4184420d881a3475fb2c6f4d95d53a8d50209a2500723d831036f7c45"},
+ {file = "regex-2024.11.6-cp311-cp311-win32.whl", hash = "sha256:c36f9b6f5f8649bb251a5f3f66564438977b7ef8386a52460ae77e6070d309d9"},
+ {file = "regex-2024.11.6-cp311-cp311-win_amd64.whl", hash = "sha256:02e28184be537f0e75c1f9b2f8847dc51e08e6e171c6bde130b2687e0c33cf60"},
+ {file = "regex-2024.11.6-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:52fb28f528778f184f870b7cf8f225f5eef0a8f6e3778529bdd40c7b3920796a"},
+ {file = "regex-2024.11.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdd6028445d2460f33136c55eeb1f601ab06d74cb3347132e1c24250187500d9"},
+ {file = "regex-2024.11.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:805e6b60c54bf766b251e94526ebad60b7de0c70f70a4e6210ee2891acb70bf2"},
+ {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b85c2530be953a890eaffde05485238f07029600e8f098cdf1848d414a8b45e4"},
+ {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb26437975da7dc36b7efad18aa9dd4ea569d2357ae6b783bf1118dabd9ea577"},
+ {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:abfa5080c374a76a251ba60683242bc17eeb2c9818d0d30117b4486be10c59d3"},
+ {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b7fa6606c2881c1db9479b0eaa11ed5dfa11c8d60a474ff0e095099f39d98e"},
+ {file = "regex-2024.11.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c32f75920cf99fe6b6c539c399a4a128452eaf1af27f39bce8909c9a3fd8cbe"},
+ {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:982e6d21414e78e1f51cf595d7f321dcd14de1f2881c5dc6a6e23bbbbd68435e"},
+ {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a7c2155f790e2fb448faed6dd241386719802296ec588a8b9051c1f5c481bc29"},
+ {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:149f5008d286636e48cd0b1dd65018548944e495b0265b45e1bffecce1ef7f39"},
+ {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e5364a4502efca094731680e80009632ad6624084aff9a23ce8c8c6820de3e51"},
+ {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0a86e7eeca091c09e021db8eb72d54751e527fa47b8d5787caf96d9831bd02ad"},
+ {file = "regex-2024.11.6-cp312-cp312-win32.whl", hash = "sha256:32f9a4c643baad4efa81d549c2aadefaeba12249b2adc5af541759237eee1c54"},
+ {file = "regex-2024.11.6-cp312-cp312-win_amd64.whl", hash = "sha256:a93c194e2df18f7d264092dc8539b8ffb86b45b899ab976aa15d48214138e81b"},
+ {file = "regex-2024.11.6-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a6ba92c0bcdf96cbf43a12c717eae4bc98325ca3730f6b130ffa2e3c3c723d84"},
+ {file = "regex-2024.11.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:525eab0b789891ac3be914d36893bdf972d483fe66551f79d3e27146191a37d4"},
+ {file = "regex-2024.11.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0"},
+ {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bde01f35767c4a7899b7eb6e823b125a64de314a8ee9791367c9a34d56af18d0"},
+ {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b583904576650166b3d920d2bcce13971f6f9e9a396c673187f49811b2769dc7"},
+ {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c4de13f06a0d54fa0d5ab1b7138bfa0d883220965a29616e3ea61b35d5f5fc7"},
+ {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c"},
+ {file = "regex-2024.11.6-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d7f453dca13f40a02b79636a339c5b62b670141e63efd511d3f8f73fba162b3"},
+ {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:59dfe1ed21aea057a65c6b586afd2a945de04fc7db3de0a6e3ed5397ad491b07"},
+ {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b97c1e0bd37c5cd7902e65f410779d39eeda155800b65fc4d04cc432efa9bc6e"},
+ {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f9d1e379028e0fc2ae3654bac3cbbef81bf3fd571272a42d56c24007979bafb6"},
+ {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:13291b39131e2d002a7940fb176e120bec5145f3aeb7621be6534e46251912c4"},
+ {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f51f88c126370dcec4908576c5a627220da6c09d0bff31cfa89f2523843316d"},
+ {file = "regex-2024.11.6-cp313-cp313-win32.whl", hash = "sha256:63b13cfd72e9601125027202cad74995ab26921d8cd935c25f09c630436348ff"},
+ {file = "regex-2024.11.6-cp313-cp313-win_amd64.whl", hash = "sha256:2b3361af3198667e99927da8b84c1b010752fa4b1115ee30beaa332cabc3ef1a"},
+ {file = "regex-2024.11.6-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3a51ccc315653ba012774efca4f23d1d2a8a8f278a6072e29c7147eee7da446b"},
+ {file = "regex-2024.11.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ad182d02e40de7459b73155deb8996bbd8e96852267879396fb274e8700190e3"},
+ {file = "regex-2024.11.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ba9b72e5643641b7d41fa1f6d5abda2c9a263ae835b917348fc3c928182ad467"},
+ {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40291b1b89ca6ad8d3f2b82782cc33807f1406cf68c8d440861da6304d8ffbbd"},
+ {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cdf58d0e516ee426a48f7b2c03a332a4114420716d55769ff7108c37a09951bf"},
+ {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a36fdf2af13c2b14738f6e973aba563623cb77d753bbbd8d414d18bfaa3105dd"},
+ {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1cee317bfc014c2419a76bcc87f071405e3966da434e03e13beb45f8aced1a6"},
+ {file = "regex-2024.11.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50153825ee016b91549962f970d6a4442fa106832e14c918acd1c8e479916c4f"},
+ {file = "regex-2024.11.6-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea1bfda2f7162605f6e8178223576856b3d791109f15ea99a9f95c16a7636fb5"},
+ {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:df951c5f4a1b1910f1a99ff42c473ff60f8225baa1cdd3539fe2819d9543e9df"},
+ {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:072623554418a9911446278f16ecb398fb3b540147a7828c06e2011fa531e773"},
+ {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:f654882311409afb1d780b940234208a252322c24a93b442ca714d119e68086c"},
+ {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:89d75e7293d2b3e674db7d4d9b1bee7f8f3d1609428e293771d1a962617150cc"},
+ {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:f65557897fc977a44ab205ea871b690adaef6b9da6afda4790a2484b04293a5f"},
+ {file = "regex-2024.11.6-cp38-cp38-win32.whl", hash = "sha256:6f44ec28b1f858c98d3036ad5d7d0bfc568bdd7a74f9c24e25f41ef1ebfd81a4"},
+ {file = "regex-2024.11.6-cp38-cp38-win_amd64.whl", hash = "sha256:bb8f74f2f10dbf13a0be8de623ba4f9491faf58c24064f32b65679b021ed0001"},
+ {file = "regex-2024.11.6-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5704e174f8ccab2026bd2f1ab6c510345ae8eac818b613d7d73e785f1310f839"},
+ {file = "regex-2024.11.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:220902c3c5cc6af55d4fe19ead504de80eb91f786dc102fbd74894b1551f095e"},
+ {file = "regex-2024.11.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e7e351589da0850c125f1600a4c4ba3c722efefe16b297de54300f08d734fbf"},
+ {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5056b185ca113c88e18223183aa1a50e66507769c9640a6ff75859619d73957b"},
+ {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e34b51b650b23ed3354b5a07aab37034d9f923db2a40519139af34f485f77d0"},
+ {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5670bce7b200273eee1840ef307bfa07cda90b38ae56e9a6ebcc9f50da9c469b"},
+ {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08986dce1339bc932923e7d1232ce9881499a0e02925f7402fb7c982515419ef"},
+ {file = "regex-2024.11.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93c0b12d3d3bc25af4ebbf38f9ee780a487e8bf6954c115b9f015822d3bb8e48"},
+ {file = "regex-2024.11.6-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:764e71f22ab3b305e7f4c21f1a97e1526a25ebdd22513e251cf376760213da13"},
+ {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f056bf21105c2515c32372bbc057f43eb02aae2fda61052e2f7622c801f0b4e2"},
+ {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:69ab78f848845569401469da20df3e081e6b5a11cb086de3eed1d48f5ed57c95"},
+ {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:86fddba590aad9208e2fa8b43b4c098bb0ec74f15718bb6a704e3c63e2cef3e9"},
+ {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:684d7a212682996d21ca12ef3c17353c021fe9de6049e19ac8481ec35574a70f"},
+ {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a03e02f48cd1abbd9f3b7e3586d97c8f7a9721c436f51a5245b3b9483044480b"},
+ {file = "regex-2024.11.6-cp39-cp39-win32.whl", hash = "sha256:41758407fc32d5c3c5de163888068cfee69cb4c2be844e7ac517a52770f9af57"},
+ {file = "regex-2024.11.6-cp39-cp39-win_amd64.whl", hash = "sha256:b2837718570f95dd41675328e111345f9b7095d821bac435aac173ac80b19983"},
+ {file = "regex-2024.11.6.tar.gz", hash = "sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519"},
+]
+
+[[package]]
+name = "requests"
+version = "2.32.3"
+description = "Python HTTP for Humans."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"},
+ {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"},
+]
+
+[package.dependencies]
+certifi = ">=2017.4.17"
+charset-normalizer = ">=2,<4"
+idna = ">=2.5,<4"
+urllib3 = ">=1.21.1,<3"
+
+[package.extras]
+socks = ["PySocks (>=1.5.6,!=1.5.7)"]
+use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
+
+[[package]]
+name = "rich"
+version = "13.9.4"
+description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
+optional = false
+python-versions = ">=3.8.0"
+files = [
+ {file = "rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90"},
+ {file = "rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098"},
+]
+
+[package.dependencies]
+markdown-it-py = ">=2.2.0"
+pygments = ">=2.13.0,<3.0.0"
+
+[package.extras]
+jupyter = ["ipywidgets (>=7.5.1,<9)"]
+
+[[package]]
+name = "ruff"
+version = "0.7.4"
+description = "An extremely fast Python linter and code formatter, written in Rust."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "ruff-0.7.4-py3-none-linux_armv6l.whl", hash = "sha256:a4919925e7684a3f18e18243cd6bea7cfb8e968a6eaa8437971f681b7ec51478"},
+ {file = "ruff-0.7.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:cfb365c135b830778dda8c04fb7d4280ed0b984e1aec27f574445231e20d6c63"},
+ {file = "ruff-0.7.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:63a569b36bc66fbadec5beaa539dd81e0527cb258b94e29e0531ce41bacc1f20"},
+ {file = "ruff-0.7.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d06218747d361d06fd2fdac734e7fa92df36df93035db3dc2ad7aa9852cb109"},
+ {file = "ruff-0.7.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e0cea28d0944f74ebc33e9f934238f15c758841f9f5edd180b5315c203293452"},
+ {file = "ruff-0.7.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:80094ecd4793c68b2571b128f91754d60f692d64bc0d7272ec9197fdd09bf9ea"},
+ {file = "ruff-0.7.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:997512325c6620d1c4c2b15db49ef59543ef9cd0f4aa8065ec2ae5103cedc7e7"},
+ {file = "ruff-0.7.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:00b4cf3a6b5fad6d1a66e7574d78956bbd09abfd6c8a997798f01f5da3d46a05"},
+ {file = "ruff-0.7.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7dbdc7d8274e1422722933d1edddfdc65b4336abf0b16dfcb9dedd6e6a517d06"},
+ {file = "ruff-0.7.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e92dfb5f00eaedb1501b2f906ccabfd67b2355bdf117fea9719fc99ac2145bc"},
+ {file = "ruff-0.7.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:3bd726099f277d735dc38900b6a8d6cf070f80828877941983a57bca1cd92172"},
+ {file = "ruff-0.7.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:2e32829c429dd081ee5ba39aef436603e5b22335c3d3fff013cd585806a6486a"},
+ {file = "ruff-0.7.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:662a63b4971807623f6f90c1fb664613f67cc182dc4d991471c23c541fee62dd"},
+ {file = "ruff-0.7.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:876f5e09eaae3eb76814c1d3b68879891d6fde4824c015d48e7a7da4cf066a3a"},
+ {file = "ruff-0.7.4-py3-none-win32.whl", hash = "sha256:75c53f54904be42dd52a548728a5b572344b50d9b2873d13a3f8c5e3b91f5cac"},
+ {file = "ruff-0.7.4-py3-none-win_amd64.whl", hash = "sha256:745775c7b39f914238ed1f1b0bebed0b9155a17cd8bc0b08d3c87e4703b990d6"},
+ {file = "ruff-0.7.4-py3-none-win_arm64.whl", hash = "sha256:11bff065102c3ae9d3ea4dc9ecdfe5a5171349cdd0787c1fc64761212fc9cf1f"},
+ {file = "ruff-0.7.4.tar.gz", hash = "sha256:cd12e35031f5af6b9b93715d8c4f40360070b2041f81273d0527683d5708fce2"},
+]
+
+[[package]]
+name = "setuptools"
+version = "75.6.0"
+description = "Easily download, build, install, upgrade, and uninstall Python packages"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "setuptools-75.6.0-py3-none-any.whl", hash = "sha256:ce74b49e8f7110f9bf04883b730f4765b774ef3ef28f722cce7c273d253aaf7d"},
+ {file = "setuptools-75.6.0.tar.gz", hash = "sha256:8199222558df7c86216af4f84c30e9b34a61d8ba19366cc914424cdbd28252f6"},
+]
+
+[package.extras]
+check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.7.0)"]
+core = ["importlib_metadata (>=6)", "jaraco.collections", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"]
+cover = ["pytest-cov"]
+doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"]
+enabler = ["pytest-enabler (>=2.2)"]
+test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"]
+type = ["importlib_metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (>=1.12,<1.14)", "pytest-mypy"]
+
+[[package]]
+name = "shellingham"
+version = "1.5.4"
+description = "Tool to Detect Surrounding Shell"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"},
+ {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"},
+]
+
+[[package]]
+name = "six"
+version = "1.16.0"
+description = "Python 2 and 3 compatibility utilities"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
+files = [
+ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
+ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
+]
+
+[[package]]
+name = "sniffio"
+version = "1.3.1"
+description = "Sniff out which async library your code is running under"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"},
+ {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
+]
+
+[[package]]
+name = "sql-smith"
+version = "1.1.1"
+description = "sql-smith is an SQL query builder with zero dependencies and a fluent interface."
+optional = false
+python-versions = ">=3.10,<4.0"
+files = [
+ {file = "sql_smith-1.1.1-py3-none-any.whl", hash = "sha256:f092a1816ee7bfd740cd381a38c2d4524e101f580eec0cb8ec6882ee8f90bbed"},
+ {file = "sql_smith-1.1.1.tar.gz", hash = "sha256:5622205e4f8f1815ddb0bd347a0bc6bece507d2fccaa948f867f407dd6cf9c3d"},
+]
+
+[[package]]
+name = "starlette"
+version = "0.37.2"
+description = "The little ASGI library that shines."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "starlette-0.37.2-py3-none-any.whl", hash = "sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee"},
+ {file = "starlette-0.37.2.tar.gz", hash = "sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823"},
+]
+
+[package.dependencies]
+anyio = ">=3.4.0,<5"
+
+[package.extras]
+full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7)", "pyyaml"]
+
+[[package]]
+name = "termcolor"
+version = "2.5.0"
+description = "ANSI color formatting for output in terminal"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "termcolor-2.5.0-py3-none-any.whl", hash = "sha256:37b17b5fc1e604945c2642c872a3764b5d547a48009871aea3edd3afa180afb8"},
+ {file = "termcolor-2.5.0.tar.gz", hash = "sha256:998d8d27da6d48442e8e1f016119076b690d962507531df4890fcd2db2ef8a6f"},
+]
+
+[package.extras]
+tests = ["pytest", "pytest-cov"]
+
+[[package]]
+name = "text-unidecode"
+version = "1.3"
+description = "The most basic Text::Unidecode port"
+optional = false
+python-versions = "*"
+files = [
+ {file = "text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"},
+ {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"},
+]
+
+[[package]]
+name = "time-machine"
+version = "2.16.0"
+description = "Travel through time in your tests."
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "time_machine-2.16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:09531af59fdfb39bfd24d28bd1e837eff5a5d98318509a31b6cfd57d27801e52"},
+ {file = "time_machine-2.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:92d0b0f3c49f34dd76eb462f0afdc61ed1cb318c06c46d03e99b44ebb489bdad"},
+ {file = "time_machine-2.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c29616e18e2349a8766d5b6817920fc74e39c00fa375d202231e9d525a1b882"},
+ {file = "time_machine-2.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c1ceb6035a64cb00650e3ab203cf3faffac18576a3f3125c24df468b784077c7"},
+ {file = "time_machine-2.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64c205ea37b8c4ba232645335fc3b75bc2d03ce30f0a34649e36cae85652ee96"},
+ {file = "time_machine-2.16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dfe92412bd11104c4f0fb2da68653e6c45b41f7217319a83a8b66ed4f20148b3"},
+ {file = "time_machine-2.16.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:d5fe7a6284e3dce87ae13a25029c53542dd27a28d151f3ef362ec4dd9c3e45fd"},
+ {file = "time_machine-2.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c0fca3025266d88d1b48be162a43b7c2d91c81cc5b3bee9f01194678ffb9969a"},
+ {file = "time_machine-2.16.0-cp310-cp310-win32.whl", hash = "sha256:4149e17018af07a5756a1df84aea71e6e178598c358c860c6bfec42170fa7970"},
+ {file = "time_machine-2.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:01bc257e9418980a4922de94775be42a966e1a082fb01a1635917f9afc7b84ca"},
+ {file = "time_machine-2.16.0-cp310-cp310-win_arm64.whl", hash = "sha256:6895e3e84119594ab12847c928f619d40ae9cedd0755515dc154a5b5dc6edd9f"},
+ {file = "time_machine-2.16.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8f936566ef9f09136a3d5db305961ef6d897b76b240c9ff4199144aed6dd4fe5"},
+ {file = "time_machine-2.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5886e23ede3478ca2a3e0a641f5d09dd784dfa9e48c96e8e5e31fc4fe77b6dc0"},
+ {file = "time_machine-2.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c76caf539fa4941e1817b7c482c87c65c52a1903fea761e84525955c6106fafb"},
+ {file = "time_machine-2.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:298aa423e07c8b21b991782f01d7749c871c792319c2af3e9755f9ab49033212"},
+ {file = "time_machine-2.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3391ae9c484736850bb44ef125cbad52fe2d1b69e42c95dc88c43af8ead2cc7"},
+ {file = "time_machine-2.16.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:503e7ff507c2089699d91885fc5b9c8ff16774a7b6aff48b4dcee0c0a0685b61"},
+ {file = "time_machine-2.16.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:eee7b0fc4fbab2c6585ea17606c6548be83919c70deea0865409fe9fc2d8cdce"},
+ {file = "time_machine-2.16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9db5e5b3ccdadaafa5730c2f9db44c38b013234c9ad01f87738907e19bdba268"},
+ {file = "time_machine-2.16.0-cp311-cp311-win32.whl", hash = "sha256:2552f0767bc10c9d668f108fef9b487809cdeb772439ce932e74136365c69baf"},
+ {file = "time_machine-2.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:12474fcdbc475aa6fe5275fe7224e685c5b9777f5939647f35980e9614ae7558"},
+ {file = "time_machine-2.16.0-cp311-cp311-win_arm64.whl", hash = "sha256:ac2df0fa564356384515ed62cb6679f33f1f529435b16b0ec0f88414635dbe39"},
+ {file = "time_machine-2.16.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:84788f4d62a8b1bf5e499bb9b0e23ceceea21c415ad6030be6267ce3d639842f"},
+ {file = "time_machine-2.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:15ec236b6571730236a193d9d6c11d472432fc6ab54e85eac1c16d98ddcd71bf"},
+ {file = "time_machine-2.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cedc989717c8b44a3881ac3d68ab5a95820448796c550de6a2149ed1525157f0"},
+ {file = "time_machine-2.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9d26d79de1c63a8c6586c75967e09b0ff306aa7e944a1eaddb74595c9b1839ca"},
+ {file = "time_machine-2.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:317b68b56a9c3731e0cf8886e0f94230727159e375988b36c60edce0ddbcb44a"},
+ {file = "time_machine-2.16.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:43e1e18279759897be3293a255d53e6b1cb0364b69d9591d0b80c51e461c94b0"},
+ {file = "time_machine-2.16.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e43adb22def972a29d2b147999b56897116085777a0fea182fd93ee45730611e"},
+ {file = "time_machine-2.16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0c766bea27a0600e36806d628ebc4b47178b12fcdfb6c24dc0a566a9c06bfe7f"},
+ {file = "time_machine-2.16.0-cp312-cp312-win32.whl", hash = "sha256:6dae82ab647d107817e013db82223e20a9853fa88543fec853ae326382d03c2e"},
+ {file = "time_machine-2.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:265462c77dc9576267c3c7f20707780a171a9fdbac93ac22e608c309efd68c33"},
+ {file = "time_machine-2.16.0-cp312-cp312-win_arm64.whl", hash = "sha256:ef768e14768eebe3bb1196c0dece8e14c1c6991605721214a0c3c68cf77eb216"},
+ {file = "time_machine-2.16.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7751bf745d54e9e8b358c0afa332815da9b8a6194b26d0fd62876ab6c4d5c9c0"},
+ {file = "time_machine-2.16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1784edf173ca840ba154de6eed000b5727f65ab92972c2f88cec5c4d6349c5f2"},
+ {file = "time_machine-2.16.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f5876a5682ce1f517e55d7ace2383432627889f6f7e338b961f99d684fd9e8d"},
+ {file = "time_machine-2.16.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:806672529a2e255cd901f244c9033767dc1fa53466d0d3e3e49565a1572a64fe"},
+ {file = "time_machine-2.16.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:667b150fedb54acdca2a4bea5bf6da837b43e6dd12857301b48191f8803ba93f"},
+ {file = "time_machine-2.16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:da3ae1028af240c0c46c79adf9c1acffecc6ed1701f2863b8132f5ceae6ae4b5"},
+ {file = "time_machine-2.16.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:520a814ea1b2706c89ab260a54023033d3015abef25c77873b83e3d7c1fafbb2"},
+ {file = "time_machine-2.16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8243664438bb468408b29c6865958662d75e51f79c91842d2794fa22629eb697"},
+ {file = "time_machine-2.16.0-cp313-cp313-win32.whl", hash = "sha256:32d445ce20d25c60ab92153c073942b0bac9815bfbfd152ce3dcc225d15ce988"},
+ {file = "time_machine-2.16.0-cp313-cp313-win_amd64.whl", hash = "sha256:f6927dda86425f97ffda36131f297b1a601c64a6ee6838bfa0e6d3149c2f0d9f"},
+ {file = "time_machine-2.16.0-cp313-cp313-win_arm64.whl", hash = "sha256:4d3843143c46dddca6491a954bbd0abfd435681512ac343169560e9bab504129"},
+ {file = "time_machine-2.16.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:23c5283c01b4f80b7dfbc88f3d8088c06c301b94b7c35366be498c2d7b308549"},
+ {file = "time_machine-2.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ac95ae4529d7d85b251f9cf0f961a8a408ba285875811268f469d824a3b0b15a"},
+ {file = "time_machine-2.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfb76674db946a74f0ca6e3b81caa8265e35dafe9b7005c7d2b8dd5bbd3825cf"},
+ {file = "time_machine-2.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0b6ff3ccde9b16bbc694a2b5facf2d8890554f3135ff626ed1429e270e3cc4f"},
+ {file = "time_machine-2.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1906ec6e26e6b803cd6aab28d420c87285b9c209ff2a69f82d12f82278f78bb"},
+ {file = "time_machine-2.16.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e46bd09c944ec7a20868abd2b83d7d7abdaf427775e9df3089b9226a122b340f"},
+ {file = "time_machine-2.16.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:cac3e2b4101db296b150cb665e5461c03621e6ede6117fc9d5048c0ec96d6e7c"},
+ {file = "time_machine-2.16.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1e0dcc97cfec12ae306e3036746e7631cc7ef65c31889f7264c25217d4938367"},
+ {file = "time_machine-2.16.0-cp39-cp39-win32.whl", hash = "sha256:c761d32d0c5d1fe5b71ac502e1bd5edec4598a7fc6f607b9b906b98e911148ce"},
+ {file = "time_machine-2.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:ddfab1c622342f2945942c5c2d6be327656980e8f2d2b2ce0c022d0aa3711361"},
+ {file = "time_machine-2.16.0-cp39-cp39-win_arm64.whl", hash = "sha256:2e08a4015d5d1aab2cb46c780e85b33efcd5cbe880bb363b282a6972e617b8bb"},
+ {file = "time_machine-2.16.0.tar.gz", hash = "sha256:4a99acc273d2f98add23a89b94d4dd9e14969c01214c8514bfa78e4e9364c7e2"},
+]
+
+[package.dependencies]
+python-dateutil = "*"
+
+[[package]]
+name = "tomli"
+version = "2.1.0"
+description = "A lil' TOML parser"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "tomli-2.1.0-py3-none-any.whl", hash = "sha256:a5c57c3d1c56f5ccdf89f6523458f60ef716e210fc47c4cfb188c5ba473e0391"},
+ {file = "tomli-2.1.0.tar.gz", hash = "sha256:3f646cae2aec94e17d04973e4249548320197cfabdf130015d023de4b74d8ab8"},
+]
+
+[[package]]
+name = "typer"
+version = "0.9.4"
+description = "Typer, build great CLIs. Easy to code. Based on Python type hints."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "typer-0.9.4-py3-none-any.whl", hash = "sha256:aa6c4a4e2329d868b80ecbaf16f807f2b54e192209d7ac9dd42691d63f7a54eb"},
+ {file = "typer-0.9.4.tar.gz", hash = "sha256:f714c2d90afae3a7929fcd72a3abb08df305e1ff61719381384211c4070af57f"},
+]
+
+[package.dependencies]
+click = ">=7.1.1,<9.0.0"
+colorama = {version = ">=0.4.3,<0.5.0", optional = true, markers = "extra == \"all\""}
+rich = {version = ">=10.11.0,<14.0.0", optional = true, markers = "extra == \"all\""}
+shellingham = {version = ">=1.3.0,<2.0.0", optional = true, markers = "extra == \"all\""}
+typing-extensions = ">=3.7.4.3"
+
+[package.extras]
+all = ["colorama (>=0.4.3,<0.5.0)", "rich (>=10.11.0,<14.0.0)", "shellingham (>=1.3.0,<2.0.0)"]
+dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "pre-commit (>=2.17.0,<3.0.0)"]
+doc = ["cairosvg (>=2.5.2,<3.0.0)", "mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pillow (>=9.3.0,<10.0.0)"]
+test = ["black (>=22.3.0,<23.0.0)", "coverage (>=6.2,<7.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.971)", "pytest (>=4.4.0,<8.0.0)", "pytest-cov (>=2.10.0,<5.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "pytest-xdist (>=1.32.0,<4.0.0)", "rich (>=10.11.0,<14.0.0)", "shellingham (>=1.3.0,<2.0.0)"]
+
+[[package]]
+name = "typing-extensions"
+version = "4.12.2"
+description = "Backported and Experimental Type Hints for Python 3.8+"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
+ {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
+]
+
+[[package]]
+name = "tzdata"
+version = "2024.2"
+description = "Provider of IANA time zone data"
+optional = false
+python-versions = ">=2"
+files = [
+ {file = "tzdata-2024.2-py2.py3-none-any.whl", hash = "sha256:a48093786cdcde33cad18c2555e8532f34422074448fbc874186f0abd79565cd"},
+ {file = "tzdata-2024.2.tar.gz", hash = "sha256:7d85cc416e9382e69095b7bdf4afd9e3880418a2413feec7069d533d6b4e31cc"},
+]
+
+[[package]]
+name = "urllib3"
+version = "2.2.3"
+description = "HTTP library with thread-safe connection pooling, file post, and more."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"},
+ {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"},
+]
+
+[package.extras]
+brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
+h2 = ["h2 (>=4,<5)"]
+socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
+zstd = ["zstandard (>=0.18.0)"]
+
+[[package]]
+name = "uvicorn"
+version = "0.27.1"
+description = "The lightning-fast ASGI server."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "uvicorn-0.27.1-py3-none-any.whl", hash = "sha256:5c89da2f3895767472a35556e539fd59f7edbe9b1e9c0e1c99eebeadc61838e4"},
+ {file = "uvicorn-0.27.1.tar.gz", hash = "sha256:3d9a267296243532db80c83a959a3400502165ade2c1338dea4e67915fd4745a"},
+]
+
+[package.dependencies]
+click = ">=7.0"
+colorama = {version = ">=0.4", optional = true, markers = "sys_platform == \"win32\" and extra == \"standard\""}
+h11 = ">=0.8"
+httptools = {version = ">=0.5.0", optional = true, markers = "extra == \"standard\""}
+python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""}
+pyyaml = {version = ">=5.1", optional = true, markers = "extra == \"standard\""}
+uvloop = {version = ">=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1", optional = true, markers = "(sys_platform != \"win32\" and sys_platform != \"cygwin\") and platform_python_implementation != \"PyPy\" and extra == \"standard\""}
+watchfiles = {version = ">=0.13", optional = true, markers = "extra == \"standard\""}
+websockets = {version = ">=10.4", optional = true, markers = "extra == \"standard\""}
+
+[package.extras]
+standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"]
+
+[[package]]
+name = "uvloop"
+version = "0.21.0"
+description = "Fast implementation of asyncio event loop on top of libuv"
+optional = false
+python-versions = ">=3.8.0"
+files = [
+ {file = "uvloop-0.21.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ec7e6b09a6fdded42403182ab6b832b71f4edaf7f37a9a0e371a01db5f0cb45f"},
+ {file = "uvloop-0.21.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:196274f2adb9689a289ad7d65700d37df0c0930fd8e4e743fa4834e850d7719d"},
+ {file = "uvloop-0.21.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f38b2e090258d051d68a5b14d1da7203a3c3677321cf32a95a6f4db4dd8b6f26"},
+ {file = "uvloop-0.21.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87c43e0f13022b998eb9b973b5e97200c8b90823454d4bc06ab33829e09fb9bb"},
+ {file = "uvloop-0.21.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:10d66943def5fcb6e7b37310eb6b5639fd2ccbc38df1177262b0640c3ca68c1f"},
+ {file = "uvloop-0.21.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:67dd654b8ca23aed0a8e99010b4c34aca62f4b7fce88f39d452ed7622c94845c"},
+ {file = "uvloop-0.21.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c0f3fa6200b3108919f8bdabb9a7f87f20e7097ea3c543754cabc7d717d95cf8"},
+ {file = "uvloop-0.21.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0878c2640cf341b269b7e128b1a5fed890adc4455513ca710d77d5e93aa6d6a0"},
+ {file = "uvloop-0.21.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9fb766bb57b7388745d8bcc53a359b116b8a04c83a2288069809d2b3466c37e"},
+ {file = "uvloop-0.21.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a375441696e2eda1c43c44ccb66e04d61ceeffcd76e4929e527b7fa401b90fb"},
+ {file = "uvloop-0.21.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:baa0e6291d91649c6ba4ed4b2f982f9fa165b5bbd50a9e203c416a2797bab3c6"},
+ {file = "uvloop-0.21.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4509360fcc4c3bd2c70d87573ad472de40c13387f5fda8cb58350a1d7475e58d"},
+ {file = "uvloop-0.21.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:359ec2c888397b9e592a889c4d72ba3d6befba8b2bb01743f72fffbde663b59c"},
+ {file = "uvloop-0.21.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f7089d2dc73179ce5ac255bdf37c236a9f914b264825fdaacaded6990a7fb4c2"},
+ {file = "uvloop-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:baa4dcdbd9ae0a372f2167a207cd98c9f9a1ea1188a8a526431eef2f8116cc8d"},
+ {file = "uvloop-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86975dca1c773a2c9864f4c52c5a55631038e387b47eaf56210f873887b6c8dc"},
+ {file = "uvloop-0.21.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:461d9ae6660fbbafedd07559c6a2e57cd553b34b0065b6550685f6653a98c1cb"},
+ {file = "uvloop-0.21.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:183aef7c8730e54c9a3ee3227464daed66e37ba13040bb3f350bc2ddc040f22f"},
+ {file = "uvloop-0.21.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bfd55dfcc2a512316e65f16e503e9e450cab148ef11df4e4e679b5e8253a5281"},
+ {file = "uvloop-0.21.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:787ae31ad8a2856fc4e7c095341cccc7209bd657d0e71ad0dc2ea83c4a6fa8af"},
+ {file = "uvloop-0.21.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ee4d4ef48036ff6e5cfffb09dd192c7a5027153948d85b8da7ff705065bacc6"},
+ {file = "uvloop-0.21.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3df876acd7ec037a3d005b3ab85a7e4110422e4d9c1571d4fc89b0fc41b6816"},
+ {file = "uvloop-0.21.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd53ecc9a0f3d87ab847503c2e1552b690362e005ab54e8a48ba97da3924c0dc"},
+ {file = "uvloop-0.21.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a5c39f217ab3c663dc699c04cbd50c13813e31d917642d459fdcec07555cc553"},
+ {file = "uvloop-0.21.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:17df489689befc72c39a08359efac29bbee8eee5209650d4b9f34df73d22e414"},
+ {file = "uvloop-0.21.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bc09f0ff191e61c2d592a752423c767b4ebb2986daa9ed62908e2b1b9a9ae206"},
+ {file = "uvloop-0.21.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0ce1b49560b1d2d8a2977e3ba4afb2414fb46b86a1b64056bc4ab929efdafbe"},
+ {file = "uvloop-0.21.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e678ad6fe52af2c58d2ae3c73dc85524ba8abe637f134bf3564ed07f555c5e79"},
+ {file = "uvloop-0.21.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:460def4412e473896ef179a1671b40c039c7012184b627898eea5072ef6f017a"},
+ {file = "uvloop-0.21.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:10da8046cc4a8f12c91a1c39d1dd1585c41162a15caaef165c2174db9ef18bdc"},
+ {file = "uvloop-0.21.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c097078b8031190c934ed0ebfee8cc5f9ba9642e6eb88322b9958b649750f72b"},
+ {file = "uvloop-0.21.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:46923b0b5ee7fc0020bef24afe7836cb068f5050ca04caf6b487c513dc1a20b2"},
+ {file = "uvloop-0.21.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:53e420a3afe22cdcf2a0f4846e377d16e718bc70103d7088a4f7623567ba5fb0"},
+ {file = "uvloop-0.21.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88cb67cdbc0e483da00af0b2c3cdad4b7c61ceb1ee0f33fe00e09c81e3a6cb75"},
+ {file = "uvloop-0.21.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:221f4f2a1f46032b403bf3be628011caf75428ee3cc204a22addf96f586b19fd"},
+ {file = "uvloop-0.21.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2d1f581393673ce119355d56da84fe1dd9d2bb8b3d13ce792524e1607139feff"},
+ {file = "uvloop-0.21.0.tar.gz", hash = "sha256:3bf12b0fda68447806a7ad847bfa591613177275d35b6724b1ee573faa3704e3"},
+]
+
+[package.extras]
+dev = ["Cython (>=3.0,<4.0)", "setuptools (>=60)"]
+docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"]
+test = ["aiohttp (>=3.10.5)", "flake8 (>=5.0,<6.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=23.0.0,<23.1.0)", "pycodestyle (>=2.9.0,<2.10.0)"]
+
+[[package]]
+name = "virtualenv"
+version = "20.27.1"
+description = "Virtual Python Environment builder"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "virtualenv-20.27.1-py3-none-any.whl", hash = "sha256:f11f1b8a29525562925f745563bfd48b189450f61fb34c4f9cc79dd5aa32a1f4"},
+ {file = "virtualenv-20.27.1.tar.gz", hash = "sha256:142c6be10212543b32c6c45d3d3893dff89112cc588b7d0879ae5a1ec03a47ba"},
+]
+
+[package.dependencies]
+distlib = ">=0.3.7,<1"
+filelock = ">=3.12.2,<4"
+platformdirs = ">=3.9.1,<5"
+
+[package.extras]
+docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
+test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"]
+
+[[package]]
+name = "watchdog"
+version = "6.0.0"
+description = "Filesystem events monitoring"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26"},
+ {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112"},
+ {file = "watchdog-6.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3"},
+ {file = "watchdog-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c"},
+ {file = "watchdog-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2"},
+ {file = "watchdog-6.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c"},
+ {file = "watchdog-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948"},
+ {file = "watchdog-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860"},
+ {file = "watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0"},
+ {file = "watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c"},
+ {file = "watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134"},
+ {file = "watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b"},
+ {file = "watchdog-6.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e6f0e77c9417e7cd62af82529b10563db3423625c5fce018430b249bf977f9e8"},
+ {file = "watchdog-6.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:90c8e78f3b94014f7aaae121e6b909674df5b46ec24d6bebc45c44c56729af2a"},
+ {file = "watchdog-6.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e7631a77ffb1f7d2eefa4445ebbee491c720a5661ddf6df3498ebecae5ed375c"},
+ {file = "watchdog-6.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881"},
+ {file = "watchdog-6.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11"},
+ {file = "watchdog-6.0.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7a0e56874cfbc4b9b05c60c8a1926fedf56324bb08cfbc188969777940aef3aa"},
+ {file = "watchdog-6.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:e6439e374fc012255b4ec786ae3c4bc838cd7309a540e5fe0952d03687d8804e"},
+ {file = "watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13"},
+ {file = "watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379"},
+ {file = "watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e"},
+ {file = "watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f"},
+ {file = "watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26"},
+ {file = "watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c"},
+ {file = "watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2"},
+ {file = "watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a"},
+ {file = "watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680"},
+ {file = "watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f"},
+ {file = "watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282"},
+]
+
+[package.extras]
+watchmedo = ["PyYAML (>=3.10)"]
+
+[[package]]
+name = "watchfiles"
+version = "0.24.0"
+description = "Simple, modern and high performance file watching and code reload in python."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "watchfiles-0.24.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:083dc77dbdeef09fa44bb0f4d1df571d2e12d8a8f985dccde71ac3ac9ac067a0"},
+ {file = "watchfiles-0.24.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e94e98c7cb94cfa6e071d401ea3342767f28eb5a06a58fafdc0d2a4974f4f35c"},
+ {file = "watchfiles-0.24.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82ae557a8c037c42a6ef26c494d0631cacca040934b101d001100ed93d43f361"},
+ {file = "watchfiles-0.24.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:acbfa31e315a8f14fe33e3542cbcafc55703b8f5dcbb7c1eecd30f141df50db3"},
+ {file = "watchfiles-0.24.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b74fdffce9dfcf2dc296dec8743e5b0332d15df19ae464f0e249aa871fc1c571"},
+ {file = "watchfiles-0.24.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:449f43f49c8ddca87c6b3980c9284cab6bd1f5c9d9a2b00012adaaccd5e7decd"},
+ {file = "watchfiles-0.24.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4abf4ad269856618f82dee296ac66b0cd1d71450fc3c98532d93798e73399b7a"},
+ {file = "watchfiles-0.24.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f895d785eb6164678ff4bb5cc60c5996b3ee6df3edb28dcdeba86a13ea0465e"},
+ {file = "watchfiles-0.24.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7ae3e208b31be8ce7f4c2c0034f33406dd24fbce3467f77223d10cd86778471c"},
+ {file = "watchfiles-0.24.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2efec17819b0046dde35d13fb8ac7a3ad877af41ae4640f4109d9154ed30a188"},
+ {file = "watchfiles-0.24.0-cp310-none-win32.whl", hash = "sha256:6bdcfa3cd6fdbdd1a068a52820f46a815401cbc2cb187dd006cb076675e7b735"},
+ {file = "watchfiles-0.24.0-cp310-none-win_amd64.whl", hash = "sha256:54ca90a9ae6597ae6dc00e7ed0a040ef723f84ec517d3e7ce13e63e4bc82fa04"},
+ {file = "watchfiles-0.24.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:bdcd5538e27f188dd3c804b4a8d5f52a7fc7f87e7fd6b374b8e36a4ca03db428"},
+ {file = "watchfiles-0.24.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2dadf8a8014fde6addfd3c379e6ed1a981c8f0a48292d662e27cabfe4239c83c"},
+ {file = "watchfiles-0.24.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6509ed3f467b79d95fc62a98229f79b1a60d1b93f101e1c61d10c95a46a84f43"},
+ {file = "watchfiles-0.24.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8360f7314a070c30e4c976b183d1d8d1585a4a50c5cb603f431cebcbb4f66327"},
+ {file = "watchfiles-0.24.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:316449aefacf40147a9efaf3bd7c9bdd35aaba9ac5d708bd1eb5763c9a02bef5"},
+ {file = "watchfiles-0.24.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73bde715f940bea845a95247ea3e5eb17769ba1010efdc938ffcb967c634fa61"},
+ {file = "watchfiles-0.24.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3770e260b18e7f4e576edca4c0a639f704088602e0bc921c5c2e721e3acb8d15"},
+ {file = "watchfiles-0.24.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa0fd7248cf533c259e59dc593a60973a73e881162b1a2f73360547132742823"},
+ {file = "watchfiles-0.24.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d7a2e3b7f5703ffbd500dabdefcbc9eafeff4b9444bbdd5d83d79eedf8428fab"},
+ {file = "watchfiles-0.24.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d831ee0a50946d24a53821819b2327d5751b0c938b12c0653ea5be7dea9c82ec"},
+ {file = "watchfiles-0.24.0-cp311-none-win32.whl", hash = "sha256:49d617df841a63b4445790a254013aea2120357ccacbed00253f9c2b5dc24e2d"},
+ {file = "watchfiles-0.24.0-cp311-none-win_amd64.whl", hash = "sha256:d3dcb774e3568477275cc76554b5a565024b8ba3a0322f77c246bc7111c5bb9c"},
+ {file = "watchfiles-0.24.0-cp311-none-win_arm64.whl", hash = "sha256:9301c689051a4857d5b10777da23fafb8e8e921bcf3abe6448a058d27fb67633"},
+ {file = "watchfiles-0.24.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:7211b463695d1e995ca3feb38b69227e46dbd03947172585ecb0588f19b0d87a"},
+ {file = "watchfiles-0.24.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4b8693502d1967b00f2fb82fc1e744df128ba22f530e15b763c8d82baee15370"},
+ {file = "watchfiles-0.24.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdab9555053399318b953a1fe1f586e945bc8d635ce9d05e617fd9fe3a4687d6"},
+ {file = "watchfiles-0.24.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:34e19e56d68b0dad5cff62273107cf5d9fbaf9d75c46277aa5d803b3ef8a9e9b"},
+ {file = "watchfiles-0.24.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:41face41f036fee09eba33a5b53a73e9a43d5cb2c53dad8e61fa6c9f91b5a51e"},
+ {file = "watchfiles-0.24.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5148c2f1ea043db13ce9b0c28456e18ecc8f14f41325aa624314095b6aa2e9ea"},
+ {file = "watchfiles-0.24.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e4bd963a935aaf40b625c2499f3f4f6bbd0c3776f6d3bc7c853d04824ff1c9f"},
+ {file = "watchfiles-0.24.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c79d7719d027b7a42817c5d96461a99b6a49979c143839fc37aa5748c322f234"},
+ {file = "watchfiles-0.24.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:32aa53a9a63b7f01ed32e316e354e81e9da0e6267435c7243bf8ae0f10b428ef"},
+ {file = "watchfiles-0.24.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ce72dba6a20e39a0c628258b5c308779b8697f7676c254a845715e2a1039b968"},
+ {file = "watchfiles-0.24.0-cp312-none-win32.whl", hash = "sha256:d9018153cf57fc302a2a34cb7564870b859ed9a732d16b41a9b5cb2ebed2d444"},
+ {file = "watchfiles-0.24.0-cp312-none-win_amd64.whl", hash = "sha256:551ec3ee2a3ac9cbcf48a4ec76e42c2ef938a7e905a35b42a1267fa4b1645896"},
+ {file = "watchfiles-0.24.0-cp312-none-win_arm64.whl", hash = "sha256:b52a65e4ea43c6d149c5f8ddb0bef8d4a1e779b77591a458a893eb416624a418"},
+ {file = "watchfiles-0.24.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:3d2e3ab79a1771c530233cadfd277fcc762656d50836c77abb2e5e72b88e3a48"},
+ {file = "watchfiles-0.24.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:327763da824817b38ad125dcd97595f942d720d32d879f6c4ddf843e3da3fe90"},
+ {file = "watchfiles-0.24.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd82010f8ab451dabe36054a1622870166a67cf3fce894f68895db6f74bbdc94"},
+ {file = "watchfiles-0.24.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d64ba08db72e5dfd5c33be1e1e687d5e4fcce09219e8aee893a4862034081d4e"},
+ {file = "watchfiles-0.24.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1cf1f6dd7825053f3d98f6d33f6464ebdd9ee95acd74ba2c34e183086900a827"},
+ {file = "watchfiles-0.24.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:43e3e37c15a8b6fe00c1bce2473cfa8eb3484bbeecf3aefbf259227e487a03df"},
+ {file = "watchfiles-0.24.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88bcd4d0fe1d8ff43675360a72def210ebad3f3f72cabfeac08d825d2639b4ab"},
+ {file = "watchfiles-0.24.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:999928c6434372fde16c8f27143d3e97201160b48a614071261701615a2a156f"},
+ {file = "watchfiles-0.24.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:30bbd525c3262fd9f4b1865cb8d88e21161366561cd7c9e1194819e0a33ea86b"},
+ {file = "watchfiles-0.24.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:edf71b01dec9f766fb285b73930f95f730bb0943500ba0566ae234b5c1618c18"},
+ {file = "watchfiles-0.24.0-cp313-none-win32.whl", hash = "sha256:f4c96283fca3ee09fb044f02156d9570d156698bc3734252175a38f0e8975f07"},
+ {file = "watchfiles-0.24.0-cp313-none-win_amd64.whl", hash = "sha256:a974231b4fdd1bb7f62064a0565a6b107d27d21d9acb50c484d2cdba515b9366"},
+ {file = "watchfiles-0.24.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:ee82c98bed9d97cd2f53bdb035e619309a098ea53ce525833e26b93f673bc318"},
+ {file = "watchfiles-0.24.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fd92bbaa2ecdb7864b7600dcdb6f2f1db6e0346ed425fbd01085be04c63f0b05"},
+ {file = "watchfiles-0.24.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f83df90191d67af5a831da3a33dd7628b02a95450e168785586ed51e6d28943c"},
+ {file = "watchfiles-0.24.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fca9433a45f18b7c779d2bae7beeec4f740d28b788b117a48368d95a3233ed83"},
+ {file = "watchfiles-0.24.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b995bfa6bf01a9e09b884077a6d37070464b529d8682d7691c2d3b540d357a0c"},
+ {file = "watchfiles-0.24.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed9aba6e01ff6f2e8285e5aa4154e2970068fe0fc0998c4380d0e6278222269b"},
+ {file = "watchfiles-0.24.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5171ef898299c657685306d8e1478a45e9303ddcd8ac5fed5bd52ad4ae0b69b"},
+ {file = "watchfiles-0.24.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4933a508d2f78099162da473841c652ad0de892719043d3f07cc83b33dfd9d91"},
+ {file = "watchfiles-0.24.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:95cf3b95ea665ab03f5a54765fa41abf0529dbaf372c3b83d91ad2cfa695779b"},
+ {file = "watchfiles-0.24.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:01def80eb62bd5db99a798d5e1f5f940ca0a05986dcfae21d833af7a46f7ee22"},
+ {file = "watchfiles-0.24.0-cp38-none-win32.whl", hash = "sha256:4d28cea3c976499475f5b7a2fec6b3a36208656963c1a856d328aeae056fc5c1"},
+ {file = "watchfiles-0.24.0-cp38-none-win_amd64.whl", hash = "sha256:21ab23fdc1208086d99ad3f69c231ba265628014d4aed31d4e8746bd59e88cd1"},
+ {file = "watchfiles-0.24.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b665caeeda58625c3946ad7308fbd88a086ee51ccb706307e5b1fa91556ac886"},
+ {file = "watchfiles-0.24.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5c51749f3e4e269231510da426ce4a44beb98db2dce9097225c338f815b05d4f"},
+ {file = "watchfiles-0.24.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82b2509f08761f29a0fdad35f7e1638b8ab1adfa2666d41b794090361fb8b855"},
+ {file = "watchfiles-0.24.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a60e2bf9dc6afe7f743e7c9b149d1fdd6dbf35153c78fe3a14ae1a9aee3d98b"},
+ {file = "watchfiles-0.24.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f7d9b87c4c55e3ea8881dfcbf6d61ea6775fffed1fedffaa60bd047d3c08c430"},
+ {file = "watchfiles-0.24.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:78470906a6be5199524641f538bd2c56bb809cd4bf29a566a75051610bc982c3"},
+ {file = "watchfiles-0.24.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:07cdef0c84c03375f4e24642ef8d8178e533596b229d32d2bbd69e5128ede02a"},
+ {file = "watchfiles-0.24.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d337193bbf3e45171c8025e291530fb7548a93c45253897cd764a6a71c937ed9"},
+ {file = "watchfiles-0.24.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ec39698c45b11d9694a1b635a70946a5bad066b593af863460a8e600f0dff1ca"},
+ {file = "watchfiles-0.24.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2e28d91ef48eab0afb939fa446d8ebe77e2f7593f5f463fd2bb2b14132f95b6e"},
+ {file = "watchfiles-0.24.0-cp39-none-win32.whl", hash = "sha256:7138eff8baa883aeaa074359daabb8b6c1e73ffe69d5accdc907d62e50b1c0da"},
+ {file = "watchfiles-0.24.0-cp39-none-win_amd64.whl", hash = "sha256:b3ef2c69c655db63deb96b3c3e587084612f9b1fa983df5e0c3379d41307467f"},
+ {file = "watchfiles-0.24.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:632676574429bee8c26be8af52af20e0c718cc7f5f67f3fb658c71928ccd4f7f"},
+ {file = "watchfiles-0.24.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:a2a9891723a735d3e2540651184be6fd5b96880c08ffe1a98bae5017e65b544b"},
+ {file = "watchfiles-0.24.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a7fa2bc0efef3e209a8199fd111b8969fe9db9c711acc46636686331eda7dd4"},
+ {file = "watchfiles-0.24.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01550ccf1d0aed6ea375ef259706af76ad009ef5b0203a3a4cce0f6024f9b68a"},
+ {file = "watchfiles-0.24.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:96619302d4374de5e2345b2b622dc481257a99431277662c30f606f3e22f42be"},
+ {file = "watchfiles-0.24.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:85d5f0c7771dcc7a26c7a27145059b6bb0ce06e4e751ed76cdf123d7039b60b5"},
+ {file = "watchfiles-0.24.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:951088d12d339690a92cef2ec5d3cfd957692834c72ffd570ea76a6790222777"},
+ {file = "watchfiles-0.24.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49fb58bcaa343fedc6a9e91f90195b20ccb3135447dc9e4e2570c3a39565853e"},
+ {file = "watchfiles-0.24.0.tar.gz", hash = "sha256:afb72325b74fa7a428c009c1b8be4b4d7c2afedafb2982827ef2156646df2fe1"},
+]
+
+[package.dependencies]
+anyio = ">=3.0.0"
+
+[[package]]
+name = "websockets"
+version = "14.1"
+description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "websockets-14.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a0adf84bc2e7c86e8a202537b4fd50e6f7f0e4a6b6bf64d7ccb96c4cd3330b29"},
+ {file = "websockets-14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90b5d9dfbb6d07a84ed3e696012610b6da074d97453bd01e0e30744b472c8179"},
+ {file = "websockets-14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2177ee3901075167f01c5e335a6685e71b162a54a89a56001f1c3e9e3d2ad250"},
+ {file = "websockets-14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f14a96a0034a27f9d47fd9788913924c89612225878f8078bb9d55f859272b0"},
+ {file = "websockets-14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f874ba705deea77bcf64a9da42c1f5fc2466d8f14daf410bc7d4ceae0a9fcb0"},
+ {file = "websockets-14.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9607b9a442392e690a57909c362811184ea429585a71061cd5d3c2b98065c199"},
+ {file = "websockets-14.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:bea45f19b7ca000380fbd4e02552be86343080120d074b87f25593ce1700ad58"},
+ {file = "websockets-14.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:219c8187b3ceeadbf2afcf0f25a4918d02da7b944d703b97d12fb01510869078"},
+ {file = "websockets-14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ad2ab2547761d79926effe63de21479dfaf29834c50f98c4bf5b5480b5838434"},
+ {file = "websockets-14.1-cp310-cp310-win32.whl", hash = "sha256:1288369a6a84e81b90da5dbed48610cd7e5d60af62df9851ed1d1d23a9069f10"},
+ {file = "websockets-14.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0744623852f1497d825a49a99bfbec9bea4f3f946df6eb9d8a2f0c37a2fec2e"},
+ {file = "websockets-14.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:449d77d636f8d9c17952628cc7e3b8faf6e92a17ec581ec0c0256300717e1512"},
+ {file = "websockets-14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a35f704be14768cea9790d921c2c1cc4fc52700410b1c10948511039be824aac"},
+ {file = "websockets-14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b1f3628a0510bd58968c0f60447e7a692933589b791a6b572fcef374053ca280"},
+ {file = "websockets-14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c3deac3748ec73ef24fc7be0b68220d14d47d6647d2f85b2771cb35ea847aa1"},
+ {file = "websockets-14.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7048eb4415d46368ef29d32133134c513f507fff7d953c18c91104738a68c3b3"},
+ {file = "websockets-14.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6cf0ad281c979306a6a34242b371e90e891bce504509fb6bb5246bbbf31e7b6"},
+ {file = "websockets-14.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cc1fc87428c1d18b643479caa7b15db7d544652e5bf610513d4a3478dbe823d0"},
+ {file = "websockets-14.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f95ba34d71e2fa0c5d225bde3b3bdb152e957150100e75c86bc7f3964c450d89"},
+ {file = "websockets-14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9481a6de29105d73cf4515f2bef8eb71e17ac184c19d0b9918a3701c6c9c4f23"},
+ {file = "websockets-14.1-cp311-cp311-win32.whl", hash = "sha256:368a05465f49c5949e27afd6fbe0a77ce53082185bbb2ac096a3a8afaf4de52e"},
+ {file = "websockets-14.1-cp311-cp311-win_amd64.whl", hash = "sha256:6d24fc337fc055c9e83414c94e1ee0dee902a486d19d2a7f0929e49d7d604b09"},
+ {file = "websockets-14.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ed907449fe5e021933e46a3e65d651f641975a768d0649fee59f10c2985529ed"},
+ {file = "websockets-14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:87e31011b5c14a33b29f17eb48932e63e1dcd3fa31d72209848652310d3d1f0d"},
+ {file = "websockets-14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bc6ccf7d54c02ae47a48ddf9414c54d48af9c01076a2e1023e3b486b6e72c707"},
+ {file = "websockets-14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9777564c0a72a1d457f0848977a1cbe15cfa75fa2f67ce267441e465717dcf1a"},
+ {file = "websockets-14.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a655bde548ca98f55b43711b0ceefd2a88a71af6350b0c168aa77562104f3f45"},
+ {file = "websockets-14.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3dfff83ca578cada2d19e665e9c8368e1598d4e787422a460ec70e531dbdd58"},
+ {file = "websockets-14.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6a6c9bcf7cdc0fd41cc7b7944447982e8acfd9f0d560ea6d6845428ed0562058"},
+ {file = "websockets-14.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4b6caec8576e760f2c7dd878ba817653144d5f369200b6ddf9771d64385b84d4"},
+ {file = "websockets-14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eb6d38971c800ff02e4a6afd791bbe3b923a9a57ca9aeab7314c21c84bf9ff05"},
+ {file = "websockets-14.1-cp312-cp312-win32.whl", hash = "sha256:1d045cbe1358d76b24d5e20e7b1878efe578d9897a25c24e6006eef788c0fdf0"},
+ {file = "websockets-14.1-cp312-cp312-win_amd64.whl", hash = "sha256:90f4c7a069c733d95c308380aae314f2cb45bd8a904fb03eb36d1a4983a4993f"},
+ {file = "websockets-14.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:3630b670d5057cd9e08b9c4dab6493670e8e762a24c2c94ef312783870736ab9"},
+ {file = "websockets-14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36ebd71db3b89e1f7b1a5deaa341a654852c3518ea7a8ddfdf69cc66acc2db1b"},
+ {file = "websockets-14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5b918d288958dc3fa1c5a0b9aa3256cb2b2b84c54407f4813c45d52267600cd3"},
+ {file = "websockets-14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00fe5da3f037041da1ee0cf8e308374e236883f9842c7c465aa65098b1c9af59"},
+ {file = "websockets-14.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8149a0f5a72ca36720981418eeffeb5c2729ea55fa179091c81a0910a114a5d2"},
+ {file = "websockets-14.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77569d19a13015e840b81550922056acabc25e3f52782625bc6843cfa034e1da"},
+ {file = "websockets-14.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cf5201a04550136ef870aa60ad3d29d2a59e452a7f96b94193bee6d73b8ad9a9"},
+ {file = "websockets-14.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:88cf9163ef674b5be5736a584c999e98daf3aabac6e536e43286eb74c126b9c7"},
+ {file = "websockets-14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:836bef7ae338a072e9d1863502026f01b14027250a4545672673057997d5c05a"},
+ {file = "websockets-14.1-cp313-cp313-win32.whl", hash = "sha256:0d4290d559d68288da9f444089fd82490c8d2744309113fc26e2da6e48b65da6"},
+ {file = "websockets-14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8621a07991add373c3c5c2cf89e1d277e49dc82ed72c75e3afc74bd0acc446f0"},
+ {file = "websockets-14.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:01bb2d4f0a6d04538d3c5dfd27c0643269656c28045a53439cbf1c004f90897a"},
+ {file = "websockets-14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:414ffe86f4d6f434a8c3b7913655a1a5383b617f9bf38720e7c0799fac3ab1c6"},
+ {file = "websockets-14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8fda642151d5affdee8a430bd85496f2e2517be3a2b9d2484d633d5712b15c56"},
+ {file = "websockets-14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd7c11968bc3860d5c78577f0dbc535257ccec41750675d58d8dc66aa47fe52c"},
+ {file = "websockets-14.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a032855dc7db987dff813583d04f4950d14326665d7e714d584560b140ae6b8b"},
+ {file = "websockets-14.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7e7ea2f782408c32d86b87a0d2c1fd8871b0399dd762364c731d86c86069a78"},
+ {file = "websockets-14.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:39450e6215f7d9f6f7bc2a6da21d79374729f5d052333da4d5825af8a97e6735"},
+ {file = "websockets-14.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ceada5be22fa5a5a4cdeec74e761c2ee7db287208f54c718f2df4b7e200b8d4a"},
+ {file = "websockets-14.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3fc753451d471cff90b8f467a1fc0ae64031cf2d81b7b34e1811b7e2691bc4bc"},
+ {file = "websockets-14.1-cp39-cp39-win32.whl", hash = "sha256:14839f54786987ccd9d03ed7f334baec0f02272e7ec4f6e9d427ff584aeea8b4"},
+ {file = "websockets-14.1-cp39-cp39-win_amd64.whl", hash = "sha256:d9fd19ecc3a4d5ae82ddbfb30962cf6d874ff943e56e0c81f5169be2fda62979"},
+ {file = "websockets-14.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:e5dc25a9dbd1a7f61eca4b7cb04e74ae4b963d658f9e4f9aad9cd00b688692c8"},
+ {file = "websockets-14.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:04a97aca96ca2acedf0d1f332c861c5a4486fdcba7bcef35873820f940c4231e"},
+ {file = "websockets-14.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df174ece723b228d3e8734a6f2a6febbd413ddec39b3dc592f5a4aa0aff28098"},
+ {file = "websockets-14.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:034feb9f4286476f273b9a245fb15f02c34d9586a5bc936aff108c3ba1b21beb"},
+ {file = "websockets-14.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:660c308dabd2b380807ab64b62985eaccf923a78ebc572bd485375b9ca2b7dc7"},
+ {file = "websockets-14.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5a42d3ecbb2db5080fc578314439b1d79eef71d323dc661aa616fb492436af5d"},
+ {file = "websockets-14.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ddaa4a390af911da6f680be8be4ff5aaf31c4c834c1a9147bc21cbcbca2d4370"},
+ {file = "websockets-14.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a4c805c6034206143fbabd2d259ec5e757f8b29d0a2f0bf3d2fe5d1f60147a4a"},
+ {file = "websockets-14.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:205f672a6c2c671a86d33f6d47c9b35781a998728d2c7c2a3e1cf3333fcb62b7"},
+ {file = "websockets-14.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef440054124728cc49b01c33469de06755e5a7a4e83ef61934ad95fc327fbb0"},
+ {file = "websockets-14.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7591d6f440af7f73c4bd9404f3772bfee064e639d2b6cc8c94076e71b2471c1"},
+ {file = "websockets-14.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:25225cc79cfebc95ba1d24cd3ab86aaa35bcd315d12fa4358939bd55e9bd74a5"},
+ {file = "websockets-14.1-py3-none-any.whl", hash = "sha256:4d4fc827a20abe6d544a119896f6b78ee13fe81cbfef416f3f2ddf09a03f0e2e"},
+ {file = "websockets-14.1.tar.gz", hash = "sha256:398b10c77d471c0aab20a845e7a60076b6390bfdaac7a6d2edb0d2c59d75e8d8"},
+]
+
+[[package]]
+name = "win32-setctime"
+version = "1.1.0"
+description = "A small Python utility to set file creation time on Windows"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"},
+ {file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"},
+]
+
+[package.extras]
+dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"]
+
+[[package]]
+name = "yarl"
+version = "1.18.0"
+description = "Yet another URL library"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "yarl-1.18.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:074fee89caab89a97e18ef5f29060ef61ba3cae6cd77673acc54bfdd3214b7b7"},
+ {file = "yarl-1.18.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b026cf2c32daf48d90c0c4e406815c3f8f4cfe0c6dfccb094a9add1ff6a0e41a"},
+ {file = "yarl-1.18.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ae38bd86eae3ba3d2ce5636cc9e23c80c9db2e9cb557e40b98153ed102b5a736"},
+ {file = "yarl-1.18.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:685cc37f3f307c6a8e879986c6d85328f4c637f002e219f50e2ef66f7e062c1d"},
+ {file = "yarl-1.18.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8254dbfce84ee5d1e81051ee7a0f1536c108ba294c0fdb5933476398df0654f3"},
+ {file = "yarl-1.18.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:20de4a8b04de70c49698dc2390b7fd2d18d424d3b876371f9b775e2b462d4b41"},
+ {file = "yarl-1.18.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0a2074a37285570d54b55820687de3d2f2b9ecf1b714e482e48c9e7c0402038"},
+ {file = "yarl-1.18.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f576ed278860df2721a5d57da3381040176ef1d07def9688a385c8330db61a1"},
+ {file = "yarl-1.18.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3a3709450a574d61be6ac53d582496014342ea34876af8dc17cc16da32826c9a"},
+ {file = "yarl-1.18.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:bd80ed29761490c622edde5dd70537ca8c992c2952eb62ed46984f8eff66d6e8"},
+ {file = "yarl-1.18.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:32141e13a1d5a48525e519c9197d3f4d9744d818d5c7d6547524cc9eccc8971e"},
+ {file = "yarl-1.18.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8b8d3e4e014fb4274f1c5bf61511d2199e263909fb0b8bda2a7428b0894e8dc6"},
+ {file = "yarl-1.18.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:701bb4a8f4de191c8c0cc9a1e6d5142f4df880e9d1210e333b829ca9425570ed"},
+ {file = "yarl-1.18.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a45d94075ac0647621eaaf693c8751813a3eccac455d423f473ffed38c8ac5c9"},
+ {file = "yarl-1.18.0-cp310-cp310-win32.whl", hash = "sha256:34176bfb082add67cb2a20abd85854165540891147f88b687a5ed0dc225750a0"},
+ {file = "yarl-1.18.0-cp310-cp310-win_amd64.whl", hash = "sha256:73553bbeea7d6ec88c08ad8027f4e992798f0abc459361bf06641c71972794dc"},
+ {file = "yarl-1.18.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b8e8c516dc4e1a51d86ac975b0350735007e554c962281c432eaa5822aa9765c"},
+ {file = "yarl-1.18.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2e6b4466714a73f5251d84b471475850954f1fa6acce4d3f404da1d55d644c34"},
+ {file = "yarl-1.18.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c893f8c1a6d48b25961e00922724732d00b39de8bb0b451307482dc87bddcd74"},
+ {file = "yarl-1.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:13aaf2bdbc8c86ddce48626b15f4987f22e80d898818d735b20bd58f17292ee8"},
+ {file = "yarl-1.18.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd21c0128e301851de51bc607b0a6da50e82dc34e9601f4b508d08cc89ee7929"},
+ {file = "yarl-1.18.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:205de377bd23365cd85562c9c6c33844050a93661640fda38e0567d2826b50df"},
+ {file = "yarl-1.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed69af4fe2a0949b1ea1d012bf065c77b4c7822bad4737f17807af2adb15a73c"},
+ {file = "yarl-1.18.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e1c18890091aa3cc8a77967943476b729dc2016f4cfe11e45d89b12519d4a93"},
+ {file = "yarl-1.18.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:91b8fb9427e33f83ca2ba9501221ffaac1ecf0407f758c4d2f283c523da185ee"},
+ {file = "yarl-1.18.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:536a7a8a53b75b2e98ff96edb2dfb91a26b81c4fed82782035767db5a465be46"},
+ {file = "yarl-1.18.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:a64619a9c47c25582190af38e9eb382279ad42e1f06034f14d794670796016c0"},
+ {file = "yarl-1.18.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c73a6bbc97ba1b5a0c3c992ae93d721c395bdbb120492759b94cc1ac71bc6350"},
+ {file = "yarl-1.18.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:a173401d7821a2a81c7b47d4e7d5c4021375a1441af0c58611c1957445055056"},
+ {file = "yarl-1.18.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7520e799b1f84e095cce919bd6c23c9d49472deeef25fe1ef960b04cca51c3fc"},
+ {file = "yarl-1.18.0-cp311-cp311-win32.whl", hash = "sha256:c4cb992d8090d5ae5f7afa6754d7211c578be0c45f54d3d94f7781c495d56716"},
+ {file = "yarl-1.18.0-cp311-cp311-win_amd64.whl", hash = "sha256:52c136f348605974c9b1c878addd6b7a60e3bf2245833e370862009b86fa4689"},
+ {file = "yarl-1.18.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1ece25e2251c28bab737bdf0519c88189b3dd9492dc086a1d77336d940c28ced"},
+ {file = "yarl-1.18.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:454902dc1830d935c90b5b53c863ba2a98dcde0fbaa31ca2ed1ad33b2a7171c6"},
+ {file = "yarl-1.18.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:01be8688fc211dc237e628fcc209dda412d35de7642453059a0553747018d075"},
+ {file = "yarl-1.18.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d26f1fa9fa2167bb238f6f4b20218eb4e88dd3ef21bb8f97439fa6b5313e30d"},
+ {file = "yarl-1.18.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b234a4a9248a9f000b7a5dfe84b8cb6210ee5120ae70eb72a4dcbdb4c528f72f"},
+ {file = "yarl-1.18.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe94d1de77c4cd8caff1bd5480e22342dbd54c93929f5943495d9c1e8abe9f42"},
+ {file = "yarl-1.18.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b4c90c5363c6b0a54188122b61edb919c2cd1119684999d08cd5e538813a28e"},
+ {file = "yarl-1.18.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49a98ecadc5a241c9ba06de08127ee4796e1009555efd791bac514207862b43d"},
+ {file = "yarl-1.18.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9106025c7f261f9f5144f9aa7681d43867eed06349a7cfb297a1bc804de2f0d1"},
+ {file = "yarl-1.18.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:f275ede6199d0f1ed4ea5d55a7b7573ccd40d97aee7808559e1298fe6efc8dbd"},
+ {file = "yarl-1.18.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:f7edeb1dcc7f50a2c8e08b9dc13a413903b7817e72273f00878cb70e766bdb3b"},
+ {file = "yarl-1.18.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c083f6dd6951b86e484ebfc9c3524b49bcaa9c420cb4b2a78ef9f7a512bfcc85"},
+ {file = "yarl-1.18.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:80741ec5b471fbdfb997821b2842c59660a1c930ceb42f8a84ba8ca0f25a66aa"},
+ {file = "yarl-1.18.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b1a3297b9cad594e1ff0c040d2881d7d3a74124a3c73e00c3c71526a1234a9f7"},
+ {file = "yarl-1.18.0-cp312-cp312-win32.whl", hash = "sha256:cd6ab7d6776c186f544f893b45ee0c883542b35e8a493db74665d2e594d3ca75"},
+ {file = "yarl-1.18.0-cp312-cp312-win_amd64.whl", hash = "sha256:039c299a0864d1f43c3e31570045635034ea7021db41bf4842693a72aca8df3a"},
+ {file = "yarl-1.18.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6fb64dd45453225f57d82c4764818d7a205ee31ce193e9f0086e493916bd4f72"},
+ {file = "yarl-1.18.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3adaaf9c6b1b4fc258584f4443f24d775a2086aee82d1387e48a8b4f3d6aecf6"},
+ {file = "yarl-1.18.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:da206d1ec78438a563c5429ab808a2b23ad7bc025c8adbf08540dde202be37d5"},
+ {file = "yarl-1.18.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:576d258b21c1db4c6449b1c572c75d03f16a482eb380be8003682bdbe7db2f28"},
+ {file = "yarl-1.18.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c60e547c0a375c4bfcdd60eef82e7e0e8698bf84c239d715f5c1278a73050393"},
+ {file = "yarl-1.18.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e3818eabaefb90adeb5e0f62f047310079d426387991106d4fbf3519eec7d90a"},
+ {file = "yarl-1.18.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5f72421246c21af6a92fbc8c13b6d4c5427dfd949049b937c3b731f2f9076bd"},
+ {file = "yarl-1.18.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7fa7d37f2ada0f42e0723632993ed422f2a679af0e200874d9d861720a54f53e"},
+ {file = "yarl-1.18.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:42ba84e2ac26a3f252715f8ec17e6fdc0cbf95b9617c5367579fafcd7fba50eb"},
+ {file = "yarl-1.18.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:6a49ad0102c0f0ba839628d0bf45973c86ce7b590cdedf7540d5b1833ddc6f00"},
+ {file = "yarl-1.18.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:96404e8d5e1bbe36bdaa84ef89dc36f0e75939e060ca5cd45451aba01db02902"},
+ {file = "yarl-1.18.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:a0509475d714df8f6d498935b3f307cd122c4ca76f7d426c7e1bb791bcd87eda"},
+ {file = "yarl-1.18.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:1ff116f0285b5c8b3b9a2680aeca29a858b3b9e0402fc79fd850b32c2bcb9f8b"},
+ {file = "yarl-1.18.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e2580c1d7e66e6d29d6e11855e3b1c6381971e0edd9a5066e6c14d79bc8967af"},
+ {file = "yarl-1.18.0-cp313-cp313-win32.whl", hash = "sha256:14408cc4d34e202caba7b5ac9cc84700e3421a9e2d1b157d744d101b061a4a88"},
+ {file = "yarl-1.18.0-cp313-cp313-win_amd64.whl", hash = "sha256:1db1537e9cb846eb0ff206eac667f627794be8b71368c1ab3207ec7b6f8c5afc"},
+ {file = "yarl-1.18.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:fa2c9cb607e0f660d48c54a63de7a9b36fef62f6b8bd50ff592ce1137e73ac7d"},
+ {file = "yarl-1.18.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c0f4808644baf0a434a3442df5e0bedf8d05208f0719cedcd499e168b23bfdc4"},
+ {file = "yarl-1.18.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7db9584235895a1dffca17e1c634b13870852094f6389b68dcc6338086aa7b08"},
+ {file = "yarl-1.18.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:309f8d27d6f93ceeeb80aa6980e883aa57895270f7f41842b92247e65d7aeddf"},
+ {file = "yarl-1.18.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:609ffd44fed2ed88d9b4ef62ee860cf86446cf066333ad4ce4123505b819e581"},
+ {file = "yarl-1.18.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f172b8b2c72a13a06ea49225a9c47079549036ad1b34afa12d5491b881f5b993"},
+ {file = "yarl-1.18.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d89ae7de94631b60d468412c18290d358a9d805182373d804ec839978b120422"},
+ {file = "yarl-1.18.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:466d31fd043ef9af822ee3f1df8fdff4e8c199a7f4012c2642006af240eade17"},
+ {file = "yarl-1.18.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7609b8462351c4836b3edce4201acb6dd46187b207c589b30a87ffd1813b48dc"},
+ {file = "yarl-1.18.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:d9d4f5e471e8dc49b593a80766c2328257e405f943c56a3dc985c125732bc4cf"},
+ {file = "yarl-1.18.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:67b336c15e564d76869c9a21316f90edf546809a5796a083b8f57c845056bc01"},
+ {file = "yarl-1.18.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b212452b80cae26cb767aa045b051740e464c5129b7bd739c58fbb7deb339e7b"},
+ {file = "yarl-1.18.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:38b39b7b3e692b6c92b986b00137a3891eddb66311b229d1940dcbd4f025083c"},
+ {file = "yarl-1.18.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a7ee6884a8848792d58b854946b685521f41d8871afa65e0d4a774954e9c9e89"},
+ {file = "yarl-1.18.0-cp39-cp39-win32.whl", hash = "sha256:b4095c5019bb889aa866bf12ed4c85c0daea5aafcb7c20d1519f02a1e738f07f"},
+ {file = "yarl-1.18.0-cp39-cp39-win_amd64.whl", hash = "sha256:2d90f2e4d16a5b0915ee065218b435d2ef619dd228973b1b47d262a6f7cd8fa5"},
+ {file = "yarl-1.18.0-py3-none-any.whl", hash = "sha256:dbf53db46f7cf176ee01d8d98c39381440776fcda13779d269a8ba664f69bec0"},
+ {file = "yarl-1.18.0.tar.gz", hash = "sha256:20d95535e7d833889982bfe7cc321b7f63bf8879788fee982c76ae2b24cfb715"},
+]
+
+[package.dependencies]
+idna = ">=2.0"
+multidict = ">=4.0"
+propcache = ">=0.2.0"
+
+[metadata]
+lock-version = "2.0"
+python-versions = "^3.12"
+content-hash = "78a01182417e4bed52971d7e8cd7dbf3a74c69c5b3c191c77b022fb7bd0be165"
diff --git a/backend/src/poetry.toml b/backend/poetry.toml
similarity index 100%
rename from backend/src/poetry.toml
rename to backend/poetry.toml
diff --git a/backend/src/pyproject.toml b/backend/pyproject.toml
similarity index 86%
rename from backend/src/pyproject.toml
rename to backend/pyproject.toml
index e82d0429b..ba44ea2f3 100644
--- a/backend/src/pyproject.toml
+++ b/backend/pyproject.toml
@@ -19,7 +19,7 @@ pyjwt = "^2.7.0"
typer = {extras = ["all"], version = "^0.9.0"}
asyncmy = "^0.2.8"
cryptography = "^42.0.2"
-markdown = "3.5.2"
+markdown = "3.7"
pydantic= "2.6.3"
redis = "^5.0.1"
inject = "^5.2.0"
@@ -33,8 +33,8 @@ optional = true
[tool.poetry.group.dev.dependencies]
pytest = "^8.1.1"
black = {extras = ["d"], version = "^24.3.0"}
-mypy = "^1.9.0"
-ruff = "~0.3.4"
+mypy = "^1.10.0"
+ruff = "^0.7.3"
pytest-sugar = "^1.0.0"
httpx = "^0.26.0"
pytest-asyncio = "^0.21.1"
@@ -47,12 +47,13 @@ deepdiff = "^6.7.1"
optional = true
[tool.poetry.group.docs.dependencies]
-mkdocs = "^1.4.3"
-mkdocstrings = "^0.24.0"
-mkdocs-material = "^9.1.19"
-mkdocs-monorepo-plugin = "^1.0.5"
-mkdocstrings-python = "^1.2.1"
-coverage-badge = "^1.1.0"
+mkdocs = "^1.6.1"
+mkdocstrings = "^0.27.0"
+mkdocs-material = "^9.5.44"
+mkdocs-monorepo-plugin = "^1.1.0"
+mkdocstrings-python = "^1.12.2"
+coverage-badge = "^1.1.2"
+griffe-fastapi = "0.1.5"
[tool.pytest.ini_options]
markers = [
@@ -84,12 +85,14 @@ module = "deepdiff.*"
ignore_missing_imports = true
[tool.ruff]
+target-version = "py312"
+
+[tool.ruff.lint]
select = ["E", "W", "F", "C", "B", "D", "I", "N"]
fixable = ["I"]
ignore = ["D107", "D203", "D213", "D406", "D407", "E501", "N818", "B008"]
-target-version = "py310"
-[tool.ruff.pydocstyle]
+[tool.ruff.lint.pydocstyle]
convention = "google"
[build-system]
diff --git a/backend/src/kwai/__main__.py b/backend/src/kwai/__main__.py
new file mode 100644
index 000000000..041a4aa73
--- /dev/null
+++ b/backend/src/kwai/__main__.py
@@ -0,0 +1,19 @@
+"""Module for starting kwai.
+
+When this module is used, it will start the api and frontend application.
+If only the api is required, use kwai.api.
+"""
+
+import uvicorn
+
+from kwai.app import APP_NAME
+from kwai.core.args import create_args
+
+args = create_args(APP_NAME)
+uvicorn.run(
+ "kwai.app:create_app",
+ host=args.host,
+ port=args.port,
+ factory=True,
+ reload=args.reload,
+)
diff --git a/backend/src/kwai/api/__main__.py b/backend/src/kwai/api/__main__.py
index 38d3d7ca5..4141c5e99 100644
--- a/backend/src/kwai/api/__main__.py
+++ b/backend/src/kwai/api/__main__.py
@@ -1,29 +1,17 @@
-"""Module for starting the api server."""
-import argparse
-
-import uvicorn
+"""Module for starting the api server.
+This will only start the api server. Use this when the frontend is not served
+by FastAPI or if the api server is running on another server.
+"""
-def create_args():
- """Parse and create cli arguments."""
- parser = argparse.ArgumentParser(description="kwai backend")
- parser.add_argument(
- "--reload",
- action=argparse.BooleanOptionalAction,
- help="Watch for code changes or not",
- )
- parser.add_argument(
- "--host", type=str, default="0.0.0.0", help="The host of the api server."
- )
- parser.add_argument(
- "--port", type=int, default=8000, help="The port of the api server."
- )
- return parser.parse_args()
+import uvicorn
+from kwai.api.app import APP_NAME
+from kwai.core.args import create_args
-args = create_args()
+args = create_args(APP_NAME)
uvicorn.run(
- "kwai.api.app:create_app",
+ "kwai.api.app.create_api",
host=args.host,
port=args.port,
factory=True,
diff --git a/backend/src/kwai/api/app.py b/backend/src/kwai/api/app.py
index 9871545ef..cc1dcb01c 100644
--- a/backend/src/kwai/api/app.py
+++ b/backend/src/kwai/api/app.py
@@ -1,4 +1,5 @@
"""Module that implements a factory method for a FastAPI application."""
+
import os
import sys
import uuid
@@ -14,16 +15,19 @@
from kwai.api.v1.news.api import api_router as news_api_router
from kwai.api.v1.pages.api import api_router as pages_api_router
from kwai.api.v1.portal.api import api_router as portal_api_router
+from kwai.api.v1.teams.api import router as teams_api_router
from kwai.api.v1.trainings.api import api_router as training_api_router
from kwai.core.settings import LoggerSettings, Settings, get_settings
+APP_NAME = "kwai API"
+
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Log the start/stop of the application."""
- logger.info("kwai is starting")
+ logger.info(f"{APP_NAME} is starting")
yield
- logger.warning("kwai has ended!")
+ logger.warning(f"{APP_NAME} has ended!")
def configure_logger(settings: LoggerSettings):
@@ -57,13 +61,13 @@ def log_format(record):
)
-def create_app(settings: Settings | None = None) -> FastAPI:
+def create_api(settings: Settings | None = None) -> FastAPI:
"""Create the FastAPI application.
Args:
settings: Settings to use in this application.
"""
- app = FastAPI(title="kwai", lifespan=lifespan, separate_input_output_schemas=False)
+ app = FastAPI(lifespan=lifespan, separate_input_output_schemas=False)
if settings is None:
settings = get_settings()
@@ -110,11 +114,12 @@ async def log(request: Request, call_next):
if settings.logger:
configure_logger(settings.logger)
- app.include_router(auth_api_router, prefix="/api/v1")
- app.include_router(portal_api_router, prefix="/api/v1")
- app.include_router(pages_api_router, prefix="/api/v1")
- app.include_router(news_api_router, prefix="/api/v1")
- app.include_router(training_api_router, prefix="/api/v1")
- app.include_router(club_api_router, prefix="/api/v1")
+ app.include_router(auth_api_router, prefix="/v1")
+ app.include_router(portal_api_router, prefix="/v1")
+ app.include_router(pages_api_router, prefix="/v1")
+ app.include_router(news_api_router, prefix="/v1")
+ app.include_router(teams_api_router, prefix="/v1")
+ app.include_router(training_api_router, prefix="/v1")
+ app.include_router(club_api_router, prefix="/v1")
return app
diff --git a/backend/src/kwai/api/dependencies.py b/backend/src/kwai/api/dependencies.py
index 56e523dde..e16f761f5 100644
--- a/backend/src/kwai/api/dependencies.py
+++ b/backend/src/kwai/api/dependencies.py
@@ -1,9 +1,11 @@
"""Module that integrates the dependencies in FastAPI."""
+
from typing import AsyncGenerator
import jwt
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
+from fastapi.templating import Jinja2Templates
from jwt import ExpiredSignatureError
from redis.asyncio import Redis
@@ -34,6 +36,13 @@ async def create_database(
await database.close()
+async def create_templates(settings=Depends(get_settings)) -> Jinja2Templates:
+ """Create the template engine dependency."""
+ templates = Jinja2Templates(directory=settings.template.path)
+ templates.env.add_extension("jinja2.ext.do")
+ return templates
+
+
async def get_current_user(
settings=Depends(get_settings),
db=Depends(create_database),
diff --git a/backend/src/kwai/api/v1/auth/api.py b/backend/src/kwai/api/v1/auth/api.py
index 80301154c..9961336f4 100644
--- a/backend/src/kwai/api/v1/auth/api.py
+++ b/backend/src/kwai/api/v1/auth/api.py
@@ -1,4 +1,5 @@
"""Module that defines the auth apis."""
+
from fastapi import APIRouter
from kwai.api.v1.auth.endpoints import login, user, user_invitations
diff --git a/backend/src/kwai/api/v1/auth/endpoints/login.py b/backend/src/kwai/api/v1/auth/endpoints/login.py
index 9d92eefdd..dd2b74e7e 100644
--- a/backend/src/kwai/api/v1/auth/endpoints/login.py
+++ b/backend/src/kwai/api/v1/auth/endpoints/login.py
@@ -1,7 +1,9 @@
"""Module that implements all APIs for login."""
+from typing import Annotated
+
import jwt
-from fastapi import APIRouter, Depends, Form, HTTPException, Response, status
+from fastapi import APIRouter, Depends, Form, HTTPException, status
from fastapi.security import OAuth2PasswordRequestForm
from jwt import ExpiredSignatureError
from loguru import logger
@@ -71,23 +73,25 @@ class TokenSchema(BaseModel):
@router.post(
"/login",
summary="Create access and refresh token for a user.",
+ responses={
+ 200: {"description": "The user is logged in successfully."},
+ 401: {
+ "description": "The email is invalid, authentication failed or user is unknown."
+ },
+ },
)
async def login(
- settings: Settings = Depends(get_settings),
- db: Database = Depends(create_database),
- form_data: OAuth2PasswordRequestForm = Depends(),
+ settings: Annotated[Settings, Depends(get_settings)],
+ db: Annotated[Database, Depends(create_database)],
+ form_data: Annotated[OAuth2PasswordRequestForm, Depends()],
) -> TokenSchema:
"""Login a user.
- The response is a TokenSchema.
-
- Note:
- This request expects a form (application/x-www-form-urlencoded).
+ This request expects a form (application/x-www-form-urlencoded). The form
+ must contain a `username` and `password` field. The username is
+ the email address of the user.
- Args:
- settings: Settings dependency
- db: Database dependency
- form_data: Form data that contains the username and password
+ The response is a [TokenSchema][kwai.api.v1.auth.endpoints.login.TokenSchema].
"""
command = AuthenticateUserCommand(
username=form_data.username,
@@ -118,27 +122,27 @@ async def login(
return _encode_token(refresh_token, settings.security)
-@router.post("/logout", summary="Logout the current user")
+@router.post(
+ "/logout",
+ summary="Logout the current user",
+ responses={
+ 200: {"description": "The user is logged out successfully."},
+ 404: {"description": "The token is not found."},
+ },
+)
async def logout(
- settings=Depends(get_settings),
- db=Depends(create_database),
- user: UserEntity = Depends(get_current_user),
- refresh_token: str = Form(),
+ settings: Annotated[Settings, Depends(get_settings)],
+ db: Annotated[Database, Depends(create_database)],
+ user: Annotated[UserEntity, Depends(get_current_user)], # noqa
+ refresh_token: Annotated[str, Form()],
) -> None:
"""Log out the current user.
A user is logged out by revoking the refresh token. The associated access token
will also be revoked.
- Args:
- settings: Settings dependency
- db: Database dependency
- user: The currently logged-in user
- refresh_token: The active refresh token of the user
-
- Returns:
- Http code 200 on success, 401 when the user is not logged in,
- 404 when the refresh token is not found.
+ This request expects a form (application/x-www-form-urlencoded). The form
+ must contain a **refresh_token** field.
"""
decoded_refresh_token = jwt.decode(
refresh_token,
@@ -160,21 +164,24 @@ async def logout(
@router.post(
"/access_token",
summary="Renew an access token using a refresh token.",
+ responses={
+ 200: {"description": "The access token is renewed."},
+ 401: {"description": "The refresh token is expired."},
+ },
)
async def renew_access_token(
- settings=Depends(get_settings),
- db=Depends(create_database),
- refresh_token: str = Form(),
+ settings: Annotated[Settings, Depends(get_settings)],
+ db: Annotated[Database, Depends(create_database)],
+ refresh_token: Annotated[str, Form()],
) -> TokenSchema:
"""Refresh the access token.
- Args:
- settings(Settings): Settings dependency
- db(Database): Database dependency
- refresh_token(str): The active refresh token of the user
+ The response is a [TokenSchema][kwai.api.v1.auth.endpoints.login.TokenSchema].
- Returns:
- TokenSchema: On success a new TokenSchema is returned.
+ When the refresh token is expired, the user needs to log in again.
+
+ This request expects a form (application/x-www-form-urlencoded). The form
+ must contain a **refresh_token** field.
"""
try:
decoded_refresh_token = jwt.decode(
@@ -208,25 +215,24 @@ async def renew_access_token(
@router.post(
"/recover",
summary="Initiate a password reset flow",
- status_code=status.HTTP_200_OK,
- response_class=Response,
+ responses={
+ 200: {"description": "Ok."},
+ },
)
async def recover_user(
- email: str = Form(),
- db=Depends(create_database),
- publisher: Publisher = Depends(get_publisher),
+ db: Annotated[Database, Depends(create_database)],
+ publisher: Annotated[Publisher, Depends(get_publisher)],
+ email: Annotated[str, Form()],
) -> None:
"""Start a recover password flow for the given email address.
A mail with a unique id will be sent using the message bus.
- Note:
- To avoid leaking information, this api will always respond with 200
+ This request expects a form (application/x-www-form-urlencoded). The form
+ must contain an **email** field.
- Args:
- email(str): The email of the user that wants to reset the password.
- db(Database): Database dependency
- publisher(Publisher): A publisher to publish the event
+ !!! Note
+ To avoid leaking information, this api will always respond with 200
"""
command = RecoverUserCommand(email=email)
try:
@@ -242,19 +248,26 @@ async def recover_user(
@router.post(
"/reset",
summary="Reset the password of a user.",
- status_code=status.HTTP_200_OK,
+ responses={ # noqa B006
+ 200: {"description": "The password is reset successfully."},
+ 403: {"description": "This request is forbidden."},
+ 404: {"description": "The uniqued id of the recovery could not be found."},
+ 422: {"description": "The user could not be found."},
+ },
)
-async def reset_password(uuid=Form(), password=Form(), db=Depends(create_database)):
+async def reset_password(
+ uuid: Annotated[str, Form()],
+ password: Annotated[str, Form()],
+ db: Annotated[Database, Depends(create_database)],
+):
"""Reset the password of the user.
- Args:
- uuid(str): The unique id of the password recovery.
- password(str): The new password
- db(Database): Database dependency
+ Http code 200 on success, 404 when the unique is invalid, 422 when the
+ request can't be processed, 403 when the request is forbidden.
- Returns:
- Http code 200 on success, 404 when the unique is invalid, 422 when the
- request can't be processed, 403 when the request is forbidden.
+ This request expects a form (application/x-www-form-urlencoded). The form
+ must contain an **uuid** and **password** field. The unique id must be still valid
+ and is retrieved by [/api/v1/auth/recover][post_/recover].
"""
command = ResetPasswordCommand(uuid=uuid, password=password)
try:
@@ -286,7 +299,7 @@ def _encode_token(
access_token=jwt.encode(
{
"iat": refresh_token.access_token.traceable_time.created_at.timestamp,
- "exp": refresh_token.access_token.expiration,
+ "exp": refresh_token.access_token.expiration.timestamp,
"jti": str(refresh_token.access_token.identifier),
"sub": str(refresh_token.access_token.user_account.user.uuid),
"scope": [],
@@ -297,11 +310,11 @@ def _encode_token(
refresh_token=jwt.encode(
{
"iat": refresh_token.traceable_time.created_at.timestamp,
- "exp": refresh_token.expiration,
+ "exp": refresh_token.expiration.timestamp,
"jti": str(refresh_token.identifier),
},
settings.jwt_refresh_secret,
settings.jwt_algorithm,
),
- expiration=refresh_token.access_token.expiration.isoformat(" ", "seconds"),
+ expiration=str(refresh_token.access_token.expiration),
)
diff --git a/backend/src/kwai/api/v1/auth/endpoints/user.py b/backend/src/kwai/api/v1/auth/endpoints/user.py
index 3ab352268..218486abc 100644
--- a/backend/src/kwai/api/v1/auth/endpoints/user.py
+++ b/backend/src/kwai/api/v1/auth/endpoints/user.py
@@ -8,7 +8,14 @@
router = APIRouter()
-@router.get("/user")
+@router.get(
+ "/user",
+ summary="Get the id of the current user",
+ responses={
+ 200: {"description": "Ok."},
+ 401: {"description": "Not authorized"},
+ },
+)
def get(user: UserEntity = Depends(get_current_user)):
"""Get the current user."""
return {"id": str(user.uuid)}
diff --git a/backend/src/kwai/api/v1/auth/endpoints/user_invitations.py b/backend/src/kwai/api/v1/auth/endpoints/user_invitations.py
index a9f8cb0ec..86de5b986 100644
--- a/backend/src/kwai/api/v1/auth/endpoints/user_invitations.py
+++ b/backend/src/kwai/api/v1/auth/endpoints/user_invitations.py
@@ -1,6 +1,6 @@
"""Module that implements invitations endpoints."""
-from fastapi import APIRouter, Depends, HTTPException, Response, status
+from fastapi import APIRouter, Depends, HTTPException, status
from loguru import logger
from kwai.api.dependencies import create_database, get_current_user, get_publisher
@@ -30,14 +30,27 @@
router = APIRouter()
-@router.post("/invitations")
+@router.post(
+ "/invitations",
+ summary="Create a user invitation",
+ status_code=status.HTTP_201_CREATED,
+ responses={
+ 201: {"description": "User invitation is created"},
+ 401: {"description": "Not authorized."},
+ 422: {"description": "User invitation could not be created"},
+ },
+)
async def create_user_invitation(
user_invitation_document: UserInvitationDocument,
db=Depends(create_database),
user: UserEntity = Depends(get_current_user),
publisher=Depends(get_publisher),
) -> UserInvitationDocument:
- """Create a user invitation."""
+ """Create a user invitation.
+
+ A wrong email address or a still pending user invitation will result in a 422
+ status code.
+ """
command = InviteUserCommand(
first_name=user_invitation_document.resource.attributes.first_name,
last_name=user_invitation_document.resource.attributes.last_name,
@@ -67,13 +80,18 @@ async def create_user_invitation(
"/invitations/{uuid}",
summary="Delete a user invitation",
status_code=status.HTTP_200_OK,
- response_class=Response,
+ responses={
+ 200: {"description": "User invitation is deleted."},
+ 401: {"description": "Not authorized."},
+ 404: {"description": "User invitation does not exist."},
+ 422: {"description": "Invalid unique id passed for the user invitation."},
+ },
)
async def delete_user_invitation(
uuid: str,
db=Depends(create_database),
user: UserEntity = Depends(get_current_user),
-):
+) -> None:
"""Delete the user invitation with the given unique id."""
command = DeleteUserInvitationCommand(uuid=uuid)
try:
@@ -88,13 +106,23 @@ async def delete_user_invitation(
) from ex
-@router.get("/invitations")
+@router.get(
+ "/invitations",
+ summary="Get a list of user invitations",
+ responses={
+ 200: {"description": "Ok."},
+ 401: {"description": "Not authorized."},
+ },
+)
async def get_user_invitations(
pagination: PaginationModel = Depends(PaginationModel),
db=Depends(create_database),
user: UserEntity = Depends(get_current_user),
) -> UserInvitationDocument:
- """Get all user invitations."""
+ """Get all user invitations.
+
+ Use the page[offset] and page[limit] query parameters to get a paginated result.
+ """
command = GetInvitationsCommand(offset=pagination.offset, limit=pagination.limit)
count, invitation_iterator = await GetInvitations(
UserInvitationDbRepository(db)
@@ -111,7 +139,11 @@ async def get_user_invitations(
return result
-@router.get("/invitations/{uuid}")
+@router.get(
+ "/invitations/{uuid}",
+ summary="Get a user invitation",
+ responses={200: {"description": "Ok."}, 401: {"description": "Not authorized."}},
+)
async def get_user_invitation(
uuid: str,
db=Depends(create_database),
diff --git a/backend/src/kwai/api/v1/club/endpoints/members.py b/backend/src/kwai/api/v1/club/endpoints/members.py
index 3c29fa974..f573eea36 100644
--- a/backend/src/kwai/api/v1/club/endpoints/members.py
+++ b/backend/src/kwai/api/v1/club/endpoints/members.py
@@ -4,13 +4,14 @@
from pydantic import BaseModel, Field
from kwai.api.dependencies import create_database, get_current_user
+from kwai.api.v1.club.presenters import JsonApiMemberPresenter, JsonApiMembersPresenter
from kwai.api.v1.club.schemas.member import MemberDocument
-from kwai.core.json_api import Meta, PaginationModel
+from kwai.core.json_api import PaginationModel
from kwai.modules.club.get_member import GetMember, GetMemberCommand
from kwai.modules.club.get_members import GetMembers, GetMembersCommand
-from kwai.modules.club.members.member_db_repository import MemberDbRepository
-from kwai.modules.club.members.member_repository import MemberNotFoundException
-from tests.core.domain.test_entity import UserEntity
+from kwai.modules.club.repositories.member_db_repository import MemberDbRepository
+from kwai.modules.club.repositories.member_repository import MemberNotFoundException
+from kwai.modules.identity.users.user import UserEntity
router = APIRouter()
@@ -38,15 +39,10 @@ async def get_members(
license_end_year=members_filter.license_end_year,
license_end_month=members_filter.license_end_month,
)
- count, member_iterator = await GetMembers(MemberDbRepository(db)).execute(command)
- result = MemberDocument(
- meta=Meta(count=count, offset=command.offset, limit=command.limit), data=[]
- )
- async for member in member_iterator:
- member_document = MemberDocument.create(member)
- result.merge(member_document)
+ presenter = JsonApiMembersPresenter()
+ await GetMembers(MemberDbRepository(db), presenter).execute(command)
- return result
+ return presenter.get_document()
@router.get("/members/{uuid}")
@@ -58,11 +54,12 @@ async def get_member(
"""Get a member with the given unique id."""
command = GetMemberCommand(uuid=uuid)
+ presenter = JsonApiMemberPresenter()
try:
- member = await GetMember(MemberDbRepository(db)).execute(command)
+ await GetMember(MemberDbRepository(db), presenter).execute(command)
except MemberNotFoundException as ex:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail=str(ex)
) from ex
- return MemberDocument.create(member)
+ return presenter.get_document()
diff --git a/backend/src/kwai/api/v1/club/endpoints/upload_members.py b/backend/src/kwai/api/v1/club/endpoints/upload_members.py
index 3c8a50bad..0fbe69a7e 100644
--- a/backend/src/kwai/api/v1/club/endpoints/upload_members.py
+++ b/backend/src/kwai/api/v1/club/endpoints/upload_members.py
@@ -3,26 +3,26 @@
from pathlib import Path
from typing import Annotated
-from fastapi import APIRouter, Depends, File, HTTPException, UploadFile, status
+from fastapi import APIRouter, Depends, File, HTTPException, Query, UploadFile, status
from pydantic import BaseModel, Field
from kwai.api.dependencies import create_database, get_current_user
+from kwai.api.v1.club.presenters import JsonApiUploadMemberPresenter
from kwai.api.v1.club.schemas.member import MemberDocument
from kwai.core.db.database import Database
from kwai.core.db.uow import UnitOfWork
from kwai.core.functions import generate_filenames
-from kwai.core.json_api import Meta
from kwai.core.settings import Settings, get_settings
from kwai.modules.club.import_members import (
- FailureResult,
ImportMembers,
ImportMembersCommand,
- OkResult,
)
-from kwai.modules.club.members.country_db_repository import CountryDbRepository
-from kwai.modules.club.members.file_upload_db_repository import FileUploadDbRepository
-from kwai.modules.club.members.flemish_member_importer import FlemishMemberImporter
-from kwai.modules.club.members.member_db_repository import MemberDbRepository
+from kwai.modules.club.repositories.country_db_repository import CountryDbRepository
+from kwai.modules.club.repositories.file_upload_db_repository import (
+ FileUploadDbRepository,
+)
+from kwai.modules.club.repositories.flemish_member_importer import FlemishMemberImporter
+from kwai.modules.club.repositories.member_db_repository import MemberDbRepository
from kwai.modules.identity.users.user import UserEntity
router = APIRouter()
@@ -54,6 +54,7 @@ async def upload(
settings: Annotated[Settings, Depends(get_settings)],
database: Annotated[Database, Depends(create_database)],
user: Annotated[UserEntity, Depends(get_current_user)],
+ preview: Annotated[bool, Query(description="Whether or not to preview")] = True,
) -> MemberDocument:
"""Upload a members csv file."""
if member_file.filename is None:
@@ -70,8 +71,9 @@ async def upload(
detail=f"Failed to upload members file: {ex}",
) from ex
+ presenter = JsonApiUploadMemberPresenter()
async with UnitOfWork(database):
- imported_member_generator = ImportMembers(
+ await ImportMembers(
FlemishMemberImporter(
str(member_filename),
user.create_owner(),
@@ -79,43 +81,9 @@ async def upload(
),
FileUploadDbRepository(database),
MemberDbRepository(database),
- ).execute(ImportMembersCommand())
-
- meta = Meta(count=0, offset=0, limit=0, errors=[])
- response = MemberDocument(meta=meta, data=[])
- upload_entity = None
- async for result in imported_member_generator:
- if upload_entity is None:
- upload_entity = result.file_upload
-
- match result:
- case OkResult():
- member_document = MemberDocument.create(result.member)
- member_document.resource.meta.row = result.row
- member_document.resource.meta.new = not result.member.has_id()
- # A new member has related resources that are not saved yet,
- # so give them temporarily the same id as the member.
- if member_document.resource.meta.new:
- member_document.resource.relationships.person.data.id = (
- member_document.resource.id
- )
- for included in member_document.included:
- if included.type == "persons":
- included.relationships.contact.data.id = (
- member_document.resource.id
- )
- if included.id == "0":
- included.id = member_document.resource.id
- meta.count += 1
- response.merge(member_document)
- case FailureResult():
- meta.errors.append({"row": result.row, "message": result.to_message()})
- case _:
- raise HTTPException(
- status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
- detail="Unexpected result returned",
- )
- return response
+ presenter,
+ ).execute(ImportMembersCommand(preview=preview))
+ return presenter.get_document()
async def upload_file(uploaded_file, path: str):
diff --git a/backend/src/kwai/api/v1/club/presenters.py b/backend/src/kwai/api/v1/club/presenters.py
new file mode 100644
index 000000000..ba0025d10
--- /dev/null
+++ b/backend/src/kwai/api/v1/club/presenters.py
@@ -0,0 +1,74 @@
+"""Module that defines presenters for the club api."""
+
+from kwai.api.v1.club.schemas.member import MemberDocument
+from kwai.core.domain.presenter import AsyncPresenter, IterableResult, Presenter
+from kwai.core.json_api import Error, ErrorSource, JsonApiPresenter, Meta
+from kwai.modules.club.domain.member import MemberEntity
+from kwai.modules.club.import_members import (
+ FailureMemberImportResult,
+ MemberImportResult,
+ OkMemberImportResult,
+)
+
+
+class JsonApiMemberPresenter(JsonApiPresenter[MemberDocument], Presenter[MemberEntity]):
+ """A presenter that transform a member entity into a JSON:API document."""
+
+ def present(self, member: MemberEntity) -> None:
+ self._document = MemberDocument.create(member)
+
+
+class JsonApiMembersPresenter(
+ JsonApiPresenter[MemberDocument], AsyncPresenter[IterableResult[MemberEntity]]
+):
+ """A presenter that transform an iterator for members into a JSON:API document."""
+
+ async def present(self, result: IterableResult[MemberEntity]) -> None:
+ self._document = MemberDocument(
+ meta=Meta(count=result.count, offset=result.offset, limit=result.limit),
+ data=[],
+ )
+ async for member in result.iterator:
+ member_document = MemberDocument.create(member)
+ self._document.merge(member_document)
+
+
+class JsonApiUploadMemberPresenter(
+ JsonApiPresenter[MemberDocument], Presenter[MemberImportResult]
+):
+ """A presenter that transform a file upload of a member into a JSON:API document."""
+
+ def __init__(self) -> None:
+ super().__init__()
+ self._document = MemberDocument(
+ meta=Meta(count=0, offset=0, limit=0), data=[], errors=[]
+ )
+
+ def present(self, result: MemberImportResult) -> None:
+ match result:
+ case OkMemberImportResult():
+ member_document = MemberDocument.create(result.member)
+ member_document.resource.meta.row = result.row
+ member_document.resource.meta.new = not result.member.has_id()
+ # A new member has related resources that are not saved yet,
+ # so give them temporarily the same id as the member.
+ if member_document.resource.meta.new:
+ member_document.resource.relationships.person.data.id = (
+ member_document.resource.id
+ )
+ for included in member_document.included:
+ if included.type == "persons":
+ included.relationships.contact.data.id = (
+ member_document.resource.id
+ )
+ if included.id == "0":
+ included.id = member_document.resource.id
+ self._document.meta.count += 1
+ self._document.merge(member_document)
+ case FailureMemberImportResult():
+ self._document.errors.append(
+ Error(
+ source=ErrorSource(pointer=str(result.row)),
+ detail=result.to_message(),
+ )
+ )
diff --git a/backend/src/kwai/api/v1/club/schemas/contact.py b/backend/src/kwai/api/v1/club/schemas/contact.py
index 2092707cb..60cee1d94 100644
--- a/backend/src/kwai/api/v1/club/schemas/contact.py
+++ b/backend/src/kwai/api/v1/club/schemas/contact.py
@@ -4,16 +4,13 @@
from pydantic import BaseModel, Field
-from kwai.api.v1.club.schemas.country import (
- CountryDocument,
- CountryResource,
-)
from kwai.api.v1.club.schemas.resources import (
ContactResourceIdentifier,
- CountryResourceIdentifier,
)
+from kwai.api.v1.resources import CountryResourceIdentifier
+from kwai.api.v1.schemas import CountryDocument, CountryResource
from kwai.core.json_api import Document, Relationship, ResourceData, ResourceMeta
-from kwai.modules.club.members.contact import ContactEntity
+from kwai.modules.club.domain.contact import ContactEntity
class ContactAttributes(BaseModel):
diff --git a/backend/src/kwai/api/v1/club/schemas/member.py b/backend/src/kwai/api/v1/club/schemas/member.py
index 28f681225..d9cf468fb 100644
--- a/backend/src/kwai/api/v1/club/schemas/member.py
+++ b/backend/src/kwai/api/v1/club/schemas/member.py
@@ -5,7 +5,6 @@
from pydantic import BaseModel, Field
from kwai.api.v1.club.schemas.contact import ContactResource
-from kwai.api.v1.club.schemas.country import CountryResource
from kwai.api.v1.club.schemas.person import (
PersonDocument,
PersonResource,
@@ -14,8 +13,9 @@
MemberResourceIdentifier,
PersonResourceIdentifier,
)
+from kwai.api.v1.schemas import CountryResource
from kwai.core.json_api import Document, Relationship, ResourceData, ResourceMeta
-from kwai.modules.club.members.member import MemberEntity
+from kwai.modules.club.domain.member import MemberEntity
class MemberAttributes(BaseModel):
diff --git a/backend/src/kwai/api/v1/club/schemas/person.py b/backend/src/kwai/api/v1/club/schemas/person.py
index aa15daf76..dc9acaa32 100644
--- a/backend/src/kwai/api/v1/club/schemas/person.py
+++ b/backend/src/kwai/api/v1/club/schemas/person.py
@@ -5,14 +5,14 @@
from pydantic import BaseModel, Field
from kwai.api.v1.club.schemas.contact import ContactDocument, ContactResource
-from kwai.api.v1.club.schemas.country import CountryDocument, CountryResource
from kwai.api.v1.club.schemas.resources import (
ContactResourceIdentifier,
- CountryResourceIdentifier,
PersonResourceIdentifier,
)
+from kwai.api.v1.resources import CountryResourceIdentifier
+from kwai.api.v1.schemas import CountryDocument, CountryResource
from kwai.core.json_api import Document, Relationship, ResourceData, ResourceMeta
-from kwai.modules.club.members.person import PersonEntity
+from kwai.modules.club.domain.person import PersonEntity
class PersonAttributes(BaseModel):
diff --git a/backend/src/kwai/api/v1/club/schemas/resources.py b/backend/src/kwai/api/v1/club/schemas/resources.py
index c179e8df7..2f3464c24 100644
--- a/backend/src/kwai/api/v1/club/schemas/resources.py
+++ b/backend/src/kwai/api/v1/club/schemas/resources.py
@@ -23,7 +23,7 @@ class ContactResourceIdentifier(ResourceIdentifier):
type: Literal["contacts"] = "contacts"
-class CountryResourceIdentifier(ResourceIdentifier):
- """A JSON:API resource identifier for a country."""
+class UploadResourceIdentifier(ResourceIdentifier):
+ """A JSON:API resource identifier for a upload."""
- type: Literal["countries"] = "countries"
+ type: Literal["uploads"] = "uploads"
diff --git a/backend/src/kwai/api/v1/club/schemas/upload.py b/backend/src/kwai/api/v1/club/schemas/upload.py
new file mode 100644
index 000000000..3504fd8da
--- /dev/null
+++ b/backend/src/kwai/api/v1/club/schemas/upload.py
@@ -0,0 +1,46 @@
+"""Module for defining the JSON:API resource for an upload."""
+
+from types import NoneType
+from typing import Self
+
+from pydantic import BaseModel
+
+from kwai.api.v1.club.schemas.resources import (
+ UploadResourceIdentifier,
+)
+from kwai.core.json_api import Document, ResourceData, ResourceMeta
+from kwai.modules.club.domain.file_upload import FileUploadEntity
+
+
+class UploadAttributes(BaseModel):
+ """Attributes for the upload JSON:API resource."""
+
+ filename: str
+ remark: str
+ preview: bool
+
+
+class UploadResource(
+ UploadResourceIdentifier, ResourceData[UploadAttributes, NoneType]
+):
+ """A JSON:API resource for an upload."""
+
+
+class UploadDocument(Document[UploadResource, NoneType]):
+ """A JSON:API document for an upload."""
+
+ @classmethod
+ def create(cls, upload: FileUploadEntity) -> Self:
+ """Create a document for an upload."""
+ upload_resource = UploadResource(
+ id=str(upload.uuid),
+ attributes=UploadAttributes(
+ filename=upload.filename, remark=upload.remark, preview=upload.preview
+ ),
+ meta=ResourceMeta(
+ created_at=str(upload.traceable_time.created_at),
+ updated_at=str(upload.traceable_time.updated_at),
+ ),
+ )
+
+ return cls(data=upload_resource)
diff --git a/backend/src/kwai/api/v1/portal/endpoints/applications.py b/backend/src/kwai/api/v1/portal/endpoints/applications.py
index 15effeeb2..882babc79 100644
--- a/backend/src/kwai/api/v1/portal/endpoints/applications.py
+++ b/backend/src/kwai/api/v1/portal/endpoints/applications.py
@@ -1,9 +1,11 @@
"""Module that implements applications endpoints."""
+
from fastapi import APIRouter, Depends, HTTPException, status
from kwai.api.dependencies import create_database, get_current_user
from kwai.api.schemas.application import ApplicationDocument
from kwai.core.json_api import Meta
+from kwai.modules.identity.users.user import UserEntity
from kwai.modules.portal.applications.application_db_repository import (
ApplicationDbRepository,
)
@@ -16,7 +18,6 @@
UpdateApplication,
UpdateApplicationCommand,
)
-from tests.core.domain.test_entity import UserEntity
router = APIRouter()
diff --git a/backend/src/kwai/api/v1/resources.py b/backend/src/kwai/api/v1/resources.py
new file mode 100644
index 000000000..9ecb7e4ff
--- /dev/null
+++ b/backend/src/kwai/api/v1/resources.py
@@ -0,0 +1,11 @@
+"""Module that defines common JSON:API resource identifiers."""
+
+from typing import Literal
+
+from kwai.core.json_api import ResourceIdentifier
+
+
+class CountryResourceIdentifier(ResourceIdentifier):
+ """A JSON:API resource identifier for a country."""
+
+ type: Literal["countries"] = "countries"
diff --git a/backend/src/kwai/api/v1/club/schemas/country.py b/backend/src/kwai/api/v1/schemas.py
similarity index 82%
rename from backend/src/kwai/api/v1/club/schemas/country.py
rename to backend/src/kwai/api/v1/schemas.py
index 56ec07e1a..5d7ce22be 100644
--- a/backend/src/kwai/api/v1/club/schemas/country.py
+++ b/backend/src/kwai/api/v1/schemas.py
@@ -1,12 +1,12 @@
-"""Module for defining the JSON:API resource for a country."""
+"""Module for defining common JSON:API schemas."""
from typing import Self
from pydantic import BaseModel
-from kwai.api.v1.club.schemas.resources import CountryResourceIdentifier
+from kwai.api.v1.resources import CountryResourceIdentifier
from kwai.core.json_api import Document, ResourceData
-from kwai.modules.club.members.country import CountryEntity
+from kwai.modules.club.domain.country import CountryEntity
class CountryAttributes(BaseModel):
diff --git a/backend/src/kwai/api/v1/teams/__init__.py b/backend/src/kwai/api/v1/teams/__init__.py
new file mode 100644
index 000000000..52f3e4a9b
--- /dev/null
+++ b/backend/src/kwai/api/v1/teams/__init__.py
@@ -0,0 +1 @@
+"""Package for the teams API."""
diff --git a/backend/src/kwai/api/v1/teams/api.py b/backend/src/kwai/api/v1/teams/api.py
new file mode 100644
index 000000000..a4d5fae80
--- /dev/null
+++ b/backend/src/kwai/api/v1/teams/api.py
@@ -0,0 +1,221 @@
+"""Module that defines the teams API."""
+
+from typing import Annotated
+
+from fastapi import APIRouter, Depends, HTTPException, Query, status
+from pydantic import BaseModel, Field
+
+from kwai.api.dependencies import create_database, get_current_user
+from kwai.api.v1.teams.presenters import (
+ JsonApiMembersPresenter,
+ JsonApiTeamMemberPresenter,
+ JsonApiTeamMembersPresenter,
+ JsonApiTeamPresenter,
+ JsonApiTeamsPresenter,
+)
+from kwai.api.v1.teams.schemas import TeamDocument, TeamMemberDocument
+from kwai.core.db.database import Database
+from kwai.core.db.uow import UnitOfWork
+from kwai.core.json_api import PaginationModel
+from kwai.modules.identity.users.user import UserEntity
+from kwai.modules.teams.create_team import CreateTeam, CreateTeamCommand
+from kwai.modules.teams.create_team_member import (
+ CreateTeamMember,
+ CreateTeamMemberCommand,
+)
+from kwai.modules.teams.delete_team import DeleteTeam, DeleteTeamCommand
+from kwai.modules.teams.domain.team import TeamMemberAlreadyExistException
+from kwai.modules.teams.get_members import GetMembers, GetMembersCommand
+from kwai.modules.teams.get_team import GetTeam, GetTeamCommand
+from kwai.modules.teams.get_teams import GetTeams, GetTeamsCommand
+from kwai.modules.teams.repositories.member_db_repository import MemberDbRepository
+from kwai.modules.teams.repositories.member_repository import MemberNotFoundException
+from kwai.modules.teams.repositories.team_db_repository import TeamDbRepository
+from kwai.modules.teams.update_team import UpdateTeam, UpdateTeamCommand
+from kwai.modules.training.teams.team_repository import TeamNotFoundException
+
+router = APIRouter(tags=["teams"])
+
+
+@router.get("/teams")
+async def get_teams(
+ database: Annotated[Database, Depends(create_database)],
+) -> TeamDocument:
+ """Get all teams of the club."""
+ presenter = JsonApiTeamsPresenter()
+ command = GetTeamsCommand(offset=0, limit=0)
+ await GetTeams(TeamDbRepository(database), presenter).execute(command)
+ return presenter.get_document()
+
+
+class TeamMemberFilterModel(BaseModel):
+ """Define the JSON:API filter for team members."""
+
+ team: str | None = Field(Query(default=None, alias="filter[team]"))
+
+
+@router.get("/teams/members")
+async def get_members(
+ database: Annotated[Database, Depends(create_database)],
+ pagination: Annotated[PaginationModel, Depends(PaginationModel)],
+ team_filter: Annotated[TeamMemberFilterModel, Depends(TeamMemberFilterModel)],
+) -> TeamMemberDocument:
+ """Get all members that can be part of a team."""
+ presenter = JsonApiMembersPresenter()
+ if team_filter.team is not None:
+ if ":" in team_filter.team:
+ operand, team_id = team_filter.team.split(":")
+ if operand not in ("eq", "noteq"):
+ raise HTTPException(
+ status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
+ detail="Invalid operand",
+ )
+ if not team_id.isdigit():
+ raise HTTPException(
+ status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
+ detail="Invalid team id",
+ )
+
+ command = GetMembersCommand(
+ team_id=int(team_id),
+ in_team=operand == "eq",
+ offset=pagination.offset,
+ limit=pagination.limit,
+ )
+ else:
+ if team_filter.team.isdigit():
+ command = GetMembersCommand(
+ team_id=int(team_filter.team),
+ offset=pagination.offset,
+ limit=pagination.limit,
+ )
+ else:
+ raise HTTPException(
+ status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
+ detail="Invalid team id",
+ )
+ else:
+ command = GetMembersCommand(offset=pagination.offset, limit=pagination.limit)
+ await GetMembers(MemberDbRepository(database), presenter).execute(command)
+ return presenter.get_document()
+
+
+@router.get("/teams/{id}")
+async def get_team(
+ id: int,
+ database: Annotated[Database, Depends(create_database)],
+) -> TeamDocument:
+ """Get the team with the given id."""
+ presenter = JsonApiTeamPresenter()
+ command = GetTeamCommand(id=id)
+ await GetTeam(TeamDbRepository(database), presenter).execute(command)
+ return presenter.get_document()
+
+
+@router.post("/teams", status_code=status.HTTP_201_CREATED)
+async def create_team(
+ resource: TeamDocument,
+ database: Annotated[Database, Depends(create_database)],
+ user: Annotated[UserEntity, Depends(get_current_user)],
+) -> TeamDocument:
+ """Create a new team."""
+ command = CreateTeamCommand(
+ name=resource.data.attributes.name,
+ active=resource.data.attributes.active,
+ remark=resource.data.attributes.remark,
+ )
+ team_presenter = JsonApiTeamPresenter()
+ async with UnitOfWork(database):
+ await CreateTeam(TeamDbRepository(database), team_presenter).execute(command)
+ return team_presenter.get_document()
+
+
+@router.patch(
+ "/teams/{id}",
+ status_code=status.HTTP_200_OK,
+ responses={status.HTTP_404_NOT_FOUND: {"description": "Team not found"}},
+)
+async def update_team(
+ id: int,
+ resource: TeamDocument,
+ database: Annotated[Database, Depends(create_database)],
+ user: Annotated[UserEntity, Depends(get_current_user)],
+) -> TeamDocument:
+ """Update an existing team."""
+ command = UpdateTeamCommand(
+ id=id,
+ name=resource.data.attributes.name,
+ active=resource.data.attributes.active,
+ remark=resource.data.attributes.remark,
+ )
+ team_presenter = JsonApiTeamPresenter()
+ async with UnitOfWork(database):
+ await UpdateTeam(TeamDbRepository(database), team_presenter).execute(command)
+ return team_presenter.get_document()
+
+
+@router.delete(
+ "/teams/{id}",
+ status_code=status.HTTP_200_OK,
+ responses={status.HTTP_404_NOT_FOUND: {"description": "Team not found"}},
+)
+async def delete_team(
+ id: int,
+ database: Annotated[Database, Depends(create_database)],
+ user: Annotated[UserEntity, Depends(get_current_user)],
+):
+ """Delete the team with the given id."""
+ command = DeleteTeamCommand(id=id)
+
+ try:
+ async with UnitOfWork(database):
+ await DeleteTeam(TeamDbRepository(database)).execute(command)
+ except TeamNotFoundException as ex:
+ raise HTTPException(
+ status_code=status.HTTP_404_NOT_FOUND, detail=str(ex)
+ ) from ex
+
+
+@router.get("/teams/{id}/members")
+async def get_team_members(
+ id: int,
+ database: Annotated[Database, Depends(create_database)],
+) -> TeamMemberDocument:
+ """Get the members of the team with the given id."""
+ presenter = JsonApiTeamMembersPresenter()
+ command = GetTeamCommand(id=id)
+ await GetTeam(TeamDbRepository(database), presenter).execute(command)
+ return presenter.get_document()
+
+
+@router.post("/teams/{id}/members", status_code=status.HTTP_201_CREATED)
+async def create_team_member(
+ id: int,
+ resource: TeamMemberDocument,
+ database: Annotated[Database, Depends(create_database)],
+) -> TeamMemberDocument:
+ """Add a member to the team with the given id."""
+ presenter = JsonApiTeamMemberPresenter()
+ command = CreateTeamMemberCommand(
+ team_id=id,
+ member_id=resource.data.id,
+ active=resource.data.attributes.active,
+ )
+ try:
+ async with UnitOfWork(database):
+ await CreateTeamMember(
+ TeamDbRepository(database), MemberDbRepository(database), presenter
+ ).execute(command)
+ return presenter.get_document()
+ except TeamNotFoundException as ex:
+ raise HTTPException(
+ status_code=status.HTTP_404_NOT_FOUND, detail=str(ex)
+ ) from ex
+ except MemberNotFoundException as ex:
+ raise HTTPException(
+ status_code=status.HTTP_404_NOT_FOUND, detail=str(ex)
+ ) from ex
+ except TeamMemberAlreadyExistException as ex:
+ raise HTTPException(
+ status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(ex)
+ ) from ex
diff --git a/backend/src/kwai/api/v1/teams/presenters.py b/backend/src/kwai/api/v1/teams/presenters.py
new file mode 100644
index 000000000..f353b0946
--- /dev/null
+++ b/backend/src/kwai/api/v1/teams/presenters.py
@@ -0,0 +1,70 @@
+"""Module for defining presenters of the teams api."""
+
+from kwai.api.v1.teams.schemas import TeamDocument, TeamMemberDocument
+from kwai.core.domain.presenter import AsyncPresenter, IterableResult, Presenter
+from kwai.core.json_api import JsonApiPresenter, Meta
+from kwai.modules.teams.domain.team import TeamEntity
+from kwai.modules.teams.domain.team_member import MemberEntity, TeamMember
+
+
+class JsonApiTeamPresenter(JsonApiPresenter[TeamDocument], Presenter[TeamEntity]):
+ """A presenter that transform a team entity into a JSON:API document."""
+
+ def present(self, team: TeamEntity) -> None:
+ self._document = TeamDocument.create(team)
+
+
+class JsonApiTeamsPresenter(
+ JsonApiPresenter[TeamDocument], AsyncPresenter[IterableResult[TeamEntity]]
+):
+ """A presenter that transforms an iterator of teams into a JSON:API document."""
+
+ async def present(self, result: IterableResult[TeamEntity]) -> None:
+ self._document = TeamDocument(
+ meta=Meta(count=result.count, offset=result.offset, limit=result.limit),
+ data=[],
+ )
+ async for team in result.iterator:
+ team_document = TeamDocument.create(team)
+ self._document.merge(team_document)
+
+
+class JsonApiMembersPresenter(
+ JsonApiPresenter[TeamMemberDocument], AsyncPresenter[IterableResult[MemberEntity]]
+):
+ """A presenter that transforms an iterator of members into a TeamMember document."""
+
+ async def present(self, result: IterableResult[MemberEntity]) -> None:
+ self._document = TeamMemberDocument(
+ meta=Meta(count=result.count, offset=result.offset, limit=result.limit),
+ data=[],
+ )
+ async for member in result.iterator:
+ team_member_document = TeamMemberDocument.create(TeamMember(member=member))
+ self._document.merge(team_member_document)
+
+
+class JsonApiTeamMembersPresenter(
+ JsonApiPresenter[TeamMemberDocument], Presenter[TeamEntity]
+):
+ """A presenter that transforms team members into a JSON:API document."""
+
+ def present(self, team: TeamEntity) -> None:
+ self._document = TeamMemberDocument(
+ meta=Meta(count=len(team.members)),
+ data=[],
+ )
+ for member in team.members.values():
+ team_member_document = TeamMemberDocument.create(member, team)
+ self._document.merge(team_member_document)
+
+
+class JsonApiTeamMemberPresenter(
+ JsonApiPresenter[TeamMemberDocument], Presenter[tuple[TeamMember, TeamEntity]]
+):
+ """A presenter that transforms a team member into a JSON:API document."""
+
+ def present(self, use_case_result: tuple[TeamMember, TeamEntity]) -> None:
+ self._document = TeamMemberDocument.create(
+ use_case_result[0], use_case_result[1]
+ )
diff --git a/backend/src/kwai/api/v1/teams/resources.py b/backend/src/kwai/api/v1/teams/resources.py
new file mode 100644
index 000000000..69814d28f
--- /dev/null
+++ b/backend/src/kwai/api/v1/teams/resources.py
@@ -0,0 +1,11 @@
+"""Module that defines all JSON:API resource identifiers for the team API."""
+
+from typing import Literal
+
+from kwai.core.json_api import ResourceIdentifier
+
+
+class TeamMemberResourceIdentifier(ResourceIdentifier):
+ """A JSON:API resource identifier for a team member."""
+
+ type: Literal["team_members"] = "team_members"
diff --git a/backend/src/kwai/api/v1/teams/schemas.py b/backend/src/kwai/api/v1/teams/schemas.py
new file mode 100644
index 000000000..b496dc23a
--- /dev/null
+++ b/backend/src/kwai/api/v1/teams/schemas.py
@@ -0,0 +1,137 @@
+"""Module that defines the schemas for the teams API."""
+
+from typing import Annotated, Self
+
+from pydantic import BaseModel, Field
+
+from kwai.api.schemas.resources import TeamResourceIdentifier
+from kwai.api.v1.resources import CountryResourceIdentifier
+from kwai.api.v1.schemas import CountryDocument, CountryResource
+from kwai.api.v1.teams.resources import TeamMemberResourceIdentifier
+from kwai.core.json_api import Document, Relationship, ResourceData, ResourceMeta
+from kwai.modules.teams.domain.team import TeamEntity
+from kwai.modules.teams.domain.team_member import TeamMember
+
+
+class TeamMemberAttributes(BaseModel):
+ """Attributes for a team member."""
+
+ active: bool
+ first_name: str
+ last_name: str
+ license_number: str
+ license_end_date: str
+ gender: int
+ birthdate: str
+ active_in_club: bool
+
+
+class TeamMemberRelationships(BaseModel):
+ """Relationships for a team member JSON:API resource."""
+
+ nationality: Relationship[CountryResourceIdentifier]
+ team: Relationship[TeamResourceIdentifier] | None = None
+
+
+class TeamMemberResource(
+ TeamMemberResourceIdentifier,
+ ResourceData[TeamMemberAttributes, TeamMemberRelationships],
+):
+ """A JSON:API resource for a team member."""
+
+
+TeamMemberInclude = Annotated[CountryResource, Field(discriminator="type")]
+
+
+class TeamMemberDocument(Document[TeamMemberResource, TeamMemberInclude]):
+ """A JSON:API document for one or more team members."""
+
+ @classmethod
+ def create(cls, team_member: TeamMember, team: TeamEntity | None = None) -> Self:
+ """Create a team member document."""
+ nationality_document = CountryDocument.create(team_member.member.nationality)
+
+ team_member_resource = TeamMemberResource(
+ id=str(team_member.member.uuid),
+ attributes=TeamMemberAttributes(
+ active=team_member.active,
+ first_name=team_member.member.name.first_name,
+ last_name=team_member.member.name.last_name,
+ license_number=team_member.member.license.number,
+ license_end_date=str(team_member.member.license.end_date),
+ gender=team_member.member.gender,
+ birthdate=str(team_member.member.birthdate),
+ active_in_club=team_member.member.is_active_in_club,
+ ),
+ meta=ResourceMeta(
+ created_at=str(team_member.traceable_time.created_at),
+ updated_at=str(team_member.traceable_time.updated_at),
+ ),
+ )
+ team_member_resource.relationships = TeamMemberRelationships(
+ nationality=Relationship[CountryResourceIdentifier](
+ data=CountryResourceIdentifier(id=nationality_document.resource.id),
+ ),
+ team=(
+ None
+ if team is None
+ else Relationship[TeamResourceIdentifier](
+ data=TeamResourceIdentifier(id=str(team.id))
+ )
+ ),
+ )
+
+ return cls(data=team_member_resource, included={nationality_document.resource})
+
+
+class TeamAttributes(BaseModel):
+ """Attributes for the team JSON:API resource."""
+
+ name: str
+ active: bool
+ remark: str
+
+
+class TeamRelationships(BaseModel):
+ """Relationships for a team JSON:API resource."""
+
+ team_members: Relationship[TeamMemberResourceIdentifier]
+
+
+class TeamResource(
+ TeamResourceIdentifier, ResourceData[TeamAttributes, TeamRelationships]
+):
+ """A JSON:API resource for a team."""
+
+
+TeamInclude = Annotated[
+ TeamMemberResource | CountryResource, Field(discriminator="type")
+]
+
+
+class TeamDocument(Document[TeamResource, TeamInclude]):
+ """A JSON:API document for one or more teams."""
+
+ @classmethod
+ def create(cls, team: TeamEntity) -> Self:
+ """Create a team document from a team entity."""
+ team_member_document = TeamMemberDocument(data=[], included=set())
+ for team_member in team.members.values():
+ team_member_document.merge(TeamMemberDocument.create(team_member))
+
+ team_resource = TeamResource(
+ id=str(team.id),
+ attributes=TeamAttributes(
+ name=team.name, active=team.is_active, remark=team.remark
+ ),
+ relationships=TeamRelationships(
+ team_members=Relationship[TeamMemberResourceIdentifier](
+ data=team_member_document.resources
+ )
+ ),
+ )
+
+ included: set[TeamInclude] = set(team_member_document.resources)
+ included = included.union(team_member_document.included)
+
+ return TeamDocument(data=team_resource, included=included)
diff --git a/backend/src/kwai/app.py b/backend/src/kwai/app.py
new file mode 100644
index 000000000..c2f10e0aa
--- /dev/null
+++ b/backend/src/kwai/app.py
@@ -0,0 +1,32 @@
+"""Module that creates a FastAPI application for the API and Frontend."""
+
+from contextlib import asynccontextmanager
+
+from fastapi import FastAPI
+from loguru import logger
+
+from kwai.api.app import create_api
+from kwai.frontend.app import create_frontend
+
+APP_NAME = "kwai"
+
+
+@asynccontextmanager
+async def lifespan(app: FastAPI):
+ """Log the start/stop of the application."""
+ logger.info(f"{APP_NAME} is starting")
+ yield
+ logger.warning(f"{APP_NAME} has ended!")
+
+
+def create_app() -> FastAPI:
+ """Create the FastAPI application for API and frontend."""
+ main_app = FastAPI(title=APP_NAME, lifespan=lifespan)
+
+ api_app = create_api()
+ main_app.mount("/api", api_app)
+
+ frontend_app = create_frontend()
+ main_app.mount("/", frontend_app)
+
+ return main_app
diff --git a/backend/src/kwai/core/args.py b/backend/src/kwai/core/args.py
new file mode 100644
index 000000000..3d4038573
--- /dev/null
+++ b/backend/src/kwai/core/args.py
@@ -0,0 +1,21 @@
+"""Module for handling arguments for starting a uvicorn application."""
+
+import argparse
+from argparse import Namespace
+
+
+def create_args(prog: str, default_port: int = 8000) -> Namespace:
+ """Parse and create cli arguments."""
+ parser = argparse.ArgumentParser(prog=prog)
+ parser.add_argument(
+ "--reload",
+ action=argparse.BooleanOptionalAction,
+ help="Watch for code changes or not",
+ )
+ parser.add_argument(
+ "--host", type=str, default="0.0.0.0", help="The host of the server."
+ )
+ parser.add_argument(
+ "--port", type=int, default=default_port, help="The port of the server."
+ )
+ return parser.parse_args()
diff --git a/backend/src/kwai/core/db/database.py b/backend/src/kwai/core/db/database.py
index a6c2d6c25..1330a9222 100644
--- a/backend/src/kwai/core/db/database.py
+++ b/backend/src/kwai/core/db/database.py
@@ -96,6 +96,8 @@ async def execute(self, query: AbstractQuery) -> int | None:
async with self._connection.cursor() as cursor:
try:
await cursor.execute(compiled_query.sql, compiled_query.params)
+ if cursor.rowcount != -1:
+ self.log_affected_rows(cursor.rowcount)
return cursor.lastrowid
except Exception as exc:
raise QueryException(compiled_query.sql) from exc
@@ -243,6 +245,19 @@ def log_query(self, query: str):
"DB: {database} - Query: {query}", database=self._settings.name, query=query
)
+ def log_affected_rows(self, rowcount: int):
+ """Log the number of affected rows of the last executed query.
+
+ Args:
+ rowcount: The number of affected rows.
+ """
+ db_logger = logger.bind(database=self._settings.name)
+ db_logger.info(
+ "DB: {database} - Affected rows: {rowcount}",
+ database=self._settings.name,
+ rowcount=rowcount,
+ )
+
@property
def settings(self) -> DatabaseSettings:
"""Return the database settings.
diff --git a/backend/src/kwai/core/db/rows.py b/backend/src/kwai/core/db/rows.py
index 9a0d065d6..d1da39304 100644
--- a/backend/src/kwai/core/db/rows.py
+++ b/backend/src/kwai/core/db/rows.py
@@ -4,6 +4,7 @@
from datetime import datetime
from kwai.core.db.table import Table
+from kwai.core.db.table_row import TableRow
from kwai.core.domain.value_objects.identifier import IntIdentifier
from kwai.core.domain.value_objects.name import Name
from kwai.core.domain.value_objects.owner import Owner
@@ -34,6 +35,26 @@ def create_owner(self) -> Owner:
OwnersTable = Table("users", OwnerRow)
+@dataclass(kw_only=True, frozen=True, slots=True)
+class OwnerTableRow(TableRow):
+ """Represent the owner data."""
+
+ __table_name__ = "users"
+
+ id: int
+ uuid: str
+ first_name: str
+ last_name: str
+
+ def create_owner(self) -> Owner:
+ """Create an Author value object from row data."""
+ return Owner(
+ id=IntIdentifier(self.id),
+ uuid=UniqueId.create_from_string(self.uuid),
+ name=Name(first_name=self.first_name, last_name=self.last_name),
+ )
+
+
@dataclass(kw_only=True, frozen=True, slots=True)
class TextRow:
"""Represent a row for a content table.
@@ -72,7 +93,7 @@ def create_text(self, author: Owner) -> LocaleText:
summary=self.summary,
author=author,
traceable_time=TraceableTime(
- created_at=Timestamp(timestamp=self.created_at),
- updated_at=Timestamp(timestamp=self.updated_at),
+ created_at=Timestamp.create_utc(self.created_at),
+ updated_at=Timestamp.create_utc(self.updated_at),
),
)
diff --git a/backend/src/kwai/core/db/table.py b/backend/src/kwai/core/db/table.py
index 144cfd70a..d3bff8c90 100644
--- a/backend/src/kwai/core/db/table.py
+++ b/backend/src/kwai/core/db/table.py
@@ -1,15 +1,13 @@
"""Module for the table decorator."""
from dataclasses import fields, is_dataclass
-from typing import Any, Callable, Generic, TypeVar
+from typing import Any, Callable
from sql_smith.functions import alias
from sql_smith.functions import field as sql_field
-T = TypeVar("T", bound=Callable)
-
-class Table(Generic[T]):
+class Table[T: Callable]:
"""Represent a table in the database.
With this class a table row can be transformed into a dataclass. It can also
@@ -30,7 +28,7 @@ def __call__(self, row: dict[str, Any], table_name: str | None = None) -> T:
"""Shortcut for map_row."""
return self.map_row(row, table_name)
- def alias_name(self, column_name: str, table_name: str | None = None):
+ def alias_name(self, column_name: str, table_name: str | None = None) -> str:
"""Return an alias for a column.
The alias will be the name of the table delimited with an
diff --git a/backend/src/kwai/core/domain/entity.py b/backend/src/kwai/core/domain/entity.py
index ef967693a..bdac872c0 100644
--- a/backend/src/kwai/core/domain/entity.py
+++ b/backend/src/kwai/core/domain/entity.py
@@ -1,6 +1,7 @@
"""Module that defines a generic entity."""
+
import inspect
-from typing import Any, Generic, TypeVar
+from typing import Any, Generic, Self, TypeVar
from kwai.core.domain.value_objects.identifier import Identifier
@@ -27,11 +28,11 @@ def has_id(self) -> bool:
return not self._id.is_empty()
@classmethod
- def replace(cls, entity: "Entity[T]", **changes) -> Any:
+ def replace(cls, entity: Self, **changes: Any) -> Any:
"""Return a new entity from the existing entity.
Args:
- entity(Entity[T]): The entity to copy the values from
+ entity: The entity to copy the values from
changes: the values to override when creating the new entity.
Use the same keyword arguments as used on the class constructor (__init__) to
diff --git a/backend/src/kwai/core/domain/presenter.py b/backend/src/kwai/core/domain/presenter.py
new file mode 100644
index 000000000..5b15eb512
--- /dev/null
+++ b/backend/src/kwai/core/domain/presenter.py
@@ -0,0 +1,51 @@
+"""Module for defining a presenter."""
+
+from abc import ABC, abstractmethod
+from dataclasses import dataclass
+from typing import AsyncIterator
+
+
+@dataclass(frozen=True, kw_only=True, slots=True)
+class IterableResult[T]:
+ """A dataclass used to represent a result with multiple entities."""
+
+ count: int
+ offset: int = 0
+ limit: int = 0
+ iterator: AsyncIterator[T]
+
+
+class Presenter[T](ABC):
+ """An interface for a presenter.
+
+ A presenter is used to transform an entity into another object that can be used
+ in a view.
+
+ An example: convert to a JSON:API resource for returning the entity in a restful
+ API.
+ """
+
+ @abstractmethod
+ def present(self, use_case_result: T) -> None:
+ """Present the entity.
+
+ This method is responsible for converting the entity.
+ """
+
+
+class AsyncPresenter[T](ABC):
+ """An interface for an async presenter.
+
+ A presenter is used to transform an entity into another object that can be used
+ in a view.
+
+ An example: convert to a JSON:API resource for returning the entity in a restful
+ API.
+ """
+
+ @abstractmethod
+ async def present(self, use_case_result: T) -> None:
+ """Present the entity.
+
+ This method is responsible for converting the entity.
+ """
diff --git a/backend/src/kwai/core/domain/use_case.py b/backend/src/kwai/core/domain/use_case.py
index 1ccbbd083..52d6e092d 100644
--- a/backend/src/kwai/core/domain/use_case.py
+++ b/backend/src/kwai/core/domain/use_case.py
@@ -1,7 +1,8 @@
"""Module for defining common classes, functions, ... for use cases."""
+
from abc import ABC, abstractmethod
from dataclasses import dataclass
-from typing import AsyncIterator, Generic, NamedTuple, TypeVar
+from typing import AsyncIterator, NamedTuple
class UseCaseResult(ABC):
@@ -13,11 +14,8 @@ def to_message(self) -> str:
raise NotImplementedError
-T = TypeVar("T")
-
-
@dataclass(kw_only=True, frozen=True, slots=True)
-class NotFoundResult(UseCaseResult, Generic[T]):
+class NotFoundResult[T](UseCaseResult):
"""A result that indicates that an entity was not found."""
entity_name: str
@@ -28,7 +26,7 @@ def to_message(self) -> str:
@dataclass(kw_only=True, frozen=True, slots=True)
-class EntitiesResult(UseCaseResult, Generic[T]):
+class EntitiesResult[T](UseCaseResult):
"""A result that returns an iterator for entities and the number of entities."""
count: int
@@ -39,7 +37,7 @@ def to_message(self) -> str:
@dataclass(kw_only=True, frozen=True, slots=True)
-class EntityResult(UseCaseResult, Generic[T]):
+class EntityResult[T](UseCaseResult):
"""A result that returns an entity."""
entity: T
diff --git a/backend/src/kwai/core/domain/value_objects/identifier.py b/backend/src/kwai/core/domain/value_objects/identifier.py
index 0e1008a9c..02c1b092c 100644
--- a/backend/src/kwai/core/domain/value_objects/identifier.py
+++ b/backend/src/kwai/core/domain/value_objects/identifier.py
@@ -1,11 +1,9 @@
"""Module that defines identifiers."""
-from abc import ABC, abstractmethod
-from typing import Generic, TypeVar
-T = TypeVar("T")
+from abc import ABC, abstractmethod
-class Identifier(ABC, Generic[T]):
+class Identifier[T](ABC):
"""Abstract and generic class for an identifier."""
def __init__(self, id_: T):
diff --git a/backend/src/kwai/core/domain/value_objects/text.py b/backend/src/kwai/core/domain/value_objects/text.py
index 62febb725..2f776ad22 100644
--- a/backend/src/kwai/core/domain/value_objects/text.py
+++ b/backend/src/kwai/core/domain/value_objects/text.py
@@ -1,6 +1,8 @@
"""Module that defines a value object for text content."""
+
from dataclasses import dataclass, field
from enum import Enum
+from typing import Self
from kwai.core.domain.value_objects.owner import Owner
from kwai.core.domain.value_objects.traceable_time import TraceableTime
@@ -79,7 +81,7 @@ def get_translation(self, locale: Locale) -> LocaleText:
The content, when available.
Raises:
- KeyError when the locale is not available.
+ KeyError: when the locale is not available.
"""
if locale in self._content:
return self._content[locale]
@@ -121,7 +123,7 @@ def remove_translation(self, content: LocaleText) -> "Text":
new_dict.pop(content.locale)
return Text(new_dict)
- def replace_translation(self, content: LocaleText):
+ def replace_translation(self, content: LocaleText) -> Self:
"""Replace a translation.
Args:
diff --git a/backend/src/kwai/core/domain/value_objects/timestamp.py b/backend/src/kwai/core/domain/value_objects/timestamp.py
index 99d4ca06d..2bf978013 100644
--- a/backend/src/kwai/core/domain/value_objects/timestamp.py
+++ b/backend/src/kwai/core/domain/value_objects/timestamp.py
@@ -1,7 +1,7 @@
"""Module that defines a value object for a local timestamp."""
from dataclasses import dataclass
-from datetime import date, datetime, time, timedelta
+from datetime import date, datetime, time, timedelta, timezone
@dataclass(frozen=True)
@@ -24,7 +24,7 @@ def is_past(self) -> bool:
if self.timestamp is None:
raise ValueError("Empty timestamp")
- return self.timestamp < datetime.utcnow()
+ return self.timestamp < Timestamp.create_now().timestamp
@property
def year(self) -> int:
@@ -112,7 +112,7 @@ def create_with_delta(cls, **kwargs):
@classmethod
def create_now(cls):
"""Create a timestamp with the current UTC time."""
- return Timestamp(timestamp=datetime.utcnow())
+ return Timestamp(timestamp=datetime.now(timezone.utc))
@classmethod
def create_from_string(
@@ -129,4 +129,17 @@ def create_from_string(
return Timestamp()
if len(date_time) == 0:
return Timestamp()
- return Timestamp(datetime.strptime(date_time, date_format))
+ return Timestamp(
+ datetime.strptime(date_time, date_format).replace(tzinfo=timezone.utc)
+ )
+
+ @classmethod
+ def create_utc(cls, timestamp: datetime | None):
+ """Create a timestamp from a datetime and make it UTC.
+
+ When None is passed, an empty timestamp will be returned.
+ """
+ if timestamp is None:
+ return Timestamp()
+
+ return Timestamp(timestamp=timestamp.replace(tzinfo=timezone.utc))
diff --git a/backend/src/kwai/core/domain/value_objects/unique_id.py b/backend/src/kwai/core/domain/value_objects/unique_id.py
index dd1f575b1..5e16bb613 100644
--- a/backend/src/kwai/core/domain/value_objects/unique_id.py
+++ b/backend/src/kwai/core/domain/value_objects/unique_id.py
@@ -1,4 +1,5 @@
"""Module that defines a value object for a unique id."""
+
import uuid
from dataclasses import dataclass
@@ -26,3 +27,7 @@ def __eq__(self, other):
def __str__(self):
"""Return a string representation."""
return str(self.id)
+
+ def __hash__(self):
+ """Return a hash value for the unique id."""
+ return hash(self.id)
diff --git a/backend/src/kwai/core/events/event.py b/backend/src/kwai/core/events/event.py
index b5e8d246a..f26d77d29 100644
--- a/backend/src/kwai/core/events/event.py
+++ b/backend/src/kwai/core/events/event.py
@@ -1,9 +1,11 @@
"""Module that defines the base class Event."""
+
import dataclasses
from dataclasses import dataclass
-from datetime import datetime
from typing import ClassVar
+from kwai.core.domain.value_objects.timestamp import Timestamp
+
@dataclass(kw_only=True, frozen=True)
class EventMeta:
@@ -26,7 +28,7 @@ def data(self) -> dict:
return {
"meta": {
**dataclasses.asdict(self.__class__.meta),
- "date": datetime.utcnow().isoformat(sep=" ", timespec="milliseconds"),
+ "date": str(Timestamp.create_now()),
},
"data": {**dataclasses.asdict(self)},
}
diff --git a/backend/src/kwai/core/events/stream.py b/backend/src/kwai/core/events/stream.py
index 2976432e9..1a9269b47 100644
--- a/backend/src/kwai/core/events/stream.py
+++ b/backend/src/kwai/core/events/stream.py
@@ -1,4 +1,5 @@
"""Define a Redis stream."""
+
import json
from dataclasses import dataclass, field
from json import JSONDecodeError
@@ -131,7 +132,11 @@ async def add(self, message: RedisMessage) -> RedisMessage:
return RedisMessage(id=message_id.decode("utf-8"), data=message.data)
async def consume(
- self, group_name: str, consumer_name: str, id_=">", block: int | None = None
+ self,
+ group_name: str,
+ consumer_name: str,
+ id_: str = ">",
+ block: int | None = None,
) -> RedisMessage | None:
"""Consume a message from a stream.
@@ -156,7 +161,7 @@ async def consume(
return RedisMessage.create_from_redis(messages)
- async def create_group(self, group_name: str, id_="$") -> bool:
+ async def create_group(self, group_name: str, id_: str = "$") -> bool:
"""Create a group (if it doesn't exist yet).
Args:
diff --git a/backend/src/kwai/core/functions.py b/backend/src/kwai/core/functions.py
index bad8a3712..70d9b256e 100644
--- a/backend/src/kwai/core/functions.py
+++ b/backend/src/kwai/core/functions.py
@@ -1,15 +1,12 @@
"""Module that defines some common functions."""
from itertools import count
-from typing import Any, AsyncIterator, Callable, Generator, TypeVar
+from typing import Any, AsyncIterator, Callable, Generator
-T = TypeVar("T")
-R = TypeVar("R")
-
-async def async_groupby(
- it: AsyncIterator[T], key: Callable[[T], R]
-) -> AsyncIterator[tuple[Any, list[T]]]:
+async def async_groupby[
+ T, R
+](it: AsyncIterator[T], key: Callable[[T], R]) -> AsyncIterator[tuple[Any, list[T]]]:
"""An async groupby."""
try:
row = await anext(it)
diff --git a/backend/src/kwai/core/json_api.py b/backend/src/kwai/core/json_api.py
index a0971a0d4..e48e3fa99 100644
--- a/backend/src/kwai/core/json_api.py
+++ b/backend/src/kwai/core/json_api.py
@@ -1,6 +1,6 @@
"""Module that defines some JSON:API related models."""
-from typing import Any, Generic, TypeVar, cast
+from typing import Any, cast
from fastapi import Query
from pydantic import (
@@ -25,13 +25,10 @@ def __hash__(self) -> int:
return hash(str(self.id) + self.type)
-T_RELATION_SHIP = TypeVar("T_RELATION_SHIP")
-
-
-class Relationship(BaseModel, Generic[T_RELATION_SHIP]):
+class Relationship[R](BaseModel):
"""A JSON:API relationship."""
- data: T_RELATION_SHIP | list[T_RELATION_SHIP] | None
+ data: R | list[R] | None
class ResourceMeta(BaseModel):
@@ -43,16 +40,12 @@ class ResourceMeta(BaseModel):
updated_at: str | None = None
-T_ATTRS = TypeVar("T_ATTRS")
-T_RELATIONSHIPS = TypeVar("T_RELATIONSHIPS")
-
-
-class ResourceData(BaseModel, Generic[T_ATTRS, T_RELATIONSHIPS]):
+class ResourceData[A, R](BaseModel):
"""A JSON:API resource."""
meta: ResourceMeta | SkipJsonSchema[None] = None
- attributes: T_ATTRS
- relationships: T_RELATIONSHIPS | SkipJsonSchema[None] = None
+ attributes: A
+ relationships: R | SkipJsonSchema[None] = None
@model_serializer(mode="wrap")
def serialize(self, handler) -> dict[str, Any]:
@@ -65,10 +58,6 @@ def serialize(self, handler) -> dict[str, Any]:
return result
-T_RESOURCE = TypeVar("T_RESOURCE")
-T_INCLUDE = TypeVar("T_INCLUDE")
-
-
class Meta(BaseModel):
"""Defines the metadata for the document model.
@@ -87,15 +76,31 @@ class Meta(BaseModel):
limit: int | None = None
-class Document(BaseModel, Generic[T_RESOURCE, T_INCLUDE]):
+class ErrorSource(BaseModel):
+ """Defines the model for an error source."""
+
+ pointer: str
+
+
+class Error(BaseModel):
+ """Defines the model for a JSON:API error."""
+
+ status: str = ""
+ source: ErrorSource | None = None
+ title: str = ""
+ detail: str = ""
+
+
+class Document[R, I](BaseModel):
"""A JSON:API document."""
meta: Meta | SkipJsonSchema[None] = None
- data: T_RESOURCE | list[T_RESOURCE]
- included: set[T_INCLUDE] | SkipJsonSchema[None] = None
+ data: R | list[R]
+ included: set[I] | SkipJsonSchema[None] = None
+ errors: list[Error] | SkipJsonSchema[None] = None
@property
- def resource(self) -> T_RESOURCE:
+ def resource(self) -> R:
"""Return the resource of this document.
An assert will occur, when the resource is a list.
@@ -104,7 +109,7 @@ def resource(self) -> T_RESOURCE:
return self.data
@property
- def resources(self) -> list[T_RESOURCE]:
+ def resources(self) -> list[R]:
"""Return the list of resources of this document.
An assert will occur, when the resource is not a list.
@@ -112,6 +117,16 @@ def resources(self) -> list[T_RESOURCE]:
assert isinstance(self.data, list)
return self.data
+ def __repr__(self):
+ """Return representation of a document."""
+ if isinstance(self.data, list):
+ if len(self.data) > 0:
+ return f"<{self.__class__.__name__} type={self.data[0].type}[]>"
+ else:
+ return f"<{self.__class__.__name__} type=[]>"
+ else:
+ return f"<{self.__class__.__name__} type={self.data.type}>"
+
@classmethod
def __get_pydantic_json_schema__(
cls,
@@ -135,6 +150,8 @@ def serialize(self, handler) -> dict[str, Any]:
del result["included"]
if self.meta is None:
del result["meta"]
+ if not self.errors:
+ del result["errors"]
return result
def merge(self, other: "Document"):
@@ -167,3 +184,14 @@ class PaginationModel(BaseModel):
offset: int | None = Field(Query(default=None, alias="page[offset]"))
limit: int | None = Field(Query(default=None, alias="page[limit]"))
+
+
+class JsonApiPresenter[Document]:
+ """An interface for a presenter that generates a JSON:API document."""
+
+ def __init__(self):
+ self._document: Document = None
+
+ def get_document(self) -> Document:
+ """Return the JSON:API document."""
+ return self._document
diff --git a/backend/src/kwai/core/settings.py b/backend/src/kwai/core/settings.py
index 4b09d6bce..e8e2df76f 100644
--- a/backend/src/kwai/core/settings.py
+++ b/backend/src/kwai/core/settings.py
@@ -1,4 +1,5 @@
"""Module for the settings of this application."""
+
import os
from functools import lru_cache
@@ -12,6 +13,33 @@ class SettingsException(Exception):
"""Raised when a problem occurred while loading the settings."""
+class FrontendApplicationSettings(BaseModel):
+ """Settings for a frontend application."""
+
+ server: str | None = None
+ base: str | None = None
+ entries: list[str] | str
+
+
+class FrontendApplications(BaseModel):
+ """All applications."""
+
+ auth: FrontendApplicationSettings
+ author: FrontendApplicationSettings
+ club: FrontendApplicationSettings
+ coach: FrontendApplicationSettings
+ portal: FrontendApplicationSettings
+
+
+class FrontendSettings(BaseModel):
+ """Settings for the frontend."""
+
+ test: bool = False
+ path: str
+ apps: FrontendApplications
+ root_app: str
+
+
class FilesSettings(BaseModel):
"""Settings for files (upload)."""
@@ -92,6 +120,8 @@ class TemplateSettings(BaseModel):
class Settings(BaseModel):
"""Class with settings."""
+ frontend: FrontendSettings
+
files: FilesSettings
security: SecuritySettings
diff --git a/backend/src/kwai/frontend/__init__.py b/backend/src/kwai/frontend/__init__.py
new file mode 100644
index 000000000..c656fddb5
--- /dev/null
+++ b/backend/src/kwai/frontend/__init__.py
@@ -0,0 +1 @@
+"""Package that defines modules for serving the frontend from the Python backend."""
diff --git a/backend/src/kwai/frontend/app.py b/backend/src/kwai/frontend/app.py
new file mode 100644
index 000000000..484b2c14f
--- /dev/null
+++ b/backend/src/kwai/frontend/app.py
@@ -0,0 +1,73 @@
+"""Module that defines a sub application for handling the frontend."""
+
+import uuid
+from pathlib import Path
+from typing import Annotated
+
+from fastapi import Depends, FastAPI, Request, status
+from fastapi.responses import JSONResponse, RedirectResponse
+from loguru import logger
+
+from kwai.core.settings import Settings, get_settings
+from kwai.frontend.apps import application_routers
+
+
+def create_frontend():
+ """Create the frontend."""
+ frontend_app = FastAPI()
+
+ @frontend_app.middleware("http")
+ async def log(request: Request, call_next):
+ """Middleware for logging the requests."""
+ request_id = str(uuid.uuid4())
+ with logger.contextualize(request_id=request_id):
+ logger.info(f"{request.url} - {request.method} - Request started")
+
+ response = None # Make pylint happy...
+ try:
+ response = await call_next(request)
+ except Exception as ex:
+ logger.error(f"{request.url} - Request failed: {ex}")
+ logger.exception(ex)
+ response = JSONResponse(
+ content={
+ "detail": str(ex),
+ },
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
+ )
+ finally:
+ response.headers["X-Request-ID"] = request_id
+ logger.info(
+ f"{request.url} - {request.method} - Request ended: "
+ f"{response.status_code}"
+ )
+
+ return response
+
+ for router in application_routers:
+ frontend_app.include_router(router, prefix="/apps")
+
+ @frontend_app.get("/news/{path:path}", name="frontend.news")
+ def news(path: Path, settings: Annotated[Settings, Depends(get_settings)]):
+ """Redirect the news path to the portal application.
+
+ When FastAPI serves the frontend, the root path can't be used for the portal.
+ So redirect this url to the root application.
+ """
+ return RedirectResponse(f"/apps/{settings.frontend.root_app}/news/{path}")
+
+ @frontend_app.get("/pages/{path:path}", name="frontend.pages")
+ def pages(path: Path, settings: Annotated[Settings, Depends(get_settings)]):
+ """Redirect the pages path to the portal application.
+
+ When FastAPI serves the frontend, the root path can't be used for the portal.
+ So redirect this url to the root application.
+ """
+ return RedirectResponse(f"/apps/{settings.frontend.root_app}/pages/{path}")
+
+ @frontend_app.get("/", name="frontend.home")
+ def root(settings: Annotated[Settings, Depends(get_settings)]):
+ """Redirect index to the portal application."""
+ return RedirectResponse(f"/apps/{settings.frontend.root_app}")
+
+ return frontend_app
diff --git a/backend/src/kwai/frontend/apps/__init__.py b/backend/src/kwai/frontend/apps/__init__.py
new file mode 100644
index 000000000..8a700ff75
--- /dev/null
+++ b/backend/src/kwai/frontend/apps/__init__.py
@@ -0,0 +1,15 @@
+"""Package for defining the routes for all frontend applications."""
+
+from kwai.frontend.apps._auth import router as auth_router
+from kwai.frontend.apps._author import router as author_router
+from kwai.frontend.apps._club import router as club_router
+from kwai.frontend.apps._coach import router as coach_router
+from kwai.frontend.apps._portal import router as portal_router
+
+application_routers = [
+ auth_router,
+ author_router,
+ club_router,
+ coach_router,
+ portal_router,
+]
diff --git a/backend/src/kwai/frontend/apps/_auth.py b/backend/src/kwai/frontend/apps/_auth.py
new file mode 100644
index 000000000..89e982b03
--- /dev/null
+++ b/backend/src/kwai/frontend/apps/_auth.py
@@ -0,0 +1,46 @@
+"""Module that defines the routes for the authentication frontend application."""
+
+from pathlib import Path
+from typing import Annotated
+
+from fastapi import APIRouter, Depends, Request
+from fastapi.templating import Jinja2Templates
+
+from kwai.api.dependencies import create_templates
+from kwai.frontend.dependencies import ViteDependency
+from kwai.frontend.etag_file_response import EtagFileResponse
+from kwai.frontend.vite import Vite
+
+APP_NAME = "auth"
+
+router = APIRouter(prefix=f"/{APP_NAME}")
+
+_auth_vite_dependency = ViteDependency(APP_NAME)
+
+
+@router.get("/{path:path}", name=APP_NAME)
+async def get_app(
+ path: Path,
+ request: Request,
+ templates: Annotated[Jinja2Templates, Depends(create_templates)],
+ vite: Annotated[Vite, Depends(_auth_vite_dependency)],
+):
+ asset_file_path = vite.get_asset_path(path)
+ if asset_file_path is not None:
+ return EtagFileResponse(asset_file_path)
+
+ url = request.url_for(APP_NAME, path="")
+ if "x-forwarded-proto" in request.headers:
+ url = url.replace(scheme=request.headers["x-forwarded-proto"])
+
+ return templates.TemplateResponse(
+ "index.jinja2",
+ {
+ "application": {
+ "name": APP_NAME,
+ "url": str(url),
+ },
+ "request": request,
+ "vite": vite,
+ },
+ )
diff --git a/backend/src/kwai/frontend/apps/_author.py b/backend/src/kwai/frontend/apps/_author.py
new file mode 100644
index 000000000..71faf6208
--- /dev/null
+++ b/backend/src/kwai/frontend/apps/_author.py
@@ -0,0 +1,46 @@
+"""Module that defines the routes for the author frontend application."""
+
+from pathlib import Path
+from typing import Annotated
+
+from fastapi import APIRouter, Depends, Request
+from fastapi.templating import Jinja2Templates
+
+from kwai.api.dependencies import create_templates
+from kwai.frontend.dependencies import ViteDependency
+from kwai.frontend.etag_file_response import EtagFileResponse
+from kwai.frontend.vite import Vite
+
+APP_NAME = "author"
+
+router = APIRouter(prefix=f"/{APP_NAME}")
+
+_auth_vite_dependency = ViteDependency(APP_NAME)
+
+
+@router.get("/{path:path}", name=APP_NAME)
+async def get_app(
+ path: Path,
+ request: Request,
+ templates: Annotated[Jinja2Templates, Depends(create_templates)],
+ vite: Annotated[Vite, Depends(_auth_vite_dependency)],
+):
+ asset_file_path = vite.get_asset_path(path)
+ if asset_file_path is not None:
+ return EtagFileResponse(asset_file_path)
+
+ url = request.url_for(APP_NAME, path="")
+ if "x-forwarded-proto" in request.headers:
+ url = url.replace(scheme=request.headers["x-forwarded-proto"])
+
+ return templates.TemplateResponse(
+ "index.jinja2",
+ {
+ "application": {
+ "name": APP_NAME,
+ "url": str(url),
+ },
+ "request": request,
+ "vite": vite,
+ },
+ )
diff --git a/backend/src/kwai/frontend/apps/_club.py b/backend/src/kwai/frontend/apps/_club.py
new file mode 100644
index 000000000..fa490c7ca
--- /dev/null
+++ b/backend/src/kwai/frontend/apps/_club.py
@@ -0,0 +1,46 @@
+"""Module that defines the routes for the club frontend application."""
+
+from pathlib import Path
+from typing import Annotated
+
+from fastapi import APIRouter, Depends, Request
+from fastapi.templating import Jinja2Templates
+
+from kwai.api.dependencies import create_templates
+from kwai.frontend.dependencies import ViteDependency
+from kwai.frontend.etag_file_response import EtagFileResponse
+from kwai.frontend.vite import Vite
+
+APP_NAME = "club"
+
+router = APIRouter(prefix=f"/{APP_NAME}")
+
+_club_vite_dependency = ViteDependency(APP_NAME)
+
+
+@router.get("/{path:path}", name=APP_NAME)
+async def get_app(
+ path: Path,
+ request: Request,
+ templates: Annotated[Jinja2Templates, Depends(create_templates)],
+ vite: Annotated[Vite, Depends(_club_vite_dependency)],
+):
+ asset_file_path = vite.get_asset_path(path)
+ if asset_file_path is not None:
+ return EtagFileResponse(asset_file_path)
+
+ url = request.url_for(APP_NAME, path="")
+ if "x-forwarded-proto" in request.headers:
+ url = url.replace(scheme=request.headers["x-forwarded-proto"])
+
+ return templates.TemplateResponse(
+ "index.jinja2",
+ {
+ "application": {
+ "name": APP_NAME,
+ "url": str(url),
+ },
+ "request": request,
+ "vite": vite,
+ },
+ )
diff --git a/backend/src/kwai/frontend/apps/_coach.py b/backend/src/kwai/frontend/apps/_coach.py
new file mode 100644
index 000000000..d2e3c5d0e
--- /dev/null
+++ b/backend/src/kwai/frontend/apps/_coach.py
@@ -0,0 +1,46 @@
+"""Module that defines the routes for the coach frontend application."""
+
+from pathlib import Path
+from typing import Annotated
+
+from fastapi import APIRouter, Depends, Request
+from fastapi.templating import Jinja2Templates
+
+from kwai.api.dependencies import create_templates
+from kwai.frontend.dependencies import ViteDependency
+from kwai.frontend.etag_file_response import EtagFileResponse
+from kwai.frontend.vite import Vite
+
+APP_NAME = "coach"
+
+router = APIRouter(prefix=f"/{APP_NAME}")
+
+_coach_vite_dependency = ViteDependency(APP_NAME)
+
+
+@router.get("/{path:path}", name=APP_NAME)
+async def get_app(
+ path: Path,
+ request: Request,
+ templates: Annotated[Jinja2Templates, Depends(create_templates)],
+ vite: Annotated[Vite, Depends(_coach_vite_dependency)],
+):
+ asset_file_path = vite.get_asset_path(path)
+ if asset_file_path is not None:
+ return EtagFileResponse(asset_file_path)
+
+ url = request.url_for(APP_NAME, path="")
+ if "x-forwarded-proto" in request.headers:
+ url = url.replace(scheme=request.headers["x-forwarded-proto"])
+
+ return templates.TemplateResponse(
+ "index.jinja2",
+ {
+ "application": {
+ "name": APP_NAME,
+ "url": str(url),
+ },
+ "request": request,
+ "vite": vite,
+ },
+ )
diff --git a/backend/src/kwai/frontend/apps/_portal.py b/backend/src/kwai/frontend/apps/_portal.py
new file mode 100644
index 000000000..a544eee24
--- /dev/null
+++ b/backend/src/kwai/frontend/apps/_portal.py
@@ -0,0 +1,46 @@
+"""Module that defines the routes for the portal frontend application."""
+
+from pathlib import Path
+from typing import Annotated
+
+from fastapi import APIRouter, Depends, Request
+from fastapi.templating import Jinja2Templates
+
+from kwai.api.dependencies import create_templates
+from kwai.frontend.dependencies import ViteDependency
+from kwai.frontend.etag_file_response import EtagFileResponse
+from kwai.frontend.vite import Vite
+
+APP_NAME = "portal"
+
+router = APIRouter(prefix=f"/{APP_NAME}")
+
+_portal_vite_dependency = ViteDependency(APP_NAME)
+
+
+@router.get("/{path:path}", name=APP_NAME)
+async def get_app(
+ path: Path,
+ request: Request,
+ templates: Annotated[Jinja2Templates, Depends(create_templates)],
+ vite: Annotated[Vite, Depends(_portal_vite_dependency)],
+):
+ asset_file_path = vite.get_asset_path(path)
+ if asset_file_path is not None:
+ return EtagFileResponse(asset_file_path)
+
+ url = request.url_for(APP_NAME, path="")
+ if "x-forwarded-proto" in request.headers:
+ url = url.replace(scheme=request.headers["x-forwarded-proto"])
+
+ return templates.TemplateResponse(
+ "index.jinja2",
+ {
+ "application": {
+ "name": APP_NAME,
+ "url": str(url),
+ },
+ "request": request,
+ "vite": vite,
+ },
+ )
diff --git a/backend/src/kwai/frontend/dependencies.py b/backend/src/kwai/frontend/dependencies.py
new file mode 100644
index 000000000..94a5a61a8
--- /dev/null
+++ b/backend/src/kwai/frontend/dependencies.py
@@ -0,0 +1,57 @@
+"""Module for defining dependencies for the frontend applications."""
+
+from pathlib import Path
+from typing import Annotated
+
+from fastapi import Depends, HTTPException, status
+
+from kwai.core.settings import Settings, get_settings
+from kwai.frontend.vite import DevelopmentVite, ProductionVite, Vite
+
+
+class ViteDependency:
+ """Vite is a dependency."""
+
+ def __init__(self, application_name: str):
+ self._application_name = application_name
+
+ def __call__(self, settings: Annotated[Settings, Depends(get_settings)]) -> Vite:
+ """Create a Vite environment for this application."""
+ if not hasattr(settings.frontend.apps, self._application_name):
+ raise HTTPException(
+ status_code=status.HTTP_400_BAD_REQUEST,
+ detail=f"Application {self._application_name} does not exist.",
+ )
+
+ app_setting = getattr(settings.frontend.apps, self._application_name)
+ if settings.frontend.test:
+ if app_setting.server is None:
+ raise HTTPException(
+ status_code=status.HTTP_400_BAD_REQUEST,
+ detail=f"Setting 'server' not set for application {self._application_name}",
+ )
+ if app_setting.base is None:
+ raise HTTPException(
+ status_code=status.HTTP_400_BAD_REQUEST,
+ detail=f"Setting 'base' not set for application {self._application_name}",
+ )
+ return DevelopmentVite(app_setting.server, app_setting.base)
+
+ manifest_path = (
+ Path(settings.frontend.path)
+ / "apps"
+ / self._application_name
+ / "dist"
+ / ".vite"
+ / "manifest.json"
+ )
+ if not manifest_path.exists():
+ raise HTTPException(
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
+ detail=f"Manifest file {manifest_path} not found",
+ )
+
+ return ProductionVite(
+ manifest_path,
+ Path(settings.frontend.path) / "apps" / self._application_name,
+ )
diff --git a/backend/src/kwai/frontend/etag_file_response.py b/backend/src/kwai/frontend/etag_file_response.py
new file mode 100644
index 000000000..daf9a9992
--- /dev/null
+++ b/backend/src/kwai/frontend/etag_file_response.py
@@ -0,0 +1,39 @@
+from starlette._compat import md5_hexdigest # noqa
+from pathlib import Path
+
+from fastapi import Request
+from fastapi.responses import FileResponse, Response
+
+
+class EtagFileResponse(FileResponse):
+ """A FileResponse that will check the etag when if-none-match header is passed.
+
+ _generate_etag uses the same implementation as FileResponse.
+ FileResponse automatically sets the etag header with this etag value.
+ """
+
+ def __init__(self, path: Path, **kwargs) -> None:
+ super().__init__(path, **kwargs)
+ self._path = path
+
+ def _generate_etag(self) -> str:
+ file_stat = self._path.stat()
+ etag_base = str(file_stat.st_mtime) + "-" + str(file_stat.st_size)
+ return f'"{md5_hexdigest(etag_base.encode(), usedforsecurity=False)}"'
+
+ async def __call__(self, scope, receive, send) -> None:
+ """Check the etag, and return 304 when the file is not modified."""
+ request = Request(scope, receive)
+ if_none_match = request.headers.get("if-none-match")
+
+ if not if_none_match:
+ await super().__call__(scope, receive, send)
+ return
+
+ etag = self._generate_etag()
+ if if_none_match == etag:
+ response = Response(status_code=304)
+ await response(scope, receive, send)
+ return
+
+ await super().__call__(scope, receive, send)
diff --git a/backend/src/kwai/frontend/manifest.py b/backend/src/kwai/frontend/manifest.py
new file mode 100644
index 000000000..5ef5606dd
--- /dev/null
+++ b/backend/src/kwai/frontend/manifest.py
@@ -0,0 +1,71 @@
+"""Module that defines a class for handling the manifest file of Vite."""
+
+import json
+from dataclasses import dataclass, field
+from pathlib import Path
+from typing import Self
+
+
+@dataclass(frozen=True, kw_only=True, slots=True)
+class Chunk:
+ """An entry of a manifest file."""
+
+ src: str | None = None
+ name: str | None = None
+ entry: bool = False
+ dynamic_entry: bool = False
+ file: str
+ css: list[str] = field(default_factory=list)
+ assets: list[str] = field(default_factory=list)
+ imports: list[str] = field(default_factory=list)
+ dynamic_imports: list[str] = field(default_factory=list)
+
+
+class Manifest:
+ """Class for handling a manifest file of Vite."""
+
+ def __init__(self, entries: dict[str, Chunk]) -> None:
+ """Initialize the Manifest class."""
+ self._entries = entries
+
+ @property
+ def chunks(self):
+ """Return the entries."""
+ return self._entries.copy()
+
+ def has_chunk(self, entry_name: str):
+ """Check if the entry exists in the manifest file."""
+ return entry_name in self._entries
+
+ def get_chunk(self, entry_name: str) -> Chunk:
+ """Return the entry with the given name."""
+ return self._entries[entry_name]
+
+ @classmethod
+ def load_from_file(cls, file_path: Path) -> Self:
+ """Load the manifest from a file."""
+ with open(file_path, "r") as manifest_file:
+ return cls.load_from_string(manifest_file.read())
+
+ @classmethod
+ def load_from_string(cls, content: str) -> Self:
+ """Load the manifest from a string."""
+ entries: dict[str, Chunk] = {}
+ json_data = json.loads(content)
+ for k, v in json_data.items():
+ if not isinstance(v, dict):
+ continue
+ entry = Chunk(
+ src=v.get("src", None),
+ name=v.get("name", None),
+ entry=v.get("isEntry", False),
+ dynamic_entry=v.get("isDynamicEntry", False),
+ file=v.get("file"),
+ css=v.get("css", []),
+ assets=v.get("assets", []),
+ imports=v.get("imports", []),
+ dynamic_imports=v.get("dynamicImports", []),
+ )
+ entries[k] = entry
+
+ return cls(entries=entries)
diff --git a/backend/src/kwai/frontend/vite.py b/backend/src/kwai/frontend/vite.py
new file mode 100644
index 000000000..72cd6f614
--- /dev/null
+++ b/backend/src/kwai/frontend/vite.py
@@ -0,0 +1,171 @@
+"""Module for defining a class that handles files and assets created with vite."""
+
+from abc import ABC, abstractmethod
+from pathlib import Path
+
+from kwai.frontend.manifest import Chunk, Manifest
+
+
+class Vite(ABC):
+ """Interface for a Vite runtime."""
+
+ @abstractmethod
+ def init(self, *entries: str):
+ """Initialize the Vite runtime for the given entries."""
+ raise NotImplementedError
+
+ @abstractmethod
+ def get_scripts(self, base_url: str) -> list[str]:
+ """Get the scripts for the given entries."""
+ raise NotImplementedError
+
+ @abstractmethod
+ def get_css(self, base_url: str) -> list[str]:
+ """Get the css files for the given entries."""
+ raise NotImplementedError
+
+ @abstractmethod
+ def get_preloads(self, base_url: str) -> list[str]:
+ """Get the preloads for the given entries."""
+ raise NotImplementedError
+
+ @abstractmethod
+ def get_asset_path(self, asset_path: Path) -> Path | None:
+ """Return the path for an asset.
+
+ None is returned when the file should not be processed. This is the case
+ in the development environment, because Vite will serve the assets.
+
+ None should also be returned when the file does not exist in the dist folder.
+ This way, the url path will be handled by Vue Router.
+
+ When the path starts with public, the path without 'public' is used to search
+ the file in the dist folder.
+ """
+
+
+class DevelopmentVite(Vite):
+ """Vite implementation for development."""
+
+ def __init__(self, server_url: str, base_path: str):
+ """Initialize the development version of vite.
+
+ Args:
+ server_url: The url for the vite server
+ base_path: The base path for the development version of vite.
+
+ !!! Note
+ When vite is configured with a base then make sure that this
+ base is also part of the base_path argument. For example: when base is
+ '/apps/author' and the server is running on localhost with port 3001, then
+ base_path should be: 'http://localhost:3001/apps/author'.
+ """
+ self._server_url = server_url
+ self._base_path = base_path
+ self._entries: list[str] = []
+
+ def init(self, *entries: str):
+ self._entries = entries
+
+ def get_scripts(self, base_url: str) -> list[str]:
+ scripts = [f"{self._server_url}/@vite/client"]
+ for entry in self._entries:
+ scripts.append(
+ "/".join(
+ list(
+ filter(
+ lambda item: item,
+ [self._server_url, self._base_path, entry],
+ )
+ )
+ )
+ )
+ return scripts
+
+ def get_css(self, base_url: str) -> list[str]:
+ return []
+
+ def get_preloads(self, base_url: str) -> list[str]:
+ return []
+
+ def get_asset_path(self, asset_path: Path) -> Path | None:
+ return None
+
+
+class ProductionVite(Vite):
+ """Vite implementation for production."""
+
+ def __init__(self, manifest_filepath: Path, base_path: Path):
+ """Initialize the production Vite runtime.
+
+ Args:
+ manifest_filepath: Path to the manifest file.
+ base_path: Path to the dist folder.
+ """
+ self._manifest_filepath: Path = manifest_filepath
+ self._base_path: Path = base_path
+ self._manifest: Manifest | None = None
+ self._imported_chunks: dict[str, Chunk] = {} # chunks imported by the entries
+
+ def init(self, *entries: str):
+ """Load the manifest file."""
+ self._manifest = Manifest.load_from_file(self._manifest_filepath)
+ self._imported_chunks = self._find_imported_chunks(*entries)
+
+ def get_scripts(self, base_url: str) -> list[str]:
+ scripts = []
+
+ for chunk in self._imported_chunks.values():
+ if chunk.entry:
+ scripts.append(base_url + chunk.file)
+
+ return scripts
+
+ def get_css(self, base_url: str) -> list[str]:
+ styles = []
+ for chunk in self._imported_chunks.values():
+ for css in chunk.css:
+ styles.append(base_url + css)
+ return styles
+
+ def get_preloads(self, base_url: str) -> list[str]:
+ preloads = []
+
+ for chunk in self._imported_chunks.values():
+ if chunk.file.endswith(".js") and not chunk.entry:
+ preloads.append(base_url + chunk.file)
+
+ return preloads
+
+ def _find_imported_chunks(self, *entries: str) -> dict[str, Chunk]:
+ chunks = {}
+
+ for entry in entries:
+ if not self._manifest.has_chunk(entry):
+ raise ValueError(f"{entry} is not a chunk in {self._manifest_filepath}")
+
+ chunk = self._manifest.get_chunk(entry)
+ if not chunk.entry:
+ raise ValueError(
+ f"{entry} is not an entry point in {self._manifest_filepath}"
+ )
+
+ chunks[entry] = chunk
+
+ imports = chunk.imports
+ while imports:
+ import_ = imports.pop()
+ if import_ not in chunks:
+ import_chunk = self._manifest.get_chunk(import_)
+ chunks[import_] = import_chunk
+ imports.extend(import_chunk.imports)
+
+ return chunks
+
+ def get_asset_path(self, path: Path) -> Path | None:
+ dist_path = self._base_path / "dist"
+ asset_file = dist_path / path
+ if asset_file.is_relative_to(dist_path) and asset_file.is_file():
+ return asset_file
+
+ return None
diff --git a/backend/src/kwai/modules/club/domain/__init__.py b/backend/src/kwai/modules/club/domain/__init__.py
new file mode 100644
index 000000000..42179d38e
--- /dev/null
+++ b/backend/src/kwai/modules/club/domain/__init__.py
@@ -0,0 +1 @@
+"""Package for entities and value objects."""
diff --git a/backend/src/kwai/modules/club/domain/coach.py b/backend/src/kwai/modules/club/domain/coach.py
new file mode 100644
index 000000000..8f18fa80d
--- /dev/null
+++ b/backend/src/kwai/modules/club/domain/coach.py
@@ -0,0 +1,92 @@
+"""Module for defining a coach entity."""
+
+from kwai.core.domain.entity import Entity
+from kwai.core.domain.value_objects.identifier import IntIdentifier
+from kwai.core.domain.value_objects.name import Name
+from kwai.core.domain.value_objects.owner import Owner
+from kwai.core.domain.value_objects.traceable_time import TraceableTime
+from kwai.modules.club.domain.member import MemberEntity
+
+CoachIdentifier = IntIdentifier
+
+
+class CoachEntity(Entity[CoachIdentifier]):
+ """A coach entity."""
+
+ def __init__(
+ self,
+ *,
+ id_: CoachIdentifier | None = None,
+ member: MemberEntity,
+ description: str = "",
+ diploma: str = "",
+ active: bool = True,
+ remark: str = "",
+ user: Owner | None = None,
+ traceable_time: TraceableTime | None = None,
+ ):
+ """Initialize a coach.
+
+ Args:
+ id_ (CoachIdentifier): The id of the coach.
+ member: A coach is a member of the club.
+ description: The description (bio) of the coach.
+ diploma: The diploma of the coach.
+ active: Whether the coach is active.
+ remark: A remark about the coach.
+ user: A coach can also be a user of the system.
+ traceable_time: The creation and modification timestamp of the coach.
+ """
+ super().__init__(id_ or CoachIdentifier())
+ self._member = member
+ self._description = description
+ self._diploma = diploma
+ self._active = active
+ self._remark = remark
+ self._user = user
+ self._traceable_time = traceable_time or TraceableTime()
+
+ @property
+ def is_active(self) -> bool:
+ """Is the coach active?"""
+ return self._active
+
+ @property
+ def member(self) -> MemberEntity:
+ """Return the related member."""
+ return self._member
+
+ @property
+ def name(self) -> Name:
+ """Return the name of the coach."""
+ return self._member.person.name
+
+ @property
+ def diploma(self) -> str:
+ """Return the diploma of the coach."""
+ return self._diploma
+
+ @property
+ def description(self) -> str:
+ """Return the description of the coach."""
+ return self._description
+
+ @property
+ def remark(self) -> str:
+ """Return the remark of the coach."""
+ return self._remark
+
+ @property
+ def traceable_time(self) -> TraceableTime:
+ """Return the traceable_time."""
+ return self._traceable_time
+
+ @property
+ def uuid(self):
+ """Return the uuid of the coach."""
+ return self._member.uuid
+
+ @property
+ def user(self) -> Owner | None:
+ """Return the related user."""
+ return self._user
diff --git a/backend/src/kwai/modules/club/members/contact.py b/backend/src/kwai/modules/club/domain/contact.py
similarity index 97%
rename from backend/src/kwai/modules/club/members/contact.py
rename to backend/src/kwai/modules/club/domain/contact.py
index ba7ef04f3..3634c9a40 100644
--- a/backend/src/kwai/modules/club/members/contact.py
+++ b/backend/src/kwai/modules/club/domain/contact.py
@@ -4,7 +4,7 @@
from kwai.core.domain.value_objects.email_address import EmailAddress
from kwai.core.domain.value_objects.identifier import IntIdentifier
from kwai.core.domain.value_objects.traceable_time import TraceableTime
-from kwai.modules.club.members.value_objects import Address
+from kwai.modules.club.domain.value_objects import Address
ContactIdentifier = IntIdentifier
diff --git a/backend/src/kwai/modules/club/members/country.py b/backend/src/kwai/modules/club/domain/country.py
similarity index 100%
rename from backend/src/kwai/modules/club/members/country.py
rename to backend/src/kwai/modules/club/domain/country.py
diff --git a/backend/src/kwai/modules/club/members/file_upload.py b/backend/src/kwai/modules/club/domain/file_upload.py
similarity index 89%
rename from backend/src/kwai/modules/club/members/file_upload.py
rename to backend/src/kwai/modules/club/domain/file_upload.py
index 59911bc4a..f0974740a 100644
--- a/backend/src/kwai/modules/club/members/file_upload.py
+++ b/backend/src/kwai/modules/club/domain/file_upload.py
@@ -20,6 +20,7 @@ def __init__(
filename: str,
owner: Owner,
remark: str = "",
+ preview: bool = False,
traceable_time: TraceableTime | None = None,
):
"""Initialize a file upload entity.
@@ -28,8 +29,9 @@ def __init__(
id_: The id of the upload.
uuid: The unique id of the upload.
filename: The name of the file.
- remark: A remark about the upload.
owner: The user who uploaded the file.
+ remark: A remark about the upload.
+ preview: Whether the upload is a preview.
traceable_time: The creation and modification timestamp of the upload.
"""
super().__init__(id_ or FileUploadIdentifier())
@@ -37,6 +39,7 @@ def __init__(
self._filename = filename
self._owner = owner
self._remark = remark
+ self._preview = preview
self._traceable_time = traceable_time or TraceableTime()
@property
@@ -59,6 +62,11 @@ def uuid(self) -> UniqueId:
"""Return the uuid."""
return self._uuid
+ @property
+ def preview(self) -> bool:
+ """Return the preview."""
+ return self._preview
+
@property
def traceable_time(self) -> TraceableTime:
"""Return the creation/modification time."""
diff --git a/backend/src/kwai/modules/club/members/member.py b/backend/src/kwai/modules/club/domain/member.py
similarity index 89%
rename from backend/src/kwai/modules/club/members/member.py
rename to backend/src/kwai/modules/club/domain/member.py
index 657ad03c1..7b271d5b4 100644
--- a/backend/src/kwai/modules/club/members/member.py
+++ b/backend/src/kwai/modules/club/domain/member.py
@@ -1,10 +1,12 @@
"""Module for defining the Member entity."""
+
from kwai.core.domain.entity import Entity
from kwai.core.domain.value_objects.identifier import IntIdentifier
+from kwai.core.domain.value_objects.name import Name
from kwai.core.domain.value_objects.traceable_time import TraceableTime
from kwai.core.domain.value_objects.unique_id import UniqueId
-from kwai.modules.club.members.person import PersonEntity
-from kwai.modules.club.members.value_objects import License
+from kwai.modules.club.domain.person import PersonEntity
+from kwai.modules.club.domain.value_objects import License
MemberIdentifier = IntIdentifier
@@ -60,6 +62,11 @@ def license(self) -> License:
"""Return the license."""
return self._license
+ @property
+ def name(self) -> Name:
+ """Return the name of the member."""
+ return self.person.name
+
@property
def person(self) -> PersonEntity:
"""Return the person."""
diff --git a/backend/src/kwai/modules/club/members/person.py b/backend/src/kwai/modules/club/domain/person.py
similarity index 92%
rename from backend/src/kwai/modules/club/members/person.py
rename to backend/src/kwai/modules/club/domain/person.py
index c43815025..1ab08dd14 100644
--- a/backend/src/kwai/modules/club/members/person.py
+++ b/backend/src/kwai/modules/club/domain/person.py
@@ -4,9 +4,9 @@
from kwai.core.domain.value_objects.identifier import IntIdentifier
from kwai.core.domain.value_objects.name import Name
from kwai.core.domain.value_objects.traceable_time import TraceableTime
-from kwai.modules.club.members.contact import ContactEntity
-from kwai.modules.club.members.country import CountryEntity
-from kwai.modules.club.members.value_objects import Birthdate, Gender
+from kwai.modules.club.domain.contact import ContactEntity
+from kwai.modules.club.domain.country import CountryEntity
+from kwai.modules.club.domain.value_objects import Birthdate, Gender
PersonIdentifier = IntIdentifier
diff --git a/backend/src/kwai/modules/club/members/value_objects.py b/backend/src/kwai/modules/club/domain/value_objects.py
similarity index 95%
rename from backend/src/kwai/modules/club/members/value_objects.py
rename to backend/src/kwai/modules/club/domain/value_objects.py
index dd5e2058b..eda85759d 100644
--- a/backend/src/kwai/modules/club/members/value_objects.py
+++ b/backend/src/kwai/modules/club/domain/value_objects.py
@@ -4,7 +4,7 @@
from enum import Enum
from kwai.core.domain.value_objects.date import Date
-from kwai.modules.club.members.country import CountryEntity
+from kwai.modules.club.domain.country import CountryEntity
@dataclass(kw_only=True, frozen=True, slots=True)
diff --git a/backend/src/kwai/modules/club/get_member.py b/backend/src/kwai/modules/club/get_member.py
index 6959cb840..bd736c4e2 100644
--- a/backend/src/kwai/modules/club/get_member.py
+++ b/backend/src/kwai/modules/club/get_member.py
@@ -2,9 +2,10 @@
from dataclasses import dataclass
+from kwai.core.domain.presenter import Presenter
from kwai.core.domain.value_objects.unique_id import UniqueId
-from kwai.modules.club.members.member import MemberEntity
-from kwai.modules.club.members.member_repository import MemberRepository
+from kwai.modules.club.domain.member import MemberEntity
+from kwai.modules.club.repositories.member_repository import MemberRepository
@dataclass(kw_only=True, frozen=True, slots=True)
@@ -21,15 +22,17 @@ class GetMemberCommand:
class GetMember:
"""Use case 'Get Member'."""
- def __init__(self, repo: MemberRepository):
+ def __init__(self, repo: MemberRepository, presenter: Presenter[MemberEntity]):
"""Initialize the use case.
Args:
repo: The repository used to get the member.
+ presenter: The presenter used to handle the result of the use case.
"""
self._repo = repo
+ self._presenter = presenter
- async def execute(self, command: GetMemberCommand) -> MemberEntity:
+ async def execute(self, command: GetMemberCommand) -> None:
"""Execute the use case.
Args:
@@ -44,4 +47,5 @@ async def execute(self, command: GetMemberCommand) -> MemberEntity:
query = self._repo.create_query()
query.filter_by_uuid(UniqueId.create_from_string(command.uuid))
- return await self._repo.get(query)
+ member = await self._repo.get(query)
+ self._presenter.present(member)
diff --git a/backend/src/kwai/modules/club/get_members.py b/backend/src/kwai/modules/club/get_members.py
index 848841fb6..9172252ed 100644
--- a/backend/src/kwai/modules/club/get_members.py
+++ b/backend/src/kwai/modules/club/get_members.py
@@ -2,9 +2,10 @@
from dataclasses import dataclass
-from kwai.core.domain.use_case import UseCaseBrowseResult
+from kwai.core.domain.presenter import AsyncPresenter, IterableResult
from kwai.core.domain.value_objects.date import Date
-from kwai.modules.club.members.member_repository import MemberRepository
+from kwai.modules.club.domain.member import MemberEntity
+from kwai.modules.club.repositories.member_repository import MemberRepository
@dataclass(kw_only=True, frozen=True, slots=True)
@@ -29,15 +30,21 @@ class GetMembersCommand:
class GetMembers:
"""Use case get members."""
- def __init__(self, repo: MemberRepository):
+ def __init__(
+ self,
+ repo: MemberRepository,
+ presenter: AsyncPresenter[IterableResult[MemberEntity]],
+ ):
"""Initialize use case.
Args:
repo: The repository for members.
+ presenter: The presenter for members.
"""
self._repo = repo
+ self._presenter = presenter
- async def execute(self, command: GetMembersCommand) -> UseCaseBrowseResult:
+ async def execute(self, command: GetMembersCommand):
"""Execute the use case.
Args:
@@ -53,7 +60,11 @@ async def execute(self, command: GetMembersCommand) -> UseCaseBrowseResult:
command.license_end_month, command.license_end_year or Date.today().year
)
- return UseCaseBrowseResult(
- count=await query.count(),
- iterator=self._repo.get_all(query, command.limit, command.offset),
+ await self._presenter.present(
+ IterableResult(
+ count=await query.count(),
+ limit=command.limit,
+ offset=command.offset,
+ iterator=self._repo.get_all(query, command.limit, command.offset),
+ )
)
diff --git a/backend/src/kwai/modules/club/import_members.py b/backend/src/kwai/modules/club/import_members.py
index e3ff5e088..3148acabe 100644
--- a/backend/src/kwai/modules/club/import_members.py
+++ b/backend/src/kwai/modules/club/import_members.py
@@ -2,22 +2,22 @@
from abc import ABC
from dataclasses import dataclass
-from typing import AsyncGenerator
from kwai.core.domain.entity import Entity
+from kwai.core.domain.presenter import Presenter
from kwai.core.domain.use_case import UseCaseResult
-from kwai.modules.club.members import member_importer
-from kwai.modules.club.members.file_upload import FileUploadEntity
-from kwai.modules.club.members.file_upload_repository import FileUploadRepository
-from kwai.modules.club.members.member import MemberEntity
-from kwai.modules.club.members.member_repository import (
+from kwai.modules.club.domain.file_upload import FileUploadEntity
+from kwai.modules.club.domain.member import MemberEntity
+from kwai.modules.club.repositories import member_importer
+from kwai.modules.club.repositories.file_upload_repository import FileUploadRepository
+from kwai.modules.club.repositories.member_repository import (
MemberNotFoundException,
MemberRepository,
)
@dataclass(kw_only=True, slots=True, frozen=True)
-class Result(UseCaseResult, ABC):
+class MemberImportResult(UseCaseResult, ABC):
"""The result of the use case ImportMembers."""
file_upload: FileUploadEntity
@@ -25,7 +25,7 @@ class Result(UseCaseResult, ABC):
@dataclass(kw_only=True, slots=True, frozen=True)
-class OkResult(Result):
+class OkMemberImportResult(MemberImportResult):
"""A successful import of a member."""
member: MemberEntity
@@ -35,20 +35,20 @@ def to_message(self) -> str:
@dataclass(kw_only=True, slots=True, frozen=True)
-class FailureResult(Result):
+class FailureMemberImportResult(MemberImportResult):
"""An import of a member failed."""
message: str
def to_message(self) -> str:
- return f"Import failed for row {self.row}: {self.message}."
+ return self.message
@dataclass(kw_only=True, slots=True, frozen=True)
class ImportMembersCommand:
"""Input for the use case "ImportMembers"."""
- test: bool = True
+ preview: bool = True
class ImportMembers:
@@ -59,6 +59,7 @@ def __init__(
importer: member_importer.MemberImporter,
file_upload_repo: FileUploadRepository,
member_repo: MemberRepository,
+ presenter: Presenter,
):
"""Initialize the use case.
@@ -66,49 +67,57 @@ def __init__(
importer: A class that is responsible for importing members from a resource.
file_upload_repo: A repository for storing the file upload information.
member_repo: A repository for managing members.
+ presenter: A presenter
"""
self._importer = importer
self._file_upload_repo = file_upload_repo
self._member_repo = member_repo
+ self._presenter = presenter
- async def execute(
- self, command: ImportMembersCommand
- ) -> AsyncGenerator[Result, None]:
- """Execute the use case.
-
- Yields:
- OkResult: When the row was successfully imported.
- FailureResult: When the row was not successfully imported.
- """
+ async def execute(self, command: ImportMembersCommand):
+ """Execute the use case."""
file_upload_entity = await self._file_upload_repo.create(
- self._importer.create_file_upload_entity()
+ self._importer.create_file_upload_entity(command.preview)
)
async for import_result in self._importer.import_():
match import_result:
case member_importer.OkResult():
- member = await self._save_member(import_result.member, command.test)
- yield OkResult(
- file_upload=file_upload_entity,
- row=import_result.row,
- member=member,
+ member = await self._save_member(
+ file_upload_entity, import_result.member, command.preview
+ )
+ self._presenter.present(
+ OkMemberImportResult(
+ file_upload=file_upload_entity,
+ row=import_result.row,
+ member=member,
+ )
)
case member_importer.FailureResult():
- yield FailureResult(
- file_upload=file_upload_entity,
- row=import_result.row,
- message=import_result.message,
+ self._presenter.present(
+ FailureMemberImportResult(
+ file_upload=file_upload_entity,
+ row=import_result.row,
+ message=import_result.message,
+ )
)
+ if not command.preview:
+ await self._activate_members(file_upload_entity)
- async def _save_member(self, member: MemberEntity, test: bool) -> MemberEntity:
+ async def _save_member(
+ self, file_upload: FileUploadEntity, member: MemberEntity, preview: bool
+ ) -> MemberEntity:
"""Create or update the member."""
existing_member = await self._get_member(member)
if existing_member is not None:
updated_member = self._update_member(existing_member, member)
- if not test:
+ if not preview:
await self._member_repo.update(updated_member)
+ await self._file_upload_repo.save_member(file_upload, updated_member)
return updated_member
- if not test:
- return await self._member_repo.create(member)
+
+ if not preview:
+ member = await self._member_repo.create(member)
+ await self._file_upload_repo.save_member(file_upload, member)
return member
@classmethod
@@ -154,3 +163,12 @@ async def _get_member(self, member: MemberEntity) -> MemberEntity | None:
return None
return member
+
+ async def _activate_members(self, upload_entity: FileUploadEntity):
+ """Activate members.
+
+ Members that are part of the upload will be activated.
+ Members not part of the upload will be deactivated.
+ """
+ await self._member_repo.activate_members(upload_entity)
+ await self._member_repo.deactivate_members(upload_entity)
diff --git a/backend/src/kwai/modules/club/members/__init__.py b/backend/src/kwai/modules/club/members/__init__.py
deleted file mode 100644
index f103a4d4a..000000000
--- a/backend/src/kwai/modules/club/members/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-"""Package for all modules related to members."""
diff --git a/backend/src/kwai/modules/club/repositories/__init__.py b/backend/src/kwai/modules/club/repositories/__init__.py
new file mode 100644
index 000000000..c6660d92a
--- /dev/null
+++ b/backend/src/kwai/modules/club/repositories/__init__.py
@@ -0,0 +1 @@
+"""Package for all the repositories."""
diff --git a/backend/src/kwai/modules/club/members/member_tables.py b/backend/src/kwai/modules/club/repositories/_tables.py
similarity index 78%
rename from backend/src/kwai/modules/club/members/member_tables.py
rename to backend/src/kwai/modules/club/repositories/_tables.py
index b2ceca2ce..0f73f56dd 100644
--- a/backend/src/kwai/modules/club/members/member_tables.py
+++ b/backend/src/kwai/modules/club/repositories/_tables.py
@@ -11,12 +11,13 @@
from kwai.core.domain.value_objects.timestamp import Timestamp
from kwai.core.domain.value_objects.traceable_time import TraceableTime
from kwai.core.domain.value_objects.unique_id import UniqueId
-from kwai.modules.club.members.contact import ContactEntity, ContactIdentifier
-from kwai.modules.club.members.country import CountryEntity, CountryIdentifier
-from kwai.modules.club.members.file_upload import FileUploadEntity
-from kwai.modules.club.members.member import MemberEntity, MemberIdentifier
-from kwai.modules.club.members.person import PersonEntity, PersonIdentifier
-from kwai.modules.club.members.value_objects import (
+from kwai.modules.club.domain.coach import CoachEntity
+from kwai.modules.club.domain.contact import ContactEntity, ContactIdentifier
+from kwai.modules.club.domain.country import CountryEntity, CountryIdentifier
+from kwai.modules.club.domain.file_upload import FileUploadEntity
+from kwai.modules.club.domain.member import MemberEntity, MemberIdentifier
+from kwai.modules.club.domain.person import PersonEntity, PersonIdentifier
+from kwai.modules.club.domain.value_objects import (
Address,
Birthdate,
Gender,
@@ -90,6 +91,7 @@ class FileUploadRow(TableRow):
uuid: str
filename: str
remark: str
+ preview: int
user_id: int
created_at: datetime
updated_at: datetime | None
@@ -106,6 +108,7 @@ def persist(cls, file_upload: FileUploadEntity) -> Self:
uuid=str(file_upload.uuid),
filename=file_upload.filename,
remark=file_upload.remark,
+ preview=1 if file_upload.preview else 0,
user_id=file_upload.owner.id.value,
created_at=file_upload.traceable_time.created_at.timestamp, # type: ignore[arg-type]
updated_at=file_upload.traceable_time.updated_at.timestamp,
@@ -198,8 +201,8 @@ def create_entity(
remark=self.remark or "",
contact=contact,
traceable_time=TraceableTime(
- created_at=Timestamp(self.created_at),
- updated_at=Timestamp(self.updated_at),
+ created_at=Timestamp.create_utc(self.created_at),
+ updated_at=Timestamp.create_utc(self.updated_at),
),
nationality=nationality,
)
@@ -253,8 +256,8 @@ def create_entity(self, person: PersonEntity) -> MemberEntity:
active=self.active == 1,
person=person,
traceable_time=TraceableTime(
- created_at=Timestamp(self.created_at),
- updated_at=Timestamp(self.updated_at),
+ created_at=Timestamp.create_utc(self.created_at),
+ updated_at=Timestamp.create_utc(self.updated_at),
),
)
@@ -273,3 +276,53 @@ def persist(cls, member: MemberEntity) -> Self:
created_at=member.traceable_time.created_at.timestamp, # type: ignore[arg-type]
updated_at=member.traceable_time.updated_at.timestamp,
)
+
+
+@dataclass(kw_only=True, frozen=True, slots=True)
+class MemberUploadRow(TableRow):
+ """Represents a row of the judo member imports table."""
+
+ __table_name__ = "judo_member_imports"
+
+ member_id: int
+ import_id: int
+ created_at: datetime
+
+ @classmethod
+ def persist(cls, upload: FileUploadEntity, member: MemberEntity) -> Self:
+ return cls(
+ member_id=member.id.value,
+ import_id=upload.id.value,
+ created_at=datetime.now(UTC),
+ )
+
+
+@dataclass(kw_only=True, frozen=True, slots=True)
+class CoachRow(TableRow):
+ """Represents a row of the coach table."""
+
+ __table_name__ = "coaches"
+
+ id: int
+ member_id: int
+ description: str
+ diploma: str
+ active: int
+ remark: str
+ user_id: int | None
+ created_at: datetime
+ updated_at: datetime | None
+
+ @classmethod
+ def persist(cls, coach: CoachEntity) -> Self:
+ return cls(
+ id=coach.id.value,
+ member_id=coach.member.id.value,
+ description=coach.description,
+ diploma=coach.diploma,
+ active=1 if coach.is_active else 0,
+ remark=coach.remark,
+ user_id=None if coach.user is None else coach.user.id.value,
+ created_at=coach.traceable_time.created_at.timestamp, # type: ignore[arg-type]
+ updated_at=coach.traceable_time.updated_at.timestamp,
+ )
diff --git a/backend/src/kwai/modules/club/repositories/coach_db_repository.py b/backend/src/kwai/modules/club/repositories/coach_db_repository.py
new file mode 100644
index 000000000..6bb325578
--- /dev/null
+++ b/backend/src/kwai/modules/club/repositories/coach_db_repository.py
@@ -0,0 +1,23 @@
+"""Module for defining a coach repository using a database."""
+
+from kwai.core.db.database import Database
+from kwai.core.domain.entity import Entity
+from kwai.modules.club.domain.coach import CoachEntity, CoachIdentifier
+from kwai.modules.club.repositories._tables import CoachRow
+from kwai.modules.club.repositories.coach_repository import CoachRepository
+
+
+class CoachDbRepository(CoachRepository):
+ """A coach repository using a database."""
+
+ def __init__(self, database: Database) -> None:
+ self._database = database
+
+ async def create(self, coach: CoachEntity):
+ new_coach_id = await self._database.insert(
+ CoachRow.__table_name__, CoachRow.persist(coach)
+ )
+ return Entity.replace(coach, id_=CoachIdentifier(new_coach_id))
+
+ async def delete(self, coach: CoachEntity):
+ await self._database.delete(coach.id.value, CoachRow.__table_name__)
diff --git a/backend/src/kwai/modules/club/repositories/coach_repository.py b/backend/src/kwai/modules/club/repositories/coach_repository.py
new file mode 100644
index 000000000..3f9e8ffc5
--- /dev/null
+++ b/backend/src/kwai/modules/club/repositories/coach_repository.py
@@ -0,0 +1,19 @@
+"""Module for defining an interface for a coach repository."""
+
+from abc import ABC, abstractmethod
+
+from kwai.modules.club.domain.coach import CoachEntity
+
+
+class CoachRepository(ABC):
+ """An interface for a coach repository."""
+
+ @abstractmethod
+ async def create(self, coach: CoachEntity):
+ """Save a new coach."""
+ raise NotImplementedError
+
+ @abstractmethod
+ async def delete(self, coach: CoachEntity):
+ """Delete an existing coach."""
+ raise NotImplementedError
diff --git a/backend/src/kwai/modules/club/members/contact_db_repository.py b/backend/src/kwai/modules/club/repositories/contact_db_repository.py
similarity index 90%
rename from backend/src/kwai/modules/club/members/contact_db_repository.py
rename to backend/src/kwai/modules/club/repositories/contact_db_repository.py
index 270e073d8..297dcf9d8 100644
--- a/backend/src/kwai/modules/club/members/contact_db_repository.py
+++ b/backend/src/kwai/modules/club/repositories/contact_db_repository.py
@@ -7,12 +7,12 @@
from kwai.core.db.database import Database
from kwai.core.db.table_row import JoinedTableRow
from kwai.core.domain.entity import Entity
-from kwai.modules.club.members.contact import ContactEntity, ContactIdentifier
-from kwai.modules.club.members.contact_repository import (
+from kwai.modules.club.domain.contact import ContactEntity, ContactIdentifier
+from kwai.modules.club.repositories._tables import ContactRow, CountryRow
+from kwai.modules.club.repositories.contact_repository import (
ContactNotFoundException,
ContactRepository,
)
-from kwai.modules.club.members.member_tables import ContactRow, CountryRow
@dataclass(kw_only=True, frozen=True, slots=True)
diff --git a/backend/src/kwai/modules/club/members/contact_repository.py b/backend/src/kwai/modules/club/repositories/contact_repository.py
similarity index 90%
rename from backend/src/kwai/modules/club/members/contact_repository.py
rename to backend/src/kwai/modules/club/repositories/contact_repository.py
index 11973b60b..39f0caab9 100644
--- a/backend/src/kwai/modules/club/members/contact_repository.py
+++ b/backend/src/kwai/modules/club/repositories/contact_repository.py
@@ -2,7 +2,7 @@
from abc import ABC, abstractmethod
-from kwai.modules.club.members.contact import ContactEntity, ContactIdentifier
+from kwai.modules.club.domain.contact import ContactEntity, ContactIdentifier
class ContactNotFoundException(Exception):
diff --git a/backend/src/kwai/modules/club/members/country_db_repository.py b/backend/src/kwai/modules/club/repositories/country_db_repository.py
similarity index 86%
rename from backend/src/kwai/modules/club/members/country_db_repository.py
rename to backend/src/kwai/modules/club/repositories/country_db_repository.py
index 02c7d678b..d578c3e5b 100644
--- a/backend/src/kwai/modules/club/members/country_db_repository.py
+++ b/backend/src/kwai/modules/club/repositories/country_db_repository.py
@@ -4,12 +4,12 @@
from kwai.core.db.database import Database
from kwai.core.domain.entity import Entity
-from kwai.modules.club.members.country import CountryEntity, CountryIdentifier
-from kwai.modules.club.members.country_repository import (
+from kwai.modules.club.domain.country import CountryEntity, CountryIdentifier
+from kwai.modules.club.repositories._tables import CountryRow
+from kwai.modules.club.repositories.country_repository import (
CountryNotFoundException,
CountryRepository,
)
-from kwai.modules.club.members.member_tables import CountryRow
class CountryDbRepository(CountryRepository):
diff --git a/backend/src/kwai/modules/club/members/country_repository.py b/backend/src/kwai/modules/club/repositories/country_repository.py
similarity index 91%
rename from backend/src/kwai/modules/club/members/country_repository.py
rename to backend/src/kwai/modules/club/repositories/country_repository.py
index 1dcd08107..1584889b2 100644
--- a/backend/src/kwai/modules/club/members/country_repository.py
+++ b/backend/src/kwai/modules/club/repositories/country_repository.py
@@ -2,7 +2,7 @@
from abc import ABC, abstractmethod
-from kwai.modules.club.members.country import CountryEntity
+from kwai.modules.club.domain.country import CountryEntity
class CountryNotFoundException(Exception):
diff --git a/backend/src/kwai/modules/club/members/file_upload_db_repository.py b/backend/src/kwai/modules/club/repositories/file_upload_db_repository.py
similarity index 58%
rename from backend/src/kwai/modules/club/members/file_upload_db_repository.py
rename to backend/src/kwai/modules/club/repositories/file_upload_db_repository.py
index f6937b3c1..eb8b263ff 100644
--- a/backend/src/kwai/modules/club/members/file_upload_db_repository.py
+++ b/backend/src/kwai/modules/club/repositories/file_upload_db_repository.py
@@ -2,9 +2,10 @@
from kwai.core.db.database import Database
from kwai.core.domain.entity import Entity
-from kwai.modules.club.members.file_upload import FileUploadEntity, FileUploadIdentifier
-from kwai.modules.club.members.file_upload_repository import FileUploadRepository
-from kwai.modules.club.members.member_tables import FileUploadRow
+from kwai.modules.club.domain.file_upload import FileUploadEntity, FileUploadIdentifier
+from kwai.modules.club.domain.member import MemberEntity
+from kwai.modules.club.repositories._tables import FileUploadRow, MemberUploadRow
+from kwai.modules.club.repositories.file_upload_repository import FileUploadRepository
class FileUploadDbRepository(FileUploadRepository):
@@ -22,5 +23,10 @@ async def create(self, file_upload: FileUploadEntity) -> FileUploadEntity:
new_id = await self._database.insert(
FileUploadRow.__table_name__, FileUploadRow.persist(file_upload)
)
- await self._database.commit()
return Entity.replace(file_upload, id_=FileUploadIdentifier(new_id))
+
+ async def save_member(self, file_upload: FileUploadEntity, member: MemberEntity):
+ await self._database.insert(
+ MemberUploadRow.__table_name__,
+ MemberUploadRow.persist(file_upload, member),
+ )
diff --git a/backend/src/kwai/modules/club/members/file_upload_repository.py b/backend/src/kwai/modules/club/repositories/file_upload_repository.py
similarity index 52%
rename from backend/src/kwai/modules/club/members/file_upload_repository.py
rename to backend/src/kwai/modules/club/repositories/file_upload_repository.py
index a7fe55b95..5fe282b81 100644
--- a/backend/src/kwai/modules/club/members/file_upload_repository.py
+++ b/backend/src/kwai/modules/club/repositories/file_upload_repository.py
@@ -1,7 +1,9 @@
"""Module that defines an interface for a file upload repository."""
+
from abc import ABC, abstractmethod
-from kwai.modules.club.members.file_upload import FileUploadEntity
+from kwai.modules.club.domain.file_upload import FileUploadEntity
+from kwai.modules.club.domain.member import MemberEntity
class FileUploadRepository(ABC):
@@ -18,3 +20,13 @@ async def create(self, file_upload: FileUploadEntity) -> FileUploadEntity:
file_upload: A fileupload to save.
"""
raise NotImplementedError
+
+ @abstractmethod
+ async def save_member(self, file_upload: FileUploadEntity, member: MemberEntity):
+ """Save a member imported from the file upload.
+
+ Args:
+ file_upload: The file upload.
+ member: The member from the file upload.
+ """
+ raise NotImplementedError
diff --git a/backend/src/kwai/modules/club/members/flemish_member_importer.py b/backend/src/kwai/modules/club/repositories/flemish_member_importer.py
similarity index 90%
rename from backend/src/kwai/modules/club/members/flemish_member_importer.py
rename to backend/src/kwai/modules/club/repositories/flemish_member_importer.py
index 82540f834..6a453640a 100644
--- a/backend/src/kwai/modules/club/members/flemish_member_importer.py
+++ b/backend/src/kwai/modules/club/repositories/flemish_member_importer.py
@@ -10,20 +10,20 @@
)
from kwai.core.domain.value_objects.name import Name
from kwai.core.domain.value_objects.owner import Owner
-from kwai.modules.club.members.contact import ContactEntity
-from kwai.modules.club.members.country_repository import (
+from kwai.modules.club.domain.contact import ContactEntity
+from kwai.modules.club.domain.member import MemberEntity
+from kwai.modules.club.domain.person import PersonEntity
+from kwai.modules.club.domain.value_objects import Address, Birthdate, Gender, License
+from kwai.modules.club.repositories.country_repository import (
CountryNotFoundException,
CountryRepository,
)
-from kwai.modules.club.members.member import MemberEntity
-from kwai.modules.club.members.member_importer import (
+from kwai.modules.club.repositories.member_importer import (
FailureResult,
MemberImporter,
OkResult,
Result,
)
-from kwai.modules.club.members.person import PersonEntity
-from kwai.modules.club.members.value_objects import Address, Birthdate, Gender, License
class FlemishMemberImporter(MemberImporter):
@@ -68,7 +68,7 @@ async def import_(self) -> AsyncGenerator[Result, None]:
emails = []
try:
for email in row["email"].split(";"):
- emails.append(EmailAddress(email))
+ emails.append(EmailAddress(email.strip()))
except InvalidEmailException as exc:
yield FailureResult(row=row_index, message=str(exc))
continue
diff --git a/backend/src/kwai/modules/club/members/member_db_query.py b/backend/src/kwai/modules/club/repositories/member_db_query.py
similarity index 94%
rename from backend/src/kwai/modules/club/members/member_db_query.py
rename to backend/src/kwai/modules/club/repositories/member_db_query.py
index 55ab71296..b6aa4f591 100644
--- a/backend/src/kwai/modules/club/members/member_db_query.py
+++ b/backend/src/kwai/modules/club/repositories/member_db_query.py
@@ -9,14 +9,14 @@
from kwai.core.db.database_query import DatabaseQuery
from kwai.core.db.table_row import JoinedTableRow
from kwai.core.domain.value_objects.unique_id import UniqueId
-from kwai.modules.club.members.member import MemberEntity, MemberIdentifier
-from kwai.modules.club.members.member_query import MemberQuery
-from kwai.modules.club.members.member_tables import (
+from kwai.modules.club.domain.member import MemberEntity, MemberIdentifier
+from kwai.modules.club.repositories._tables import (
ContactRow,
CountryRow,
MemberRow,
PersonRow,
)
+from kwai.modules.club.repositories.member_query import MemberQuery
@dataclass(kw_only=True, frozen=True, slots=True)
diff --git a/backend/src/kwai/modules/club/members/member_db_repository.py b/backend/src/kwai/modules/club/repositories/member_db_repository.py
similarity index 57%
rename from backend/src/kwai/modules/club/members/member_db_repository.py
rename to backend/src/kwai/modules/club/repositories/member_db_repository.py
index 07d08d34f..05cfefcf7 100644
--- a/backend/src/kwai/modules/club/members/member_db_repository.py
+++ b/backend/src/kwai/modules/club/repositories/member_db_repository.py
@@ -2,17 +2,20 @@
from typing import AsyncGenerator
+from sql_smith.functions import field
+
from kwai.core.db.database import Database
from kwai.core.domain.entity import Entity
-from kwai.modules.club.members.member import MemberEntity, MemberIdentifier
-from kwai.modules.club.members.member_db_query import MemberDbQuery, MemberQueryRow
-from kwai.modules.club.members.member_query import MemberQuery
-from kwai.modules.club.members.member_repository import (
+from kwai.modules.club.domain.file_upload import FileUploadEntity
+from kwai.modules.club.domain.member import MemberEntity, MemberIdentifier
+from kwai.modules.club.repositories._tables import MemberRow, MemberUploadRow
+from kwai.modules.club.repositories.member_db_query import MemberDbQuery, MemberQueryRow
+from kwai.modules.club.repositories.member_query import MemberQuery
+from kwai.modules.club.repositories.member_repository import (
MemberNotFoundException,
MemberRepository,
)
-from kwai.modules.club.members.member_tables import MemberRow
-from kwai.modules.club.members.person_db_repository import PersonDbRepository
+from kwai.modules.club.repositories.person_db_repository import PersonDbRepository
class MemberDbRepository(MemberRepository):
@@ -70,3 +73,31 @@ async def update(self, member: MemberEntity) -> None:
async def delete(self, member: MemberEntity) -> None:
await PersonDbRepository(self._database).delete(member.person)
await self._database.delete(member.id, MemberRow.__table_name__)
+
+ async def activate_members(self, upload: FileUploadEntity) -> None:
+ member_upload_query = (
+ self._database.create_query_factory()
+ .select("member_id")
+ .from_(MemberUploadRow.__table_name__)
+ .where(field("import_id").eq(upload.id.value))
+ )
+ update_query = (
+ self._database.create_query_factory()
+ .update(MemberRow.__table_name__, {"active": 1})
+ .where(field("id").in_(member_upload_query))
+ )
+ await self._database.execute(update_query)
+
+ async def deactivate_members(self, upload: FileUploadEntity) -> None:
+ member_upload_query = (
+ self._database.create_query_factory()
+ .select("member_id")
+ .from_(MemberUploadRow.__table_name__)
+ .where(field("import_id").eq(upload.id.value))
+ )
+ update_query = (
+ self._database.create_query_factory()
+ .update(MemberRow.__table_name__, {"active": 0})
+ .where(field("id").not_in(member_upload_query))
+ )
+ await self._database.execute(update_query)
diff --git a/backend/src/kwai/modules/club/members/member_importer.py b/backend/src/kwai/modules/club/repositories/member_importer.py
similarity index 80%
rename from backend/src/kwai/modules/club/members/member_importer.py
rename to backend/src/kwai/modules/club/repositories/member_importer.py
index a4e1007e4..e1e85a181 100644
--- a/backend/src/kwai/modules/club/members/member_importer.py
+++ b/backend/src/kwai/modules/club/repositories/member_importer.py
@@ -7,10 +7,10 @@
from async_lru import alru_cache
from kwai.core.domain.value_objects.owner import Owner
-from kwai.modules.club.members.country import CountryEntity
-from kwai.modules.club.members.country_repository import CountryRepository
-from kwai.modules.club.members.file_upload import FileUploadEntity
-from kwai.modules.club.members.member import MemberEntity
+from kwai.modules.club.domain.country import CountryEntity
+from kwai.modules.club.domain.file_upload import FileUploadEntity
+from kwai.modules.club.domain.member import MemberEntity
+from kwai.modules.club.repositories.country_repository import CountryRepository
@dataclass(kw_only=True, frozen=True, slots=True)
@@ -56,9 +56,11 @@ def import_(self) -> AsyncGenerator[Result, None]:
For each imported (or failed import) of a member, a result will be yielded.
"""
- def create_file_upload_entity(self) -> FileUploadEntity:
+ def create_file_upload_entity(self, preview: bool) -> FileUploadEntity:
"""Create a file upload entity."""
- return FileUploadEntity(filename=self._filename, owner=self._owner)
+ return FileUploadEntity(
+ filename=self._filename, owner=self._owner, preview=preview
+ )
@staticmethod
@alru_cache
diff --git a/backend/src/kwai/modules/club/members/member_query.py b/backend/src/kwai/modules/club/repositories/member_query.py
similarity index 93%
rename from backend/src/kwai/modules/club/members/member_query.py
rename to backend/src/kwai/modules/club/repositories/member_query.py
index 3d27e6dd5..bcd4e72d8 100644
--- a/backend/src/kwai/modules/club/members/member_query.py
+++ b/backend/src/kwai/modules/club/repositories/member_query.py
@@ -5,7 +5,7 @@
from kwai.core.domain.repository.query import Query
from kwai.core.domain.value_objects.unique_id import UniqueId
-from kwai.modules.club.members.member import MemberIdentifier
+from kwai.modules.club.domain.member import MemberIdentifier
class MemberQuery(Query, ABC):
diff --git a/backend/src/kwai/modules/club/members/member_repository.py b/backend/src/kwai/modules/club/repositories/member_repository.py
similarity index 75%
rename from backend/src/kwai/modules/club/members/member_repository.py
rename to backend/src/kwai/modules/club/repositories/member_repository.py
index c1bf81cea..2cfb33d8e 100644
--- a/backend/src/kwai/modules/club/members/member_repository.py
+++ b/backend/src/kwai/modules/club/repositories/member_repository.py
@@ -3,8 +3,9 @@
from abc import ABC, abstractmethod
from typing import AsyncGenerator
-from kwai.modules.club.members.member import MemberEntity
-from kwai.modules.club.members.member_query import MemberQuery
+from kwai.modules.club.domain.file_upload import FileUploadEntity
+from kwai.modules.club.domain.member import MemberEntity
+from kwai.modules.club.repositories.member_query import MemberQuery
class MemberNotFoundException(Exception):
@@ -27,7 +28,7 @@ async def get(self, query: MemberQuery | None = None) -> MemberEntity:
query: The query to use for getting the first member.
Raises:
- MemberNotFoundException
+ MemberNotFoundException: Raised when the member is not found.
"""
raise NotImplementedError
@@ -79,3 +80,13 @@ async def delete(self, member: MemberEntity) -> None:
member: The member to delete.
"""
raise NotImplementedError
+
+ @abstractmethod
+ async def activate_members(self, upload: FileUploadEntity) -> None:
+ """Activate all members that have been uploaded."""
+ raise NotImplementedError
+
+ @abstractmethod
+ async def deactivate_members(self, upload: FileUploadEntity) -> None:
+ """Deactivate all members that are not being uploaded."""
+ raise NotImplementedError
diff --git a/backend/src/kwai/modules/club/members/person_db_repository.py b/backend/src/kwai/modules/club/repositories/person_db_repository.py
similarity index 89%
rename from backend/src/kwai/modules/club/members/person_db_repository.py
rename to backend/src/kwai/modules/club/repositories/person_db_repository.py
index eb55a89b4..a61364eb9 100644
--- a/backend/src/kwai/modules/club/members/person_db_repository.py
+++ b/backend/src/kwai/modules/club/repositories/person_db_repository.py
@@ -7,10 +7,14 @@
from kwai.core.db.database import Database
from kwai.core.db.table_row import JoinedTableRow
from kwai.core.domain.entity import Entity
-from kwai.modules.club.members.contact_db_repository import ContactDbRepository
-from kwai.modules.club.members.member_tables import ContactRow, CountryRow, PersonRow
-from kwai.modules.club.members.person import PersonEntity, PersonIdentifier
-from kwai.modules.club.members.person_repository import (
+from kwai.modules.club.domain.person import PersonEntity, PersonIdentifier
+from kwai.modules.club.repositories._tables import (
+ ContactRow,
+ CountryRow,
+ PersonRow,
+)
+from kwai.modules.club.repositories.contact_db_repository import ContactDbRepository
+from kwai.modules.club.repositories.person_repository import (
PersonNotFoundException,
PersonRepository,
)
diff --git a/backend/src/kwai/modules/club/members/person_repository.py b/backend/src/kwai/modules/club/repositories/person_repository.py
similarity index 90%
rename from backend/src/kwai/modules/club/members/person_repository.py
rename to backend/src/kwai/modules/club/repositories/person_repository.py
index d5de5d4f5..6f81ecfe3 100644
--- a/backend/src/kwai/modules/club/members/person_repository.py
+++ b/backend/src/kwai/modules/club/repositories/person_repository.py
@@ -2,7 +2,7 @@
from abc import ABC, abstractmethod
-from kwai.modules.club.members.person import PersonEntity, PersonIdentifier
+from kwai.modules.club.domain.person import PersonEntity, PersonIdentifier
class PersonNotFoundException(Exception):
diff --git a/backend/src/kwai/modules/identity/authenticate_user.py b/backend/src/kwai/modules/identity/authenticate_user.py
index 919fa4c2a..bcb7c998f 100644
--- a/backend/src/kwai/modules/identity/authenticate_user.py
+++ b/backend/src/kwai/modules/identity/authenticate_user.py
@@ -1,8 +1,9 @@
"""Module that implements the use case: authenticate user."""
+
from dataclasses import dataclass
-from datetime import datetime, timedelta
from kwai.core.domain.value_objects.email_address import EmailAddress
+from kwai.core.domain.value_objects.timestamp import Timestamp
from kwai.modules.identity.exceptions import AuthenticationException
from kwai.modules.identity.tokens.access_token import AccessTokenEntity
from kwai.modules.identity.tokens.access_token_repository import AccessTokenRepository
@@ -87,8 +88,9 @@ async def execute(self, command: AuthenticateUserCommand) -> RefreshTokenEntity:
access_token = await self._access_token_repo.create(
AccessTokenEntity(
identifier=TokenIdentifier.generate(),
- expiration=datetime.utcnow()
- + timedelta(minutes=command.access_token_expiry_minutes),
+ expiration=Timestamp.create_with_delta(
+ minutes=command.access_token_expiry_minutes
+ ),
user_account=user_account,
)
)
@@ -96,8 +98,9 @@ async def execute(self, command: AuthenticateUserCommand) -> RefreshTokenEntity:
return await self._refresh_token_repo.create(
RefreshTokenEntity(
identifier=TokenIdentifier.generate(),
- expiration=datetime.utcnow()
- + timedelta(minutes=command.refresh_token_expiry_minutes),
+ expiration=Timestamp.create_with_delta(
+ minutes=command.refresh_token_expiry_minutes
+ ),
access_token=access_token,
)
)
diff --git a/backend/src/kwai/modules/identity/refresh_access_token.py b/backend/src/kwai/modules/identity/refresh_access_token.py
index 1814cec26..1265af7d4 100644
--- a/backend/src/kwai/modules/identity/refresh_access_token.py
+++ b/backend/src/kwai/modules/identity/refresh_access_token.py
@@ -1,7 +1,8 @@
"""Module that defines the use case for refreshing an access token."""
+
from dataclasses import dataclass
-from datetime import datetime, timedelta
+from kwai.core.domain.value_objects.timestamp import Timestamp
from kwai.modules.identity.authenticate_user import AuthenticationException
from kwai.modules.identity.tokens.access_token import AccessTokenEntity
from kwai.modules.identity.tokens.access_token_repository import AccessTokenRepository
@@ -82,8 +83,9 @@ async def execute(self, command: RefreshAccessTokenCommand) -> RefreshTokenEntit
access_token = await self._access_token_repo.create(
AccessTokenEntity(
identifier=TokenIdentifier.generate(),
- expiration=datetime.utcnow()
- + timedelta(minutes=command.access_token_expiry_minutes),
+ expiration=Timestamp.create_with_delta(
+ minutes=command.access_token_expiry_minutes
+ ),
user_account=refresh_token.access_token.user_account,
)
)
@@ -91,8 +93,9 @@ async def execute(self, command: RefreshAccessTokenCommand) -> RefreshTokenEntit
return await self._refresh_token_repo.create(
RefreshTokenEntity(
identifier=TokenIdentifier.generate(),
- expiration=datetime.utcnow()
- + timedelta(minutes=command.refresh_token_expiry_minutes),
+ expiration=Timestamp.create_with_delta(
+ minutes=command.refresh_token_expiry_minutes
+ ),
access_token=access_token,
)
)
diff --git a/backend/src/kwai/modules/identity/tokens/access_token.py b/backend/src/kwai/modules/identity/tokens/access_token.py
index cea3c6e6d..c208ef71b 100644
--- a/backend/src/kwai/modules/identity/tokens/access_token.py
+++ b/backend/src/kwai/modules/identity/tokens/access_token.py
@@ -1,8 +1,8 @@
"""Module that defines an access token entity."""
-from datetime import datetime
from kwai.core.domain.entity import Entity
from kwai.core.domain.value_objects.identifier import IntIdentifier
+from kwai.core.domain.value_objects.timestamp import Timestamp
from kwai.core.domain.value_objects.traceable_time import TraceableTime
from kwai.modules.identity.tokens.token_identifier import TokenIdentifier
from kwai.modules.identity.users.user_account import UserAccountEntity
@@ -19,26 +19,26 @@ def __init__(
id_: AccessTokenIdentifier | None = None,
user_account: UserAccountEntity,
identifier: TokenIdentifier | None = None,
- expiration: datetime | None = None,
+ expiration: Timestamp | None = None,
revoked: bool = False,
traceable_time: TraceableTime | None = None,
):
super().__init__(id_ or AccessTokenIdentifier())
self._user_account = user_account
self._identifier = identifier or TokenIdentifier.generate()
- self._expiration = expiration or datetime.utcnow()
+ self._expiration = expiration or Timestamp.create_now()
self._revoked = revoked
self._traceable_time = traceable_time or TraceableTime()
@property
- def expiration(self) -> datetime:
+ def expiration(self) -> Timestamp:
"""Return the expiration timestamp of the access token."""
return self._expiration
@property
def expired(self) -> bool:
"""Return true when the access token is expired."""
- return self._expiration < datetime.utcnow()
+ return self._expiration.is_past
@property
def identifier(self) -> TokenIdentifier:
diff --git a/backend/src/kwai/modules/identity/tokens/refresh_token.py b/backend/src/kwai/modules/identity/tokens/refresh_token.py
index b7f02907a..72cca7245 100644
--- a/backend/src/kwai/modules/identity/tokens/refresh_token.py
+++ b/backend/src/kwai/modules/identity/tokens/refresh_token.py
@@ -1,8 +1,8 @@
"""Module for a refresh token entity."""
-from datetime import datetime
from kwai.core.domain.entity import Entity
from kwai.core.domain.value_objects.identifier import IntIdentifier
+from kwai.core.domain.value_objects.timestamp import Timestamp
from kwai.core.domain.value_objects.traceable_time import TraceableTime
from kwai.modules.identity.tokens.access_token import AccessTokenEntity
from kwai.modules.identity.tokens.token_identifier import TokenIdentifier
@@ -19,14 +19,14 @@ def __init__(
id_: RefreshTokenIdentifier | None = None,
access_token: AccessTokenEntity,
identifier: TokenIdentifier | None = None,
- expiration: datetime | None,
+ expiration: Timestamp | None,
revoked: bool = False,
traceable_time: TraceableTime | None = None,
):
super().__init__(id_ or RefreshTokenIdentifier())
self._access_token = access_token
self._identifier = identifier or TokenIdentifier.generate()
- self._expiration = expiration or datetime.utcnow()
+ self._expiration = expiration or Timestamp.create_now()
self._revoked = revoked
self._traceable_time = traceable_time or TraceableTime()
@@ -36,14 +36,14 @@ def access_token(self) -> AccessTokenEntity:
return self._access_token
@property
- def expiration(self) -> datetime:
+ def expiration(self) -> Timestamp:
"""Return the expiration timestamp of the refresh token."""
return self._expiration
@property
def expired(self) -> bool:
"""Return True when the token is expired."""
- return self._expiration < datetime.utcnow()
+ return self._expiration.is_past
@property
def identifier(self) -> TokenIdentifier:
diff --git a/backend/src/kwai/modules/identity/tokens/token_tables.py b/backend/src/kwai/modules/identity/tokens/token_tables.py
index 0ae02cbb4..1303b3346 100644
--- a/backend/src/kwai/modules/identity/tokens/token_tables.py
+++ b/backend/src/kwai/modules/identity/tokens/token_tables.py
@@ -35,12 +35,12 @@ def create_entity(self, user_account: UserAccountEntity) -> AccessTokenEntity:
return AccessTokenEntity(
id_=AccessTokenIdentifier(self.id),
identifier=TokenIdentifier(hex_string=self.identifier),
- expiration=self.expiration,
+ expiration=Timestamp.create_utc(self.expiration),
user_account=user_account,
revoked=self.revoked,
traceable_time=TraceableTime(
- created_at=Timestamp(timestamp=self.created_at),
- updated_at=Timestamp(timestamp=self.updated_at),
+ created_at=Timestamp.create_utc(self.created_at),
+ updated_at=Timestamp.create_utc(self.updated_at),
),
)
@@ -50,7 +50,7 @@ def persist(cls, access_token: AccessTokenEntity) -> "AccessTokenRow":
return AccessTokenRow(
id=access_token.id.value,
identifier=str(access_token.identifier),
- expiration=access_token.expiration,
+ expiration=access_token.expiration.timestamp,
user_id=access_token.user_account.id.value,
revoked=access_token.revoked,
created_at=access_token.traceable_time.created_at.timestamp,
@@ -79,11 +79,11 @@ def create_entity(self, access_token: AccessTokenEntity) -> RefreshTokenEntity:
id_=RefreshTokenIdentifier(self.id),
identifier=TokenIdentifier(hex_string=self.identifier),
access_token=access_token,
- expiration=self.expiration,
+ expiration=Timestamp.create_utc(self.expiration),
revoked=self.revoked,
traceable_time=TraceableTime(
- created_at=Timestamp(timestamp=self.created_at),
- updated_at=Timestamp(timestamp=self.updated_at),
+ created_at=Timestamp.create_utc(self.created_at),
+ updated_at=Timestamp.create_utc(self.updated_at),
),
)
@@ -94,7 +94,7 @@ def persist(cls, refresh_token: RefreshTokenEntity) -> "RefreshTokenRow":
id=refresh_token.id.value,
identifier=str(refresh_token.identifier),
access_token_id=refresh_token.access_token.id.value,
- expiration=refresh_token.expiration,
+ expiration=refresh_token.expiration.timestamp,
revoked=refresh_token.revoked,
created_at=refresh_token.traceable_time.created_at.timestamp,
updated_at=refresh_token.traceable_time.updated_at.timestamp,
diff --git a/backend/src/kwai/modules/identity/user_invitations/user_invitation_query.py b/backend/src/kwai/modules/identity/user_invitations/user_invitation_query.py
index 12c73ed76..df618b1fb 100644
--- a/backend/src/kwai/modules/identity/user_invitations/user_invitation_query.py
+++ b/backend/src/kwai/modules/identity/user_invitations/user_invitation_query.py
@@ -18,10 +18,10 @@ def filter_by_id(self, id_: UserInvitationIdentifier) -> "UserInvitationQuery":
"""Add a filter on the user invitation for id.
Args:
- id_(UserInvitationIdentifier): An id of a user invitation.
+ id_: An id of a user invitation.
Returns:
- (UserInvitationQuery): The active query
+ The active query
"""
raise NotImplementedError
@@ -29,10 +29,10 @@ def filter_by_uuid(self, uuid: UniqueId) -> "UserInvitationQuery":
"""Add a filter on the user invitation for the unique id.
Args:
- uuid(UniqueId): A unique id of a user invitation.
+ uuid: A unique id of a user invitation.
Returns:
- (UserInvitationQuery): The active query
+ The active query
"""
raise NotImplementedError
diff --git a/backend/src/kwai/modules/identity/user_invitations/user_invitation_repository.py b/backend/src/kwai/modules/identity/user_invitations/user_invitation_repository.py
index aa30b88ca..89b65ff2a 100644
--- a/backend/src/kwai/modules/identity/user_invitations/user_invitation_repository.py
+++ b/backend/src/kwai/modules/identity/user_invitations/user_invitation_repository.py
@@ -1,4 +1,5 @@
"""Module that defines an interface for an invitation repository."""
+
from abc import ABC, abstractmethod
from typing import AsyncIterator
@@ -54,7 +55,7 @@ async def get_invitation_by_id(
"""Get an invitation using the id.
Args:
- id_(UserInvitationIdentifier): The id of the invitation to search for.
+ id_: The id of the invitation to search for.
"""
raise NotImplementedError
@@ -63,7 +64,7 @@ async def get_invitation_by_uuid(self, uuid: UniqueId) -> UserInvitationEntity:
"""Get an invitation using the unique id.
Args:
- uuid(UniqueId): The unique id to use for searching the invitation.
+ uuid: The unique id to use for searching the invitation.
"""
raise NotImplementedError
@@ -72,7 +73,7 @@ async def create(self, invitation: UserInvitationEntity) -> UserInvitationEntity
"""Create a new invitation.
Args:
- invitation(UserInvitationEntity): The invitation to create.
+ invitation: The invitation to create.
"""
raise NotImplementedError
@@ -81,7 +82,7 @@ async def update(self, invitation: UserInvitationEntity) -> None:
"""Update an existing invitation.
Args:
- invitation(UserInvitationEntity): The invitation to update.
+ invitation: The invitation to update.
"""
raise NotImplementedError
@@ -90,6 +91,6 @@ async def delete(self, invitation: UserInvitationEntity) -> None:
"""Delete the invitation.
Args:
- invitation(UserInvitationEntity): The invitation to delete.
+ invitation: The invitation to delete.
"""
raise NotImplementedError
diff --git a/backend/src/kwai/modules/identity/user_invitations/user_invitation_tables.py b/backend/src/kwai/modules/identity/user_invitations/user_invitation_tables.py
index 45d8697b2..ac1c5f8f9 100644
--- a/backend/src/kwai/modules/identity/user_invitations/user_invitation_tables.py
+++ b/backend/src/kwai/modules/identity/user_invitations/user_invitation_tables.py
@@ -54,25 +54,25 @@ def create_entity(self, user: UserEntity) -> UserInvitationEntity:
"""Create a user invitation entity from the table row.
Args:
- user(UserEntity): The associated user entity
+ user: The associated user entity
Returns:
- (UserInvitationEntity)
+ A user invitation entity.
"""
return UserInvitationEntity(
id_=UserInvitationIdentifier(self.id),
email=EmailAddress(self.email),
name=Name(last_name=self.last_name, first_name=self.first_name),
uuid=UniqueId.create_from_string(self.uuid),
- expired_at=Timestamp(self.expired_at),
+ expired_at=Timestamp.create_utc(self.expired_at),
user=user,
remark=self.remark or "",
- mailed_at=Timestamp(self.mailed_at),
- confirmed_at=Timestamp(self.confirmed_at),
+ mailed_at=Timestamp.create_utc(self.mailed_at),
+ confirmed_at=Timestamp.create_utc(self.confirmed_at),
revoked=self.revoked == 1,
traceable_time=TraceableTime(
- created_at=Timestamp(self.created_at),
- updated_at=Timestamp(self.updated_at),
+ created_at=Timestamp.create_utc(self.created_at),
+ updated_at=Timestamp.create_utc(self.updated_at),
),
)
@@ -81,10 +81,10 @@ def persist(cls, invitation: UserInvitationEntity) -> "UserInvitationRow":
"""Persist a user invitation entity into a table row.
Args:
- invitation(UserInvitationEntity): The user invitation entity to persist.
+ invitation: The user invitation entity to persist.
Returns:
- (UserInvitationRow): A dataclass containing the table row data.
+ A dataclass containing the table row data.
"""
return UserInvitationRow(
id=invitation.id.value,
diff --git a/backend/src/kwai/modules/identity/user_recoveries/user_recovery_tables.py b/backend/src/kwai/modules/identity/user_recoveries/user_recovery_tables.py
index 0bbb57958..8f71718c5 100644
--- a/backend/src/kwai/modules/identity/user_recoveries/user_recovery_tables.py
+++ b/backend/src/kwai/modules/identity/user_recoveries/user_recovery_tables.py
@@ -34,13 +34,13 @@ def create_entity(self, user: UserEntity) -> UserRecoveryEntity:
id_=UserRecoveryIdentifier(self.id),
uuid=UniqueId.create_from_string(self.uuid),
user=user,
- expiration=Timestamp(self.expired_at),
+ expiration=Timestamp.create_utc(self.expired_at),
remark=self.remark,
- confirmation=Timestamp(self.confirmed_at),
- mailed_at=Timestamp(self.mailed_at),
+ confirmation=Timestamp.create_utc(self.confirmed_at),
+ mailed_at=Timestamp.create_utc(self.mailed_at),
traceable_time=TraceableTime(
- created_at=Timestamp(timestamp=self.created_at),
- updated_at=Timestamp(timestamp=self.updated_at),
+ created_at=Timestamp.create_utc(timestamp=self.created_at),
+ updated_at=Timestamp.create_utc(timestamp=self.updated_at),
),
)
diff --git a/backend/src/kwai/modules/identity/users/user_account.py b/backend/src/kwai/modules/identity/users/user_account.py
index 42a1666a8..d783af931 100644
--- a/backend/src/kwai/modules/identity/users/user_account.py
+++ b/backend/src/kwai/modules/identity/users/user_account.py
@@ -54,7 +54,7 @@ def login(self, password: str) -> bool:
When login fails, last_unsuccessful_login will be updated.
Args:
- password(str): The password.
+ password: The password.
"""
if self._password.verify(password):
self._last_login = Timestamp.create_now()
@@ -72,7 +72,7 @@ def reset_password(self, password: Password):
"""Reset the password of the user account.
Args:
- password(Password): The new password.
+ password: The new password.
"""
if self._revoked:
raise NotAllowedException()
diff --git a/backend/src/kwai/modules/identity/users/user_tables.py b/backend/src/kwai/modules/identity/users/user_tables.py
index 013995d7c..0e7393ad5 100644
--- a/backend/src/kwai/modules/identity/users/user_tables.py
+++ b/backend/src/kwai/modules/identity/users/user_tables.py
@@ -43,8 +43,8 @@ def create_entity(self) -> UserEntity:
remark=self.remark,
email=EmailAddress(self.email),
traceable_time=TraceableTime(
- created_at=Timestamp(timestamp=self.created_at),
- updated_at=Timestamp(timestamp=self.updated_at),
+ created_at=Timestamp.create_utc(timestamp=self.created_at),
+ updated_at=Timestamp.create_utc(timestamp=self.updated_at),
),
)
@@ -104,8 +104,8 @@ def create_entity(self) -> UserAccountEntity:
),
email=EmailAddress(self.email),
traceable_time=TraceableTime(
- created_at=Timestamp(self.created_at),
- updated_at=Timestamp(self.updated_at),
+ created_at=Timestamp.create_utc(self.created_at),
+ updated_at=Timestamp.create_utc(self.updated_at),
),
),
)
diff --git a/backend/src/kwai/modules/portal/applications/application_tables.py b/backend/src/kwai/modules/portal/applications/application_tables.py
index cd8310e4e..af2d3e41d 100644
--- a/backend/src/kwai/modules/portal/applications/application_tables.py
+++ b/backend/src/kwai/modules/portal/applications/application_tables.py
@@ -25,7 +25,7 @@ class ApplicationRow:
remark: a remark about the application
news: does this application can contain news stories?
pages: does this application can contain pages?
- events does this application can contain events?
+ events: does this application can contain events?
weight: a weight that can be used to order the applications
created_at: the timestamp of creation
updated_at: the timestamp of the last modification
@@ -62,8 +62,8 @@ def create_entity(self) -> ApplicationEntity:
events=self.events == 1,
weight=self.weight,
traceable_time=TraceableTime(
- created_at=Timestamp(self.created_at),
- updated_at=Timestamp(self.updated_at),
+ created_at=Timestamp.create_utc(self.created_at),
+ updated_at=Timestamp.create_utc(self.updated_at),
),
)
diff --git a/backend/src/kwai/modules/portal/news/news_item_db_query.py b/backend/src/kwai/modules/portal/news/news_item_db_query.py
index b7d165e21..bc1033518 100644
--- a/backend/src/kwai/modules/portal/news/news_item_db_query.py
+++ b/backend/src/kwai/modules/portal/news/news_item_db_query.py
@@ -1,5 +1,5 @@
"""Module that implements a NewsItemQuery for a database."""
-from datetime import datetime
+
from typing import AsyncIterator
from sql_smith.functions import criteria, express, func, group, literal, on
@@ -7,6 +7,7 @@
from kwai.core.db.database import Database
from kwai.core.db.database_query import DatabaseQuery
from kwai.core.db.rows import OwnersTable
+from kwai.core.domain.value_objects.timestamp import Timestamp
from kwai.core.domain.value_objects.unique_id import UniqueId
from kwai.modules.portal.applications.application_tables import ApplicationsTable
from kwai.modules.portal.news.news_item import NewsItemIdentifier
@@ -93,7 +94,7 @@ def filter_by_publication_date(
return self
def filter_by_promoted(self) -> "NewsItemQuery":
- now = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")
+ now = str(Timestamp.create_now())
condition = (
NewsItemsTable.field("promotion")
.gt(0)
@@ -118,7 +119,7 @@ def filter_by_application(self, application: int | str) -> "NewsItemQuery":
return self
def filter_by_active(self) -> "NewsItemQuery":
- now = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")
+ now = str(Timestamp.create_now())
self._query.and_where(
group(
NewsItemsTable.field("enabled")
diff --git a/backend/src/kwai/modules/portal/news/news_tables.py b/backend/src/kwai/modules/portal/news/news_tables.py
index b6e26e6bb..dbe983c91 100644
--- a/backend/src/kwai/modules/portal/news/news_tables.py
+++ b/backend/src/kwai/modules/portal/news/news_tables.py
@@ -88,18 +88,18 @@ def create_entity(
enabled=self.enabled == 1,
promotion=Promotion(
priority=self.promotion,
- end_date=Timestamp(self.promotion_end_date),
+ end_date=Timestamp.create_utc(self.promotion_end_date),
),
period=Period(
- start_date=Timestamp(self.publish_date),
- end_date=Timestamp(self.end_date),
+ start_date=Timestamp.create_utc(self.publish_date),
+ end_date=Timestamp.create_utc(self.end_date),
),
application=application,
texts=texts,
remark=self.remark or "",
traceable_time=TraceableTime(
- created_at=Timestamp(timestamp=self.created_at),
- updated_at=Timestamp(timestamp=self.updated_at),
+ created_at=Timestamp.create_utc(timestamp=self.created_at),
+ updated_at=Timestamp.create_utc(timestamp=self.updated_at),
),
)
diff --git a/backend/src/kwai/modules/portal/pages/page_tables.py b/backend/src/kwai/modules/portal/pages/page_tables.py
index a1ff04c08..9613434ed 100644
--- a/backend/src/kwai/modules/portal/pages/page_tables.py
+++ b/backend/src/kwai/modules/portal/pages/page_tables.py
@@ -80,8 +80,8 @@ def create_entity(
texts=content,
remark=self.remark,
traceable_time=TraceableTime(
- created_at=Timestamp(timestamp=self.created_at),
- updated_at=Timestamp(timestamp=self.updated_at),
+ created_at=Timestamp.create_utc(timestamp=self.created_at),
+ updated_at=Timestamp.create_utc(timestamp=self.updated_at),
),
)
diff --git a/backend/src/kwai/modules/teams/__init__.py b/backend/src/kwai/modules/teams/__init__.py
new file mode 100644
index 000000000..e805ce150
--- /dev/null
+++ b/backend/src/kwai/modules/teams/__init__.py
@@ -0,0 +1 @@
+"""Package for the teams module."""
diff --git a/backend/src/kwai/modules/teams/create_team.py b/backend/src/kwai/modules/teams/create_team.py
new file mode 100644
index 000000000..f9e090c6f
--- /dev/null
+++ b/backend/src/kwai/modules/teams/create_team.py
@@ -0,0 +1,37 @@
+"""Module that defines the use case 'Create Team'."""
+
+from dataclasses import dataclass
+
+from kwai.core.domain.presenter import Presenter
+from kwai.modules.teams.domain.team import TeamEntity
+from kwai.modules.teams.repositories.team_repository import TeamRepository
+
+
+@dataclass(kw_only=True, frozen=True, slots=True)
+class CreateTeamCommand:
+ """Input for the use case 'Create Team'."""
+
+ name: str
+ active: bool
+ remark: str
+
+
+class CreateTeam:
+ """Use case 'Create Team'."""
+
+ def __init__(self, team_repo: TeamRepository, presenter: Presenter[TeamEntity]):
+ """Initialize the use case.
+
+ Args:
+ team_repo: A repository that creates the team.
+ presenter: A presenter for a team entity.
+ """
+ self._team_repo = team_repo
+ self._presenter = presenter
+
+ async def execute(self, command: CreateTeamCommand) -> None:
+ """Executes the use case."""
+ team = TeamEntity(
+ name=command.name, active=command.active, remark=command.remark
+ )
+ self._presenter.present(await self._team_repo.create(team))
diff --git a/backend/src/kwai/modules/teams/create_team_member.py b/backend/src/kwai/modules/teams/create_team_member.py
new file mode 100644
index 000000000..b4f5485d2
--- /dev/null
+++ b/backend/src/kwai/modules/teams/create_team_member.py
@@ -0,0 +1,65 @@
+"""Module that defines the use case for creating a team member."""
+
+from dataclasses import dataclass
+
+from kwai.core.domain.presenter import Presenter
+from kwai.core.domain.value_objects.unique_id import UniqueId
+from kwai.modules.teams.domain.team import TeamEntity, TeamIdentifier
+from kwai.modules.teams.domain.team_member import TeamMember
+from kwai.modules.teams.repositories.member_repository import MemberRepository
+from kwai.modules.teams.repositories.team_repository import TeamRepository
+
+
+@dataclass(frozen=True, kw_only=True, slots=True)
+class CreateTeamMemberCommand:
+ """Input for the 'Create Team Member' use case."""
+
+ team_id: int
+ member_id: str
+ active: bool = True
+
+
+class CreateTeamMember:
+ """Implements the 'Create Team Member' use case."""
+
+ def __init__(
+ self,
+ team_repository: TeamRepository,
+ member_repository: MemberRepository,
+ presenter: Presenter[tuple[TeamMember, TeamEntity]],
+ ):
+ """Initialize the use case.
+
+ Args:
+ team_repository: A repository for retrieving the team.
+ member_repository: A repository for retrieving the member.
+ presenter: A Presenter for processing the result.
+ """
+ self._team_repository = team_repository
+ self._member_repository = member_repository
+ self._presenter = presenter
+
+ async def execute(self, command: CreateTeamMemberCommand) -> None:
+ """Execute the use case.
+
+ Raises:
+ TeamNotFoundException: If the team does not exist.
+ MemberNotFoundException: If the member does not exist.
+ TeamMemberAlreadyExistException: If the member is already part of the team.
+ """
+ team_query = self._team_repository.create_query().filter_by_id(
+ TeamIdentifier(command.team_id)
+ )
+ team = await self._team_repository.get(team_query)
+
+ member_query = self._member_repository.create_query().filter_by_uuid(
+ UniqueId.create_from_string(command.member_id)
+ )
+ member = await self._member_repository.get(member_query)
+
+ team_member = TeamMember(member=member, active=command.active)
+ team.add_member(team_member)
+
+ await self._team_repository.add_team_member(team, team_member)
+
+ self._presenter.present((team_member, team))
diff --git a/backend/src/kwai/modules/teams/delete_team.py b/backend/src/kwai/modules/teams/delete_team.py
new file mode 100644
index 000000000..b8e59b95f
--- /dev/null
+++ b/backend/src/kwai/modules/teams/delete_team.py
@@ -0,0 +1,40 @@
+"""Module that defines the use case "Delete Team"."""
+
+from dataclasses import dataclass
+
+from kwai.modules.teams.domain.team import TeamIdentifier
+from kwai.modules.teams.repositories.team_repository import TeamRepository
+
+
+@dataclass(kw_only=True, frozen=True, slots=True)
+class DeleteTeamCommand:
+ """Input for the use case DeleteTeam."""
+
+ id: int
+
+
+class DeleteTeam:
+ """Use case for deleting a team."""
+
+ def __init__(self, repo: TeamRepository):
+ """Initialize the use case.
+
+ Args:
+ repo: A repository for deleting a team.
+ """
+ self._repo = repo
+
+ async def execute(self, command: DeleteTeamCommand) -> None:
+ """Execute the use case.
+
+ Args:
+ command: The input for the use case.
+
+ Raises:
+ TeamNotFoundException: If the team does not exist.
+ """
+ team = await self._repo.get(
+ self._repo.create_query().filter_by_id(TeamIdentifier(command.id))
+ )
+ # TODO: check if the team is not attached to one or more trainings...
+ await self._repo.delete(team)
diff --git a/backend/src/kwai/modules/teams/domain/__init__.py b/backend/src/kwai/modules/teams/domain/__init__.py
new file mode 100644
index 000000000..cff765361
--- /dev/null
+++ b/backend/src/kwai/modules/teams/domain/__init__.py
@@ -0,0 +1 @@
+"""Package for domain models of the teams module."""
diff --git a/backend/src/kwai/modules/teams/domain/team.py b/backend/src/kwai/modules/teams/domain/team.py
new file mode 100644
index 000000000..1d8ec98f6
--- /dev/null
+++ b/backend/src/kwai/modules/teams/domain/team.py
@@ -0,0 +1,77 @@
+"""Module for defining the team entity."""
+
+from kwai.core.domain.entity import Entity
+from kwai.core.domain.value_objects.identifier import IntIdentifier
+from kwai.core.domain.value_objects.traceable_time import TraceableTime
+from kwai.core.domain.value_objects.unique_id import UniqueId
+from kwai.modules.teams.domain.team_member import TeamMember
+
+TeamIdentifier = IntIdentifier
+
+
+class TeamMemberAlreadyExistException(Exception):
+ """Raised when the member is already part of the team."""
+
+
+class TeamEntity(Entity[TeamIdentifier]):
+ """Entity for a team of the club."""
+
+ def __init__(
+ self,
+ *,
+ id_: TeamIdentifier | None = None,
+ name: str,
+ active: bool = True,
+ remark: str = "",
+ members: dict[UniqueId, TeamMember] = None,
+ traceable_time: TraceableTime | None = None,
+ ):
+ super().__init__(id_ or TeamIdentifier())
+ self._name = name
+ self._active = active
+ self._remark = remark
+ self._members = {} if members is None else members.copy()
+ self._traceable_time = traceable_time or TraceableTime()
+
+ def __str__(self):
+ """Return string representation of the team entity."""
+ return f""
+
+ def __repr__(self):
+ """Return representation of the team entity."""
+ return f"<{self.__class__.__name__} id={self.id} name={self.name!r}>"
+
+ @property
+ def name(self) -> str:
+ """Return the name of the team."""
+ return self._name
+
+ @property
+ def is_active(self):
+ """Is this team active?"""
+ return self._active
+
+ @property
+ def remark(self) -> str:
+ """Return the remark of the team."""
+ return self._remark
+
+ @property
+ def traceable_time(self) -> TraceableTime:
+ """Return the traceable_time."""
+ return self._traceable_time
+
+ @property
+ def members(self) -> dict[UniqueId, TeamMember]:
+ """Return the members.
+
+ Note: the returned list is a copy.
+ """
+ return self._members.copy()
+
+ def add_member(self, team_member: TeamMember):
+ if team_member.member.uuid in self._members:
+ raise TeamMemberAlreadyExistException(
+ f"Team member (id={team_member.member.id}) already part of team {self._name}"
+ )
+ self._members[team_member.member.uuid] = team_member
diff --git a/backend/src/kwai/modules/teams/domain/team_member.py b/backend/src/kwai/modules/teams/domain/team_member.py
new file mode 100644
index 000000000..c92421cff
--- /dev/null
+++ b/backend/src/kwai/modules/teams/domain/team_member.py
@@ -0,0 +1,98 @@
+"""Module for defining the team member entity."""
+
+from dataclasses import dataclass
+
+from kwai.core.domain.entity import Entity
+from kwai.core.domain.value_objects.identifier import IntIdentifier
+from kwai.core.domain.value_objects.name import Name
+from kwai.core.domain.value_objects.traceable_time import TraceableTime
+from kwai.core.domain.value_objects.unique_id import UniqueId
+from kwai.modules.club.domain.country import CountryEntity
+from kwai.modules.club.domain.value_objects import Birthdate, Gender, License
+
+MemberIdentifier = IntIdentifier
+
+
+class MemberEntity(Entity[MemberIdentifier]):
+ """A member entity.
+
+ A member entity is an entity which holds specific information of a member
+ that can be used for a member of a team.
+ """
+
+ def __init__(
+ self,
+ *,
+ id_: MemberIdentifier,
+ uuid: UniqueId,
+ name: Name,
+ license: License,
+ birthdate: Birthdate,
+ nationality: CountryEntity,
+ gender: Gender,
+ active_in_club: bool = True,
+ ):
+ super().__init__(id_)
+ self._name = name
+ self._uuid = uuid
+ self._license = license
+ self._birthdate = birthdate
+ self._nationality = nationality
+ self._gender = gender
+ self._active_in_club = active_in_club
+
+ def __str__(self) -> str:
+ """Return a string of this entity."""
+ return f"{self._uuid} - {self._name}"
+
+ def __repr__(self) -> str:
+ """Return a representation of this entity."""
+ return f"<{self.__class__.__name__} id={self.id}, uuid={self.uuid}, name={self.name}>"
+
+ @property
+ def name(self) -> Name:
+ """Return the name."""
+ return self._name
+
+ @property
+ def uuid(self) -> UniqueId:
+ """Return the uuid."""
+ return self._uuid
+
+ @property
+ def license(self) -> License:
+ """Return the license."""
+ return self._license
+
+ @property
+ def birthdate(self) -> Birthdate:
+ """Return the birthdate."""
+ return self._birthdate
+
+ @property
+ def nationality(self) -> CountryEntity:
+ """Return the nat."""
+ return self._nationality
+
+ @property
+ def gender(self) -> Gender:
+ """Return the gender."""
+ return self._gender
+
+ @property
+ def is_active_in_club(self) -> bool:
+ """Return if the member is active."""
+ return self._active_in_club
+
+
+@dataclass(kw_only=True, frozen=True, slots=True)
+class TeamMember:
+ """Represent a member of a team.
+
+ When active is False, it means the member is not active for the team it belongs
+ to.
+ """
+
+ active: bool = False
+ member: MemberEntity
+ traceable_time: TraceableTime = TraceableTime()
diff --git a/backend/src/kwai/modules/teams/get_members.py b/backend/src/kwai/modules/teams/get_members.py
new file mode 100644
index 000000000..997e1a3d6
--- /dev/null
+++ b/backend/src/kwai/modules/teams/get_members.py
@@ -0,0 +1,51 @@
+"""Module for defining the use case 'Get Members'."""
+
+from dataclasses import dataclass
+
+from kwai.core.domain.presenter import AsyncPresenter, IterableResult
+from kwai.modules.teams.domain.team import TeamIdentifier
+from kwai.modules.teams.domain.team_member import MemberEntity
+from kwai.modules.teams.repositories.member_repository import MemberRepository
+
+
+@dataclass(frozen=True, kw_only=True, slots=True)
+class GetMembersCommand:
+ """Input for the use case 'Get Members'.
+
+ When in_team is False and a team_id is set, only the members that are not
+ part of that team will be returned.
+ """
+
+ team_id: int | None = None
+ in_team: bool = True
+ limit: int | None = None
+ offset: int | None = None
+
+
+class GetMembers:
+ """Implements the use case 'Get Members'."""
+
+ def __init__(
+ self,
+ member_repository: MemberRepository,
+ presenter: AsyncPresenter[IterableResult[MemberEntity]],
+ ):
+ """Initialize the use case."""
+ self._member_repository = member_repository
+ self._presenter = presenter
+
+ async def execute(self, command: GetMembersCommand):
+ """Execute the use case."""
+ member_query = self._member_repository.create_query()
+ if command.team_id is not None:
+ member_query = member_query.filter_by_team(
+ TeamIdentifier(command.team_id), command.in_team
+ )
+ await self._presenter.present(
+ IterableResult(
+ count=await member_query.count(),
+ limit=command.limit,
+ offset=command.offset,
+ iterator=self._member_repository.get_all(member_query),
+ )
+ )
diff --git a/backend/src/kwai/modules/teams/get_team.py b/backend/src/kwai/modules/teams/get_team.py
new file mode 100644
index 000000000..9fff9c6c7
--- /dev/null
+++ b/backend/src/kwai/modules/teams/get_team.py
@@ -0,0 +1,33 @@
+"""Module that implements the use case 'Get Team'."""
+
+from dataclasses import dataclass
+
+from kwai.core.domain.presenter import Presenter
+from kwai.modules.teams.domain.team import TeamEntity, TeamIdentifier
+from kwai.modules.teams.repositories.team_repository import TeamRepository
+
+
+@dataclass(kw_only=True, frozen=True, slots=True)
+class GetTeamCommand:
+ """Input for the use case 'Get Team'."""
+
+ id: int
+
+
+class GetTeam:
+ """Implement the use case 'Get Teams'."""
+
+ def __init__(
+ self,
+ team_repo: TeamRepository,
+ presenter: Presenter[TeamEntity],
+ ):
+ """Initialize the use case."""
+ self._team_repo = team_repo
+ self._presenter = presenter
+
+ async def execute(self, command: GetTeamCommand) -> None:
+ """Execute the use case."""
+ query = self._team_repo.create_query()
+ query.filter_by_id(TeamIdentifier(command.id))
+ self._presenter.present(await self._team_repo.get(query))
diff --git a/backend/src/kwai/modules/teams/get_teams.py b/backend/src/kwai/modules/teams/get_teams.py
new file mode 100644
index 000000000..5bb7d91b7
--- /dev/null
+++ b/backend/src/kwai/modules/teams/get_teams.py
@@ -0,0 +1,40 @@
+"""Module that implements the use case 'Get Teams'."""
+
+from dataclasses import dataclass
+
+from kwai.core.domain.presenter import AsyncPresenter, IterableResult
+from kwai.modules.teams.domain.team import TeamEntity
+from kwai.modules.teams.repositories.team_repository import TeamRepository
+
+
+@dataclass(kw_only=True, frozen=True, slots=True)
+class GetTeamsCommand:
+ """Input for the use case 'Get Teams'."""
+
+ offset: int | None = None
+ limit: int | None = None
+
+
+class GetTeams:
+ """Implement the use case 'Get Teams'."""
+
+ def __init__(
+ self,
+ team_repo: TeamRepository,
+ presenter: AsyncPresenter[IterableResult[TeamEntity]],
+ ):
+ """Initialize the use case."""
+ self._team_repo = team_repo
+ self._presenter = presenter
+
+ async def execute(self, command: GetTeamsCommand) -> None:
+ """Execute the use case."""
+ query = self._team_repo.create_query()
+ await self._presenter.present(
+ IterableResult(
+ count=await query.count(),
+ limit=command.limit,
+ offset=command.offset,
+ iterator=self._team_repo.get_all(query, command.offset, command.limit),
+ )
+ )
diff --git a/backend/src/kwai/modules/teams/repositories/__init__.py b/backend/src/kwai/modules/teams/repositories/__init__.py
new file mode 100644
index 000000000..96987a8f8
--- /dev/null
+++ b/backend/src/kwai/modules/teams/repositories/__init__.py
@@ -0,0 +1 @@
+"""Package for the repositories of the teams module."""
diff --git a/backend/src/kwai/modules/teams/repositories/_tables.py b/backend/src/kwai/modules/teams/repositories/_tables.py
new file mode 100644
index 000000000..20b67a2f5
--- /dev/null
+++ b/backend/src/kwai/modules/teams/repositories/_tables.py
@@ -0,0 +1,148 @@
+from dataclasses import dataclass
+from datetime import date, datetime
+from typing import Self
+
+from kwai.core.db.table_row import TableRow
+from kwai.core.domain.value_objects.timestamp import Timestamp
+from kwai.core.domain.value_objects.traceable_time import TraceableTime
+from kwai.core.domain.value_objects.unique_id import UniqueId
+from kwai.modules.club.domain.country import CountryEntity, CountryIdentifier
+from kwai.modules.teams.domain.team import TeamEntity, TeamIdentifier
+from kwai.modules.teams.domain.team_member import MemberEntity, TeamMember
+
+
+@dataclass(kw_only=True, frozen=True, slots=True)
+class TeamRow(TableRow):
+ """Represents a row of the teams table."""
+
+ __table_name__ = "teams"
+
+ id: int
+ name: str
+ season_id: int | None
+ team_category_id: int | None
+ active: int
+ remark: str | None
+ created_at: datetime
+ updated_at: datetime | None
+
+ def create_entity(self, team_members: dict[UniqueId, TeamMember]) -> TeamEntity:
+ return TeamEntity(
+ id_=TeamIdentifier(self.id),
+ name=self.name,
+ active=self.active == 1,
+ remark=self.remark or "",
+ members=team_members,
+ traceable_time=TraceableTime(
+ created_at=Timestamp.create_utc(self.created_at),
+ updated_at=Timestamp.create_utc(self.updated_at),
+ ),
+ )
+
+ @classmethod
+ def persist(cls, team: TeamEntity) -> Self:
+ return cls(
+ id=team.id.value,
+ name=team.name,
+ season_id=None,
+ team_category_id=None,
+ active=1 if team.is_active else 0,
+ remark=team.remark,
+ created_at=team.traceable_time.created_at.timestamp, # type: ignore[arg-type]
+ updated_at=team.traceable_time.updated_at.timestamp,
+ )
+
+
+@dataclass(kw_only=True, frozen=True, slots=True)
+class MemberRow(TableRow):
+ """Represents a row of the members table used for a team member."""
+
+ __table_name__ = "judo_members"
+
+ id: int | None
+ uuid: str | None
+ license: str | None
+ license_end_date: date | None
+ person_id: int | None
+ active: int | None
+
+
+@dataclass(kw_only=True, frozen=True, slots=True)
+class MemberPersonRow(TableRow):
+ """Represents a row of the persons table used for a team member."""
+
+ __table_name__ = "persons"
+
+ id: int | None
+ firstname: str | None
+ lastname: str | None
+ gender: int | None
+ birthdate: date | None
+ nationality_id: int | None
+
+
+@dataclass(kw_only=True, frozen=True, slots=True)
+class TeamMemberRow(TableRow):
+ """Represents a row of the team members table."""
+
+ __table_name__ = "team_members"
+
+ team_id: int | None
+ member_id: int | None
+ active: int | None
+ created_at: datetime | None
+ updated_at: datetime | None
+
+ def create_team_member(self, member: MemberEntity):
+ return TeamMember(
+ active=True if self.active == 1 else False,
+ member=member,
+ traceable_time=TraceableTime(
+ created_at=Timestamp.create_utc(self.created_at),
+ updated_at=Timestamp.create_utc(self.updated_at),
+ ),
+ )
+
+ @classmethod
+ def persist(cls, team: TeamEntity, team_member: TeamMember) -> Self:
+ """Persist a team member to the table row."""
+ return cls(
+ team_id=team.id.value,
+ member_id=team_member.member.id.value,
+ active=1 if team_member.active else 0,
+ created_at=team_member.traceable_time.created_at.timestamp, # type: ignore[arg-type]
+ updated_at=team_member.traceable_time.updated_at.timestamp,
+ )
+
+
+@dataclass(kw_only=True, frozen=True, slots=True)
+class CountryRow(TableRow):
+ """Represent a row of the countries table.
+
+ Attributes:
+ id: The id of the country.
+ iso_2: The ISO 2 code of the country.
+ iso_3: The ISO 3 code of the country.
+ """
+
+ __table_name__ = "countries"
+
+ id: int | None = None
+ iso_2: str | None
+ iso_3: str | None
+ name: str | None
+ created_at: datetime | None
+ updated_at: datetime | None
+
+ def create_country(self) -> CountryEntity:
+ """Create a Country value object from the row.
+
+ Returns:
+ A country value object.
+ """
+ return CountryEntity(
+ id_=CountryIdentifier(self.id),
+ iso_2=self.iso_2,
+ iso_3=self.iso_3,
+ name=self.name,
+ )
diff --git a/backend/src/kwai/modules/teams/repositories/member_db_repository.py b/backend/src/kwai/modules/teams/repositories/member_db_repository.py
new file mode 100644
index 000000000..5e8e0da64
--- /dev/null
+++ b/backend/src/kwai/modules/teams/repositories/member_db_repository.py
@@ -0,0 +1,138 @@
+"""Module for defining a team member repository for a database."""
+
+from dataclasses import dataclass
+from typing import AsyncGenerator, Self
+
+from sql_smith.functions import express, on
+
+from kwai.core.db.database import Database
+from kwai.core.db.database_query import DatabaseQuery
+from kwai.core.db.table_row import JoinedTableRow
+from kwai.core.domain.value_objects.date import Date
+from kwai.core.domain.value_objects.name import Name
+from kwai.core.domain.value_objects.unique_id import UniqueId
+from kwai.modules.club.domain.value_objects import Birthdate, Gender, License
+from kwai.modules.teams.domain.team import TeamIdentifier
+from kwai.modules.teams.domain.team_member import MemberEntity, MemberIdentifier
+from kwai.modules.teams.repositories._tables import (
+ CountryRow,
+ MemberPersonRow,
+ MemberRow,
+ TeamMemberRow,
+)
+from kwai.modules.teams.repositories.member_repository import (
+ MemberNotFoundException,
+ MemberQuery,
+ MemberRepository,
+)
+
+
+@dataclass(kw_only=True, frozen=True, slots=True)
+class MemberQueryRow(JoinedTableRow):
+ """A data transfer object for the member query."""
+
+ member: MemberRow
+ person: MemberPersonRow
+ country: CountryRow
+
+ def create_entity(self) -> MemberEntity:
+ """Create a team member entity from a row."""
+ return MemberEntity(
+ id_=MemberIdentifier(self.member.id),
+ uuid=UniqueId.create_from_string(self.member.uuid),
+ name=Name(first_name=self.person.firstname, last_name=self.person.lastname),
+ license=License(
+ number=self.member.license,
+ end_date=Date.create_from_date(self.member.license_end_date),
+ ),
+ birthdate=Birthdate(Date.create_from_date(self.person.birthdate)),
+ gender=Gender(self.person.gender),
+ nationality=self.country.create_country(),
+ active_in_club=self.member.active == 1,
+ )
+
+
+class MemberDbQuery(MemberQuery, DatabaseQuery):
+ """A team member query for a database."""
+
+ def __init__(self, database: Database):
+ super().__init__(database)
+
+ def init(self):
+ self._query.from_(MemberRow.__table_name__).inner_join(
+ MemberPersonRow.__table_name__,
+ on(MemberPersonRow.column("id"), MemberRow.column("person_id")),
+ ).inner_join(
+ CountryRow.__table_name__,
+ on(CountryRow.column("id"), MemberPersonRow.column("nationality_id")),
+ )
+
+ @property
+ def columns(self):
+ return MemberQueryRow.get_aliases()
+
+ @property
+ def count_column(self):
+ return MemberRow.column("id")
+
+ def filter_by_id(self, id_: MemberIdentifier) -> Self:
+ self._query.and_where(MemberRow.field("id").eq(id_.value))
+ return self
+
+ def filter_by_birthdate(
+ self, start_date: Date, end_date: Date | None = None
+ ) -> Self:
+ if end_date is None:
+ self._query.and_where(MemberPersonRow.field("birthdate").gte(start_date))
+ else:
+ self._query.and_where(
+ MemberPersonRow.field("birthdate").between(start_date, end_date)
+ )
+ return self
+
+ def filter_by_uuid(self, uuid: UniqueId) -> Self:
+ self._query.and_where(MemberRow.field("uuid").eq(str(uuid)))
+ return self
+
+ def filter_by_team(self, team_id: TeamIdentifier, in_team: bool = True) -> Self:
+ inner_select = (
+ self._database.create_query_factory()
+ .select()
+ .columns(TeamMemberRow.column("member_id"))
+ .from_(TeamMemberRow.__table_name__)
+ .where(TeamMemberRow.field("team_id").eq(team_id.value))
+ )
+ if in_team:
+ condition = MemberRow.field("id").in_(express("{}", inner_select))
+ else:
+ condition = MemberRow.field("id").not_in(express("{}", inner_select))
+ self._query.and_where(condition)
+ return self
+
+
+class MemberDbRepository(MemberRepository):
+ """A member repository for a database."""
+
+ def __init__(self, database: Database):
+ self._database = database
+
+ def create_query(self) -> MemberQuery:
+ return MemberDbQuery(self._database)
+
+ async def get(self, query: MemberQuery | None = None) -> MemberEntity:
+ team_member_iterator = self.get_all(query)
+ try:
+ return await anext(team_member_iterator)
+ except StopAsyncIteration:
+ raise MemberNotFoundException("Member not found") from None
+
+ async def get_all(
+ self,
+ query: MemberQuery | None = None,
+ limit: int | None = None,
+ offset: int | None = None,
+ ) -> AsyncGenerator[MemberEntity, None]:
+ query = query or self.create_query()
+
+ async for row in query.fetch(limit, offset):
+ yield MemberQueryRow.map(row).create_entity()
diff --git a/backend/src/kwai/modules/teams/repositories/member_repository.py b/backend/src/kwai/modules/teams/repositories/member_repository.py
new file mode 100644
index 000000000..13bb84b19
--- /dev/null
+++ b/backend/src/kwai/modules/teams/repositories/member_repository.py
@@ -0,0 +1,87 @@
+"""Module for defining the member repository interface."""
+
+from abc import ABC, abstractmethod
+from typing import AsyncGenerator, Self
+
+from kwai.core.domain.repository.query import Query
+from kwai.core.domain.value_objects.date import Date
+from kwai.core.domain.value_objects.unique_id import UniqueId
+from kwai.modules.teams.domain.team import TeamIdentifier
+from kwai.modules.teams.domain.team_member import MemberEntity, MemberIdentifier
+
+
+class MemberNotFoundException(Exception):
+ """Raised when a member does not exist."""
+
+
+class MemberQuery(Query, ABC):
+ """An interface for a member query."""
+
+ @abstractmethod
+ def filter_by_id(self, id_: MemberIdentifier) -> Self:
+ """Find a team member by its id."""
+ raise NotImplementedError
+
+ @abstractmethod
+ def filter_by_uuid(self, uuid: UniqueId) -> Self:
+ """Find a team member by its uuid."""
+ raise NotImplementedError
+
+ @abstractmethod
+ def filter_by_birthdate(
+ self, start_date: Date, end_date: Date | None = None
+ ) -> Self:
+ """Find team members by their birthdate."""
+ raise NotImplementedError
+
+ @abstractmethod
+ def filter_by_team(self, team_id: TeamIdentifier, in_team: bool = True) -> Self:
+ """Find members that are (not) part of the team.
+
+ To get only the members that are not part of the team, set in_team to False.
+
+ Args:
+ team_id: The id of the team
+ in_team: Whether the member should be part of the team
+ """
+ raise NotImplementedError
+
+
+class MemberRepository(ABC):
+ """An interface for a member repository."""
+
+ @abstractmethod
+ def create_query(self) -> MemberQuery:
+ """Create a query for querying team members."""
+ raise NotImplementedError
+
+ @abstractmethod
+ async def get(self, query: MemberQuery | None = None) -> MemberEntity:
+ """Return the first returned element of the given query.
+
+ Args:
+ query: The query to use for getting the first member.
+
+ Raises:
+ MemberNotFoundException: If the member is not found.
+ """
+ raise NotImplementedError
+
+ @abstractmethod
+ def get_all(
+ self,
+ query: MemberQuery | None = None,
+ limit: int | None = None,
+ offset: int | None = None,
+ ) -> AsyncGenerator[MemberEntity, None]:
+ """Return all members of the given query.
+
+ Args:
+ query: The query to use for getting the members.
+ limit: The maximum number of members to return.
+ offset: The offset to use for fetching members.
+
+ Yields:
+ A team member entity.
+ """
+ raise NotImplementedError
diff --git a/backend/src/kwai/modules/teams/repositories/team_db_repository.py b/backend/src/kwai/modules/teams/repositories/team_db_repository.py
new file mode 100644
index 000000000..7ef0ac494
--- /dev/null
+++ b/backend/src/kwai/modules/teams/repositories/team_db_repository.py
@@ -0,0 +1,179 @@
+"""Module that implements a team repository for a database."""
+
+from dataclasses import dataclass
+from typing import Any, AsyncGenerator, Self
+
+from sql_smith.functions import field, on
+
+from kwai.core.db.database import Database
+from kwai.core.db.database_query import DatabaseQuery
+from kwai.core.db.table_row import JoinedTableRow
+from kwai.core.domain.entity import Entity
+from kwai.core.domain.value_objects.date import Date
+from kwai.core.domain.value_objects.name import Name
+from kwai.core.domain.value_objects.unique_id import UniqueId
+from kwai.core.functions import async_groupby
+from kwai.modules.club.domain.value_objects import Birthdate, Gender, License
+from kwai.modules.teams.domain.team import TeamEntity, TeamIdentifier
+from kwai.modules.teams.domain.team_member import (
+ MemberEntity,
+ MemberIdentifier,
+ TeamMember,
+)
+from kwai.modules.teams.repositories._tables import (
+ CountryRow,
+ MemberPersonRow,
+ MemberRow,
+ TeamMemberRow,
+ TeamRow,
+)
+from kwai.modules.teams.repositories.team_repository import (
+ TeamNotFoundException,
+ TeamQuery,
+ TeamRepository,
+)
+
+
+@dataclass(kw_only=True, frozen=True, slots=True)
+class MemberPersonCountryMixin:
+ """Dataclass for a member related row."""
+
+ member: MemberRow
+ member_person: MemberPersonRow
+ country: CountryRow
+
+ def create_member_entity(self) -> MemberEntity:
+ """Create a member entity from a row."""
+ return MemberEntity(
+ id_=MemberIdentifier(self.member.id),
+ name=Name(
+ first_name=self.member_person.firstname,
+ last_name=self.member_person.lastname,
+ ),
+ license=License(
+ number=self.member.license,
+ end_date=Date.create_from_date(self.member.license_end_date),
+ ),
+ birthdate=Birthdate(
+ date=Date.create_from_date(self.member_person.birthdate)
+ ),
+ nationality=self.country.create_country(),
+ gender=Gender(self.member_person.gender),
+ uuid=UniqueId.create_from_string(self.member.uuid),
+ active_in_club=self.member.active == 1,
+ )
+
+
+@dataclass(kw_only=True, frozen=True, slots=True)
+class TeamQueryRow(MemberPersonCountryMixin, JoinedTableRow):
+ """A data transfer object for the team query."""
+
+ team: TeamRow
+ team_member: TeamMemberRow
+
+ @classmethod
+ def create_entity(cls, rows: list[dict[str, Any]]) -> TeamEntity:
+ """Create a team entity from a group of rows."""
+ team_query_row = cls.map(rows[0])
+ team_members = {}
+ for row in rows:
+ mapped_row = cls.map(row)
+ if mapped_row.member.id is None:
+ continue
+
+ member = mapped_row.create_member_entity()
+ team_members[member.uuid] = mapped_row.team_member.create_team_member(
+ member
+ )
+ return team_query_row.team.create_entity(team_members)
+
+
+class TeamDbQuery(TeamQuery, DatabaseQuery):
+ """A team query for a database."""
+
+ def __init__(self, database: Database):
+ super().__init__(database)
+
+ def init(self):
+ self._query.from_(TeamRow.__table_name__).left_join(
+ TeamMemberRow.__table_name__,
+ on(TeamRow.column("id"), TeamMemberRow.column("team_id")),
+ ).left_join(
+ MemberRow.__table_name__,
+ on(MemberRow.column("id"), TeamMemberRow.column("member_id")),
+ ).left_join(
+ MemberPersonRow.__table_name__,
+ on(MemberPersonRow.column("id"), MemberRow.column("person_id")),
+ ).left_join(
+ CountryRow.__table_name__,
+ on(CountryRow.column("id"), MemberPersonRow.column("nationality_id")),
+ )
+
+ @property
+ def columns(self):
+ return TeamQueryRow.get_aliases()
+
+ @property
+ def count_column(self) -> str:
+ return TeamRow.column("id")
+
+ def filter_by_id(self, id_: TeamIdentifier) -> Self:
+ self._query.and_where(TeamRow.field("id").eq(id_.value))
+ return self
+
+
+class TeamDbRepository(TeamRepository):
+ """A team repository for a database."""
+
+ def create_query(self) -> TeamQuery:
+ return TeamDbQuery(self._database)
+
+ async def get(self, query: TeamQuery | None = None) -> TeamEntity:
+ team_iterator = self.get_all(query)
+ try:
+ return await anext(team_iterator)
+ except StopAsyncIteration:
+ raise TeamNotFoundException("Team not found") from None
+
+ async def get_all(
+ self,
+ query: TeamQuery | None = None,
+ limit: int | None = None,
+ offset: int | None = None,
+ ) -> AsyncGenerator[TeamEntity, None]:
+ if query is None:
+ query = self.create_query()
+
+ group_by_column = "team_id"
+ row_iterator = query.fetch(limit=limit, offset=offset)
+ async for _, group in async_groupby(
+ row_iterator, key=lambda row: row[group_by_column]
+ ):
+ yield TeamQueryRow.create_entity(group)
+
+ def __init__(self, database: Database):
+ self._database = database
+
+ async def create(self, team: TeamEntity) -> TeamEntity:
+ new_team_id = await self._database.insert(
+ TeamRow.__table_name__, TeamRow.persist(team)
+ )
+ return Entity.replace(team, id_=TeamIdentifier(new_team_id))
+
+ async def delete(self, team: TeamEntity) -> None:
+ delete_team_members_query = (
+ self._database.create_query_factory()
+ .delete(TeamMemberRow.__table_name__)
+ .where(field("team_id").eq(team.id.value))
+ )
+ await self._database.execute(delete_team_members_query)
+ await self._database.delete(team.id.value, TeamRow.__table_name__)
+
+ async def update(self, team: TeamEntity):
+ await self._database.update(
+ team.id.value, TeamRow.__table_name__, TeamRow.persist(team)
+ )
+
+ async def add_team_member(self, team: TeamEntity, member: TeamMember):
+ team_member_row = TeamMemberRow.persist(team, member)
+ await self._database.insert(TeamMemberRow.__table_name__, team_member_row)
diff --git a/backend/src/kwai/modules/teams/repositories/team_member_db_query.py b/backend/src/kwai/modules/teams/repositories/team_member_db_query.py
new file mode 100644
index 000000000..57e844dbe
--- /dev/null
+++ b/backend/src/kwai/modules/teams/repositories/team_member_db_query.py
@@ -0,0 +1,112 @@
+"""Module that defines a database query for team members."""
+
+from collections import defaultdict
+from dataclasses import dataclass
+from typing import Self
+
+from sql_smith.functions import on
+
+from kwai.core.db.database_query import DatabaseQuery
+from kwai.core.db.table_row import JoinedTableRow
+from kwai.core.domain.value_objects.date import Date
+from kwai.core.domain.value_objects.name import Name
+from kwai.core.domain.value_objects.timestamp import Timestamp
+from kwai.core.domain.value_objects.traceable_time import TraceableTime
+from kwai.core.domain.value_objects.unique_id import UniqueId
+from kwai.modules.club.domain.value_objects import Birthdate, Gender, License
+from kwai.modules.teams.domain.team import TeamIdentifier
+from kwai.modules.teams.domain.team_member import (
+ MemberEntity,
+ MemberIdentifier,
+ TeamMember,
+)
+from kwai.modules.teams.repositories._tables import (
+ CountryRow,
+ MemberPersonRow,
+ MemberRow,
+ TeamMemberRow,
+)
+
+
+@dataclass(frozen=True, kw_only=True, slots=True)
+class TeamMemberQueryRow(JoinedTableRow):
+ """A data transfer object for the team member query."""
+
+ team_member: TeamMemberRow
+ member: MemberRow
+ person: MemberPersonRow
+ country: CountryRow
+
+ def create_team_member(self) -> TeamMember:
+ """Create a team member from a row."""
+ return TeamMember(
+ active=self.team_member.active == 1,
+ member=MemberEntity(
+ id_=MemberIdentifier(self.member.id),
+ uuid=UniqueId.create_from_string(self.member.uuid),
+ name=Name(
+ first_name=self.person.firstname, last_name=self.person.lastname
+ ),
+ license=License(
+ number=self.member.license,
+ end_date=Date.create_from_date(self.member.license_end_date),
+ ),
+ birthdate=Birthdate(Date.create_from_date(self.person.birthdate)),
+ gender=Gender(self.person.gender),
+ nationality=self.country.create_country(),
+ active_in_club=self.member.active == 1,
+ ),
+ traceable_time=TraceableTime(
+ created_at=Timestamp(self.team_member.created_at),
+ updated_at=Timestamp(self.team_member.updated_at),
+ ),
+ )
+
+
+class TeamMemberDbQuery(DatabaseQuery):
+ """A database query for getting team members."""
+
+ def init(self):
+ self._query.from_(TeamMemberRow.__table_name__).left_join(
+ MemberRow.__table_name__,
+ on(TeamMemberRow.column("member_id"), MemberRow.column("id")),
+ ).join(
+ MemberPersonRow.__table_name__,
+ on(MemberRow.column("person_id"), MemberPersonRow.column("id")),
+ ).inner_join(
+ CountryRow.__table_name__,
+ on(CountryRow.column("id"), MemberPersonRow.column("nationality_id")),
+ )
+
+ @property
+ def columns(self):
+ return TeamMemberQueryRow.get_aliases()
+
+ def filter_by_teams(self, *ids: TeamIdentifier) -> Self:
+ """Filter by teams.
+
+ Only the rows that belong to the teams with the given ids, will be returned.
+ """
+ unpacked_ids = tuple(i.value for i in ids)
+ self._query.and_where(TeamMemberRow.field("team_id").in_(*unpacked_ids))
+ return self
+
+ async def fetch_team_members(self) -> dict[TeamIdentifier, list[TeamMember]]:
+ """Fetch team members.
+
+ A specialized fetch method that already transforms the rows into TeamMember
+ objects.
+
+ Returns:
+ A dictionary that contains the list of team members for each team.
+ The key is the identifier of the team.
+ """
+ result: dict[TeamIdentifier, list[TeamMember]] = defaultdict(list)
+
+ async for row in self.fetch():
+ team_member_row = TeamMemberQueryRow.map(row)
+ result[TeamIdentifier(team_member_row.team_member.team_id)].append(
+ team_member_row.create_team_member()
+ )
+
+ return result
diff --git a/backend/src/kwai/modules/teams/repositories/team_repository.py b/backend/src/kwai/modules/teams/repositories/team_repository.py
new file mode 100644
index 000000000..ddd72e865
--- /dev/null
+++ b/backend/src/kwai/modules/teams/repositories/team_repository.py
@@ -0,0 +1,78 @@
+"""Module that defines an interface for a team repository."""
+
+from abc import ABC, abstractmethod
+from typing import AsyncGenerator, Self
+
+from kwai.core.domain.repository.query import Query
+from kwai.modules.teams.domain.team import TeamEntity, TeamIdentifier
+from kwai.modules.teams.domain.team_member import TeamMember
+
+
+class TeamNotFoundException(Exception):
+ """Raised when a team cannot be found."""
+
+
+class TeamQuery(Query, ABC):
+ """An interface for a team query."""
+
+ @abstractmethod
+ def filter_by_id(self, id_: TeamIdentifier) -> Self:
+ """Find a team by its id."""
+ raise NotImplementedError
+
+
+class TeamRepository(ABC):
+ """An interface for a team repository."""
+
+ @abstractmethod
+ def create_query(self) -> TeamQuery:
+ """Create a team query."""
+ raise NotImplementedError
+
+ @abstractmethod
+ async def get(self, query: TeamQuery | None = None) -> TeamEntity:
+ """Return the first returned element of the given query.
+
+ Args:
+ query: The query to use for getting the first team.
+
+ Raises:
+ TeamNotFoundException: If the team cannot be found.
+ """
+ raise NotImplementedError
+
+ @abstractmethod
+ def get_all(
+ self,
+ query: TeamQuery | None = None,
+ limit: int | None = None,
+ offset: int | None = None,
+ ) -> AsyncGenerator[TeamEntity, None]:
+ """Return all teams of the given query.
+
+ Args:
+ query: The query to use for getting the teams.
+ limit: The maximum number of teams to return.
+ offset: The offset to use for fetching teams.
+
+ Yields:
+ A team entity.
+
+ """
+ raise NotImplementedError
+
+ @abstractmethod
+ async def create(self, team: TeamEntity) -> TeamEntity:
+ """Save a new team."""
+
+ @abstractmethod
+ async def delete(self, team: TeamEntity) -> None:
+ """Delete a team."""
+
+ @abstractmethod
+ async def update(self, team: TeamEntity) -> None:
+ """Update a team."""
+
+ @abstractmethod
+ async def add_team_member(self, team: TeamEntity, member: TeamMember):
+ """Add a member to a team."""
diff --git a/backend/src/kwai/modules/teams/update_team.py b/backend/src/kwai/modules/teams/update_team.py
new file mode 100644
index 000000000..e52fb1df5
--- /dev/null
+++ b/backend/src/kwai/modules/teams/update_team.py
@@ -0,0 +1,53 @@
+"""Module that defines the Update Team use case."""
+
+from dataclasses import dataclass
+
+from kwai.core.domain.entity import Entity
+from kwai.core.domain.presenter import Presenter
+from kwai.modules.teams.domain.team import TeamEntity, TeamIdentifier
+from kwai.modules.teams.repositories.team_repository import TeamRepository
+
+
+@dataclass(frozen=True, kw_only=True, slots=True)
+class UpdateTeamCommand:
+ """Input for the Update Team use case."""
+
+ id: int
+ name: str
+ active: bool
+ remark: str
+
+
+class UpdateTeam:
+ """Use case for updating a team."""
+
+ def __init__(self, team_repo: TeamRepository, presenter: Presenter[TeamEntity]):
+ """Initialize the use case.
+
+ Args:
+ team_repo: A repository for updating the team.
+ presenter: A presenter for a team entity.
+ """
+ self._team_repo = team_repo
+ self._presenter = presenter
+
+ async def execute(self, command: UpdateTeamCommand) -> None:
+ """Execute the use case.
+
+ Raises:
+ TeamNotFoundException: raise when the team does not exist.
+ """
+ team = await self._team_repo.get(
+ self._team_repo.create_query().filter_by_id(TeamIdentifier(command.id))
+ )
+
+ team = Entity.replace(
+ team,
+ name=command.name,
+ active=command.active,
+ remark=command.remark,
+ traceable_time=team.traceable_time.mark_for_update(),
+ )
+ await self._team_repo.update(team)
+
+ self._presenter.present(team)
diff --git a/backend/src/kwai/modules/training/coaches/_tables.py b/backend/src/kwai/modules/training/coaches/_tables.py
new file mode 100644
index 000000000..5cc439e3a
--- /dev/null
+++ b/backend/src/kwai/modules/training/coaches/_tables.py
@@ -0,0 +1,36 @@
+"""Module that defines all dataclasses for the tables containing coaches."""
+
+from dataclasses import dataclass
+
+from kwai.core.db.table_row import TableRow
+
+
+@dataclass(kw_only=True, frozen=True, slots=True)
+class MemberRow(TableRow):
+ """Represent a row of the members table."""
+
+ __table_name__ = "judo_members"
+
+ id: int
+
+
+@dataclass(kw_only=True, frozen=True, slots=True)
+class PersonRow(TableRow):
+ """Represent a row of the persons table."""
+
+ __table_name__ = "persons"
+
+ id: int
+ lastname: str
+ firstname: str
+
+
+@dataclass(kw_only=True, frozen=True, slots=True)
+class CoachRow(TableRow):
+ """Represent a row of the coaches table."""
+
+ __table_name__ = "coaches"
+
+ id: int
+ member_id: int
+ active: int
diff --git a/backend/src/kwai/modules/training/coaches/coach_db_query.py b/backend/src/kwai/modules/training/coaches/coach_db_query.py
index 3f4081809..8a3fa4bc3 100644
--- a/backend/src/kwai/modules/training/coaches/coach_db_query.py
+++ b/backend/src/kwai/modules/training/coaches/coach_db_query.py
@@ -1,10 +1,36 @@
"""Module that defines a database query for coaches."""
+
+from dataclasses import dataclass
+
from sql_smith.functions import on
from kwai.core.db.database_query import DatabaseQuery
-from kwai.modules.training.coaches.coach import CoachIdentifier
+from kwai.core.db.table_row import JoinedTableRow
+from kwai.core.domain.value_objects.name import Name
+from kwai.modules.training.coaches._tables import (
+ CoachRow,
+ MemberRow,
+ PersonRow,
+)
+from kwai.modules.training.coaches.coach import CoachEntity, CoachIdentifier
from kwai.modules.training.coaches.coach_query import CoachQuery
-from kwai.modules.training.coaches.coach_tables import CoachesTable, PersonsTable
+
+
+@dataclass(kw_only=True, frozen=True, slots=True)
+class CoachQueryRow(JoinedTableRow):
+ """A data transfer object for the coach query."""
+
+ member: MemberRow
+ person: PersonRow
+ coach: CoachRow
+
+ def create_entity(self) -> CoachEntity:
+ """Create a coach entity from a row."""
+ return CoachEntity(
+ id_=CoachIdentifier(self.coach.id),
+ name=Name(first_name=self.person.firstname, last_name=self.person.lastname),
+ active=self.coach.active == 1,
+ )
class CoachDbQuery(DatabaseQuery, CoachQuery):
@@ -12,29 +38,30 @@ class CoachDbQuery(DatabaseQuery, CoachQuery):
@property
def count_column(self) -> str:
- return CoachesTable.column("id")
+ return CoachRow.column("id")
def init(self):
- self._query.from_(CoachesTable.table_name).columns(
- *(CoachesTable.aliases() + PersonsTable.aliases())
- ).join(
- PersonsTable.table_name,
- on(CoachesTable.column("person_id"), PersonsTable.column("id")),
+ self._query.from_(CoachRow.__table_name__).join(
+ MemberRow.__table_name__,
+ on(MemberRow.column("id"), CoachRow.column("member_id")),
+ ).inner_join(
+ PersonRow.__table_name__,
+ on(MemberRow.column("person_id"), PersonRow.column("id")),
)
@property
def columns(self):
- return CoachesTable.aliases() + PersonsTable.aliases()
+ return CoachQueryRow.get_aliases()
def filter_by_ids(self, *ids: CoachIdentifier) -> "CoachQuery":
unpacked_ids = tuple(i.value for i in ids)
- self._query.and_where(CoachesTable.field("id").in_(*unpacked_ids))
+ self._query.and_where(CoachRow.field("id").in_(*unpacked_ids))
return self
def filter_by_id(self, id_: CoachIdentifier) -> "CoachQuery":
- self._query.and_where(CoachesTable.field("id").eq(id_.value))
+ self._query.and_where(CoachRow.field("id").eq(id_.value))
return self
def filter_by_active(self) -> "CoachQuery":
- self._query.and_where(CoachesTable.field("active").eq(1))
+ self._query.and_where(CoachRow.field("active").eq(1))
return self
diff --git a/backend/src/kwai/modules/training/coaches/coach_db_repository.py b/backend/src/kwai/modules/training/coaches/coach_db_repository.py
index 723e54d5e..22440e270 100644
--- a/backend/src/kwai/modules/training/coaches/coach_db_repository.py
+++ b/backend/src/kwai/modules/training/coaches/coach_db_repository.py
@@ -1,20 +1,19 @@
"""Module that defines a coach repository for a database."""
+
from typing import AsyncIterator
from kwai.core.db.database import Database
+from kwai.modules.training.coaches._tables import (
+ CoachRow,
+ PersonRow,
+)
from kwai.modules.training.coaches.coach import CoachEntity, CoachIdentifier
-from kwai.modules.training.coaches.coach_db_query import CoachDbQuery
+from kwai.modules.training.coaches.coach_db_query import CoachDbQuery, CoachQueryRow
from kwai.modules.training.coaches.coach_query import CoachQuery
from kwai.modules.training.coaches.coach_repository import (
CoachNotFoundException,
CoachRepository,
)
-from kwai.modules.training.coaches.coach_tables import (
- CoachesTable,
- CoachRow,
- PersonRow,
- PersonsTable,
-)
def _create_entity(coach_row: CoachRow, person_row: PersonRow) -> CoachEntity:
@@ -43,17 +42,17 @@ async def get_by_id(self, id: CoachIdentifier) -> CoachEntity:
if not row:
raise CoachNotFoundException(f"Coach with id {id} not found.")
- return _create_entity(CoachesTable(row), PersonsTable(row))
+ return CoachQueryRow.map(row).create_entity()
async def get_by_ids(self, *ids: CoachIdentifier) -> AsyncIterator[CoachEntity]:
query = self.create_query().filter_by_ids(*ids)
async for row in query.fetch():
- yield _create_entity(CoachesTable(row), PersonsTable(row))
+ yield CoachQueryRow.map(row).create_entity()
async def get_all(
self, query: CoachQuery | None = None
) -> AsyncIterator[CoachEntity]:
query = query or self.create_query()
async for row in query.fetch():
- yield _create_entity(CoachesTable(row), PersonsTable(row))
+ yield CoachQueryRow.map(row).create_entity()
diff --git a/backend/src/kwai/modules/training/coaches/coach_tables.py b/backend/src/kwai/modules/training/coaches/coach_tables.py
deleted file mode 100644
index 10c719c8e..000000000
--- a/backend/src/kwai/modules/training/coaches/coach_tables.py
+++ /dev/null
@@ -1,38 +0,0 @@
-"""Module that defines all dataclasses for the tables containing coaches."""
-from dataclasses import dataclass
-
-from kwai.core.db.table import Table
-from kwai.core.domain.value_objects.name import Name
-from kwai.modules.training.coaches.coach import CoachEntity, CoachIdentifier
-
-
-@dataclass(kw_only=True, frozen=True, slots=True)
-class PersonRow:
- """Represent a row of the persons table."""
-
- id: int
- lastname: str
- firstname: str
-
-
-PersonsTable = Table("persons", PersonRow)
-
-
-@dataclass(kw_only=True, frozen=True, slots=True)
-class CoachRow:
- """Represent a row of the coaches table."""
-
- id: int
- person_id: int
- active: int
-
- def create_entity(self, person_row: PersonRow) -> CoachEntity:
- """Create a coach entity from this row."""
- return CoachEntity(
- id_=CoachIdentifier(self.id),
- name=Name(first_name=person_row.firstname, last_name=person_row.lastname),
- active=self.active == 1,
- )
-
-
-CoachesTable = Table("coaches", CoachRow)
diff --git a/backend/src/kwai/modules/training/create_training_definition.py b/backend/src/kwai/modules/training/create_training_definition.py
index 01e151fde..6511014f0 100644
--- a/backend/src/kwai/modules/training/create_training_definition.py
+++ b/backend/src/kwai/modules/training/create_training_definition.py
@@ -43,7 +43,7 @@ async def execute(
command: The input for this use case.
"""
if command.team_id is not None:
- team = self._team_repo.get_by_id(TeamIdentifier(command.team_id))
+ team = await self._team_repo.get_by_id(TeamIdentifier(command.team_id))
else:
team = None
diff --git a/backend/src/kwai/modules/training/delete_training_definition.py b/backend/src/kwai/modules/training/delete_training_definition.py
index 20940dc55..700edf190 100644
--- a/backend/src/kwai/modules/training/delete_training_definition.py
+++ b/backend/src/kwai/modules/training/delete_training_definition.py
@@ -1,4 +1,5 @@
"""Module for the use case "Delete Training Definition"."""
+
from dataclasses import dataclass
from kwai.modules.training.trainings.training_definition import (
@@ -41,8 +42,8 @@ async def execute(self, command: DeleteTrainingDefinitionCommand):
"""Execute the use case.
Raises:
- TrainingDefinitionNotFoundException when the training definition
- does not exist.
+ TrainingDefinitionNotFoundException: when the training definition
+ does not exist.
"""
training_definition = await self._repo.get_by_id(
TrainingDefinitionIdentifier(command.id)
diff --git a/backend/src/kwai/modules/training/trainings/training_coach_db_query.py b/backend/src/kwai/modules/training/trainings/training_coach_db_query.py
index 060ac84ed..6f43d7e14 100644
--- a/backend/src/kwai/modules/training/trainings/training_coach_db_query.py
+++ b/backend/src/kwai/modules/training/trainings/training_coach_db_query.py
@@ -1,39 +1,78 @@
"""Module that defines a database query to get coaches of training(s)."""
+
from collections import defaultdict
+from dataclasses import dataclass
from sql_smith.functions import on
from kwai.core.db.database_query import DatabaseQuery
-from kwai.core.db.rows import OwnersTable
-from kwai.modules.training.coaches.coach_tables import CoachesTable, PersonsTable
+from kwai.core.db.rows import OwnersTable, OwnerTableRow
+from kwai.core.db.table_row import JoinedTableRow
+from kwai.core.domain.value_objects.name import Name
+from kwai.modules.training.coaches._tables import ( # noqa
+ CoachRow,
+ MemberRow,
+ PersonRow,
+)
+from kwai.modules.training.coaches.coach import CoachEntity, CoachIdentifier
from kwai.modules.training.trainings.training import TrainingIdentifier
-from kwai.modules.training.trainings.training_tables import TrainingCoachesTable
+from kwai.modules.training.trainings.training_tables import (
+ TrainingCoachRow,
+)
from kwai.modules.training.trainings.value_objects import TrainingCoach
+@dataclass(kw_only=True, frozen=True, slots=True)
+class TrainingCoachQueryRow(JoinedTableRow):
+ """A data transfer object for the training coach query."""
+
+ training_coach: TrainingCoachRow
+ member: MemberRow
+ person: PersonRow
+ coach: CoachRow
+ owner: OwnerTableRow
+
+ def create_coach(self) -> TrainingCoach:
+ """Create a training coach from a row."""
+ return TrainingCoach(
+ coach=CoachEntity(
+ id_=CoachIdentifier(self.coach.id),
+ name=Name(
+ first_name=self.person.firstname, last_name=self.person.lastname
+ ),
+ active=self.coach.active == 1,
+ ),
+ owner=self.owner.create_owner(),
+ present=self.training_coach.present == 1,
+ type=self.training_coach.coach_type,
+ payed=self.training_coach.payed == 1,
+ remark=(
+ "" if self.training_coach.remark is None else self.training_coach.remark
+ ),
+ )
+
+
class TrainingCoachDbQuery(DatabaseQuery):
"""A database query for getting coaches of training(s)."""
def init(self):
- self._query.from_(TrainingCoachesTable.table_name).left_join(
- CoachesTable.table_name,
- on(TrainingCoachesTable.column("coach_id"), CoachesTable.column("id")),
+ self._query.from_(TrainingCoachRow.__table_name__).left_join(
+ CoachRow.__table_name__,
+ on(TrainingCoachRow.column("coach_id"), CoachRow.column("id")),
+ ).join(
+ MemberRow.__table_name__,
+ on(CoachRow.column("member_id"), MemberRow.column("id")),
).join(
- PersonsTable.table_name,
- on(CoachesTable.column("person_id"), PersonsTable.column("id")),
+ PersonRow.__table_name__,
+ on(MemberRow.column("person_id"), PersonRow.column("id")),
).join(
OwnersTable.table_name,
- on(CoachesTable.column("user_id"), OwnersTable.column("id")),
+ on(CoachRow.column("user_id"), OwnerTableRow.column("id")),
)
@property
def columns(self):
- return (
- TrainingCoachesTable.aliases()
- + CoachesTable.aliases()
- + PersonsTable.aliases()
- + OwnersTable.aliases()
- )
+ return TrainingCoachQueryRow.get_aliases()
def filter_by_trainings(self, *ids: TrainingIdentifier) -> "TrainingCoachDbQuery":
"""Filter by trainings.
@@ -41,9 +80,7 @@ def filter_by_trainings(self, *ids: TrainingIdentifier) -> "TrainingCoachDbQuery
Only the rows of the trainings with the given ids, will be returned.
"""
unpacked_ids = tuple(i.value for i in ids)
- self._query.and_where(
- TrainingCoachesTable.field("training_id").in_(*unpacked_ids)
- )
+ self._query.and_where(TrainingCoachRow.field("training_id").in_(*unpacked_ids))
return self
async def fetch_coaches(self) -> dict[TrainingIdentifier, list[TrainingCoach]]:
@@ -58,15 +95,9 @@ async def fetch_coaches(self) -> dict[TrainingIdentifier, list[TrainingCoach]]:
"""
result: dict[TrainingIdentifier, list[TrainingCoach]] = defaultdict(list)
- async for record in self.fetch():
- training_coach = TrainingCoachesTable(record)
- owner_row = OwnersTable(record).create_owner()
- coach_row = CoachesTable(record)
- person_row = PersonsTable(record)
- result[TrainingIdentifier(training_coach.training_id)].append(
- training_coach.create_coach(
- coach_row.create_entity(person_row),
- owner_row,
- )
- )
+ async for row in self.fetch():
+ training_coach_row = TrainingCoachQueryRow.map(row)
+ result[
+ TrainingIdentifier(training_coach_row.training_coach.training_id)
+ ].append(training_coach_row.create_coach())
return result
diff --git a/backend/src/kwai/modules/training/trainings/training_db_query.py b/backend/src/kwai/modules/training/trainings/training_db_query.py
index 4ca46f141..88c6b2303 100644
--- a/backend/src/kwai/modules/training/trainings/training_db_query.py
+++ b/backend/src/kwai/modules/training/trainings/training_db_query.py
@@ -1,6 +1,5 @@
"""Module that implements a training query for a database."""
-from datetime import datetime
from typing import AsyncIterator
from sql_smith.functions import alias, criteria, express, func, group, literal, on
@@ -8,6 +7,7 @@
from kwai.core.db.database import Database
from kwai.core.db.database_query import DatabaseQuery
from kwai.core.db.rows import OwnersTable
+from kwai.core.domain.value_objects.timestamp import Timestamp
from kwai.modules.training.coaches.coach import CoachEntity
from kwai.modules.training.teams.team import TeamEntity
from kwai.modules.training.teams.team_tables import TeamsTable
@@ -15,7 +15,7 @@
from kwai.modules.training.trainings.training_definition import TrainingDefinitionEntity
from kwai.modules.training.trainings.training_query import TrainingQuery
from kwai.modules.training.trainings.training_tables import (
- TrainingCoachesTable,
+ TrainingCoachRow,
TrainingContentsTable,
TrainingDefinitionsTable,
TrainingsTable,
@@ -110,17 +110,19 @@ def filter_by_year_month(
self._query.and_where(group(condition))
return self
- def filter_by_dates(self, start: datetime, end: datetime) -> "TrainingQuery":
- self._query.and_where(TrainingsTable.field("start_date").between(start, end))
+ def filter_by_dates(self, start: Timestamp, end: Timestamp) -> "TrainingQuery":
+ self._query.and_where(
+ TrainingsTable.field("start_date").between(str(start), str(end))
+ )
return self
def filter_by_coach(self, coach: CoachEntity) -> "TrainingQuery":
inner_select = (
self._database.create_query_factory()
.select()
- .columns(TrainingCoachesTable.column("training_id"))
- .from_(TrainingCoachesTable.table_name)
- .where(TrainingCoachesTable.field("coach_id").eq(coach.id.value))
+ .columns(TrainingCoachRow.column("training_id"))
+ .from_(TrainingCoachRow.__table_name__)
+ .where(TrainingCoachRow.field("coach_id").eq(coach.id.value))
)
condition = TrainingsTable.field("id").in_(express("{}", inner_select))
self._query.and_where(group(condition))
diff --git a/backend/src/kwai/modules/training/trainings/training_db_repository.py b/backend/src/kwai/modules/training/trainings/training_db_repository.py
index 0c59082ca..289b4c6df 100644
--- a/backend/src/kwai/modules/training/trainings/training_db_repository.py
+++ b/backend/src/kwai/modules/training/trainings/training_db_repository.py
@@ -1,4 +1,5 @@
"""Module for implementing a training repository for a database."""
+
from typing import AsyncIterator
from sql_smith.functions import alias, express, field
@@ -18,7 +19,6 @@
TrainingRepository,
)
from kwai.modules.training.trainings.training_tables import (
- TrainingCoachesTable,
TrainingCoachRow,
TrainingContentsTable,
TrainingDefinitionsTable,
@@ -117,17 +117,17 @@ async def get_all(
training_query = TrainingCoachDbQuery(self._database).filter_by_trainings(
*trainings.keys()
)
- coaches: dict[
- TrainingIdentifier, list[TrainingCoach]
- ] = await training_query.fetch_coaches()
+ coaches: dict[TrainingIdentifier, list[TrainingCoach]] = (
+ await training_query.fetch_coaches()
+ )
# Get the teams of all trainings
team_query = TrainingTeamDbQuery(self._database).filter_by_trainings(
*trainings.keys()
)
- teams: dict[
- TrainingIdentifier, list[TeamEntity]
- ] = await team_query.fetch_teams()
+ teams: dict[TrainingIdentifier, list[TeamEntity]] = (
+ await team_query.fetch_teams()
+ )
for training in trainings.values():
training_coaches = coaches.get(training.id, [])
@@ -190,7 +190,7 @@ async def _insert_coaches(self, training: TrainingEntity):
]
if training_coach_rows:
await self._database.insert(
- TrainingCoachesTable.table_name, *training_coach_rows
+ TrainingCoachRow.__table_name__, *training_coach_rows
)
async def _insert_teams(self, training: TrainingEntity):
@@ -207,7 +207,7 @@ async def _delete_coaches(self, training: TrainingEntity):
"""Delete coaches of the training."""
delete_coaches_query = (
self._database.create_query_factory()
- .delete(TrainingCoachesTable.table_name)
+ .delete(TrainingCoachRow.__table_name__)
.where(field("training_id").eq(training.id.value))
)
await self._database.execute(delete_coaches_query)
@@ -258,10 +258,8 @@ async def reset_definition(
delete_coaches = (
self._database.create_query_factory()
- .delete(TrainingCoachesTable.table_name)
- .and_where(
- TrainingCoachesTable.field("training_id").in_(trainings_query)
- )
+ .delete(TrainingCoachRow.__table_name__)
+ .and_where(TrainingCoachRow.field("training_id").in_(trainings_query))
)
await self._database.execute(delete_coaches)
diff --git a/backend/src/kwai/modules/training/trainings/training_query.py b/backend/src/kwai/modules/training/trainings/training_query.py
index c092809e7..a12aab982 100644
--- a/backend/src/kwai/modules/training/trainings/training_query.py
+++ b/backend/src/kwai/modules/training/trainings/training_query.py
@@ -1,8 +1,9 @@
"""Module that defines an interface for a training query."""
+
from abc import ABC, abstractmethod
-from datetime import datetime
from kwai.core.domain.repository.query import Query
+from kwai.core.domain.value_objects.timestamp import Timestamp
from kwai.modules.training.coaches.coach import CoachEntity
from kwai.modules.training.teams.team import TeamEntity
from kwai.modules.training.trainings.training import TrainingIdentifier
@@ -34,7 +35,7 @@ def filter_by_year_month(
raise NotImplementedError
@abstractmethod
- def filter_by_dates(self, start: datetime, end: datetime) -> "TrainingQuery":
+ def filter_by_dates(self, start: Timestamp, end: Timestamp) -> "TrainingQuery":
"""Add filter to get only trainings between two dates.
Args:
diff --git a/backend/src/kwai/modules/training/trainings/training_tables.py b/backend/src/kwai/modules/training/trainings/training_tables.py
index e8f5be37a..9dcfac9f2 100644
--- a/backend/src/kwai/modules/training/trainings/training_tables.py
+++ b/backend/src/kwai/modules/training/trainings/training_tables.py
@@ -5,6 +5,7 @@
from kwai.core.db.rows import TextRow
from kwai.core.db.table import Table
+from kwai.core.db.table_row import TableRow
from kwai.core.domain.value_objects.owner import Owner
from kwai.core.domain.value_objects.period import Period
from kwai.core.domain.value_objects.text import LocaleText
@@ -232,9 +233,11 @@ def persist(
@dataclass(kw_only=True, frozen=True, slots=True)
-class TrainingCoachRow:
+class TrainingCoachRow(TableRow):
"""Represent a row of the training_coaches table."""
+ __table_name__ = "training_coaches"
+
training_id: int
coach_id: int
coach_type: int
@@ -272,9 +275,6 @@ def persist(cls, training, training_coach: TrainingCoach) -> "TrainingCoachRow":
)
-TrainingCoachesTable = Table("training_coaches", TrainingCoachRow)
-
-
@dataclass(kw_only=True, frozen=True, slots=True)
class TrainingTeamRow:
"""Represent a row of the training_teams table."""
diff --git a/backend/src/kwai/modules/training/update_training_definition.py b/backend/src/kwai/modules/training/update_training_definition.py
index c86b94c08..aeeea4734 100644
--- a/backend/src/kwai/modules/training/update_training_definition.py
+++ b/backend/src/kwai/modules/training/update_training_definition.py
@@ -54,7 +54,7 @@ async def execute(
command: The input for this use case.
Raises:
- TrainingDefinitionNotFoundException when the training definition does not
+ TrainingDefinitionNotFoundException: when the training definition does not
exist.
"""
if command.team_id is not None:
diff --git a/backend/src/poetry.lock b/backend/src/poetry.lock
deleted file mode 100644
index 5195c6ce5..000000000
--- a/backend/src/poetry.lock
+++ /dev/null
@@ -1,2985 +0,0 @@
-# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
-
-[[package]]
-name = "aiohttp"
-version = "3.9.3"
-description = "Async http client/server framework (asyncio)"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:939677b61f9d72a4fa2a042a5eee2a99a24001a67c13da113b2e30396567db54"},
- {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1f5cd333fcf7590a18334c90f8c9147c837a6ec8a178e88d90a9b96ea03194cc"},
- {file = "aiohttp-3.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:82e6aa28dd46374f72093eda8bcd142f7771ee1eb9d1e223ff0fa7177a96b4a5"},
- {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f56455b0c2c7cc3b0c584815264461d07b177f903a04481dfc33e08a89f0c26b"},
- {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bca77a198bb6e69795ef2f09a5f4c12758487f83f33d63acde5f0d4919815768"},
- {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e083c285857b78ee21a96ba1eb1b5339733c3563f72980728ca2b08b53826ca5"},
- {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab40e6251c3873d86ea9b30a1ac6d7478c09277b32e14745d0d3c6e76e3c7e29"},
- {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df822ee7feaaeffb99c1a9e5e608800bd8eda6e5f18f5cfb0dc7eeb2eaa6bbec"},
- {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:acef0899fea7492145d2bbaaaec7b345c87753168589cc7faf0afec9afe9b747"},
- {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cd73265a9e5ea618014802ab01babf1940cecb90c9762d8b9e7d2cc1e1969ec6"},
- {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a78ed8a53a1221393d9637c01870248a6f4ea5b214a59a92a36f18151739452c"},
- {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6b0e029353361f1746bac2e4cc19b32f972ec03f0f943b390c4ab3371840aabf"},
- {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7cf5c9458e1e90e3c390c2639f1017a0379a99a94fdfad3a1fd966a2874bba52"},
- {file = "aiohttp-3.9.3-cp310-cp310-win32.whl", hash = "sha256:3e59c23c52765951b69ec45ddbbc9403a8761ee6f57253250c6e1536cacc758b"},
- {file = "aiohttp-3.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:055ce4f74b82551678291473f66dc9fb9048a50d8324278751926ff0ae7715e5"},
- {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6b88f9386ff1ad91ace19d2a1c0225896e28815ee09fc6a8932fded8cda97c3d"},
- {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c46956ed82961e31557b6857a5ca153c67e5476972e5f7190015018760938da2"},
- {file = "aiohttp-3.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:07b837ef0d2f252f96009e9b8435ec1fef68ef8b1461933253d318748ec1acdc"},
- {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad46e6f620574b3b4801c68255492e0159d1712271cc99d8bdf35f2043ec266"},
- {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ed3e046ea7b14938112ccd53d91c1539af3e6679b222f9469981e3dac7ba1ce"},
- {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:039df344b45ae0b34ac885ab5b53940b174530d4dd8a14ed8b0e2155b9dddccb"},
- {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7943c414d3a8d9235f5f15c22ace69787c140c80b718dcd57caaade95f7cd93b"},
- {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84871a243359bb42c12728f04d181a389718710129b36b6aad0fc4655a7647d4"},
- {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5eafe2c065df5401ba06821b9a054d9cb2848867f3c59801b5d07a0be3a380ae"},
- {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9d3c9b50f19704552f23b4eaea1fc082fdd82c63429a6506446cbd8737823da3"},
- {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:f033d80bc6283092613882dfe40419c6a6a1527e04fc69350e87a9df02bbc283"},
- {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2c895a656dd7e061b2fd6bb77d971cc38f2afc277229ce7dd3552de8313a483e"},
- {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1f5a71d25cd8106eab05f8704cd9167b6e5187bcdf8f090a66c6d88b634802b4"},
- {file = "aiohttp-3.9.3-cp311-cp311-win32.whl", hash = "sha256:50fca156d718f8ced687a373f9e140c1bb765ca16e3d6f4fe116e3df7c05b2c5"},
- {file = "aiohttp-3.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:5fe9ce6c09668063b8447f85d43b8d1c4e5d3d7e92c63173e6180b2ac5d46dd8"},
- {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:38a19bc3b686ad55804ae931012f78f7a534cce165d089a2059f658f6c91fa60"},
- {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:770d015888c2a598b377bd2f663adfd947d78c0124cfe7b959e1ef39f5b13869"},
- {file = "aiohttp-3.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee43080e75fc92bf36219926c8e6de497f9b247301bbf88c5c7593d931426679"},
- {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52df73f14ed99cee84865b95a3d9e044f226320a87af208f068ecc33e0c35b96"},
- {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc9b311743a78043b26ffaeeb9715dc360335e5517832f5a8e339f8a43581e4d"},
- {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b955ed993491f1a5da7f92e98d5dad3c1e14dc175f74517c4e610b1f2456fb11"},
- {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:504b6981675ace64c28bf4a05a508af5cde526e36492c98916127f5a02354d53"},
- {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6fe5571784af92b6bc2fda8d1925cccdf24642d49546d3144948a6a1ed58ca5"},
- {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ba39e9c8627edc56544c8628cc180d88605df3892beeb2b94c9bc857774848ca"},
- {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e5e46b578c0e9db71d04c4b506a2121c0cb371dd89af17a0586ff6769d4c58c1"},
- {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:938a9653e1e0c592053f815f7028e41a3062e902095e5a7dc84617c87267ebd5"},
- {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:c3452ea726c76e92f3b9fae4b34a151981a9ec0a4847a627c43d71a15ac32aa6"},
- {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ff30218887e62209942f91ac1be902cc80cddb86bf00fbc6783b7a43b2bea26f"},
- {file = "aiohttp-3.9.3-cp312-cp312-win32.whl", hash = "sha256:38f307b41e0bea3294a9a2a87833191e4bcf89bb0365e83a8be3a58b31fb7f38"},
- {file = "aiohttp-3.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:b791a3143681a520c0a17e26ae7465f1b6f99461a28019d1a2f425236e6eedb5"},
- {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0ed621426d961df79aa3b963ac7af0d40392956ffa9be022024cd16297b30c8c"},
- {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7f46acd6a194287b7e41e87957bfe2ad1ad88318d447caf5b090012f2c5bb528"},
- {file = "aiohttp-3.9.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:feeb18a801aacb098220e2c3eea59a512362eb408d4afd0c242044c33ad6d542"},
- {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f734e38fd8666f53da904c52a23ce517f1b07722118d750405af7e4123933511"},
- {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b40670ec7e2156d8e57f70aec34a7216407848dfe6c693ef131ddf6e76feb672"},
- {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdd215b7b7fd4a53994f238d0f46b7ba4ac4c0adb12452beee724ddd0743ae5d"},
- {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:017a21b0df49039c8f46ca0971b3a7fdc1f56741ab1240cb90ca408049766168"},
- {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e99abf0bba688259a496f966211c49a514e65afa9b3073a1fcee08856e04425b"},
- {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:648056db9a9fa565d3fa851880f99f45e3f9a771dd3ff3bb0c048ea83fb28194"},
- {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8aacb477dc26797ee089721536a292a664846489c49d3ef9725f992449eda5a8"},
- {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:522a11c934ea660ff8953eda090dcd2154d367dec1ae3c540aff9f8a5c109ab4"},
- {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:5bce0dc147ca85caa5d33debc4f4d65e8e8b5c97c7f9f660f215fa74fc49a321"},
- {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b4af9f25b49a7be47c0972139e59ec0e8285c371049df1a63b6ca81fdd216a2"},
- {file = "aiohttp-3.9.3-cp38-cp38-win32.whl", hash = "sha256:298abd678033b8571995650ccee753d9458dfa0377be4dba91e4491da3f2be63"},
- {file = "aiohttp-3.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:69361bfdca5468c0488d7017b9b1e5ce769d40b46a9f4a2eed26b78619e9396c"},
- {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0fa43c32d1643f518491d9d3a730f85f5bbaedcbd7fbcae27435bb8b7a061b29"},
- {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:835a55b7ca49468aaaac0b217092dfdff370e6c215c9224c52f30daaa735c1c1"},
- {file = "aiohttp-3.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06a9b2c8837d9a94fae16c6223acc14b4dfdff216ab9b7202e07a9a09541168f"},
- {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abf151955990d23f84205286938796c55ff11bbfb4ccfada8c9c83ae6b3c89a3"},
- {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59c26c95975f26e662ca78fdf543d4eeaef70e533a672b4113dd888bd2423caa"},
- {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f95511dd5d0e05fd9728bac4096319f80615aaef4acbecb35a990afebe953b0e"},
- {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:595f105710293e76b9dc09f52e0dd896bd064a79346234b521f6b968ffdd8e58"},
- {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7c8b816c2b5af5c8a436df44ca08258fc1a13b449393a91484225fcb7545533"},
- {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f1088fa100bf46e7b398ffd9904f4808a0612e1d966b4aa43baa535d1b6341eb"},
- {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f59dfe57bb1ec82ac0698ebfcdb7bcd0e99c255bd637ff613760d5f33e7c81b3"},
- {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:361a1026c9dd4aba0109e4040e2aecf9884f5cfe1b1b1bd3d09419c205e2e53d"},
- {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:363afe77cfcbe3a36353d8ea133e904b108feea505aa4792dad6585a8192c55a"},
- {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e2c45c208c62e955e8256949eb225bd8b66a4c9b6865729a786f2aa79b72e9d"},
- {file = "aiohttp-3.9.3-cp39-cp39-win32.whl", hash = "sha256:f7217af2e14da0856e082e96ff637f14ae45c10a5714b63c77f26d8884cf1051"},
- {file = "aiohttp-3.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:27468897f628c627230dba07ec65dc8d0db566923c48f29e084ce382119802bc"},
- {file = "aiohttp-3.9.3.tar.gz", hash = "sha256:90842933e5d1ff760fae6caca4b2b3edba53ba8f4b71e95dacf2818a2aca06f7"},
-]
-
-[package.dependencies]
-aiosignal = ">=1.1.2"
-attrs = ">=17.3.0"
-frozenlist = ">=1.1.1"
-multidict = ">=4.5,<7.0"
-yarl = ">=1.0,<2.0"
-
-[package.extras]
-speedups = ["Brotli", "aiodns", "brotlicffi"]
-
-[[package]]
-name = "aiosignal"
-version = "1.3.1"
-description = "aiosignal: a list of registered asynchronous callbacks"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"},
- {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"},
-]
-
-[package.dependencies]
-frozenlist = ">=1.1.0"
-
-[[package]]
-name = "annotated-types"
-version = "0.6.0"
-description = "Reusable constraint types to use with typing.Annotated"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"},
- {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"},
-]
-
-[[package]]
-name = "anyio"
-version = "4.3.0"
-description = "High level compatibility layer for multiple asynchronous event loop implementations"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "anyio-4.3.0-py3-none-any.whl", hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8"},
- {file = "anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6"},
-]
-
-[package.dependencies]
-idna = ">=2.8"
-sniffio = ">=1.1"
-
-[package.extras]
-doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"]
-test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"]
-trio = ["trio (>=0.23)"]
-
-[[package]]
-name = "async-lru"
-version = "2.0.4"
-description = "Simple LRU cache for asyncio"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "async-lru-2.0.4.tar.gz", hash = "sha256:b8a59a5df60805ff63220b2a0c5b5393da5521b113cd5465a44eb037d81a5627"},
- {file = "async_lru-2.0.4-py3-none-any.whl", hash = "sha256:ff02944ce3c288c5be660c42dbcca0742b32c3b279d6dceda655190240b99224"},
-]
-
-[[package]]
-name = "asyncmy"
-version = "0.2.9"
-description = "A fast asyncio MySQL driver"
-optional = false
-python-versions = ">=3.7,<4.0"
-files = [
- {file = "asyncmy-0.2.9-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:d077eaee9a126f36bbe95e0412baa89e93172dd46193ef7bf7650a686e458e50"},
- {file = "asyncmy-0.2.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83cf951a44294626df43c5a85cf328297c3bac63f25ede216f9706514dabb322"},
- {file = "asyncmy-0.2.9-cp310-cp310-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:8a1d63c1bb8e3a09c90767199954fd423c48084a1f6c0d956217bc2e48d37d6d"},
- {file = "asyncmy-0.2.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ecad6826086e47596c6aa65dcbe221305f3d9232f0d4de11b8562ee2c55464a"},
- {file = "asyncmy-0.2.9-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4a664d58f9ebe4132f6cb3128206392be8ad71ad6fb09a5f4a990b04ec142024"},
- {file = "asyncmy-0.2.9-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f2bbd7b75e2d751216f48c3b1b5092b812d70c2cd0053f8d2f50ec3f76a525a8"},
- {file = "asyncmy-0.2.9-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:55e3bc41aa0d4ab410fc3a1d0c31b9cdb6688cd3b0cae6f2ee49c2e7f42968be"},
- {file = "asyncmy-0.2.9-cp310-cp310-win32.whl", hash = "sha256:ea44eefc965c62bcfebf34e9ef00f6e807edf51046046767c56914243e0737e4"},
- {file = "asyncmy-0.2.9-cp310-cp310-win_amd64.whl", hash = "sha256:2b4a2a7cf0bd5051931756e765fefef3c9f9561550e0dd8b1e79308d048b710a"},
- {file = "asyncmy-0.2.9-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:e2b77f03a17a8db338d74311e38ca6dbd4ff9aacb07d2af6b9e0cac9cf1c7b87"},
- {file = "asyncmy-0.2.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c19f27b7ff0e297f2981335a85599ffe1c9a8a35c97230203321d5d6e9e4cb30"},
- {file = "asyncmy-0.2.9-cp311-cp311-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:bf18aef65ac98f5130ca588c55a83a56e74ae416cf0fe2c0757a2b597c4269d0"},
- {file = "asyncmy-0.2.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ef02186cc02cb767ee5d5cf9ab002d5c7910a1a9f4c16a666867a9325c9ec5e"},
- {file = "asyncmy-0.2.9-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:696da0f71db0fe11e62fa58cd5a27d7c9d9a90699d13d82640755d0061da0624"},
- {file = "asyncmy-0.2.9-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:84d20745bb187ced05bd4072ae8b0bff4b4622efa23b79935519edb717174584"},
- {file = "asyncmy-0.2.9-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ea242364523f6205c4426435272bd57cbf593c20d5e5551efb28d44cfbd595c2"},
- {file = "asyncmy-0.2.9-cp311-cp311-win32.whl", hash = "sha256:47609d34e6b49fc5ad5bd2a2a593ca120e143e2a4f4206f27a543c5c598a18ca"},
- {file = "asyncmy-0.2.9-cp311-cp311-win_amd64.whl", hash = "sha256:0d56df7342f7b5467a9d09a854f0e5602c8da09afdad8181ba40b0434d66d8a4"},
- {file = "asyncmy-0.2.9-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63c2a98f225560f9a52d5bd0d2e58517639e209e5d996e9ab7470e661b39394d"},
- {file = "asyncmy-0.2.9-cp37-cp37m-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:20ae3acc326b4b104949cc5e3a728a927e671f671c6f26266ad4a44f57ea9a5b"},
- {file = "asyncmy-0.2.9-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8171a64888453423a17ae507cd97d256541ea880b314bba16376ab9deffef6e8"},
- {file = "asyncmy-0.2.9-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c966de493928f26218e0bfaa284cfa609540e52841c423d7babf9ca97c9ff820"},
- {file = "asyncmy-0.2.9-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4321c4cb4c691689aa26a56354e3fa723d89dc2cac82751e8671b2a4e6441778"},
- {file = "asyncmy-0.2.9-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:cd7cde6759dbbfcc467c2af4ef3d75de0b756dde39a3d176383d8c6d9f8a34f3"},
- {file = "asyncmy-0.2.9-cp37-cp37m-win32.whl", hash = "sha256:7678d3641d5a19f20e7e19220c83405fe8616a3b437efbc494f34ad186cedcf0"},
- {file = "asyncmy-0.2.9-cp37-cp37m-win_amd64.whl", hash = "sha256:e8f48d09adf3426e7a59066eaae3c7c84c318ec56cc2f20732d652056c7a3f62"},
- {file = "asyncmy-0.2.9-cp38-cp38-macosx_12_0_x86_64.whl", hash = "sha256:4c4f1dc0acbaac8c3f046215031bbf3ca3d2cd7716244365325496e4f6222b78"},
- {file = "asyncmy-0.2.9-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:901aac048e5342acc62e1f68f6dec5aa3ed272cb2b138dca38d1c74fc414285d"},
- {file = "asyncmy-0.2.9-cp38-cp38-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:c2d4ad8817f99d9734912c2ff91c42e419031441f512b4aecd7e40a167908c1c"},
- {file = "asyncmy-0.2.9-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:544d3736fd6682f0201a123e4f49335420b6abf6c245abe0487f5967021f1436"},
- {file = "asyncmy-0.2.9-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f0c606a55625146e189534cc39038540f7a8f2c680ea82845c1f4315a9ad2914"},
- {file = "asyncmy-0.2.9-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:625f96371d64769b94f7f7f699cfa5be56e669828aef3698cbf4f5bb0014ccb3"},
- {file = "asyncmy-0.2.9-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eeeb53fdd54eef54b9793a7a5c849c5f7a2fb2540a637f21585a996ef9dd8845"},
- {file = "asyncmy-0.2.9-cp38-cp38-win32.whl", hash = "sha256:2136b749ac489c25ab3aab4a81ae6e9dfb18fd0a5ebda96cd72788c5e4d46927"},
- {file = "asyncmy-0.2.9-cp38-cp38-win_amd64.whl", hash = "sha256:d08fb8722150a9c0645665cf777916335687bddb5f37a8e02af772e330be777b"},
- {file = "asyncmy-0.2.9-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:dbee276a9c8750b522aaad86315a6ed1ffbcb9145ce89070db77831c00dd2da1"},
- {file = "asyncmy-0.2.9-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a8755248429f9bd3d7768c71494c9943fced18f9f526f768e96f5b9b3c727c84"},
- {file = "asyncmy-0.2.9-cp39-cp39-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:64bcd5110dca7a96cb411de85ab8f79fa867e864150939b8e76286a66eab28fc"},
- {file = "asyncmy-0.2.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a83e3895bed6d44aa334deb1c343d4ffc64b0def2215149f8df2e0e13499250"},
- {file = "asyncmy-0.2.9-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:beb3d0e434ce0bd9e609cf5341c3b82433ef544f89055d3792186e11fa2433d9"},
- {file = "asyncmy-0.2.9-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:dc608ff331c5d1065e2d3566493d2d9e17f36e315bd5fad3c91c421eea306edb"},
- {file = "asyncmy-0.2.9-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:02caedc00035b2bd0be5555ef61d83ee9cb356ab488ac40072630ba224af02b0"},
- {file = "asyncmy-0.2.9-cp39-cp39-win32.whl", hash = "sha256:5b944d9cdf7ce25b396cd1e0c9319ba24c6583bde7a5dd31157614f3b9cc5b2f"},
- {file = "asyncmy-0.2.9-cp39-cp39-win_amd64.whl", hash = "sha256:3ceb59b9307b5eb893f4d473fcbc43ac0321ffb0436e0115b20cc2e0baa44eb5"},
- {file = "asyncmy-0.2.9-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9f1ca623517552a637900b90d65b5bafc9c67bebf96e3427eecb9359ffa24b1"},
- {file = "asyncmy-0.2.9-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:49622dc4ec69b5a4cbddb3695a1e9249b31092c6f19604abb664b43dcb509b6f"},
- {file = "asyncmy-0.2.9-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8412e825443ee876ef0d55ac4356b56173f5cb64ca8e4638974f8cf5c912a63"},
- {file = "asyncmy-0.2.9-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:4025db2a27b1d84d3c68b5d5aacecac17258b69f25ec8a8c350c5f666003a778"},
- {file = "asyncmy-0.2.9-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da7640f3357849b176364ed546908e28c8460701ddc0d23cc3fa7113ec52a076"},
- {file = "asyncmy-0.2.9-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:d2593717fa7a92a7d361444726292ce34edea76d5aa67d469b5efeee1c9b729e"},
- {file = "asyncmy-0.2.9-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9f22e13bd77277593b56de2e4b65c40c2e81b1a42c4845d062403c5c5bc52bc"},
- {file = "asyncmy-0.2.9-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:a4aa17cc6ac0f7bc6b72e08d112566e69a36e2e1ebebad43d699757b7b4ff028"},
- {file = "asyncmy-0.2.9-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7e6f5205722e67c910510e294ad483bdafa7e29d5cf455d49ffa4b819e55fd8"},
- {file = "asyncmy-0.2.9-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:1021796f1910a0c2ab2d878f8f5d56f939ef0681f9c1fe925b78161cad2f8297"},
- {file = "asyncmy-0.2.9-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b1dd463bb054138bd1fd3fec9911eb618e92f54f61abb476658f863340394d1"},
- {file = "asyncmy-0.2.9-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ad06f3c02d455947e95087d29f7122411208f0eadaf8671772fe5bad97d9873a"},
- {file = "asyncmy-0.2.9.tar.gz", hash = "sha256:da188be013291d1f831d63cdd3614567f4c63bfdcde73631ddff8df00c56d614"},
-]
-
-[[package]]
-name = "attrs"
-version = "23.2.0"
-description = "Classes Without Boilerplate"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"},
- {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"},
-]
-
-[package.extras]
-cov = ["attrs[tests]", "coverage[toml] (>=5.3)"]
-dev = ["attrs[tests]", "pre-commit"]
-docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"]
-tests = ["attrs[tests-no-zope]", "zope-interface"]
-tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"]
-tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"]
-
-[[package]]
-name = "babel"
-version = "2.14.0"
-description = "Internationalization utilities"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "Babel-2.14.0-py3-none-any.whl", hash = "sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287"},
- {file = "Babel-2.14.0.tar.gz", hash = "sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363"},
-]
-
-[package.extras]
-dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"]
-
-[[package]]
-name = "bcrypt"
-version = "4.1.2"
-description = "Modern password hashing for your software and your servers"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "bcrypt-4.1.2-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:ac621c093edb28200728a9cca214d7e838529e557027ef0581685909acd28b5e"},
- {file = "bcrypt-4.1.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea505c97a5c465ab8c3ba75c0805a102ce526695cd6818c6de3b1a38f6f60da1"},
- {file = "bcrypt-4.1.2-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57fa9442758da926ed33a91644649d3e340a71e2d0a5a8de064fb621fd5a3326"},
- {file = "bcrypt-4.1.2-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:eb3bd3321517916696233b5e0c67fd7d6281f0ef48e66812db35fc963a422a1c"},
- {file = "bcrypt-4.1.2-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6cad43d8c63f34b26aef462b6f5e44fdcf9860b723d2453b5d391258c4c8e966"},
- {file = "bcrypt-4.1.2-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:44290ccc827d3a24604f2c8bcd00d0da349e336e6503656cb8192133e27335e2"},
- {file = "bcrypt-4.1.2-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:732b3920a08eacf12f93e6b04ea276c489f1c8fb49344f564cca2adb663b3e4c"},
- {file = "bcrypt-4.1.2-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1c28973decf4e0e69cee78c68e30a523be441972c826703bb93099868a8ff5b5"},
- {file = "bcrypt-4.1.2-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b8df79979c5bae07f1db22dcc49cc5bccf08a0380ca5c6f391cbb5790355c0b0"},
- {file = "bcrypt-4.1.2-cp37-abi3-win32.whl", hash = "sha256:fbe188b878313d01b7718390f31528be4010fed1faa798c5a1d0469c9c48c369"},
- {file = "bcrypt-4.1.2-cp37-abi3-win_amd64.whl", hash = "sha256:9800ae5bd5077b13725e2e3934aa3c9c37e49d3ea3d06318010aa40f54c63551"},
- {file = "bcrypt-4.1.2-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:71b8be82bc46cedd61a9f4ccb6c1a493211d031415a34adde3669ee1b0afbb63"},
- {file = "bcrypt-4.1.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e3c6642077b0c8092580c819c1684161262b2e30c4f45deb000c38947bf483"},
- {file = "bcrypt-4.1.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:387e7e1af9a4dd636b9505a465032f2f5cb8e61ba1120e79a0e1cd0b512f3dfc"},
- {file = "bcrypt-4.1.2-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f70d9c61f9c4ca7d57f3bfe88a5ccf62546ffbadf3681bb1e268d9d2e41c91a7"},
- {file = "bcrypt-4.1.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2a298db2a8ab20056120b45e86c00a0a5eb50ec4075b6142db35f593b97cb3fb"},
- {file = "bcrypt-4.1.2-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:ba55e40de38a24e2d78d34c2d36d6e864f93e0d79d0b6ce915e4335aa81d01b1"},
- {file = "bcrypt-4.1.2-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:3566a88234e8de2ccae31968127b0ecccbb4cddb629da744165db72b58d88ca4"},
- {file = "bcrypt-4.1.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b90e216dc36864ae7132cb151ffe95155a37a14e0de3a8f64b49655dd959ff9c"},
- {file = "bcrypt-4.1.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:69057b9fc5093ea1ab00dd24ede891f3e5e65bee040395fb1e66ee196f9c9b4a"},
- {file = "bcrypt-4.1.2-cp39-abi3-win32.whl", hash = "sha256:02d9ef8915f72dd6daaef40e0baeef8a017ce624369f09754baf32bb32dba25f"},
- {file = "bcrypt-4.1.2-cp39-abi3-win_amd64.whl", hash = "sha256:be3ab1071662f6065899fe08428e45c16aa36e28bc42921c4901a191fda6ee42"},
- {file = "bcrypt-4.1.2-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d75fc8cd0ba23f97bae88a6ec04e9e5351ff3c6ad06f38fe32ba50cbd0d11946"},
- {file = "bcrypt-4.1.2-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:a97e07e83e3262599434816f631cc4c7ca2aa8e9c072c1b1a7fec2ae809a1d2d"},
- {file = "bcrypt-4.1.2-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:e51c42750b7585cee7892c2614be0d14107fad9581d1738d954a262556dd1aab"},
- {file = "bcrypt-4.1.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:ba4e4cc26610581a6329b3937e02d319f5ad4b85b074846bf4fef8a8cf51e7bb"},
- {file = "bcrypt-4.1.2.tar.gz", hash = "sha256:33313a1200a3ae90b75587ceac502b048b840fc69e7f7a0905b5f87fac7a1258"},
-]
-
-[package.extras]
-tests = ["pytest (>=3.2.1,!=3.3.0)"]
-typecheck = ["mypy"]
-
-[[package]]
-name = "black"
-version = "24.3.0"
-description = "The uncompromising code formatter."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "black-24.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7d5e026f8da0322b5662fa7a8e752b3fa2dac1c1cbc213c3d7ff9bdd0ab12395"},
- {file = "black-24.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9f50ea1132e2189d8dff0115ab75b65590a3e97de1e143795adb4ce317934995"},
- {file = "black-24.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2af80566f43c85f5797365077fb64a393861a3730bd110971ab7a0c94e873e7"},
- {file = "black-24.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:4be5bb28e090456adfc1255e03967fb67ca846a03be7aadf6249096100ee32d0"},
- {file = "black-24.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4f1373a7808a8f135b774039f61d59e4be7eb56b2513d3d2f02a8b9365b8a8a9"},
- {file = "black-24.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:aadf7a02d947936ee418777e0247ea114f78aff0d0959461057cae8a04f20597"},
- {file = "black-24.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c02e4ea2ae09d16314d30912a58ada9a5c4fdfedf9512d23326128ac08ac3d"},
- {file = "black-24.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:bf21b7b230718a5f08bd32d5e4f1db7fc8788345c8aea1d155fc17852b3410f5"},
- {file = "black-24.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:2818cf72dfd5d289e48f37ccfa08b460bf469e67fb7c4abb07edc2e9f16fb63f"},
- {file = "black-24.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4acf672def7eb1725f41f38bf6bf425c8237248bb0804faa3965c036f7672d11"},
- {file = "black-24.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c7ed6668cbbfcd231fa0dc1b137d3e40c04c7f786e626b405c62bcd5db5857e4"},
- {file = "black-24.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:56f52cfbd3dabe2798d76dbdd299faa046a901041faf2cf33288bc4e6dae57b5"},
- {file = "black-24.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:79dcf34b33e38ed1b17434693763301d7ccbd1c5860674a8f871bd15139e7837"},
- {file = "black-24.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e19cb1c6365fd6dc38a6eae2dcb691d7d83935c10215aef8e6c38edee3f77abd"},
- {file = "black-24.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65b76c275e4c1c5ce6e9870911384bff5ca31ab63d19c76811cb1fb162678213"},
- {file = "black-24.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:b5991d523eee14756f3c8d5df5231550ae8993e2286b8014e2fdea7156ed0959"},
- {file = "black-24.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c45f8dff244b3c431b36e3224b6be4a127c6aca780853574c00faf99258041eb"},
- {file = "black-24.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6905238a754ceb7788a73f02b45637d820b2f5478b20fec82ea865e4f5d4d9f7"},
- {file = "black-24.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7de8d330763c66663661a1ffd432274a2f92f07feeddd89ffd085b5744f85e7"},
- {file = "black-24.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:7bb041dca0d784697af4646d3b62ba4a6b028276ae878e53f6b4f74ddd6db99f"},
- {file = "black-24.3.0-py3-none-any.whl", hash = "sha256:41622020d7120e01d377f74249e677039d20e6344ff5851de8a10f11f513bf93"},
- {file = "black-24.3.0.tar.gz", hash = "sha256:a0c9c4a0771afc6919578cec71ce82a3e31e054904e7197deacbc9382671c41f"},
-]
-
-[package.dependencies]
-aiohttp = [
- {version = ">=3.7.4,<3.9.0 || >3.9.0", optional = true, markers = "sys_platform == \"win32\" and implementation_name == \"pypy\" and extra == \"d\""},
- {version = ">=3.7.4", optional = true, markers = "sys_platform != \"win32\" and extra == \"d\" or implementation_name != \"pypy\" and extra == \"d\""},
-]
-click = ">=8.0.0"
-mypy-extensions = ">=0.4.3"
-packaging = ">=22.0"
-pathspec = ">=0.9.0"
-platformdirs = ">=2"
-
-[package.extras]
-colorama = ["colorama (>=0.4.3)"]
-d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"]
-jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
-uvloop = ["uvloop (>=0.15.2)"]
-
-[[package]]
-name = "certifi"
-version = "2024.2.2"
-description = "Python package for providing Mozilla's CA Bundle."
-optional = false
-python-versions = ">=3.6"
-files = [
- {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"},
- {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"},
-]
-
-[[package]]
-name = "cffi"
-version = "1.16.0"
-description = "Foreign Function Interface for Python calling C code."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"},
- {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"},
- {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"},
- {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"},
- {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"},
- {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"},
- {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"},
- {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"},
- {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"},
- {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"},
- {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"},
- {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"},
- {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"},
- {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"},
- {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"},
- {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"},
- {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"},
- {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"},
- {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"},
- {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"},
- {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"},
- {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"},
- {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"},
- {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"},
- {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"},
- {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"},
- {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"},
- {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"},
- {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"},
- {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"},
- {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"},
- {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"},
- {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"},
- {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"},
- {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"},
- {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"},
- {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"},
- {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"},
- {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"},
- {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"},
- {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"},
- {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"},
- {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"},
- {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"},
- {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"},
- {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"},
- {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"},
- {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"},
- {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"},
- {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"},
- {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"},
- {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"},
-]
-
-[package.dependencies]
-pycparser = "*"
-
-[[package]]
-name = "cfgv"
-version = "3.4.0"
-description = "Validate configuration and produce human readable error messages."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"},
- {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"},
-]
-
-[[package]]
-name = "charset-normalizer"
-version = "3.3.2"
-description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
-optional = false
-python-versions = ">=3.7.0"
-files = [
- {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"},
- {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"},
- {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"},
- {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"},
- {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"},
- {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"},
- {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"},
- {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"},
- {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"},
- {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"},
- {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"},
- {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"},
- {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"},
- {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"},
- {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"},
- {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"},
- {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"},
- {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"},
- {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"},
- {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"},
- {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"},
- {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"},
- {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"},
- {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"},
- {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"},
- {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"},
- {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"},
- {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"},
- {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"},
- {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"},
- {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"},
- {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"},
- {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"},
- {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"},
- {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"},
- {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"},
- {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"},
- {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"},
- {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"},
- {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"},
- {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"},
- {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"},
- {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"},
- {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"},
- {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"},
- {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"},
- {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"},
- {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"},
- {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"},
- {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"},
- {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"},
- {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"},
- {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"},
- {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"},
- {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"},
- {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"},
- {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"},
- {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"},
- {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"},
- {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"},
- {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"},
- {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"},
- {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"},
- {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"},
- {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"},
- {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"},
- {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"},
- {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"},
- {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"},
- {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"},
- {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"},
- {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"},
- {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"},
- {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"},
- {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"},
- {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"},
- {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"},
- {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"},
- {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"},
- {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"},
- {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"},
- {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"},
- {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"},
- {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"},
- {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"},
- {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"},
- {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"},
- {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"},
- {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"},
- {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"},
-]
-
-[[package]]
-name = "click"
-version = "8.1.7"
-description = "Composable command line interface toolkit"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
- {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
-]
-
-[package.dependencies]
-colorama = {version = "*", markers = "platform_system == \"Windows\""}
-
-[[package]]
-name = "colorama"
-version = "0.4.6"
-description = "Cross-platform colored terminal text."
-optional = false
-python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
-files = [
- {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
- {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
-]
-
-[[package]]
-name = "coverage"
-version = "7.4.4"
-description = "Code coverage measurement for Python"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "coverage-7.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0be5efd5127542ef31f165de269f77560d6cdef525fffa446de6f7e9186cfb2"},
- {file = "coverage-7.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ccd341521be3d1b3daeb41960ae94a5e87abe2f46f17224ba5d6f2b8398016cf"},
- {file = "coverage-7.4.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09fa497a8ab37784fbb20ab699c246053ac294d13fc7eb40ec007a5043ec91f8"},
- {file = "coverage-7.4.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b1a93009cb80730c9bca5d6d4665494b725b6e8e157c1cb7f2db5b4b122ea562"},
- {file = "coverage-7.4.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:690db6517f09336559dc0b5f55342df62370a48f5469fabf502db2c6d1cffcd2"},
- {file = "coverage-7.4.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:09c3255458533cb76ef55da8cc49ffab9e33f083739c8bd4f58e79fecfe288f7"},
- {file = "coverage-7.4.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8ce1415194b4a6bd0cdcc3a1dfbf58b63f910dcb7330fe15bdff542c56949f87"},
- {file = "coverage-7.4.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b91cbc4b195444e7e258ba27ac33769c41b94967919f10037e6355e998af255c"},
- {file = "coverage-7.4.4-cp310-cp310-win32.whl", hash = "sha256:598825b51b81c808cb6f078dcb972f96af96b078faa47af7dfcdf282835baa8d"},
- {file = "coverage-7.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:09ef9199ed6653989ebbcaacc9b62b514bb63ea2f90256e71fea3ed74bd8ff6f"},
- {file = "coverage-7.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0f9f50e7ef2a71e2fae92774c99170eb8304e3fdf9c8c3c7ae9bab3e7229c5cf"},
- {file = "coverage-7.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:623512f8ba53c422fcfb2ce68362c97945095b864cda94a92edbaf5994201083"},
- {file = "coverage-7.4.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0513b9508b93da4e1716744ef6ebc507aff016ba115ffe8ecff744d1322a7b63"},
- {file = "coverage-7.4.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40209e141059b9370a2657c9b15607815359ab3ef9918f0196b6fccce8d3230f"},
- {file = "coverage-7.4.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a2b2b78c78293782fd3767d53e6474582f62443d0504b1554370bde86cc8227"},
- {file = "coverage-7.4.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:73bfb9c09951125d06ee473bed216e2c3742f530fc5acc1383883125de76d9cd"},
- {file = "coverage-7.4.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1f384c3cc76aeedce208643697fb3e8437604b512255de6d18dae3f27655a384"},
- {file = "coverage-7.4.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:54eb8d1bf7cacfbf2a3186019bcf01d11c666bd495ed18717162f7eb1e9dd00b"},
- {file = "coverage-7.4.4-cp311-cp311-win32.whl", hash = "sha256:cac99918c7bba15302a2d81f0312c08054a3359eaa1929c7e4b26ebe41e9b286"},
- {file = "coverage-7.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:b14706df8b2de49869ae03a5ccbc211f4041750cd4a66f698df89d44f4bd30ec"},
- {file = "coverage-7.4.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:201bef2eea65e0e9c56343115ba3814e896afe6d36ffd37bab783261db430f76"},
- {file = "coverage-7.4.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:41c9c5f3de16b903b610d09650e5e27adbfa7f500302718c9ffd1c12cf9d6818"},
- {file = "coverage-7.4.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d898fe162d26929b5960e4e138651f7427048e72c853607f2b200909794ed978"},
- {file = "coverage-7.4.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ea79bb50e805cd6ac058dfa3b5c8f6c040cb87fe83de10845857f5535d1db70"},
- {file = "coverage-7.4.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce4b94265ca988c3f8e479e741693d143026632672e3ff924f25fab50518dd51"},
- {file = "coverage-7.4.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:00838a35b882694afda09f85e469c96367daa3f3f2b097d846a7216993d37f4c"},
- {file = "coverage-7.4.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:fdfafb32984684eb03c2d83e1e51f64f0906b11e64482df3c5db936ce3839d48"},
- {file = "coverage-7.4.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:69eb372f7e2ece89f14751fbcbe470295d73ed41ecd37ca36ed2eb47512a6ab9"},
- {file = "coverage-7.4.4-cp312-cp312-win32.whl", hash = "sha256:137eb07173141545e07403cca94ab625cc1cc6bc4c1e97b6e3846270e7e1fea0"},
- {file = "coverage-7.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:d71eec7d83298f1af3326ce0ff1d0ea83c7cb98f72b577097f9083b20bdaf05e"},
- {file = "coverage-7.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d5ae728ff3b5401cc320d792866987e7e7e880e6ebd24433b70a33b643bb0384"},
- {file = "coverage-7.4.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cc4f1358cb0c78edef3ed237ef2c86056206bb8d9140e73b6b89fbcfcbdd40e1"},
- {file = "coverage-7.4.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8130a2aa2acb8788e0b56938786c33c7c98562697bf9f4c7d6e8e5e3a0501e4a"},
- {file = "coverage-7.4.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf271892d13e43bc2b51e6908ec9a6a5094a4df1d8af0bfc360088ee6c684409"},
- {file = "coverage-7.4.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a4cdc86d54b5da0df6d3d3a2f0b710949286094c3a6700c21e9015932b81447e"},
- {file = "coverage-7.4.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ae71e7ddb7a413dd60052e90528f2f65270aad4b509563af6d03d53e979feafd"},
- {file = "coverage-7.4.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:38dd60d7bf242c4ed5b38e094baf6401faa114fc09e9e6632374388a404f98e7"},
- {file = "coverage-7.4.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aa5b1c1bfc28384f1f53b69a023d789f72b2e0ab1b3787aae16992a7ca21056c"},
- {file = "coverage-7.4.4-cp38-cp38-win32.whl", hash = "sha256:dfa8fe35a0bb90382837b238fff375de15f0dcdb9ae68ff85f7a63649c98527e"},
- {file = "coverage-7.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:b2991665420a803495e0b90a79233c1433d6ed77ef282e8e152a324bbbc5e0c8"},
- {file = "coverage-7.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3b799445b9f7ee8bf299cfaed6f5b226c0037b74886a4e11515e569b36fe310d"},
- {file = "coverage-7.4.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b4d33f418f46362995f1e9d4f3a35a1b6322cb959c31d88ae56b0298e1c22357"},
- {file = "coverage-7.4.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aadacf9a2f407a4688d700e4ebab33a7e2e408f2ca04dbf4aef17585389eff3e"},
- {file = "coverage-7.4.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c95949560050d04d46b919301826525597f07b33beba6187d04fa64d47ac82e"},
- {file = "coverage-7.4.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff7687ca3d7028d8a5f0ebae95a6e4827c5616b31a4ee1192bdfde697db110d4"},
- {file = "coverage-7.4.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5fc1de20b2d4a061b3df27ab9b7c7111e9a710f10dc2b84d33a4ab25065994ec"},
- {file = "coverage-7.4.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c74880fc64d4958159fbd537a091d2a585448a8f8508bf248d72112723974cbd"},
- {file = "coverage-7.4.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:742a76a12aa45b44d236815d282b03cfb1de3b4323f3e4ec933acfae08e54ade"},
- {file = "coverage-7.4.4-cp39-cp39-win32.whl", hash = "sha256:d89d7b2974cae412400e88f35d86af72208e1ede1a541954af5d944a8ba46c57"},
- {file = "coverage-7.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:9ca28a302acb19b6af89e90f33ee3e1906961f94b54ea37de6737b7ca9d8827c"},
- {file = "coverage-7.4.4-pp38.pp39.pp310-none-any.whl", hash = "sha256:b2c5edc4ac10a7ef6605a966c58929ec6c1bd0917fb8c15cb3363f65aa40e677"},
- {file = "coverage-7.4.4.tar.gz", hash = "sha256:c901df83d097649e257e803be22592aedfd5182f07b3cc87d640bbb9afd50f49"},
-]
-
-[package.extras]
-toml = ["tomli"]
-
-[[package]]
-name = "coverage-badge"
-version = "1.1.0"
-description = "Generate coverage badges for Coverage.py."
-optional = false
-python-versions = "*"
-files = [
- {file = "coverage-badge-1.1.0.tar.gz", hash = "sha256:c824a106503e981c02821e7d32f008fb3984b2338aa8c3800ec9357e33345b78"},
- {file = "coverage_badge-1.1.0-py2.py3-none-any.whl", hash = "sha256:e365d56e5202e923d1b237f82defd628a02d1d645a147f867ac85c58c81d7997"},
-]
-
-[package.dependencies]
-coverage = "*"
-
-[[package]]
-name = "cryptography"
-version = "42.0.5"
-description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "cryptography-42.0.5-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:a30596bae9403a342c978fb47d9b0ee277699fa53bbafad14706af51fe543d16"},
- {file = "cryptography-42.0.5-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:b7ffe927ee6531c78f81aa17e684e2ff617daeba7f189f911065b2ea2d526dec"},
- {file = "cryptography-42.0.5-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2424ff4c4ac7f6b8177b53c17ed5d8fa74ae5955656867f5a8affaca36a27abb"},
- {file = "cryptography-42.0.5-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:329906dcc7b20ff3cad13c069a78124ed8247adcac44b10bea1130e36caae0b4"},
- {file = "cryptography-42.0.5-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:b03c2ae5d2f0fc05f9a2c0c997e1bc18c8229f392234e8a0194f202169ccd278"},
- {file = "cryptography-42.0.5-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f8837fe1d6ac4a8052a9a8ddab256bc006242696f03368a4009be7ee3075cdb7"},
- {file = "cryptography-42.0.5-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:0270572b8bd2c833c3981724b8ee9747b3ec96f699a9665470018594301439ee"},
- {file = "cryptography-42.0.5-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:b8cac287fafc4ad485b8a9b67d0ee80c66bf3574f655d3b97ef2e1082360faf1"},
- {file = "cryptography-42.0.5-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:16a48c23a62a2f4a285699dba2e4ff2d1cff3115b9df052cdd976a18856d8e3d"},
- {file = "cryptography-42.0.5-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:2bce03af1ce5a5567ab89bd90d11e7bbdff56b8af3acbbec1faded8f44cb06da"},
- {file = "cryptography-42.0.5-cp37-abi3-win32.whl", hash = "sha256:b6cd2203306b63e41acdf39aa93b86fb566049aeb6dc489b70e34bcd07adca74"},
- {file = "cryptography-42.0.5-cp37-abi3-win_amd64.whl", hash = "sha256:98d8dc6d012b82287f2c3d26ce1d2dd130ec200c8679b6213b3c73c08b2b7940"},
- {file = "cryptography-42.0.5-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:5e6275c09d2badf57aea3afa80d975444f4be8d3bc58f7f80d2a484c6f9485c8"},
- {file = "cryptography-42.0.5-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4985a790f921508f36f81831817cbc03b102d643b5fcb81cd33df3fa291a1a1"},
- {file = "cryptography-42.0.5-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7cde5f38e614f55e28d831754e8a3bacf9ace5d1566235e39d91b35502d6936e"},
- {file = "cryptography-42.0.5-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:7367d7b2eca6513681127ebad53b2582911d1736dc2ffc19f2c3ae49997496bc"},
- {file = "cryptography-42.0.5-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:cd2030f6650c089aeb304cf093f3244d34745ce0cfcc39f20c6fbfe030102e2a"},
- {file = "cryptography-42.0.5-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a2913c5375154b6ef2e91c10b5720ea6e21007412f6437504ffea2109b5a33d7"},
- {file = "cryptography-42.0.5-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:c41fb5e6a5fe9ebcd58ca3abfeb51dffb5d83d6775405305bfa8715b76521922"},
- {file = "cryptography-42.0.5-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:3eaafe47ec0d0ffcc9349e1708be2aaea4c6dd4978d76bf6eb0cb2c13636c6fc"},
- {file = "cryptography-42.0.5-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1b95b98b0d2af784078fa69f637135e3c317091b615cd0905f8b8a087e86fa30"},
- {file = "cryptography-42.0.5-cp39-abi3-win32.whl", hash = "sha256:1f71c10d1e88467126f0efd484bd44bca5e14c664ec2ede64c32f20875c0d413"},
- {file = "cryptography-42.0.5-cp39-abi3-win_amd64.whl", hash = "sha256:a011a644f6d7d03736214d38832e030d8268bcff4a41f728e6030325fea3e400"},
- {file = "cryptography-42.0.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:9481ffe3cf013b71b2428b905c4f7a9a4f76ec03065b05ff499bb5682a8d9ad8"},
- {file = "cryptography-42.0.5-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:ba334e6e4b1d92442b75ddacc615c5476d4ad55cc29b15d590cc6b86efa487e2"},
- {file = "cryptography-42.0.5-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:ba3e4a42397c25b7ff88cdec6e2a16c2be18720f317506ee25210f6d31925f9c"},
- {file = "cryptography-42.0.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:111a0d8553afcf8eb02a4fea6ca4f59d48ddb34497aa8706a6cf536f1a5ec576"},
- {file = "cryptography-42.0.5-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cd65d75953847815962c84a4654a84850b2bb4aed3f26fadcc1c13892e1e29f6"},
- {file = "cryptography-42.0.5-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:e807b3188f9eb0eaa7bbb579b462c5ace579f1cedb28107ce8b48a9f7ad3679e"},
- {file = "cryptography-42.0.5-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f12764b8fffc7a123f641d7d049d382b73f96a34117e0b637b80643169cec8ac"},
- {file = "cryptography-42.0.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:37dd623507659e08be98eec89323469e8c7b4c1407c85112634ae3dbdb926fdd"},
- {file = "cryptography-42.0.5.tar.gz", hash = "sha256:6fe07eec95dfd477eb9530aef5bead34fec819b3aaf6c5bd6d20565da607bfe1"},
-]
-
-[package.dependencies]
-cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""}
-
-[package.extras]
-docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"]
-docstest = ["pyenchant (>=1.6.11)", "readme-renderer", "sphinxcontrib-spelling (>=4.0.1)"]
-nox = ["nox"]
-pep8test = ["check-sdist", "click", "mypy", "ruff"]
-sdist = ["build"]
-ssh = ["bcrypt (>=3.1.5)"]
-test = ["certifi", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"]
-test-randomorder = ["pytest-randomly"]
-
-[[package]]
-name = "deepdiff"
-version = "6.7.1"
-description = "Deep Difference and Search of any Python object/data. Recreate objects by adding adding deltas to each other."
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "deepdiff-6.7.1-py3-none-any.whl", hash = "sha256:58396bb7a863cbb4ed5193f548c56f18218060362311aa1dc36397b2f25108bd"},
- {file = "deepdiff-6.7.1.tar.gz", hash = "sha256:b367e6fa6caac1c9f500adc79ada1b5b1242c50d5f716a1a4362030197847d30"},
-]
-
-[package.dependencies]
-ordered-set = ">=4.0.2,<4.2.0"
-
-[package.extras]
-cli = ["click (==8.1.3)", "pyyaml (==6.0.1)"]
-optimize = ["orjson"]
-
-[[package]]
-name = "distlib"
-version = "0.3.8"
-description = "Distribution utilities"
-optional = false
-python-versions = "*"
-files = [
- {file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"},
- {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"},
-]
-
-[[package]]
-name = "dnspython"
-version = "2.6.1"
-description = "DNS toolkit"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "dnspython-2.6.1-py3-none-any.whl", hash = "sha256:5ef3b9680161f6fa89daf8ad451b5f1a33b18ae8a1c6778cdf4b43f08c0a6e50"},
- {file = "dnspython-2.6.1.tar.gz", hash = "sha256:e8f0f9c23a7b7cb99ded64e6c3a6f3e701d78f50c55e002b839dea7225cff7cc"},
-]
-
-[package.extras]
-dev = ["black (>=23.1.0)", "coverage (>=7.0)", "flake8 (>=7)", "mypy (>=1.8)", "pylint (>=3)", "pytest (>=7.4)", "pytest-cov (>=4.1.0)", "sphinx (>=7.2.0)", "twine (>=4.0.0)", "wheel (>=0.42.0)"]
-dnssec = ["cryptography (>=41)"]
-doh = ["h2 (>=4.1.0)", "httpcore (>=1.0.0)", "httpx (>=0.26.0)"]
-doq = ["aioquic (>=0.9.25)"]
-idna = ["idna (>=3.6)"]
-trio = ["trio (>=0.23)"]
-wmi = ["wmi (>=1.5.1)"]
-
-[[package]]
-name = "fastapi"
-version = "0.110.0"
-description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "fastapi-0.110.0-py3-none-any.whl", hash = "sha256:87a1f6fb632a218222c5984be540055346a8f5d8a68e8f6fb647b1dc9934de4b"},
- {file = "fastapi-0.110.0.tar.gz", hash = "sha256:266775f0dcc95af9d3ef39bad55cff525329a931d5fd51930aadd4f428bf7ff3"},
-]
-
-[package.dependencies]
-pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0"
-starlette = ">=0.36.3,<0.37.0"
-typing-extensions = ">=4.8.0"
-
-[package.extras]
-all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
-
-[[package]]
-name = "filelock"
-version = "3.13.3"
-description = "A platform independent file lock."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "filelock-3.13.3-py3-none-any.whl", hash = "sha256:5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb"},
- {file = "filelock-3.13.3.tar.gz", hash = "sha256:a79895a25bbefdf55d1a2a0a80968f7dbb28edcd6d4234a0afb3f37ecde4b546"},
-]
-
-[package.extras]
-docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"]
-testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"]
-typing = ["typing-extensions (>=4.8)"]
-
-[[package]]
-name = "frozenlist"
-version = "1.4.1"
-description = "A list-like structure which implements collections.abc.MutableSequence"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"},
- {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"},
- {file = "frozenlist-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776"},
- {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a"},
- {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad"},
- {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c"},
- {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe"},
- {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a"},
- {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98"},
- {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75"},
- {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5"},
- {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950"},
- {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc"},
- {file = "frozenlist-1.4.1-cp310-cp310-win32.whl", hash = "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1"},
- {file = "frozenlist-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439"},
- {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0"},
- {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49"},
- {file = "frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced"},
- {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0"},
- {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106"},
- {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068"},
- {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2"},
- {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19"},
- {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82"},
- {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec"},
- {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a"},
- {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74"},
- {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2"},
- {file = "frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17"},
- {file = "frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825"},
- {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae"},
- {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb"},
- {file = "frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b"},
- {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86"},
- {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480"},
- {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09"},
- {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a"},
- {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd"},
- {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6"},
- {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1"},
- {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b"},
- {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e"},
- {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8"},
- {file = "frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89"},
- {file = "frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5"},
- {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d"},
- {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826"},
- {file = "frozenlist-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb"},
- {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6"},
- {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d"},
- {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887"},
- {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a"},
- {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b"},
- {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701"},
- {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0"},
- {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11"},
- {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09"},
- {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7"},
- {file = "frozenlist-1.4.1-cp38-cp38-win32.whl", hash = "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497"},
- {file = "frozenlist-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09"},
- {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e"},
- {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d"},
- {file = "frozenlist-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8"},
- {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0"},
- {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b"},
- {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0"},
- {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897"},
- {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7"},
- {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742"},
- {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea"},
- {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5"},
- {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9"},
- {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6"},
- {file = "frozenlist-1.4.1-cp39-cp39-win32.whl", hash = "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932"},
- {file = "frozenlist-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0"},
- {file = "frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7"},
- {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"},
-]
-
-[[package]]
-name = "ghp-import"
-version = "2.1.0"
-description = "Copy your docs directly to the gh-pages branch."
-optional = false
-python-versions = "*"
-files = [
- {file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"},
- {file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"},
-]
-
-[package.dependencies]
-python-dateutil = ">=2.8.1"
-
-[package.extras]
-dev = ["flake8", "markdown", "twine", "wheel"]
-
-[[package]]
-name = "griffe"
-version = "0.42.1"
-description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "griffe-0.42.1-py3-none-any.whl", hash = "sha256:7e805e35617601355edcac0d3511cedc1ed0cb1f7645e2d336ae4b05bbae7b3b"},
- {file = "griffe-0.42.1.tar.gz", hash = "sha256:57046131384043ed078692b85d86b76568a686266cc036b9b56b704466f803ce"},
-]
-
-[package.dependencies]
-colorama = ">=0.4"
-
-[[package]]
-name = "h11"
-version = "0.14.0"
-description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
- {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
-]
-
-[[package]]
-name = "httpcore"
-version = "1.0.4"
-description = "A minimal low-level HTTP client."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "httpcore-1.0.4-py3-none-any.whl", hash = "sha256:ac418c1db41bade2ad53ae2f3834a3a0f5ae76b56cf5aa497d2d033384fc7d73"},
- {file = "httpcore-1.0.4.tar.gz", hash = "sha256:cb2839ccfcba0d2d3c1131d3c3e26dfc327326fbe7a5dc0dbfe9f6c9151bb022"},
-]
-
-[package.dependencies]
-certifi = "*"
-h11 = ">=0.13,<0.15"
-
-[package.extras]
-asyncio = ["anyio (>=4.0,<5.0)"]
-http2 = ["h2 (>=3,<5)"]
-socks = ["socksio (==1.*)"]
-trio = ["trio (>=0.22.0,<0.25.0)"]
-
-[[package]]
-name = "httptools"
-version = "0.6.1"
-description = "A collection of framework independent HTTP protocol utils."
-optional = false
-python-versions = ">=3.8.0"
-files = [
- {file = "httptools-0.6.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d2f6c3c4cb1948d912538217838f6e9960bc4a521d7f9b323b3da579cd14532f"},
- {file = "httptools-0.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:00d5d4b68a717765b1fabfd9ca755bd12bf44105eeb806c03d1962acd9b8e563"},
- {file = "httptools-0.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:639dc4f381a870c9ec860ce5c45921db50205a37cc3334e756269736ff0aac58"},
- {file = "httptools-0.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e57997ac7fb7ee43140cc03664de5f268813a481dff6245e0075925adc6aa185"},
- {file = "httptools-0.6.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0ac5a0ae3d9f4fe004318d64b8a854edd85ab76cffbf7ef5e32920faef62f142"},
- {file = "httptools-0.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3f30d3ce413088a98b9db71c60a6ada2001a08945cb42dd65a9a9fe228627658"},
- {file = "httptools-0.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:1ed99a373e327f0107cb513b61820102ee4f3675656a37a50083eda05dc9541b"},
- {file = "httptools-0.6.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7a7ea483c1a4485c71cb5f38be9db078f8b0e8b4c4dc0210f531cdd2ddac1ef1"},
- {file = "httptools-0.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:85ed077c995e942b6f1b07583e4eb0a8d324d418954fc6af913d36db7c05a5a0"},
- {file = "httptools-0.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b0bb634338334385351a1600a73e558ce619af390c2b38386206ac6a27fecfc"},
- {file = "httptools-0.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d9ceb2c957320def533671fc9c715a80c47025139c8d1f3797477decbc6edd2"},
- {file = "httptools-0.6.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4f0f8271c0a4db459f9dc807acd0eadd4839934a4b9b892f6f160e94da309837"},
- {file = "httptools-0.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6a4f5ccead6d18ec072ac0b84420e95d27c1cdf5c9f1bc8fbd8daf86bd94f43d"},
- {file = "httptools-0.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:5cceac09f164bcba55c0500a18fe3c47df29b62353198e4f37bbcc5d591172c3"},
- {file = "httptools-0.6.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:75c8022dca7935cba14741a42744eee13ba05db00b27a4b940f0d646bd4d56d0"},
- {file = "httptools-0.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:48ed8129cd9a0d62cf4d1575fcf90fb37e3ff7d5654d3a5814eb3d55f36478c2"},
- {file = "httptools-0.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f58e335a1402fb5a650e271e8c2d03cfa7cea46ae124649346d17bd30d59c90"},
- {file = "httptools-0.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93ad80d7176aa5788902f207a4e79885f0576134695dfb0fefc15b7a4648d503"},
- {file = "httptools-0.6.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9bb68d3a085c2174c2477eb3ffe84ae9fb4fde8792edb7bcd09a1d8467e30a84"},
- {file = "httptools-0.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b512aa728bc02354e5ac086ce76c3ce635b62f5fbc32ab7082b5e582d27867bb"},
- {file = "httptools-0.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:97662ce7fb196c785344d00d638fc9ad69e18ee4bfb4000b35a52efe5adcc949"},
- {file = "httptools-0.6.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8e216a038d2d52ea13fdd9b9c9c7459fb80d78302b257828285eca1c773b99b3"},
- {file = "httptools-0.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3e802e0b2378ade99cd666b5bffb8b2a7cc8f3d28988685dc300469ea8dd86cb"},
- {file = "httptools-0.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bd3e488b447046e386a30f07af05f9b38d3d368d1f7b4d8f7e10af85393db97"},
- {file = "httptools-0.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe467eb086d80217b7584e61313ebadc8d187a4d95bb62031b7bab4b205c3ba3"},
- {file = "httptools-0.6.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3c3b214ce057c54675b00108ac42bacf2ab8f85c58e3f324a4e963bbc46424f4"},
- {file = "httptools-0.6.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8ae5b97f690badd2ca27cbf668494ee1b6d34cf1c464271ef7bfa9ca6b83ffaf"},
- {file = "httptools-0.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:405784577ba6540fa7d6ff49e37daf104e04f4b4ff2d1ac0469eaa6a20fde084"},
- {file = "httptools-0.6.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:95fb92dd3649f9cb139e9c56604cc2d7c7bf0fc2e7c8d7fbd58f96e35eddd2a3"},
- {file = "httptools-0.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dcbab042cc3ef272adc11220517278519adf8f53fd3056d0e68f0a6f891ba94e"},
- {file = "httptools-0.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cf2372e98406efb42e93bfe10f2948e467edfd792b015f1b4ecd897903d3e8d"},
- {file = "httptools-0.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:678fcbae74477a17d103b7cae78b74800d795d702083867ce160fc202104d0da"},
- {file = "httptools-0.6.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e0b281cf5a125c35f7f6722b65d8542d2e57331be573e9e88bc8b0115c4a7a81"},
- {file = "httptools-0.6.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:95658c342529bba4e1d3d2b1a874db16c7cca435e8827422154c9da76ac4e13a"},
- {file = "httptools-0.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:7ebaec1bf683e4bf5e9fbb49b8cc36da482033596a415b3e4ebab5a4c0d7ec5e"},
- {file = "httptools-0.6.1.tar.gz", hash = "sha256:c6e26c30455600b95d94b1b836085138e82f177351454ee841c148f93a9bad5a"},
-]
-
-[package.extras]
-test = ["Cython (>=0.29.24,<0.30.0)"]
-
-[[package]]
-name = "httpx"
-version = "0.26.0"
-description = "The next generation HTTP client."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "httpx-0.26.0-py3-none-any.whl", hash = "sha256:8915f5a3627c4d47b73e8202457cb28f1266982d1159bd5779d86a80c0eab1cd"},
- {file = "httpx-0.26.0.tar.gz", hash = "sha256:451b55c30d5185ea6b23c2c793abf9bb237d2a7dfb901ced6ff69ad37ec1dfaf"},
-]
-
-[package.dependencies]
-anyio = "*"
-certifi = "*"
-httpcore = "==1.*"
-idna = "*"
-sniffio = "*"
-
-[package.extras]
-brotli = ["brotli", "brotlicffi"]
-cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"]
-http2 = ["h2 (>=3,<5)"]
-socks = ["socksio (==1.*)"]
-
-[[package]]
-name = "identify"
-version = "2.5.35"
-description = "File identification library for Python"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "identify-2.5.35-py2.py3-none-any.whl", hash = "sha256:c4de0081837b211594f8e877a6b4fad7ca32bbfc1a9307fdd61c28bfe923f13e"},
- {file = "identify-2.5.35.tar.gz", hash = "sha256:10a7ca245cfcd756a554a7288159f72ff105ad233c7c4b9c6f0f4d108f5f6791"},
-]
-
-[package.extras]
-license = ["ukkonen"]
-
-[[package]]
-name = "idna"
-version = "3.6"
-description = "Internationalized Domain Names in Applications (IDNA)"
-optional = false
-python-versions = ">=3.5"
-files = [
- {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"},
- {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"},
-]
-
-[[package]]
-name = "iniconfig"
-version = "2.0.0"
-description = "brain-dead simple config-ini parsing"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
- {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
-]
-
-[[package]]
-name = "inject"
-version = "5.2.1"
-description = "Python dependency injection framework."
-optional = false
-python-versions = "*"
-files = [
- {file = "inject-5.2.1-py2.py3-none-any.whl", hash = "sha256:e40a5b1bebd8a4050b6f98f3396f3de6e9e2e411ad2a2145f16f351cb6f54e51"},
- {file = "inject-5.2.1.tar.gz", hash = "sha256:f7c305a75cc4e3a331d248e996f25783ba784b88d5a9b9f73c53eacaa6d76985"},
-]
-
-[[package]]
-name = "jinja2"
-version = "3.1.3"
-description = "A very fast and expressive template engine."
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"},
- {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"},
-]
-
-[package.dependencies]
-MarkupSafe = ">=2.0"
-
-[package.extras]
-i18n = ["Babel (>=2.7)"]
-
-[[package]]
-name = "loguru"
-version = "0.7.2"
-description = "Python logging made (stupidly) simple"
-optional = false
-python-versions = ">=3.5"
-files = [
- {file = "loguru-0.7.2-py3-none-any.whl", hash = "sha256:003d71e3d3ed35f0f8984898359d65b79e5b21943f78af86aa5491210429b8eb"},
- {file = "loguru-0.7.2.tar.gz", hash = "sha256:e671a53522515f34fd406340ee968cb9ecafbc4b36c679da03c18fd8d0bd51ac"},
-]
-
-[package.dependencies]
-colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""}
-win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""}
-
-[package.extras]
-dev = ["Sphinx (==7.2.5)", "colorama (==0.4.5)", "colorama (==0.4.6)", "exceptiongroup (==1.1.3)", "freezegun (==1.1.0)", "freezegun (==1.2.2)", "mypy (==v0.910)", "mypy (==v0.971)", "mypy (==v1.4.1)", "mypy (==v1.5.1)", "pre-commit (==3.4.0)", "pytest (==6.1.2)", "pytest (==7.4.0)", "pytest-cov (==2.12.1)", "pytest-cov (==4.1.0)", "pytest-mypy-plugins (==1.9.3)", "pytest-mypy-plugins (==3.0.0)", "sphinx-autobuild (==2021.3.14)", "sphinx-rtd-theme (==1.3.0)", "tox (==3.27.1)", "tox (==4.11.0)"]
-
-[[package]]
-name = "markdown"
-version = "3.5.2"
-description = "Python implementation of John Gruber's Markdown."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "Markdown-3.5.2-py3-none-any.whl", hash = "sha256:d43323865d89fc0cb9b20c75fc8ad313af307cc087e84b657d9eec768eddeadd"},
- {file = "Markdown-3.5.2.tar.gz", hash = "sha256:e1ac7b3dc550ee80e602e71c1d168002f062e49f1b11e26a36264dafd4df2ef8"},
-]
-
-[package.extras]
-docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"]
-testing = ["coverage", "pyyaml"]
-
-[[package]]
-name = "markdown-it-py"
-version = "3.0.0"
-description = "Python port of markdown-it. Markdown parsing, done right!"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"},
- {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"},
-]
-
-[package.dependencies]
-mdurl = ">=0.1,<1.0"
-
-[package.extras]
-benchmarking = ["psutil", "pytest", "pytest-benchmark"]
-code-style = ["pre-commit (>=3.0,<4.0)"]
-compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"]
-linkify = ["linkify-it-py (>=1,<3)"]
-plugins = ["mdit-py-plugins"]
-profiling = ["gprof2dot"]
-rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"]
-testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
-
-[[package]]
-name = "markupsafe"
-version = "2.1.5"
-description = "Safely add untrusted strings to HTML/XML markup."
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"},
- {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"},
- {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"},
- {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"},
- {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"},
- {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"},
- {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"},
- {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"},
- {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"},
- {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"},
- {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"},
- {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"},
- {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"},
- {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"},
- {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"},
- {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"},
- {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"},
- {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"},
- {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"},
- {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"},
- {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"},
- {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"},
- {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"},
- {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"},
- {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"},
- {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"},
- {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"},
- {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"},
- {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"},
- {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"},
- {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"},
- {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"},
- {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"},
- {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"},
- {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"},
- {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"},
- {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"},
- {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"},
- {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"},
- {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"},
- {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"},
- {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"},
- {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"},
- {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"},
- {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"},
- {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"},
- {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"},
- {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"},
- {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"},
- {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"},
-]
-
-[[package]]
-name = "mdurl"
-version = "0.1.2"
-description = "Markdown URL utilities"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"},
- {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"},
-]
-
-[[package]]
-name = "mergedeep"
-version = "1.3.4"
-description = "A deep merge function for 🐍."
-optional = false
-python-versions = ">=3.6"
-files = [
- {file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"},
- {file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"},
-]
-
-[[package]]
-name = "mkdocs"
-version = "1.5.3"
-description = "Project documentation with Markdown."
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "mkdocs-1.5.3-py3-none-any.whl", hash = "sha256:3b3a78e736b31158d64dbb2f8ba29bd46a379d0c6e324c2246c3bc3d2189cfc1"},
- {file = "mkdocs-1.5.3.tar.gz", hash = "sha256:eb7c99214dcb945313ba30426c2451b735992c73c2e10838f76d09e39ff4d0e2"},
-]
-
-[package.dependencies]
-click = ">=7.0"
-colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""}
-ghp-import = ">=1.0"
-jinja2 = ">=2.11.1"
-markdown = ">=3.2.1"
-markupsafe = ">=2.0.1"
-mergedeep = ">=1.3.4"
-packaging = ">=20.5"
-pathspec = ">=0.11.1"
-platformdirs = ">=2.2.0"
-pyyaml = ">=5.1"
-pyyaml-env-tag = ">=0.1"
-watchdog = ">=2.0"
-
-[package.extras]
-i18n = ["babel (>=2.9.0)"]
-min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.3)", "jinja2 (==2.11.1)", "markdown (==3.2.1)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "packaging (==20.5)", "pathspec (==0.11.1)", "platformdirs (==2.2.0)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "typing-extensions (==3.10)", "watchdog (==2.0)"]
-
-[[package]]
-name = "mkdocs-autorefs"
-version = "1.0.1"
-description = "Automatically link across pages in MkDocs."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "mkdocs_autorefs-1.0.1-py3-none-any.whl", hash = "sha256:aacdfae1ab197780fb7a2dac92ad8a3d8f7ca8049a9cbe56a4218cd52e8da570"},
- {file = "mkdocs_autorefs-1.0.1.tar.gz", hash = "sha256:f684edf847eced40b570b57846b15f0bf57fb93ac2c510450775dcf16accb971"},
-]
-
-[package.dependencies]
-Markdown = ">=3.3"
-markupsafe = ">=2.0.1"
-mkdocs = ">=1.1"
-
-[[package]]
-name = "mkdocs-material"
-version = "9.5.15"
-description = "Documentation that simply works"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "mkdocs_material-9.5.15-py3-none-any.whl", hash = "sha256:e5c96dec3d19491de49ca643fc1dbb92b278e43cdb816c775bc47db77d9b62fb"},
- {file = "mkdocs_material-9.5.15.tar.gz", hash = "sha256:39f03cca45e82bf54eb7456b5a18bd252eabfdd67f237a229471484a0a4d4635"},
-]
-
-[package.dependencies]
-babel = ">=2.10,<3.0"
-colorama = ">=0.4,<1.0"
-jinja2 = ">=3.0,<4.0"
-markdown = ">=3.2,<4.0"
-mkdocs = ">=1.5.3,<1.6.0"
-mkdocs-material-extensions = ">=1.3,<2.0"
-paginate = ">=0.5,<1.0"
-pygments = ">=2.16,<3.0"
-pymdown-extensions = ">=10.2,<11.0"
-regex = ">=2022.4"
-requests = ">=2.26,<3.0"
-
-[package.extras]
-git = ["mkdocs-git-committers-plugin-2 (>=1.1,<2.0)", "mkdocs-git-revision-date-localized-plugin (>=1.2.4,<2.0)"]
-imaging = ["cairosvg (>=2.6,<3.0)", "pillow (>=10.2,<11.0)"]
-recommended = ["mkdocs-minify-plugin (>=0.7,<1.0)", "mkdocs-redirects (>=1.2,<2.0)", "mkdocs-rss-plugin (>=1.6,<2.0)"]
-
-[[package]]
-name = "mkdocs-material-extensions"
-version = "1.3.1"
-description = "Extension pack for Python Markdown and MkDocs Material."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31"},
- {file = "mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443"},
-]
-
-[[package]]
-name = "mkdocs-monorepo-plugin"
-version = "1.1.0"
-description = "Plugin for adding monorepository support in Mkdocs."
-optional = false
-python-versions = ">=3"
-files = [
- {file = "mkdocs-monorepo-plugin-1.1.0.tar.gz", hash = "sha256:ccc566e166aac5ae7fade498c15c4a337a4892d238629b51aba8ef3fc7099034"},
- {file = "mkdocs_monorepo_plugin-1.1.0-py3-none-any.whl", hash = "sha256:7bbfd9756a7fdecf64d6105dad96cce7e7bb5f0d6cfc2bfda31a1919c77cc3b9"},
-]
-
-[package.dependencies]
-mkdocs = ">=1.0.4"
-python-slugify = ">=4.0.1"
-
-[[package]]
-name = "mkdocstrings"
-version = "0.24.1"
-description = "Automatic documentation from sources, for MkDocs."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "mkdocstrings-0.24.1-py3-none-any.whl", hash = "sha256:b4206f9a2ca8a648e222d5a0ca1d36ba7dee53c88732818de183b536f9042b5d"},
- {file = "mkdocstrings-0.24.1.tar.gz", hash = "sha256:cc83f9a1c8724fc1be3c2fa071dd73d91ce902ef6a79710249ec8d0ee1064401"},
-]
-
-[package.dependencies]
-click = ">=7.0"
-Jinja2 = ">=2.11.1"
-Markdown = ">=3.3"
-MarkupSafe = ">=1.1"
-mkdocs = ">=1.4"
-mkdocs-autorefs = ">=0.3.1"
-platformdirs = ">=2.2.0"
-pymdown-extensions = ">=6.3"
-
-[package.extras]
-crystal = ["mkdocstrings-crystal (>=0.3.4)"]
-python = ["mkdocstrings-python (>=0.5.2)"]
-python-legacy = ["mkdocstrings-python-legacy (>=0.2.1)"]
-
-[[package]]
-name = "mkdocstrings-python"
-version = "1.9.0"
-description = "A Python handler for mkdocstrings."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "mkdocstrings_python-1.9.0-py3-none-any.whl", hash = "sha256:fad27d7314b4ec9c0359a187b477fb94c65ef561fdae941dca1b717c59aae96f"},
- {file = "mkdocstrings_python-1.9.0.tar.gz", hash = "sha256:6e1a442367cf75d30cf69774cbb1ad02aebec58bfff26087439df4955efecfde"},
-]
-
-[package.dependencies]
-griffe = ">=0.37"
-markdown = ">=3.3,<3.6"
-mkdocstrings = ">=0.20"
-
-[[package]]
-name = "multidict"
-version = "6.0.5"
-description = "multidict implementation"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"},
- {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"},
- {file = "multidict-6.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600"},
- {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c"},
- {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5"},
- {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f"},
- {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae"},
- {file = "multidict-6.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182"},
- {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf"},
- {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442"},
- {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a"},
- {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef"},
- {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc"},
- {file = "multidict-6.0.5-cp310-cp310-win32.whl", hash = "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319"},
- {file = "multidict-6.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8"},
- {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba"},
- {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e"},
- {file = "multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd"},
- {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3"},
- {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf"},
- {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29"},
- {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed"},
- {file = "multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733"},
- {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f"},
- {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4"},
- {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1"},
- {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc"},
- {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e"},
- {file = "multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c"},
- {file = "multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea"},
- {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"},
- {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"},
- {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"},
- {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"},
- {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"},
- {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"},
- {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"},
- {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"},
- {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"},
- {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"},
- {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"},
- {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"},
- {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"},
- {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"},
- {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"},
- {file = "multidict-6.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3"},
- {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5"},
- {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd"},
- {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e"},
- {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626"},
- {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83"},
- {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a"},
- {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c"},
- {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5"},
- {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3"},
- {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc"},
- {file = "multidict-6.0.5-cp37-cp37m-win32.whl", hash = "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee"},
- {file = "multidict-6.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423"},
- {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54"},
- {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d"},
- {file = "multidict-6.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7"},
- {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93"},
- {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8"},
- {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b"},
- {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50"},
- {file = "multidict-6.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e"},
- {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89"},
- {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386"},
- {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453"},
- {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461"},
- {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44"},
- {file = "multidict-6.0.5-cp38-cp38-win32.whl", hash = "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241"},
- {file = "multidict-6.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c"},
- {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929"},
- {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9"},
- {file = "multidict-6.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a"},
- {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1"},
- {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e"},
- {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046"},
- {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c"},
- {file = "multidict-6.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40"},
- {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527"},
- {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9"},
- {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38"},
- {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479"},
- {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c"},
- {file = "multidict-6.0.5-cp39-cp39-win32.whl", hash = "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b"},
- {file = "multidict-6.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755"},
- {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"},
- {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"},
-]
-
-[[package]]
-name = "mypy"
-version = "1.9.0"
-description = "Optional static typing for Python"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "mypy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f8a67616990062232ee4c3952f41c779afac41405806042a8126fe96e098419f"},
- {file = "mypy-1.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d357423fa57a489e8c47b7c85dfb96698caba13d66e086b412298a1a0ea3b0ed"},
- {file = "mypy-1.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49c87c15aed320de9b438ae7b00c1ac91cd393c1b854c2ce538e2a72d55df150"},
- {file = "mypy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:48533cdd345c3c2e5ef48ba3b0d3880b257b423e7995dada04248725c6f77374"},
- {file = "mypy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:4d3dbd346cfec7cb98e6cbb6e0f3c23618af826316188d587d1c1bc34f0ede03"},
- {file = "mypy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:653265f9a2784db65bfca694d1edd23093ce49740b2244cde583aeb134c008f3"},
- {file = "mypy-1.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a3c007ff3ee90f69cf0a15cbcdf0995749569b86b6d2f327af01fd1b8aee9dc"},
- {file = "mypy-1.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2418488264eb41f69cc64a69a745fad4a8f86649af4b1041a4c64ee61fc61129"},
- {file = "mypy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:68edad3dc7d70f2f17ae4c6c1b9471a56138ca22722487eebacfd1eb5321d612"},
- {file = "mypy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:85ca5fcc24f0b4aeedc1d02f93707bccc04733f21d41c88334c5482219b1ccb3"},
- {file = "mypy-1.9.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aceb1db093b04db5cd390821464504111b8ec3e351eb85afd1433490163d60cd"},
- {file = "mypy-1.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0235391f1c6f6ce487b23b9dbd1327b4ec33bb93934aa986efe8a9563d9349e6"},
- {file = "mypy-1.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4d5ddc13421ba3e2e082a6c2d74c2ddb3979c39b582dacd53dd5d9431237185"},
- {file = "mypy-1.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:190da1ee69b427d7efa8aa0d5e5ccd67a4fb04038c380237a0d96829cb157913"},
- {file = "mypy-1.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:fe28657de3bfec596bbeef01cb219833ad9d38dd5393fc649f4b366840baefe6"},
- {file = "mypy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e54396d70be04b34f31d2edf3362c1edd023246c82f1730bbf8768c28db5361b"},
- {file = "mypy-1.9.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5e6061f44f2313b94f920e91b204ec600982961e07a17e0f6cd83371cb23f5c2"},
- {file = "mypy-1.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a10926e5473c5fc3da8abb04119a1f5811a236dc3a38d92015cb1e6ba4cb9e"},
- {file = "mypy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b685154e22e4e9199fc95f298661deea28aaede5ae16ccc8cbb1045e716b3e04"},
- {file = "mypy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:5d741d3fc7c4da608764073089e5f58ef6352bedc223ff58f2f038c2c4698a89"},
- {file = "mypy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:587ce887f75dd9700252a3abbc9c97bbe165a4a630597845c61279cf32dfbf02"},
- {file = "mypy-1.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f88566144752999351725ac623471661c9d1cd8caa0134ff98cceeea181789f4"},
- {file = "mypy-1.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61758fabd58ce4b0720ae1e2fea5cfd4431591d6d590b197775329264f86311d"},
- {file = "mypy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e49499be624dead83927e70c756970a0bc8240e9f769389cdf5714b0784ca6bf"},
- {file = "mypy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:571741dc4194b4f82d344b15e8837e8c5fcc462d66d076748142327626a1b6e9"},
- {file = "mypy-1.9.0-py3-none-any.whl", hash = "sha256:a260627a570559181a9ea5de61ac6297aa5af202f06fd7ab093ce74e7181e43e"},
- {file = "mypy-1.9.0.tar.gz", hash = "sha256:3cc5da0127e6a478cddd906068496a97a7618a21ce9b54bde5bf7e539c7af974"},
-]
-
-[package.dependencies]
-mypy-extensions = ">=1.0.0"
-typing-extensions = ">=4.1.0"
-
-[package.extras]
-dmypy = ["psutil (>=4.0)"]
-install-types = ["pip"]
-mypyc = ["setuptools (>=50)"]
-reports = ["lxml"]
-
-[[package]]
-name = "mypy-extensions"
-version = "1.0.0"
-description = "Type system extensions for programs checked with the mypy type checker."
-optional = false
-python-versions = ">=3.5"
-files = [
- {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
- {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
-]
-
-[[package]]
-name = "mysql-connector-python"
-version = "8.3.0"
-description = "MySQL driver written in Python"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "mysql-connector-python-8.3.0.tar.gz", hash = "sha256:e4ff23aa8036b4c5b6463fa81398bb5a528a29f99955de6ba937f0bba57a2fe3"},
- {file = "mysql_connector_python-8.3.0-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:f4ee7e07cca6b744874d60d6b0b24817d9246eb4e8d7269b7ddbe68763a0bd13"},
- {file = "mysql_connector_python-8.3.0-cp310-cp310-macosx_13_0_x86_64.whl", hash = "sha256:5718e426cf67f041772d4984f709052201883f74190ba6feaddce5cbd3b99e6f"},
- {file = "mysql_connector_python-8.3.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:0deb38f05057e12af091a48e03a1ff00e213945880000f802879fae5665e7502"},
- {file = "mysql_connector_python-8.3.0-cp310-cp310-manylinux_2_17_x86_64.whl", hash = "sha256:4be4165e4cd5acb4659261ddc74e9164d2dfa0d795d5695d52f2bf39ea0762fa"},
- {file = "mysql_connector_python-8.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:51d97bf771519829797556718d81e8b9bdcd0a00427740ca57c085094c8bde17"},
- {file = "mysql_connector_python-8.3.0-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:5e2c86c60be08c71bae755d811fe8b89ec4feb8117ec3440ebc6c042dd6f06bc"},
- {file = "mysql_connector_python-8.3.0-cp311-cp311-macosx_13_0_x86_64.whl", hash = "sha256:de74055944b214bff56e1752ec213d705c421414c67a250fb695af0c5c214135"},
- {file = "mysql_connector_python-8.3.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:b2901391b651d60dab3cc8985df94976fc1ea59fa7324c5b19d0a4177914c8dd"},
- {file = "mysql_connector_python-8.3.0-cp311-cp311-manylinux_2_17_x86_64.whl", hash = "sha256:55cb57d8098c721abce20fdef23232663977c0e5c87a4d0f9f73466f32c7d168"},
- {file = "mysql_connector_python-8.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:201e609159b84a247be87b76f5deb79e8c6b368e91f043790e62077f13f3fed8"},
- {file = "mysql_connector_python-8.3.0-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:c57d02fd6c28be444487e7905ede09e3fecb18377cf82908ca262826369d3401"},
- {file = "mysql_connector_python-8.3.0-cp312-cp312-macosx_13_0_x86_64.whl", hash = "sha256:9302d774025e76a0fac46bfeea8854b3d6819715a6a16ff23bfcda04218a76b7"},
- {file = "mysql_connector_python-8.3.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:85fa878fdd6accaeb7d609bd2637c2cfa61592e7f9bdbdc0da18b2fa998d3d5a"},
- {file = "mysql_connector_python-8.3.0-cp312-cp312-manylinux_2_17_x86_64.whl", hash = "sha256:de0f2f2baa9e091ca8bdc4a091f874f9cd0b84b256389596adb0e032a05fe9f9"},
- {file = "mysql_connector_python-8.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:27f8be2087627366a44a6831ec68b568c98dbf0f4ceff24682d90c21db6e0f1f"},
- {file = "mysql_connector_python-8.3.0-cp38-cp38-macosx_13_0_x86_64.whl", hash = "sha256:ec6dc3434a7deef74ab04e8978f6c5e181866a5423006c1b5aec5390a189d28d"},
- {file = "mysql_connector_python-8.3.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:73ee8bc5f9626c42b37342a91a825cddb3461f6bfbbd6524d8ccfd3293aaa088"},
- {file = "mysql_connector_python-8.3.0-cp38-cp38-manylinux_2_17_x86_64.whl", hash = "sha256:1db5b48b4ff7d24344217ed2418b162c7677eec86ab9766dc0e5feae39c90974"},
- {file = "mysql_connector_python-8.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:77bae496566d3da77bb0e938d89243103d20ee41633f626a47785470451bf45c"},
- {file = "mysql_connector_python-8.3.0-cp39-cp39-macosx_13_0_arm64.whl", hash = "sha256:f7acacdf9fd4260702f360c00952ad9a9cc73e8b7475e0d0c973c085a3dd7b7d"},
- {file = "mysql_connector_python-8.3.0-cp39-cp39-macosx_13_0_x86_64.whl", hash = "sha256:5f707a9b040ad4700fc447ba955c78b08f2dd5affde37ac2401918f7b6daaba3"},
- {file = "mysql_connector_python-8.3.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:125714c998a697592bc56cce918a1acc58fadc510a7f588dbef3e53a1920e086"},
- {file = "mysql_connector_python-8.3.0-cp39-cp39-manylinux_2_17_x86_64.whl", hash = "sha256:7f4f5fa844c19ee3a78c4606f6e138b06829e75469592d90246a290c7befc322"},
- {file = "mysql_connector_python-8.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:de5c3ee89d9276356f93df003949d3ba4c486f32fec9ec9fd7bc0caab124d89c"},
- {file = "mysql_connector_python-8.3.0-py2.py3-none-any.whl", hash = "sha256:e868ccc7ad9fbc242546db04673d89cee87d12b8139affd114524553df4e5d6a"},
-]
-
-[package.extras]
-dns-srv = ["dnspython (>=1.16.0,<=2.3.0)"]
-fido2 = ["fido2 (==1.1.2)"]
-gssapi = ["gssapi (>=1.6.9,<=1.8.2)"]
-opentelemetry = ["Deprecated (>=1.2.6)", "typing-extensions (>=3.7.4)", "zipp (>=0.5)"]
-
-[[package]]
-name = "nodeenv"
-version = "1.8.0"
-description = "Node.js virtual environment builder"
-optional = false
-python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*"
-files = [
- {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"},
- {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"},
-]
-
-[package.dependencies]
-setuptools = "*"
-
-[[package]]
-name = "ordered-set"
-version = "4.1.0"
-description = "An OrderedSet is a custom MutableSet that remembers its order, so that every"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "ordered-set-4.1.0.tar.gz", hash = "sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8"},
- {file = "ordered_set-4.1.0-py3-none-any.whl", hash = "sha256:046e1132c71fcf3330438a539928932caf51ddbc582496833e23de611de14562"},
-]
-
-[package.extras]
-dev = ["black", "mypy", "pytest"]
-
-[[package]]
-name = "packaging"
-version = "24.0"
-description = "Core utilities for Python packages"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"},
- {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"},
-]
-
-[[package]]
-name = "paginate"
-version = "0.5.6"
-description = "Divides large result sets into pages for easier browsing"
-optional = false
-python-versions = "*"
-files = [
- {file = "paginate-0.5.6.tar.gz", hash = "sha256:5e6007b6a9398177a7e1648d04fdd9f8c9766a1a945bceac82f1929e8c78af2d"},
-]
-
-[[package]]
-name = "pathspec"
-version = "0.12.1"
-description = "Utility library for gitignore style pattern matching of file paths."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"},
- {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"},
-]
-
-[[package]]
-name = "pendulum"
-version = "3.0.0"
-description = "Python datetimes made easy"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "pendulum-3.0.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2cf9e53ef11668e07f73190c805dbdf07a1939c3298b78d5a9203a86775d1bfd"},
- {file = "pendulum-3.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fb551b9b5e6059377889d2d878d940fd0bbb80ae4810543db18e6f77b02c5ef6"},
- {file = "pendulum-3.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c58227ac260d5b01fc1025176d7b31858c9f62595737f350d22124a9a3ad82d"},
- {file = "pendulum-3.0.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60fb6f415fea93a11c52578eaa10594568a6716602be8430b167eb0d730f3332"},
- {file = "pendulum-3.0.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b69f6b4dbcb86f2c2fe696ba991e67347bcf87fe601362a1aba6431454b46bde"},
- {file = "pendulum-3.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:138afa9c373ee450ede206db5a5e9004fd3011b3c6bbe1e57015395cd076a09f"},
- {file = "pendulum-3.0.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:83d9031f39c6da9677164241fd0d37fbfc9dc8ade7043b5d6d62f56e81af8ad2"},
- {file = "pendulum-3.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0c2308af4033fa534f089595bcd40a95a39988ce4059ccd3dc6acb9ef14ca44a"},
- {file = "pendulum-3.0.0-cp310-none-win_amd64.whl", hash = "sha256:9a59637cdb8462bdf2dbcb9d389518c0263799189d773ad5c11db6b13064fa79"},
- {file = "pendulum-3.0.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3725245c0352c95d6ca297193192020d1b0c0f83d5ee6bb09964edc2b5a2d508"},
- {file = "pendulum-3.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6c035f03a3e565ed132927e2c1b691de0dbf4eb53b02a5a3c5a97e1a64e17bec"},
- {file = "pendulum-3.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:597e66e63cbd68dd6d58ac46cb7a92363d2088d37ccde2dae4332ef23e95cd00"},
- {file = "pendulum-3.0.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99a0f8172e19f3f0c0e4ace0ad1595134d5243cf75985dc2233e8f9e8de263ca"},
- {file = "pendulum-3.0.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:77d8839e20f54706aed425bec82a83b4aec74db07f26acd039905d1237a5e1d4"},
- {file = "pendulum-3.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afde30e8146292b059020fbc8b6f8fd4a60ae7c5e6f0afef937bbb24880bdf01"},
- {file = "pendulum-3.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:660434a6fcf6303c4efd36713ca9212c753140107ee169a3fc6c49c4711c2a05"},
- {file = "pendulum-3.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dee9e5a48c6999dc1106eb7eea3e3a50e98a50651b72c08a87ee2154e544b33e"},
- {file = "pendulum-3.0.0-cp311-none-win_amd64.whl", hash = "sha256:d4cdecde90aec2d67cebe4042fd2a87a4441cc02152ed7ed8fb3ebb110b94ec4"},
- {file = "pendulum-3.0.0-cp311-none-win_arm64.whl", hash = "sha256:773c3bc4ddda2dda9f1b9d51fe06762f9200f3293d75c4660c19b2614b991d83"},
- {file = "pendulum-3.0.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:409e64e41418c49f973d43a28afe5df1df4f1dd87c41c7c90f1a63f61ae0f1f7"},
- {file = "pendulum-3.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a38ad2121c5ec7c4c190c7334e789c3b4624798859156b138fcc4d92295835dc"},
- {file = "pendulum-3.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fde4d0b2024b9785f66b7f30ed59281bd60d63d9213cda0eb0910ead777f6d37"},
- {file = "pendulum-3.0.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b2c5675769fb6d4c11238132962939b960fcb365436b6d623c5864287faa319"},
- {file = "pendulum-3.0.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8af95e03e066826f0f4c65811cbee1b3123d4a45a1c3a2b4fc23c4b0dff893b5"},
- {file = "pendulum-3.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2165a8f33cb15e06c67070b8afc87a62b85c5a273e3aaa6bc9d15c93a4920d6f"},
- {file = "pendulum-3.0.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ad5e65b874b5e56bd942546ea7ba9dd1d6a25121db1c517700f1c9de91b28518"},
- {file = "pendulum-3.0.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:17fe4b2c844bbf5f0ece69cfd959fa02957c61317b2161763950d88fed8e13b9"},
- {file = "pendulum-3.0.0-cp312-none-win_amd64.whl", hash = "sha256:78f8f4e7efe5066aca24a7a57511b9c2119f5c2b5eb81c46ff9222ce11e0a7a5"},
- {file = "pendulum-3.0.0-cp312-none-win_arm64.whl", hash = "sha256:28f49d8d1e32aae9c284a90b6bb3873eee15ec6e1d9042edd611b22a94ac462f"},
- {file = "pendulum-3.0.0-cp37-cp37m-macosx_10_12_x86_64.whl", hash = "sha256:d4e2512f4e1a4670284a153b214db9719eb5d14ac55ada5b76cbdb8c5c00399d"},
- {file = "pendulum-3.0.0-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:3d897eb50883cc58d9b92f6405245f84b9286cd2de6e8694cb9ea5cb15195a32"},
- {file = "pendulum-3.0.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e169cc2ca419517f397811bbe4589cf3cd13fca6dc38bb352ba15ea90739ebb"},
- {file = "pendulum-3.0.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f17c3084a4524ebefd9255513692f7e7360e23c8853dc6f10c64cc184e1217ab"},
- {file = "pendulum-3.0.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:826d6e258052715f64d05ae0fc9040c0151e6a87aae7c109ba9a0ed930ce4000"},
- {file = "pendulum-3.0.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2aae97087872ef152a0c40e06100b3665d8cb86b59bc8471ca7c26132fccd0f"},
- {file = "pendulum-3.0.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ac65eeec2250d03106b5e81284ad47f0d417ca299a45e89ccc69e36130ca8bc7"},
- {file = "pendulum-3.0.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a5346d08f3f4a6e9e672187faa179c7bf9227897081d7121866358af369f44f9"},
- {file = "pendulum-3.0.0-cp37-none-win_amd64.whl", hash = "sha256:235d64e87946d8f95c796af34818c76e0f88c94d624c268693c85b723b698aa9"},
- {file = "pendulum-3.0.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:6a881d9c2a7f85bc9adafcfe671df5207f51f5715ae61f5d838b77a1356e8b7b"},
- {file = "pendulum-3.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d7762d2076b9b1cb718a6631ad6c16c23fc3fac76cbb8c454e81e80be98daa34"},
- {file = "pendulum-3.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e8e36a8130819d97a479a0e7bf379b66b3b1b520e5dc46bd7eb14634338df8c"},
- {file = "pendulum-3.0.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7dc843253ac373358ffc0711960e2dd5b94ab67530a3e204d85c6e8cb2c5fa10"},
- {file = "pendulum-3.0.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0a78ad3635d609ceb1e97d6aedef6a6a6f93433ddb2312888e668365908c7120"},
- {file = "pendulum-3.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b30a137e9e0d1f751e60e67d11fc67781a572db76b2296f7b4d44554761049d6"},
- {file = "pendulum-3.0.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c95984037987f4a457bb760455d9ca80467be792236b69d0084f228a8ada0162"},
- {file = "pendulum-3.0.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d29c6e578fe0f893766c0d286adbf0b3c726a4e2341eba0917ec79c50274ec16"},
- {file = "pendulum-3.0.0-cp38-none-win_amd64.whl", hash = "sha256:deaba8e16dbfcb3d7a6b5fabdd5a38b7c982809567479987b9c89572df62e027"},
- {file = "pendulum-3.0.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b11aceea5b20b4b5382962b321dbc354af0defe35daa84e9ff3aae3c230df694"},
- {file = "pendulum-3.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a90d4d504e82ad236afac9adca4d6a19e4865f717034fc69bafb112c320dcc8f"},
- {file = "pendulum-3.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:825799c6b66e3734227756fa746cc34b3549c48693325b8b9f823cb7d21b19ac"},
- {file = "pendulum-3.0.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad769e98dc07972e24afe0cff8d365cb6f0ebc7e65620aa1976fcfbcadc4c6f3"},
- {file = "pendulum-3.0.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6fc26907eb5fb8cc6188cc620bc2075a6c534d981a2f045daa5f79dfe50d512"},
- {file = "pendulum-3.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c717eab1b6d898c00a3e0fa7781d615b5c5136bbd40abe82be100bb06df7a56"},
- {file = "pendulum-3.0.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3ddd1d66d1a714ce43acfe337190be055cdc221d911fc886d5a3aae28e14b76d"},
- {file = "pendulum-3.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:822172853d7a9cf6da95d7b66a16c7160cb99ae6df55d44373888181d7a06edc"},
- {file = "pendulum-3.0.0-cp39-none-win_amd64.whl", hash = "sha256:840de1b49cf1ec54c225a2a6f4f0784d50bd47f68e41dc005b7f67c7d5b5f3ae"},
- {file = "pendulum-3.0.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3b1f74d1e6ffe5d01d6023870e2ce5c2191486928823196f8575dcc786e107b1"},
- {file = "pendulum-3.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:729e9f93756a2cdfa77d0fc82068346e9731c7e884097160603872686e570f07"},
- {file = "pendulum-3.0.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e586acc0b450cd21cbf0db6bae386237011b75260a3adceddc4be15334689a9a"},
- {file = "pendulum-3.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22e7944ffc1f0099a79ff468ee9630c73f8c7835cd76fdb57ef7320e6a409df4"},
- {file = "pendulum-3.0.0-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:fa30af36bd8e50686846bdace37cf6707bdd044e5cb6e1109acbad3277232e04"},
- {file = "pendulum-3.0.0-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:440215347b11914ae707981b9a57ab9c7b6983ab0babde07063c6ee75c0dc6e7"},
- {file = "pendulum-3.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:314c4038dc5e6a52991570f50edb2f08c339debdf8cea68ac355b32c4174e820"},
- {file = "pendulum-3.0.0-pp37-pypy37_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5acb1d386337415f74f4d1955c4ce8d0201978c162927d07df8eb0692b2d8533"},
- {file = "pendulum-3.0.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a789e12fbdefaffb7b8ac67f9d8f22ba17a3050ceaaa635cd1cc4645773a4b1e"},
- {file = "pendulum-3.0.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:860aa9b8a888e5913bd70d819306749e5eb488e6b99cd6c47beb701b22bdecf5"},
- {file = "pendulum-3.0.0-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:5ebc65ea033ef0281368217fbf59f5cb05b338ac4dd23d60959c7afcd79a60a0"},
- {file = "pendulum-3.0.0-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:d9fef18ab0386ef6a9ac7bad7e43ded42c83ff7ad412f950633854f90d59afa8"},
- {file = "pendulum-3.0.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:1c134ba2f0571d0b68b83f6972e2307a55a5a849e7dac8505c715c531d2a8795"},
- {file = "pendulum-3.0.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:385680812e7e18af200bb9b4a49777418c32422d05ad5a8eb85144c4a285907b"},
- {file = "pendulum-3.0.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9eec91cd87c59fb32ec49eb722f375bd58f4be790cae11c1b70fac3ee4f00da0"},
- {file = "pendulum-3.0.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4386bffeca23c4b69ad50a36211f75b35a4deb6210bdca112ac3043deb7e494a"},
- {file = "pendulum-3.0.0-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:dfbcf1661d7146d7698da4b86e7f04814221081e9fe154183e34f4c5f5fa3bf8"},
- {file = "pendulum-3.0.0-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:04a1094a5aa1daa34a6b57c865b25f691848c61583fb22722a4df5699f6bf74c"},
- {file = "pendulum-3.0.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5b0ec85b9045bd49dd3a3493a5e7ddfd31c36a2a60da387c419fa04abcaecb23"},
- {file = "pendulum-3.0.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0a15b90129765b705eb2039062a6daf4d22c4e28d1a54fa260892e8c3ae6e157"},
- {file = "pendulum-3.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:bb8f6d7acd67a67d6fedd361ad2958ff0539445ef51cbe8cd288db4306503cd0"},
- {file = "pendulum-3.0.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd69b15374bef7e4b4440612915315cc42e8575fcda2a3d7586a0d88192d0c88"},
- {file = "pendulum-3.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc00f8110db6898360c53c812872662e077eaf9c75515d53ecc65d886eec209a"},
- {file = "pendulum-3.0.0-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:83a44e8b40655d0ba565a5c3d1365d27e3e6778ae2a05b69124db9e471255c4a"},
- {file = "pendulum-3.0.0-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:1a3604e9fbc06b788041b2a8b78f75c243021e0f512447806a6d37ee5214905d"},
- {file = "pendulum-3.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:92c307ae7accebd06cbae4729f0ba9fa724df5f7d91a0964b1b972a22baa482b"},
- {file = "pendulum-3.0.0.tar.gz", hash = "sha256:5d034998dea404ec31fae27af6b22cff1708f830a1ed7353be4d1019bb9f584e"},
-]
-
-[package.dependencies]
-python-dateutil = ">=2.6"
-time-machine = {version = ">=2.6.0", optional = true, markers = "implementation_name != \"pypy\" and extra == \"test\""}
-tzdata = ">=2020.1"
-
-[package.extras]
-test = ["time-machine (>=2.6.0)"]
-
-[[package]]
-name = "platformdirs"
-version = "4.2.0"
-description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068"},
- {file = "platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"},
-]
-
-[package.extras]
-docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"]
-test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"]
-
-[[package]]
-name = "pluggy"
-version = "1.4.0"
-description = "plugin and hook calling mechanisms for python"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"},
- {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"},
-]
-
-[package.extras]
-dev = ["pre-commit", "tox"]
-testing = ["pytest", "pytest-benchmark"]
-
-[[package]]
-name = "pre-commit"
-version = "3.7.0"
-description = "A framework for managing and maintaining multi-language pre-commit hooks."
-optional = false
-python-versions = ">=3.9"
-files = [
- {file = "pre_commit-3.7.0-py2.py3-none-any.whl", hash = "sha256:5eae9e10c2b5ac51577c3452ec0a490455c45a0533f7960f993a0d01e59decab"},
- {file = "pre_commit-3.7.0.tar.gz", hash = "sha256:e209d61b8acdcf742404408531f0c37d49d2c734fd7cff2d6076083d191cb060"},
-]
-
-[package.dependencies]
-cfgv = ">=2.0.0"
-identify = ">=1.0.0"
-nodeenv = ">=0.11.1"
-pyyaml = ">=5.1"
-virtualenv = ">=20.10.0"
-
-[[package]]
-name = "pycparser"
-version = "2.21"
-description = "C parser in Python"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-files = [
- {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"},
- {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"},
-]
-
-[[package]]
-name = "pydantic"
-version = "2.6.3"
-description = "Data validation using Python type hints"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "pydantic-2.6.3-py3-none-any.whl", hash = "sha256:72c6034df47f46ccdf81869fddb81aade68056003900a8724a4f160700016a2a"},
- {file = "pydantic-2.6.3.tar.gz", hash = "sha256:e07805c4c7f5c6826e33a1d4c9d47950d7eaf34868e2690f8594d2e30241f11f"},
-]
-
-[package.dependencies]
-annotated-types = ">=0.4.0"
-pydantic-core = "2.16.3"
-typing-extensions = ">=4.6.1"
-
-[package.extras]
-email = ["email-validator (>=2.0.0)"]
-
-[[package]]
-name = "pydantic-core"
-version = "2.16.3"
-description = ""
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "pydantic_core-2.16.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:75b81e678d1c1ede0785c7f46690621e4c6e63ccd9192af1f0bd9d504bbb6bf4"},
- {file = "pydantic_core-2.16.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9c865a7ee6f93783bd5d781af5a4c43dadc37053a5b42f7d18dc019f8c9d2bd1"},
- {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:162e498303d2b1c036b957a1278fa0899d02b2842f1ff901b6395104c5554a45"},
- {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f583bd01bbfbff4eaee0868e6fc607efdfcc2b03c1c766b06a707abbc856187"},
- {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b926dd38db1519ed3043a4de50214e0d600d404099c3392f098a7f9d75029ff8"},
- {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:716b542728d4c742353448765aa7cdaa519a7b82f9564130e2b3f6766018c9ec"},
- {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4ad7f7ee1a13d9cb49d8198cd7d7e3aa93e425f371a68235f784e99741561f"},
- {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd87f48924f360e5d1c5f770d6155ce0e7d83f7b4e10c2f9ec001c73cf475c99"},
- {file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0df446663464884297c793874573549229f9eca73b59360878f382a0fc085979"},
- {file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4df8a199d9f6afc5ae9a65f8f95ee52cae389a8c6b20163762bde0426275b7db"},
- {file = "pydantic_core-2.16.3-cp310-none-win32.whl", hash = "sha256:456855f57b413f077dff513a5a28ed838dbbb15082ba00f80750377eed23d132"},
- {file = "pydantic_core-2.16.3-cp310-none-win_amd64.whl", hash = "sha256:732da3243e1b8d3eab8c6ae23ae6a58548849d2e4a4e03a1924c8ddf71a387cb"},
- {file = "pydantic_core-2.16.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:519ae0312616026bf4cedc0fe459e982734f3ca82ee8c7246c19b650b60a5ee4"},
- {file = "pydantic_core-2.16.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b3992a322a5617ded0a9f23fd06dbc1e4bd7cf39bc4ccf344b10f80af58beacd"},
- {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d62da299c6ecb04df729e4b5c52dc0d53f4f8430b4492b93aa8de1f541c4aac"},
- {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2acca2be4bb2f2147ada8cac612f8a98fc09f41c89f87add7256ad27332c2fda"},
- {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b662180108c55dfbf1280d865b2d116633d436cfc0bba82323554873967b340"},
- {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e7c6ed0dc9d8e65f24f5824291550139fe6f37fac03788d4580da0d33bc00c97"},
- {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1bb0827f56654b4437955555dc3aeeebeddc47c2d7ed575477f082622c49e"},
- {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e56f8186d6210ac7ece503193ec84104da7ceb98f68ce18c07282fcc2452e76f"},
- {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:936e5db01dd49476fa8f4383c259b8b1303d5dd5fb34c97de194560698cc2c5e"},
- {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:33809aebac276089b78db106ee692bdc9044710e26f24a9a2eaa35a0f9fa70ba"},
- {file = "pydantic_core-2.16.3-cp311-none-win32.whl", hash = "sha256:ded1c35f15c9dea16ead9bffcde9bb5c7c031bff076355dc58dcb1cb436c4721"},
- {file = "pydantic_core-2.16.3-cp311-none-win_amd64.whl", hash = "sha256:d89ca19cdd0dd5f31606a9329e309d4fcbb3df860960acec32630297d61820df"},
- {file = "pydantic_core-2.16.3-cp311-none-win_arm64.whl", hash = "sha256:6162f8d2dc27ba21027f261e4fa26f8bcb3cf9784b7f9499466a311ac284b5b9"},
- {file = "pydantic_core-2.16.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0f56ae86b60ea987ae8bcd6654a887238fd53d1384f9b222ac457070b7ac4cff"},
- {file = "pydantic_core-2.16.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9bd22a2a639e26171068f8ebb5400ce2c1bc7d17959f60a3b753ae13c632975"},
- {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4204e773b4b408062960e65468d5346bdfe139247ee5f1ca2a378983e11388a2"},
- {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f651dd19363c632f4abe3480a7c87a9773be27cfe1341aef06e8759599454120"},
- {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aaf09e615a0bf98d406657e0008e4a8701b11481840be7d31755dc9f97c44053"},
- {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8e47755d8152c1ab5b55928ab422a76e2e7b22b5ed8e90a7d584268dd49e9c6b"},
- {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:500960cb3a0543a724a81ba859da816e8cf01b0e6aaeedf2c3775d12ee49cade"},
- {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cf6204fe865da605285c34cf1172879d0314ff267b1c35ff59de7154f35fdc2e"},
- {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d33dd21f572545649f90c38c227cc8631268ba25c460b5569abebdd0ec5974ca"},
- {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:49d5d58abd4b83fb8ce763be7794d09b2f50f10aa65c0f0c1696c677edeb7cbf"},
- {file = "pydantic_core-2.16.3-cp312-none-win32.whl", hash = "sha256:f53aace168a2a10582e570b7736cc5bef12cae9cf21775e3eafac597e8551fbe"},
- {file = "pydantic_core-2.16.3-cp312-none-win_amd64.whl", hash = "sha256:0d32576b1de5a30d9a97f300cc6a3f4694c428d956adbc7e6e2f9cad279e45ed"},
- {file = "pydantic_core-2.16.3-cp312-none-win_arm64.whl", hash = "sha256:ec08be75bb268473677edb83ba71e7e74b43c008e4a7b1907c6d57e940bf34b6"},
- {file = "pydantic_core-2.16.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b1f6f5938d63c6139860f044e2538baeee6f0b251a1816e7adb6cbce106a1f01"},
- {file = "pydantic_core-2.16.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2a1ef6a36fdbf71538142ed604ad19b82f67b05749512e47f247a6ddd06afdc7"},
- {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:704d35ecc7e9c31d48926150afada60401c55efa3b46cd1ded5a01bdffaf1d48"},
- {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d937653a696465677ed583124b94a4b2d79f5e30b2c46115a68e482c6a591c8a"},
- {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9803edf8e29bd825f43481f19c37f50d2b01899448273b3a7758441b512acf8"},
- {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72282ad4892a9fb2da25defeac8c2e84352c108705c972db82ab121d15f14e6d"},
- {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f752826b5b8361193df55afcdf8ca6a57d0232653494ba473630a83ba50d8c9"},
- {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4384a8f68ddb31a0b0c3deae88765f5868a1b9148939c3f4121233314ad5532c"},
- {file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a4b2bf78342c40b3dc830880106f54328928ff03e357935ad26c7128bbd66ce8"},
- {file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:13dcc4802961b5f843a9385fc821a0b0135e8c07fc3d9949fd49627c1a5e6ae5"},
- {file = "pydantic_core-2.16.3-cp38-none-win32.whl", hash = "sha256:e3e70c94a0c3841e6aa831edab1619ad5c511199be94d0c11ba75fe06efe107a"},
- {file = "pydantic_core-2.16.3-cp38-none-win_amd64.whl", hash = "sha256:ecdf6bf5f578615f2e985a5e1f6572e23aa632c4bd1dc67f8f406d445ac115ed"},
- {file = "pydantic_core-2.16.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:bda1ee3e08252b8d41fa5537413ffdddd58fa73107171a126d3b9ff001b9b820"},
- {file = "pydantic_core-2.16.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:21b888c973e4f26b7a96491c0965a8a312e13be108022ee510248fe379a5fa23"},
- {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be0ec334369316fa73448cc8c982c01e5d2a81c95969d58b8f6e272884df0074"},
- {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5b6079cc452a7c53dd378c6f881ac528246b3ac9aae0f8eef98498a75657805"},
- {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee8d5f878dccb6d499ba4d30d757111847b6849ae07acdd1205fffa1fc1253c"},
- {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7233d65d9d651242a68801159763d09e9ec96e8a158dbf118dc090cd77a104c9"},
- {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6119dc90483a5cb50a1306adb8d52c66e447da88ea44f323e0ae1a5fcb14256"},
- {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:578114bc803a4c1ff9946d977c221e4376620a46cf78da267d946397dc9514a8"},
- {file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d8f99b147ff3fcf6b3cc60cb0c39ea443884d5559a30b1481e92495f2310ff2b"},
- {file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4ac6b4ce1e7283d715c4b729d8f9dab9627586dafce81d9eaa009dd7f25dd972"},
- {file = "pydantic_core-2.16.3-cp39-none-win32.whl", hash = "sha256:e7774b570e61cb998490c5235740d475413a1f6de823169b4cf94e2fe9e9f6b2"},
- {file = "pydantic_core-2.16.3-cp39-none-win_amd64.whl", hash = "sha256:9091632a25b8b87b9a605ec0e61f241c456e9248bfdcf7abdf344fdb169c81cf"},
- {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:36fa178aacbc277bc6b62a2c3da95226520da4f4e9e206fdf076484363895d2c"},
- {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:dcca5d2bf65c6fb591fff92da03f94cd4f315972f97c21975398bd4bd046854a"},
- {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a72fb9963cba4cd5793854fd12f4cfee731e86df140f59ff52a49b3552db241"},
- {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b60cc1a081f80a2105a59385b92d82278b15d80ebb3adb200542ae165cd7d183"},
- {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cbcc558401de90a746d02ef330c528f2e668c83350f045833543cd57ecead1ad"},
- {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:fee427241c2d9fb7192b658190f9f5fd6dfe41e02f3c1489d2ec1e6a5ab1e04a"},
- {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f4cb85f693044e0f71f394ff76c98ddc1bc0953e48c061725e540396d5c8a2e1"},
- {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b29eeb887aa931c2fcef5aa515d9d176d25006794610c264ddc114c053bf96fe"},
- {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a425479ee40ff021f8216c9d07a6a3b54b31c8267c6e17aa88b70d7ebd0e5e5b"},
- {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5c5cbc703168d1b7a838668998308018a2718c2130595e8e190220238addc96f"},
- {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99b6add4c0b39a513d323d3b93bc173dac663c27b99860dd5bf491b240d26137"},
- {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f76ee558751746d6a38f89d60b6228fa174e5172d143886af0f85aa306fd89"},
- {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:00ee1c97b5364b84cb0bd82e9bbf645d5e2871fb8c58059d158412fee2d33d8a"},
- {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:287073c66748f624be4cef893ef9174e3eb88fe0b8a78dc22e88eca4bc357ca6"},
- {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ed25e1835c00a332cb10c683cd39da96a719ab1dfc08427d476bce41b92531fc"},
- {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:86b3d0033580bd6bbe07590152007275bd7af95f98eaa5bd36f3da219dcd93da"},
- {file = "pydantic_core-2.16.3.tar.gz", hash = "sha256:1cac689f80a3abab2d3c0048b29eea5751114054f032a941a32de4c852c59cad"},
-]
-
-[package.dependencies]
-typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
-
-[[package]]
-name = "pygments"
-version = "2.17.2"
-description = "Pygments is a syntax highlighting package written in Python."
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"},
- {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"},
-]
-
-[package.extras]
-plugins = ["importlib-metadata"]
-windows-terminal = ["colorama (>=0.4.6)"]
-
-[[package]]
-name = "pyisemail"
-version = "2.0.1"
-description = "Simple, robust email validation"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "pyisemail-2.0.1-py3-none-any.whl", hash = "sha256:3d2bebd159f436673219d024a3f02bed1b468c793df9a5fa08d72b7d4b4f6cb4"},
- {file = "pyisemail-2.0.1.tar.gz", hash = "sha256:daf4b3fb2150a38f406b0aaba729e19fcd638a6d1c0549c25ff54c7b804618f8"},
-]
-
-[package.dependencies]
-dnspython = ">=2.0.0"
-
-[[package]]
-name = "pyjwt"
-version = "2.8.0"
-description = "JSON Web Token implementation in Python"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "PyJWT-2.8.0-py3-none-any.whl", hash = "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320"},
- {file = "PyJWT-2.8.0.tar.gz", hash = "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"},
-]
-
-[package.extras]
-crypto = ["cryptography (>=3.4.0)"]
-dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"]
-docs = ["sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"]
-tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"]
-
-[[package]]
-name = "pymdown-extensions"
-version = "10.7.1"
-description = "Extension pack for Python Markdown."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "pymdown_extensions-10.7.1-py3-none-any.whl", hash = "sha256:f5cc7000d7ff0d1ce9395d216017fa4df3dde800afb1fb72d1c7d3fd35e710f4"},
- {file = "pymdown_extensions-10.7.1.tar.gz", hash = "sha256:c70e146bdd83c744ffc766b4671999796aba18842b268510a329f7f64700d584"},
-]
-
-[package.dependencies]
-markdown = ">=3.5"
-pyyaml = "*"
-
-[package.extras]
-extra = ["pygments (>=2.12)"]
-
-[[package]]
-name = "pytest"
-version = "8.1.1"
-description = "pytest: simple powerful testing with Python"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "pytest-8.1.1-py3-none-any.whl", hash = "sha256:2a8386cfc11fa9d2c50ee7b2a57e7d898ef90470a7a34c4b949ff59662bb78b7"},
- {file = "pytest-8.1.1.tar.gz", hash = "sha256:ac978141a75948948817d360297b7aae0fcb9d6ff6bc9ec6d514b85d5a65c044"},
-]
-
-[package.dependencies]
-colorama = {version = "*", markers = "sys_platform == \"win32\""}
-iniconfig = "*"
-packaging = "*"
-pluggy = ">=1.4,<2.0"
-
-[package.extras]
-testing = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
-
-[[package]]
-name = "pytest-asyncio"
-version = "0.21.1"
-description = "Pytest support for asyncio"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "pytest-asyncio-0.21.1.tar.gz", hash = "sha256:40a7eae6dded22c7b604986855ea48400ab15b069ae38116e8c01238e9eeb64d"},
- {file = "pytest_asyncio-0.21.1-py3-none-any.whl", hash = "sha256:8666c1c8ac02631d7c51ba282e0c69a8a452b211ffedf2599099845da5c5c37b"},
-]
-
-[package.dependencies]
-pytest = ">=7.0.0"
-
-[package.extras]
-docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"]
-testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"]
-
-[[package]]
-name = "pytest-cov"
-version = "5.0.0"
-description = "Pytest plugin for measuring coverage."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "pytest-cov-5.0.0.tar.gz", hash = "sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857"},
- {file = "pytest_cov-5.0.0-py3-none-any.whl", hash = "sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652"},
-]
-
-[package.dependencies]
-coverage = {version = ">=5.2.1", extras = ["toml"]}
-pytest = ">=4.6"
-
-[package.extras]
-testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"]
-
-[[package]]
-name = "pytest-sugar"
-version = "1.0.0"
-description = "pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly)."
-optional = false
-python-versions = "*"
-files = [
- {file = "pytest-sugar-1.0.0.tar.gz", hash = "sha256:6422e83258f5b0c04ce7c632176c7732cab5fdb909cb39cca5c9139f81276c0a"},
- {file = "pytest_sugar-1.0.0-py3-none-any.whl", hash = "sha256:70ebcd8fc5795dc457ff8b69d266a4e2e8a74ae0c3edc749381c64b5246c8dfd"},
-]
-
-[package.dependencies]
-packaging = ">=21.3"
-pytest = ">=6.2.0"
-termcolor = ">=2.1.0"
-
-[package.extras]
-dev = ["black", "flake8", "pre-commit"]
-
-[[package]]
-name = "python-dateutil"
-version = "2.9.0.post0"
-description = "Extensions to the standard Python datetime module"
-optional = false
-python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
-files = [
- {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"},
- {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"},
-]
-
-[package.dependencies]
-six = ">=1.5"
-
-[[package]]
-name = "python-dotenv"
-version = "1.0.1"
-description = "Read key-value pairs from a .env file and set them as environment variables"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"},
- {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"},
-]
-
-[package.extras]
-cli = ["click (>=5.0)"]
-
-[[package]]
-name = "python-multipart"
-version = "0.0.9"
-description = "A streaming multipart parser for Python"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "python_multipart-0.0.9-py3-none-any.whl", hash = "sha256:97ca7b8ea7b05f977dc3849c3ba99d51689822fab725c3703af7c866a0c2b215"},
- {file = "python_multipart-0.0.9.tar.gz", hash = "sha256:03f54688c663f1b7977105f021043b0793151e4cb1c1a9d4a11fc13d622c4026"},
-]
-
-[package.extras]
-dev = ["atomicwrites (==1.4.1)", "attrs (==23.2.0)", "coverage (==7.4.1)", "hatch", "invoke (==2.2.0)", "more-itertools (==10.2.0)", "pbr (==6.0.0)", "pluggy (==1.4.0)", "py (==1.11.0)", "pytest (==8.0.0)", "pytest-cov (==4.1.0)", "pytest-timeout (==2.2.0)", "pyyaml (==6.0.1)", "ruff (==0.2.1)"]
-
-[[package]]
-name = "python-slugify"
-version = "8.0.4"
-description = "A Python slugify application that also handles Unicode"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "python-slugify-8.0.4.tar.gz", hash = "sha256:59202371d1d05b54a9e7720c5e038f928f45daaffe41dd10822f3907b937c856"},
- {file = "python_slugify-8.0.4-py2.py3-none-any.whl", hash = "sha256:276540b79961052b66b7d116620b36518847f52d5fd9e3a70164fc8c50faa6b8"},
-]
-
-[package.dependencies]
-text-unidecode = ">=1.3"
-
-[package.extras]
-unidecode = ["Unidecode (>=1.1.1)"]
-
-[[package]]
-name = "pyyaml"
-version = "6.0.1"
-description = "YAML parser and emitter for Python"
-optional = false
-python-versions = ">=3.6"
-files = [
- {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"},
- {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"},
- {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
- {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
- {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
- {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"},
- {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
- {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
- {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
- {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"},
- {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
- {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
- {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
- {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"},
- {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
- {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
- {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
- {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
- {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"},
- {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
- {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
- {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
- {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"},
- {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
- {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
- {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
- {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"},
- {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"},
- {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"},
- {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"},
- {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"},
- {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"},
- {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"},
- {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"},
- {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"},
- {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"},
- {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
- {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
- {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
- {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"},
- {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
- {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
- {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
- {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"},
- {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
- {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
- {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
- {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"},
- {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
- {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
- {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
-]
-
-[[package]]
-name = "pyyaml-env-tag"
-version = "0.1"
-description = "A custom YAML tag for referencing environment variables in YAML files. "
-optional = false
-python-versions = ">=3.6"
-files = [
- {file = "pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"},
- {file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"},
-]
-
-[package.dependencies]
-pyyaml = "*"
-
-[[package]]
-name = "redis"
-version = "5.0.3"
-description = "Python client for Redis database and key-value store"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "redis-5.0.3-py3-none-any.whl", hash = "sha256:5da9b8fe9e1254293756c16c008e8620b3d15fcc6dde6babde9541850e72a32d"},
- {file = "redis-5.0.3.tar.gz", hash = "sha256:4973bae7444c0fbed64a06b87446f79361cb7e4ec1538c022d696ed7a5015580"},
-]
-
-[package.extras]
-hiredis = ["hiredis (>=1.0.0)"]
-ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"]
-
-[[package]]
-name = "regex"
-version = "2023.12.25"
-description = "Alternative regular expression module, to replace re."
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0694219a1d54336fd0445ea382d49d36882415c0134ee1e8332afd1529f0baa5"},
- {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b014333bd0217ad3d54c143de9d4b9a3ca1c5a29a6d0d554952ea071cff0f1f8"},
- {file = "regex-2023.12.25-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d865984b3f71f6d0af64d0d88f5733521698f6c16f445bb09ce746c92c97c586"},
- {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e0eabac536b4cc7f57a5f3d095bfa557860ab912f25965e08fe1545e2ed8b4c"},
- {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c25a8ad70e716f96e13a637802813f65d8a6760ef48672aa3502f4c24ea8b400"},
- {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9b6d73353f777630626f403b0652055ebfe8ff142a44ec2cf18ae470395766e"},
- {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9cc99d6946d750eb75827cb53c4371b8b0fe89c733a94b1573c9dd16ea6c9e4"},
- {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88d1f7bef20c721359d8675f7d9f8e414ec5003d8f642fdfd8087777ff7f94b5"},
- {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cb3fe77aec8f1995611f966d0c656fdce398317f850d0e6e7aebdfe61f40e1cd"},
- {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7aa47c2e9ea33a4a2a05f40fcd3ea36d73853a2aae7b4feab6fc85f8bf2c9704"},
- {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:df26481f0c7a3f8739fecb3e81bc9da3fcfae34d6c094563b9d4670b047312e1"},
- {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c40281f7d70baf6e0db0c2f7472b31609f5bc2748fe7275ea65a0b4601d9b392"},
- {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:d94a1db462d5690ebf6ae86d11c5e420042b9898af5dcf278bd97d6bda065423"},
- {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ba1b30765a55acf15dce3f364e4928b80858fa8f979ad41f862358939bdd1f2f"},
- {file = "regex-2023.12.25-cp310-cp310-win32.whl", hash = "sha256:150c39f5b964e4d7dba46a7962a088fbc91f06e606f023ce57bb347a3b2d4630"},
- {file = "regex-2023.12.25-cp310-cp310-win_amd64.whl", hash = "sha256:09da66917262d9481c719599116c7dc0c321ffcec4b1f510c4f8a066f8768105"},
- {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1b9d811f72210fa9306aeb88385b8f8bcef0dfbf3873410413c00aa94c56c2b6"},
- {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97"},
- {file = "regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887"},
- {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb"},
- {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:636ba0a77de609d6510235b7f0e77ec494d2657108f777e8765efc060094c98c"},
- {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fda75704357805eb953a3ee15a2b240694a9a514548cd49b3c5124b4e2ad01b"},
- {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa"},
- {file = "regex-2023.12.25-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db2a0b1857f18b11e3b0e54ddfefc96af46b0896fb678c85f63fb8c37518b3e7"},
- {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7502534e55c7c36c0978c91ba6f61703faf7ce733715ca48f499d3dbbd7657e0"},
- {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e8c7e08bb566de4faaf11984af13f6bcf6a08f327b13631d41d62592681d24fe"},
- {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:283fc8eed679758de38fe493b7d7d84a198b558942b03f017b1f94dda8efae80"},
- {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f44dd4d68697559d007462b0a3a1d9acd61d97072b71f6d1968daef26bc744bd"},
- {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:67d3ccfc590e5e7197750fcb3a2915b416a53e2de847a728cfa60141054123d4"},
- {file = "regex-2023.12.25-cp311-cp311-win32.whl", hash = "sha256:68191f80a9bad283432385961d9efe09d783bcd36ed35a60fb1ff3f1ec2efe87"},
- {file = "regex-2023.12.25-cp311-cp311-win_amd64.whl", hash = "sha256:7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f"},
- {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8a0ccf52bb37d1a700375a6b395bff5dd15c50acb745f7db30415bae3c2b0715"},
- {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c3c4a78615b7762740531c27cf46e2f388d8d727d0c0c739e72048beb26c8a9d"},
- {file = "regex-2023.12.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ad83e7545b4ab69216cef4cc47e344d19622e28aabec61574b20257c65466d6a"},
- {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7a635871143661feccce3979e1727c4e094f2bdfd3ec4b90dfd4f16f571a87a"},
- {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d498eea3f581fbe1b34b59c697512a8baef88212f92e4c7830fcc1499f5b45a5"},
- {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:43f7cd5754d02a56ae4ebb91b33461dc67be8e3e0153f593c509e21d219c5060"},
- {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51f4b32f793812714fd5307222a7f77e739b9bc566dc94a18126aba3b92b98a3"},
- {file = "regex-2023.12.25-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba99d8077424501b9616b43a2d208095746fb1284fc5ba490139651f971d39d9"},
- {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4bfc2b16e3ba8850e0e262467275dd4d62f0d045e0e9eda2bc65078c0110a11f"},
- {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8c2c19dae8a3eb0ea45a8448356ed561be843b13cbc34b840922ddf565498c1c"},
- {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:60080bb3d8617d96f0fb7e19796384cc2467447ef1c491694850ebd3670bc457"},
- {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b77e27b79448e34c2c51c09836033056a0547aa360c45eeeb67803da7b0eedaf"},
- {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:518440c991f514331f4850a63560321f833979d145d7d81186dbe2f19e27ae3d"},
- {file = "regex-2023.12.25-cp312-cp312-win32.whl", hash = "sha256:e2610e9406d3b0073636a3a2e80db05a02f0c3169b5632022b4e81c0364bcda5"},
- {file = "regex-2023.12.25-cp312-cp312-win_amd64.whl", hash = "sha256:cc37b9aeebab425f11f27e5e9e6cf580be7206c6582a64467a14dda211abc232"},
- {file = "regex-2023.12.25-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:da695d75ac97cb1cd725adac136d25ca687da4536154cdc2815f576e4da11c69"},
- {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d126361607b33c4eb7b36debc173bf25d7805847346dd4d99b5499e1fef52bc7"},
- {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4719bb05094d7d8563a450cf8738d2e1061420f79cfcc1fa7f0a44744c4d8f73"},
- {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5dd58946bce44b53b06d94aa95560d0b243eb2fe64227cba50017a8d8b3cd3e2"},
- {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22a86d9fff2009302c440b9d799ef2fe322416d2d58fc124b926aa89365ec482"},
- {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2aae8101919e8aa05ecfe6322b278f41ce2994c4a430303c4cd163fef746e04f"},
- {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e692296c4cc2873967771345a876bcfc1c547e8dd695c6b89342488b0ea55cd8"},
- {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:263ef5cc10979837f243950637fffb06e8daed7f1ac1e39d5910fd29929e489a"},
- {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:d6f7e255e5fa94642a0724e35406e6cb7001c09d476ab5fce002f652b36d0c39"},
- {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:88ad44e220e22b63b0f8f81f007e8abbb92874d8ced66f32571ef8beb0643b2b"},
- {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:3a17d3ede18f9cedcbe23d2daa8a2cd6f59fe2bf082c567e43083bba3fb00347"},
- {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d15b274f9e15b1a0b7a45d2ac86d1f634d983ca40d6b886721626c47a400bf39"},
- {file = "regex-2023.12.25-cp37-cp37m-win32.whl", hash = "sha256:ed19b3a05ae0c97dd8f75a5d8f21f7723a8c33bbc555da6bbe1f96c470139d3c"},
- {file = "regex-2023.12.25-cp37-cp37m-win_amd64.whl", hash = "sha256:a6d1047952c0b8104a1d371f88f4ab62e6275567d4458c1e26e9627ad489b445"},
- {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b43523d7bc2abd757119dbfb38af91b5735eea45537ec6ec3a5ec3f9562a1c53"},
- {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:efb2d82f33b2212898f1659fb1c2e9ac30493ac41e4d53123da374c3b5541e64"},
- {file = "regex-2023.12.25-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b7fca9205b59c1a3d5031f7e64ed627a1074730a51c2a80e97653e3e9fa0d415"},
- {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086dd15e9435b393ae06f96ab69ab2d333f5d65cbe65ca5a3ef0ec9564dfe770"},
- {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e81469f7d01efed9b53740aedd26085f20d49da65f9c1f41e822a33992cb1590"},
- {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:34e4af5b27232f68042aa40a91c3b9bb4da0eeb31b7632e0091afc4310afe6cb"},
- {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9852b76ab558e45b20bf1893b59af64a28bd3820b0c2efc80e0a70a4a3ea51c1"},
- {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff100b203092af77d1a5a7abe085b3506b7eaaf9abf65b73b7d6905b6cb76988"},
- {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cc038b2d8b1470364b1888a98fd22d616fba2b6309c5b5f181ad4483e0017861"},
- {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:094ba386bb5c01e54e14434d4caabf6583334090865b23ef58e0424a6286d3dc"},
- {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5cd05d0f57846d8ba4b71d9c00f6f37d6b97d5e5ef8b3c3840426a475c8f70f4"},
- {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:9aa1a67bbf0f957bbe096375887b2505f5d8ae16bf04488e8b0f334c36e31360"},
- {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:98a2636994f943b871786c9e82bfe7883ecdaba2ef5df54e1450fa9869d1f756"},
- {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:37f8e93a81fc5e5bd8db7e10e62dc64261bcd88f8d7e6640aaebe9bc180d9ce2"},
- {file = "regex-2023.12.25-cp38-cp38-win32.whl", hash = "sha256:d78bd484930c1da2b9679290a41cdb25cc127d783768a0369d6b449e72f88beb"},
- {file = "regex-2023.12.25-cp38-cp38-win_amd64.whl", hash = "sha256:b521dcecebc5b978b447f0f69b5b7f3840eac454862270406a39837ffae4e697"},
- {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f7bc09bc9c29ebead055bcba136a67378f03d66bf359e87d0f7c759d6d4ffa31"},
- {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e14b73607d6231f3cc4622809c196b540a6a44e903bcfad940779c80dffa7be7"},
- {file = "regex-2023.12.25-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9eda5f7a50141291beda3edd00abc2d4a5b16c29c92daf8d5bd76934150f3edc"},
- {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc6bb9aa69aacf0f6032c307da718f61a40cf970849e471254e0e91c56ffca95"},
- {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:298dc6354d414bc921581be85695d18912bea163a8b23cac9a2562bbcd5088b1"},
- {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f4e475a80ecbd15896a976aa0b386c5525d0ed34d5c600b6d3ebac0a67c7ddf"},
- {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:531ac6cf22b53e0696f8e1d56ce2396311254eb806111ddd3922c9d937151dae"},
- {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22f3470f7524b6da61e2020672df2f3063676aff444db1daa283c2ea4ed259d6"},
- {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:89723d2112697feaa320c9d351e5f5e7b841e83f8b143dba8e2d2b5f04e10923"},
- {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0ecf44ddf9171cd7566ef1768047f6e66975788258b1c6c6ca78098b95cf9a3d"},
- {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:905466ad1702ed4acfd67a902af50b8db1feeb9781436372261808df7a2a7bca"},
- {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:4558410b7a5607a645e9804a3e9dd509af12fb72b9825b13791a37cd417d73a5"},
- {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7e316026cc1095f2a3e8cc012822c99f413b702eaa2ca5408a513609488cb62f"},
- {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3b1de218d5375cd6ac4b5493e0b9f3df2be331e86520f23382f216c137913d20"},
- {file = "regex-2023.12.25-cp39-cp39-win32.whl", hash = "sha256:11a963f8e25ab5c61348d090bf1b07f1953929c13bd2309a0662e9ff680763c9"},
- {file = "regex-2023.12.25-cp39-cp39-win_amd64.whl", hash = "sha256:e693e233ac92ba83a87024e1d32b5f9ab15ca55ddd916d878146f4e3406b5c91"},
- {file = "regex-2023.12.25.tar.gz", hash = "sha256:29171aa128da69afdf4bde412d5bedc335f2ca8fcfe4489038577d05f16181e5"},
-]
-
-[[package]]
-name = "requests"
-version = "2.31.0"
-description = "Python HTTP for Humans."
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"},
- {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"},
-]
-
-[package.dependencies]
-certifi = ">=2017.4.17"
-charset-normalizer = ">=2,<4"
-idna = ">=2.5,<4"
-urllib3 = ">=1.21.1,<3"
-
-[package.extras]
-socks = ["PySocks (>=1.5.6,!=1.5.7)"]
-use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
-
-[[package]]
-name = "rich"
-version = "13.7.1"
-description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
-optional = false
-python-versions = ">=3.7.0"
-files = [
- {file = "rich-13.7.1-py3-none-any.whl", hash = "sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222"},
- {file = "rich-13.7.1.tar.gz", hash = "sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432"},
-]
-
-[package.dependencies]
-markdown-it-py = ">=2.2.0"
-pygments = ">=2.13.0,<3.0.0"
-
-[package.extras]
-jupyter = ["ipywidgets (>=7.5.1,<9)"]
-
-[[package]]
-name = "ruff"
-version = "0.3.4"
-description = "An extremely fast Python linter and code formatter, written in Rust."
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "ruff-0.3.4-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:60c870a7d46efcbc8385d27ec07fe534ac32f3b251e4fc44b3cbfd9e09609ef4"},
- {file = "ruff-0.3.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6fc14fa742e1d8f24910e1fff0bd5e26d395b0e0e04cc1b15c7c5e5fe5b4af91"},
- {file = "ruff-0.3.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3ee7880f653cc03749a3bfea720cf2a192e4f884925b0cf7eecce82f0ce5854"},
- {file = "ruff-0.3.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cf133dd744f2470b347f602452a88e70dadfbe0fcfb5fd46e093d55da65f82f7"},
- {file = "ruff-0.3.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f3860057590e810c7ffea75669bdc6927bfd91e29b4baa9258fd48b540a4365"},
- {file = "ruff-0.3.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:986f2377f7cf12efac1f515fc1a5b753c000ed1e0a6de96747cdf2da20a1b369"},
- {file = "ruff-0.3.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fd98e85869603e65f554fdc5cddf0712e352fe6e61d29d5a6fe087ec82b76c"},
- {file = "ruff-0.3.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:64abeed785dad51801b423fa51840b1764b35d6c461ea8caef9cf9e5e5ab34d9"},
- {file = "ruff-0.3.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df52972138318bc7546d92348a1ee58449bc3f9eaf0db278906eb511889c4b50"},
- {file = "ruff-0.3.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:98e98300056445ba2cc27d0b325fd044dc17fcc38e4e4d2c7711585bd0a958ed"},
- {file = "ruff-0.3.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:519cf6a0ebed244dce1dc8aecd3dc99add7a2ee15bb68cf19588bb5bf58e0488"},
- {file = "ruff-0.3.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:bb0acfb921030d00070539c038cd24bb1df73a2981e9f55942514af8b17be94e"},
- {file = "ruff-0.3.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:cf187a7e7098233d0d0c71175375c5162f880126c4c716fa28a8ac418dcf3378"},
- {file = "ruff-0.3.4-py3-none-win32.whl", hash = "sha256:af27ac187c0a331e8ef91d84bf1c3c6a5dea97e912a7560ac0cef25c526a4102"},
- {file = "ruff-0.3.4-py3-none-win_amd64.whl", hash = "sha256:de0d5069b165e5a32b3c6ffbb81c350b1e3d3483347196ffdf86dc0ef9e37dd6"},
- {file = "ruff-0.3.4-py3-none-win_arm64.whl", hash = "sha256:6810563cc08ad0096b57c717bd78aeac888a1bfd38654d9113cb3dc4d3f74232"},
- {file = "ruff-0.3.4.tar.gz", hash = "sha256:f0f4484c6541a99862b693e13a151435a279b271cff20e37101116a21e2a1ad1"},
-]
-
-[[package]]
-name = "setuptools"
-version = "69.2.0"
-description = "Easily download, build, install, upgrade, and uninstall Python packages"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "setuptools-69.2.0-py3-none-any.whl", hash = "sha256:c21c49fb1042386df081cb5d86759792ab89efca84cf114889191cd09aacc80c"},
- {file = "setuptools-69.2.0.tar.gz", hash = "sha256:0ff4183f8f42cd8fa3acea16c45205521a4ef28f73c6391d8a25e92893134f2e"},
-]
-
-[package.extras]
-docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
-testing = ["build[virtualenv]", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
-testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
-
-[[package]]
-name = "shellingham"
-version = "1.5.4"
-description = "Tool to Detect Surrounding Shell"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"},
- {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"},
-]
-
-[[package]]
-name = "six"
-version = "1.16.0"
-description = "Python 2 and 3 compatibility utilities"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
-files = [
- {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
- {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
-]
-
-[[package]]
-name = "sniffio"
-version = "1.3.1"
-description = "Sniff out which async library your code is running under"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"},
- {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
-]
-
-[[package]]
-name = "sql-smith"
-version = "1.1.1"
-description = "sql-smith is an SQL query builder with zero dependencies and a fluent interface."
-optional = false
-python-versions = ">=3.10,<4.0"
-files = [
- {file = "sql_smith-1.1.1-py3-none-any.whl", hash = "sha256:f092a1816ee7bfd740cd381a38c2d4524e101f580eec0cb8ec6882ee8f90bbed"},
- {file = "sql_smith-1.1.1.tar.gz", hash = "sha256:5622205e4f8f1815ddb0bd347a0bc6bece507d2fccaa948f867f407dd6cf9c3d"},
-]
-
-[[package]]
-name = "starlette"
-version = "0.36.3"
-description = "The little ASGI library that shines."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "starlette-0.36.3-py3-none-any.whl", hash = "sha256:13d429aa93a61dc40bf503e8c801db1f1bca3dc706b10ef2434a36123568f044"},
- {file = "starlette-0.36.3.tar.gz", hash = "sha256:90a671733cfb35771d8cc605e0b679d23b992f8dcfad48cc60b38cb29aeb7080"},
-]
-
-[package.dependencies]
-anyio = ">=3.4.0,<5"
-
-[package.extras]
-full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7)", "pyyaml"]
-
-[[package]]
-name = "termcolor"
-version = "2.4.0"
-description = "ANSI color formatting for output in terminal"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "termcolor-2.4.0-py3-none-any.whl", hash = "sha256:9297c0df9c99445c2412e832e882a7884038a25617c60cea2ad69488d4040d63"},
- {file = "termcolor-2.4.0.tar.gz", hash = "sha256:aab9e56047c8ac41ed798fa36d892a37aca6b3e9159f3e0c24bc64a9b3ac7b7a"},
-]
-
-[package.extras]
-tests = ["pytest", "pytest-cov"]
-
-[[package]]
-name = "text-unidecode"
-version = "1.3"
-description = "The most basic Text::Unidecode port"
-optional = false
-python-versions = "*"
-files = [
- {file = "text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"},
- {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"},
-]
-
-[[package]]
-name = "time-machine"
-version = "2.14.1"
-description = "Travel through time in your tests."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "time-machine-2.14.1.tar.gz", hash = "sha256:57dc7efc1dde4331902d1bdefd34e8ee890a5c28533157e3b14a429c86b39533"},
- {file = "time_machine-2.14.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:528d588d1e8ba83e45319a74acab4be0569eb141113fdf50368045d0a7d79cee"},
- {file = "time_machine-2.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06e913d570d7ee3e199e3316f10f10c8046287049141b0a101197712b4eac106"},
- {file = "time_machine-2.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ddbbba954e9a409e7d66d60df2b6b8daeb897f8338f909a92d9d20e431ec70d1"},
- {file = "time_machine-2.14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:72a153b085b4aee652d6b3bf9019ca897f1597ba9869b640b06f28736b267182"},
- {file = "time_machine-2.14.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b94274abe24b6a90d8a5c042167a9a7af2d3438b42ac8eb5ede50fbc73c08db"},
- {file = "time_machine-2.14.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:364353858708628655bf9fa4c2825febd679c729d9e1dd424ff86845828bac05"},
- {file = "time_machine-2.14.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:b951b6f4b8a752ab8c441df422e21954a721a0a5276aa3814ce8cf7205aeb6da"},
- {file = "time_machine-2.14.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:be215eb63d74a3d580f7924bb4209c783fabcfb3253073f4dcb3424d57d0f518"},
- {file = "time_machine-2.14.1-cp310-cp310-win32.whl", hash = "sha256:0e120f95c17bf8e0c097fd8863a8eb24054f9b17d9b17c465694be50f8348a3a"},
- {file = "time_machine-2.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:fb467d6c9e9ab615c8cf22d751d34296dacf801be323a57adeb4ff345cf72473"},
- {file = "time_machine-2.14.1-cp310-cp310-win_arm64.whl", hash = "sha256:19db257117739b2dda1d57e149bb715a593313899b3902a7e6d752c5f1d22542"},
- {file = "time_machine-2.14.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:442d42f1b0ef006f03a5a34905829a1d3ac569a5bcda64d29706e6dc60832f94"},
- {file = "time_machine-2.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0312b47f220e46f1bbfaded7fc1469882d9c2a27c6daf44e119aea7006b595cc"},
- {file = "time_machine-2.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a39dba3033d9c28347d2db16bcb16041bbf4e9032e2b70023686b6f95deac9d"},
- {file = "time_machine-2.14.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e030d2051bb515251d7f6edd9bbcf79b2b47811e2c402aba9c126af713843d26"},
- {file = "time_machine-2.14.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:993ab140eb5678d1ee7f1197f08e4499dc8ea883ad6b8858737de70d509ec5b5"},
- {file = "time_machine-2.14.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:90725f936ad8b123149bc82a46394dd7057e63157ee11ba878164053fa5bd8ad"},
- {file = "time_machine-2.14.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:59a02c3d3b3b29e2dc3a708e775c5d6b951b0024c4013fed883f0d2205305c9e"},
- {file = "time_machine-2.14.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4f00f67d532da82538c4dfbbddc587e70c82664f168c11e1c2915d0c85ec2fc8"},
- {file = "time_machine-2.14.1-cp311-cp311-win32.whl", hash = "sha256:27f735cba4c6352ad7bc53ce2d86b715379261a634e690b79fac329081e26fb6"},
- {file = "time_machine-2.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:ee68597bd3fa5ab94633c8a9d3ebd4032091559610e078381818a732910002bc"},
- {file = "time_machine-2.14.1-cp311-cp311-win_arm64.whl", hash = "sha256:6ced9de5eff1fb37efb12984ab7b63f31f0aeadeedec4be6d0404ec4fa91f2e7"},
- {file = "time_machine-2.14.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:30a4a18357fa6cf089eeefcb37e9549b42523aebb5933894770a8919e6c398e1"},
- {file = "time_machine-2.14.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d45bd60bea85869615b117667f10a821e3b0d3603c47bfd105b45d1f67156fc8"},
- {file = "time_machine-2.14.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:39de6d37a14ff8882d4f1cbd50c53268b54e1cf4ef9be2bfe590d10a51ccd314"},
- {file = "time_machine-2.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fd7d188b4f9d358c6bd477daf93b460d9b244a4c296ddd065945f2b6193c2bd"},
- {file = "time_machine-2.14.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99e6f013e67c4f74a9d8f57e34173b2047f2ad48f764e44c38f3ee5344a38c01"},
- {file = "time_machine-2.14.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a927d87501da8b053a27e80f5d0e1e58fbde4b50d70df2d3853ed67e89a731cf"},
- {file = "time_machine-2.14.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c77a616561dd4c7c442e9eee8cbb915750496e9a5a7fca6bcb11a9860226d2d0"},
- {file = "time_machine-2.14.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e7fa70a6bdca40cc4a8386fd85bc1bae0a23ab11e49604ef853ab3ce92be127f"},
- {file = "time_machine-2.14.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:d63ef00d389fa6d2c76c863af580b3e4a8f0ccc6a9aea8e64590588e37f13c00"},
- {file = "time_machine-2.14.1-cp312-cp312-win32.whl", hash = "sha256:6706eb06487354a5e219cacea709fb3ec44dec3842c6218237d5069fa5f1ad64"},
- {file = "time_machine-2.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:36aa4f17adcd73a6064bf4991a29126cac93521f0690805edb91db837c4e1453"},
- {file = "time_machine-2.14.1-cp312-cp312-win_arm64.whl", hash = "sha256:edea570f3835a036e8860bb8d6eb8d08473c59313db86e36e3b207f796fd7b14"},
- {file = "time_machine-2.14.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:87e80408e6b6670e9ce33f94b1cc6b72b1a9b646f5e19f586908129871f74b40"},
- {file = "time_machine-2.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c69c0cb498c86ef843cd15964714e76465cc25d64464da57d5d1318f499de099"},
- {file = "time_machine-2.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc48d3934109b0bdbbdc5e9ce577213f7148a92fed378420ee13453503fe4db9"},
- {file = "time_machine-2.14.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7161cea2ff3244cc6075e365fab89000df70ead63a3da9d473983d580558d2de"},
- {file = "time_machine-2.14.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39fceeb131e6c07b386de042ce1016be771576e9516124b78e75cbab94ae5041"},
- {file = "time_machine-2.14.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:fe508a6c43fb72fa4f66b50b14684cf58d3db95fed617177ec197a7a90427bae"},
- {file = "time_machine-2.14.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5f3d5c21884aee10e13b00ef45fab893a43db9d59ec27271573528bd359b0ef5"},
- {file = "time_machine-2.14.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a75e24e59f58059bbbc50e7f97aa6d126bbc2f603a8a5cd1e884beffcf130d8f"},
- {file = "time_machine-2.14.1-cp38-cp38-win32.whl", hash = "sha256:b0f8ba70fbb71d7fbc6d6adb90bed72a83db15b3318c7af0060467539b2f1b63"},
- {file = "time_machine-2.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:15cf3623a4ba2bb4fce4529295570acd5f6c6b44bcbfd1b8d0756ce56c38fe82"},
- {file = "time_machine-2.14.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bb3a2518c52aa944989b541e5297b833388eb3fe72d91eb875b21fe771597b04"},
- {file = "time_machine-2.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:416d94eab7723c7d8a37fe6b3b1882046fdbf3c31b9abec3cac87cf35dbb8230"},
- {file = "time_machine-2.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:adfbfa796dd96383400b44681eacc5ab06d3cbfad39c30878e5ead0bfdca808a"},
- {file = "time_machine-2.14.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:31e6e9bff89b7c6e4cbc169ba1d00d6c107b3abc43173b2799352b6995cf7cb2"},
- {file = "time_machine-2.14.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:107caed387438d689180b692e8d84aa1ebe8918790df83dc5e2146e60e5e0859"},
- {file = "time_machine-2.14.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:cab4abf4d1490a7da35db5a321ff8a4d4a2195f4832a792c75b626ffc4a5584c"},
- {file = "time_machine-2.14.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:fd8645b820f7895fdafbc4412d1ce376956e36ad4fd05a43269aa06c3132afc3"},
- {file = "time_machine-2.14.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:dd26039a9ffea2d5ee1309f2ec9b656d4925371c65563822d52e4037a4186eca"},
- {file = "time_machine-2.14.1-cp39-cp39-win32.whl", hash = "sha256:5e19b19d20bfbff8c97949e06e150998cf9d0a676e1641fb90597e59a9d7d5e2"},
- {file = "time_machine-2.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:f5d371a5218318121a6b44c21438258b6408b8bfe7ccccb754cf8eb880505576"},
- {file = "time_machine-2.14.1-cp39-cp39-win_arm64.whl", hash = "sha256:2c774f4b603a36ca2611327c57aa8ce0d5042298da008238ee5234b31ce7b22c"},
-]
-
-[package.dependencies]
-python-dateutil = "*"
-
-[[package]]
-name = "tomli"
-version = "2.0.1"
-description = "A lil' TOML parser"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
- {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
-]
-
-[[package]]
-name = "typer"
-version = "0.9.4"
-description = "Typer, build great CLIs. Easy to code. Based on Python type hints."
-optional = false
-python-versions = ">=3.6"
-files = [
- {file = "typer-0.9.4-py3-none-any.whl", hash = "sha256:aa6c4a4e2329d868b80ecbaf16f807f2b54e192209d7ac9dd42691d63f7a54eb"},
- {file = "typer-0.9.4.tar.gz", hash = "sha256:f714c2d90afae3a7929fcd72a3abb08df305e1ff61719381384211c4070af57f"},
-]
-
-[package.dependencies]
-click = ">=7.1.1,<9.0.0"
-colorama = {version = ">=0.4.3,<0.5.0", optional = true, markers = "extra == \"all\""}
-rich = {version = ">=10.11.0,<14.0.0", optional = true, markers = "extra == \"all\""}
-shellingham = {version = ">=1.3.0,<2.0.0", optional = true, markers = "extra == \"all\""}
-typing-extensions = ">=3.7.4.3"
-
-[package.extras]
-all = ["colorama (>=0.4.3,<0.5.0)", "rich (>=10.11.0,<14.0.0)", "shellingham (>=1.3.0,<2.0.0)"]
-dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "pre-commit (>=2.17.0,<3.0.0)"]
-doc = ["cairosvg (>=2.5.2,<3.0.0)", "mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pillow (>=9.3.0,<10.0.0)"]
-test = ["black (>=22.3.0,<23.0.0)", "coverage (>=6.2,<7.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.971)", "pytest (>=4.4.0,<8.0.0)", "pytest-cov (>=2.10.0,<5.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "pytest-xdist (>=1.32.0,<4.0.0)", "rich (>=10.11.0,<14.0.0)", "shellingham (>=1.3.0,<2.0.0)"]
-
-[[package]]
-name = "typing-extensions"
-version = "4.10.0"
-description = "Backported and Experimental Type Hints for Python 3.8+"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"},
- {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"},
-]
-
-[[package]]
-name = "tzdata"
-version = "2024.1"
-description = "Provider of IANA time zone data"
-optional = false
-python-versions = ">=2"
-files = [
- {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"},
- {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"},
-]
-
-[[package]]
-name = "urllib3"
-version = "2.2.1"
-description = "HTTP library with thread-safe connection pooling, file post, and more."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"},
- {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"},
-]
-
-[package.extras]
-brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
-h2 = ["h2 (>=4,<5)"]
-socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
-zstd = ["zstandard (>=0.18.0)"]
-
-[[package]]
-name = "uvicorn"
-version = "0.27.1"
-description = "The lightning-fast ASGI server."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "uvicorn-0.27.1-py3-none-any.whl", hash = "sha256:5c89da2f3895767472a35556e539fd59f7edbe9b1e9c0e1c99eebeadc61838e4"},
- {file = "uvicorn-0.27.1.tar.gz", hash = "sha256:3d9a267296243532db80c83a959a3400502165ade2c1338dea4e67915fd4745a"},
-]
-
-[package.dependencies]
-click = ">=7.0"
-colorama = {version = ">=0.4", optional = true, markers = "sys_platform == \"win32\" and extra == \"standard\""}
-h11 = ">=0.8"
-httptools = {version = ">=0.5.0", optional = true, markers = "extra == \"standard\""}
-python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""}
-pyyaml = {version = ">=5.1", optional = true, markers = "extra == \"standard\""}
-uvloop = {version = ">=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1", optional = true, markers = "(sys_platform != \"win32\" and sys_platform != \"cygwin\") and platform_python_implementation != \"PyPy\" and extra == \"standard\""}
-watchfiles = {version = ">=0.13", optional = true, markers = "extra == \"standard\""}
-websockets = {version = ">=10.4", optional = true, markers = "extra == \"standard\""}
-
-[package.extras]
-standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"]
-
-[[package]]
-name = "uvloop"
-version = "0.19.0"
-description = "Fast implementation of asyncio event loop on top of libuv"
-optional = false
-python-versions = ">=3.8.0"
-files = [
- {file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:de4313d7f575474c8f5a12e163f6d89c0a878bc49219641d49e6f1444369a90e"},
- {file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5588bd21cf1fcf06bded085f37e43ce0e00424197e7c10e77afd4bbefffef428"},
- {file = "uvloop-0.19.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b1fd71c3843327f3bbc3237bedcdb6504fd50368ab3e04d0410e52ec293f5b8"},
- {file = "uvloop-0.19.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a05128d315e2912791de6088c34136bfcdd0c7cbc1cf85fd6fd1bb321b7c849"},
- {file = "uvloop-0.19.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:cd81bdc2b8219cb4b2556eea39d2e36bfa375a2dd021404f90a62e44efaaf957"},
- {file = "uvloop-0.19.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5f17766fb6da94135526273080f3455a112f82570b2ee5daa64d682387fe0dcd"},
- {file = "uvloop-0.19.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4ce6b0af8f2729a02a5d1575feacb2a94fc7b2e983868b009d51c9a9d2149bef"},
- {file = "uvloop-0.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:31e672bb38b45abc4f26e273be83b72a0d28d074d5b370fc4dcf4c4eb15417d2"},
- {file = "uvloop-0.19.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:570fc0ed613883d8d30ee40397b79207eedd2624891692471808a95069a007c1"},
- {file = "uvloop-0.19.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5138821e40b0c3e6c9478643b4660bd44372ae1e16a322b8fc07478f92684e24"},
- {file = "uvloop-0.19.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:91ab01c6cd00e39cde50173ba4ec68a1e578fee9279ba64f5221810a9e786533"},
- {file = "uvloop-0.19.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:47bf3e9312f63684efe283f7342afb414eea4d3011542155c7e625cd799c3b12"},
- {file = "uvloop-0.19.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:da8435a3bd498419ee8c13c34b89b5005130a476bda1d6ca8cfdde3de35cd650"},
- {file = "uvloop-0.19.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:02506dc23a5d90e04d4f65c7791e65cf44bd91b37f24cfc3ef6cf2aff05dc7ec"},
- {file = "uvloop-0.19.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2693049be9d36fef81741fddb3f441673ba12a34a704e7b4361efb75cf30befc"},
- {file = "uvloop-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7010271303961c6f0fe37731004335401eb9075a12680738731e9c92ddd96ad6"},
- {file = "uvloop-0.19.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5daa304d2161d2918fa9a17d5635099a2f78ae5b5960e742b2fcfbb7aefaa593"},
- {file = "uvloop-0.19.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7207272c9520203fea9b93843bb775d03e1cf88a80a936ce760f60bb5add92f3"},
- {file = "uvloop-0.19.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:78ab247f0b5671cc887c31d33f9b3abfb88d2614b84e4303f1a63b46c046c8bd"},
- {file = "uvloop-0.19.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:472d61143059c84947aa8bb74eabbace30d577a03a1805b77933d6bd13ddebbd"},
- {file = "uvloop-0.19.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45bf4c24c19fb8a50902ae37c5de50da81de4922af65baf760f7c0c42e1088be"},
- {file = "uvloop-0.19.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:271718e26b3e17906b28b67314c45d19106112067205119dddbd834c2b7ce797"},
- {file = "uvloop-0.19.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:34175c9fd2a4bc3adc1380e1261f60306344e3407c20a4d684fd5f3be010fa3d"},
- {file = "uvloop-0.19.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e27f100e1ff17f6feeb1f33968bc185bf8ce41ca557deee9d9bbbffeb72030b7"},
- {file = "uvloop-0.19.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13dfdf492af0aa0a0edf66807d2b465607d11c4fa48f4a1fd41cbea5b18e8e8b"},
- {file = "uvloop-0.19.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6e3d4e85ac060e2342ff85e90d0c04157acb210b9ce508e784a944f852a40e67"},
- {file = "uvloop-0.19.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8ca4956c9ab567d87d59d49fa3704cf29e37109ad348f2d5223c9bf761a332e7"},
- {file = "uvloop-0.19.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f467a5fd23b4fc43ed86342641f3936a68ded707f4627622fa3f82a120e18256"},
- {file = "uvloop-0.19.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:492e2c32c2af3f971473bc22f086513cedfc66a130756145a931a90c3958cb17"},
- {file = "uvloop-0.19.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2df95fca285a9f5bfe730e51945ffe2fa71ccbfdde3b0da5772b4ee4f2e770d5"},
- {file = "uvloop-0.19.0.tar.gz", hash = "sha256:0246f4fd1bf2bf702e06b0d45ee91677ee5c31242f39aab4ea6fe0c51aedd0fd"},
-]
-
-[package.extras]
-docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"]
-test = ["Cython (>=0.29.36,<0.30.0)", "aiohttp (==3.9.0b0)", "aiohttp (>=3.8.1)", "flake8 (>=5.0,<6.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=23.0.0,<23.1.0)", "pycodestyle (>=2.9.0,<2.10.0)"]
-
-[[package]]
-name = "virtualenv"
-version = "20.25.1"
-description = "Virtual Python Environment builder"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "virtualenv-20.25.1-py3-none-any.whl", hash = "sha256:961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a"},
- {file = "virtualenv-20.25.1.tar.gz", hash = "sha256:e08e13ecdca7a0bd53798f356d5831434afa5b07b93f0abdf0797b7a06ffe197"},
-]
-
-[package.dependencies]
-distlib = ">=0.3.7,<1"
-filelock = ">=3.12.2,<4"
-platformdirs = ">=3.9.1,<5"
-
-[package.extras]
-docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
-test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"]
-
-[[package]]
-name = "watchdog"
-version = "4.0.0"
-description = "Filesystem events monitoring"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "watchdog-4.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:39cb34b1f1afbf23e9562501673e7146777efe95da24fab5707b88f7fb11649b"},
- {file = "watchdog-4.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c522392acc5e962bcac3b22b9592493ffd06d1fc5d755954e6be9f4990de932b"},
- {file = "watchdog-4.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6c47bdd680009b11c9ac382163e05ca43baf4127954c5f6d0250e7d772d2b80c"},
- {file = "watchdog-4.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8350d4055505412a426b6ad8c521bc7d367d1637a762c70fdd93a3a0d595990b"},
- {file = "watchdog-4.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c17d98799f32e3f55f181f19dd2021d762eb38fdd381b4a748b9f5a36738e935"},
- {file = "watchdog-4.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4986db5e8880b0e6b7cd52ba36255d4793bf5cdc95bd6264806c233173b1ec0b"},
- {file = "watchdog-4.0.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:11e12fafb13372e18ca1bbf12d50f593e7280646687463dd47730fd4f4d5d257"},
- {file = "watchdog-4.0.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5369136a6474678e02426bd984466343924d1df8e2fd94a9b443cb7e3aa20d19"},
- {file = "watchdog-4.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76ad8484379695f3fe46228962017a7e1337e9acadafed67eb20aabb175df98b"},
- {file = "watchdog-4.0.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:45cc09cc4c3b43fb10b59ef4d07318d9a3ecdbff03abd2e36e77b6dd9f9a5c85"},
- {file = "watchdog-4.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:eed82cdf79cd7f0232e2fdc1ad05b06a5e102a43e331f7d041e5f0e0a34a51c4"},
- {file = "watchdog-4.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ba30a896166f0fee83183cec913298151b73164160d965af2e93a20bbd2ab605"},
- {file = "watchdog-4.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d18d7f18a47de6863cd480734613502904611730f8def45fc52a5d97503e5101"},
- {file = "watchdog-4.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2895bf0518361a9728773083908801a376743bcc37dfa252b801af8fd281b1ca"},
- {file = "watchdog-4.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:87e9df830022488e235dd601478c15ad73a0389628588ba0b028cb74eb72fed8"},
- {file = "watchdog-4.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6e949a8a94186bced05b6508faa61b7adacc911115664ccb1923b9ad1f1ccf7b"},
- {file = "watchdog-4.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6a4db54edea37d1058b08947c789a2354ee02972ed5d1e0dca9b0b820f4c7f92"},
- {file = "watchdog-4.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d31481ccf4694a8416b681544c23bd271f5a123162ab603c7d7d2dd7dd901a07"},
- {file = "watchdog-4.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:8fec441f5adcf81dd240a5fe78e3d83767999771630b5ddfc5867827a34fa3d3"},
- {file = "watchdog-4.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:6a9c71a0b02985b4b0b6d14b875a6c86ddea2fdbebd0c9a720a806a8bbffc69f"},
- {file = "watchdog-4.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:557ba04c816d23ce98a06e70af6abaa0485f6d94994ec78a42b05d1c03dcbd50"},
- {file = "watchdog-4.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:d0f9bd1fd919134d459d8abf954f63886745f4660ef66480b9d753a7c9d40927"},
- {file = "watchdog-4.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:f9b2fdca47dc855516b2d66eef3c39f2672cbf7e7a42e7e67ad2cbfcd6ba107d"},
- {file = "watchdog-4.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:73c7a935e62033bd5e8f0da33a4dcb763da2361921a69a5a95aaf6c93aa03a87"},
- {file = "watchdog-4.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:6a80d5cae8c265842c7419c560b9961561556c4361b297b4c431903f8c33b269"},
- {file = "watchdog-4.0.0-py3-none-win32.whl", hash = "sha256:8f9a542c979df62098ae9c58b19e03ad3df1c9d8c6895d96c0d51da17b243b1c"},
- {file = "watchdog-4.0.0-py3-none-win_amd64.whl", hash = "sha256:f970663fa4f7e80401a7b0cbeec00fa801bf0287d93d48368fc3e6fa32716245"},
- {file = "watchdog-4.0.0-py3-none-win_ia64.whl", hash = "sha256:9a03e16e55465177d416699331b0f3564138f1807ecc5f2de9d55d8f188d08c7"},
- {file = "watchdog-4.0.0.tar.gz", hash = "sha256:e3e7065cbdabe6183ab82199d7a4f6b3ba0a438c5a512a68559846ccb76a78ec"},
-]
-
-[package.extras]
-watchmedo = ["PyYAML (>=3.10)"]
-
-[[package]]
-name = "watchfiles"
-version = "0.21.0"
-description = "Simple, modern and high performance file watching and code reload in python."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "watchfiles-0.21.0-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:27b4035013f1ea49c6c0b42d983133b136637a527e48c132d368eb19bf1ac6aa"},
- {file = "watchfiles-0.21.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c81818595eff6e92535ff32825f31c116f867f64ff8cdf6562cd1d6b2e1e8f3e"},
- {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6c107ea3cf2bd07199d66f156e3ea756d1b84dfd43b542b2d870b77868c98c03"},
- {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d9ac347653ebd95839a7c607608703b20bc07e577e870d824fa4801bc1cb124"},
- {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5eb86c6acb498208e7663ca22dbe68ca2cf42ab5bf1c776670a50919a56e64ab"},
- {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f564bf68404144ea6b87a78a3f910cc8de216c6b12a4cf0b27718bf4ec38d303"},
- {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d0f32ebfaa9c6011f8454994f86108c2eb9c79b8b7de00b36d558cadcedaa3d"},
- {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6d45d9b699ecbac6c7bd8e0a2609767491540403610962968d258fd6405c17c"},
- {file = "watchfiles-0.21.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:aff06b2cac3ef4616e26ba17a9c250c1fe9dd8a5d907d0193f84c499b1b6e6a9"},
- {file = "watchfiles-0.21.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d9792dff410f266051025ecfaa927078b94cc7478954b06796a9756ccc7e14a9"},
- {file = "watchfiles-0.21.0-cp310-none-win32.whl", hash = "sha256:214cee7f9e09150d4fb42e24919a1e74d8c9b8a9306ed1474ecaddcd5479c293"},
- {file = "watchfiles-0.21.0-cp310-none-win_amd64.whl", hash = "sha256:1ad7247d79f9f55bb25ab1778fd47f32d70cf36053941f07de0b7c4e96b5d235"},
- {file = "watchfiles-0.21.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:668c265d90de8ae914f860d3eeb164534ba2e836811f91fecc7050416ee70aa7"},
- {file = "watchfiles-0.21.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a23092a992e61c3a6a70f350a56db7197242f3490da9c87b500f389b2d01eef"},
- {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e7941bbcfdded9c26b0bf720cb7e6fd803d95a55d2c14b4bd1f6a2772230c586"},
- {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:11cd0c3100e2233e9c53106265da31d574355c288e15259c0d40a4405cbae317"},
- {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d78f30cbe8b2ce770160d3c08cff01b2ae9306fe66ce899b73f0409dc1846c1b"},
- {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6674b00b9756b0af620aa2a3346b01f8e2a3dc729d25617e1b89cf6af4a54eb1"},
- {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fd7ac678b92b29ba630d8c842d8ad6c555abda1b9ef044d6cc092dacbfc9719d"},
- {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c873345680c1b87f1e09e0eaf8cf6c891b9851d8b4d3645e7efe2ec20a20cc7"},
- {file = "watchfiles-0.21.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:49f56e6ecc2503e7dbe233fa328b2be1a7797d31548e7a193237dcdf1ad0eee0"},
- {file = "watchfiles-0.21.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:02d91cbac553a3ad141db016e3350b03184deaafeba09b9d6439826ee594b365"},
- {file = "watchfiles-0.21.0-cp311-none-win32.whl", hash = "sha256:ebe684d7d26239e23d102a2bad2a358dedf18e462e8808778703427d1f584400"},
- {file = "watchfiles-0.21.0-cp311-none-win_amd64.whl", hash = "sha256:4566006aa44cb0d21b8ab53baf4b9c667a0ed23efe4aaad8c227bfba0bf15cbe"},
- {file = "watchfiles-0.21.0-cp311-none-win_arm64.whl", hash = "sha256:c550a56bf209a3d987d5a975cdf2063b3389a5d16caf29db4bdddeae49f22078"},
- {file = "watchfiles-0.21.0-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:51ddac60b96a42c15d24fbdc7a4bfcd02b5a29c047b7f8bf63d3f6f5a860949a"},
- {file = "watchfiles-0.21.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:511f0b034120cd1989932bf1e9081aa9fb00f1f949fbd2d9cab6264916ae89b1"},
- {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cfb92d49dbb95ec7a07511bc9efb0faff8fe24ef3805662b8d6808ba8409a71a"},
- {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f92944efc564867bbf841c823c8b71bb0be75e06b8ce45c084b46411475a915"},
- {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:642d66b75eda909fd1112d35c53816d59789a4b38c141a96d62f50a3ef9b3360"},
- {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d23bcd6c8eaa6324fe109d8cac01b41fe9a54b8c498af9ce464c1aeeb99903d6"},
- {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18d5b4da8cf3e41895b34e8c37d13c9ed294954907929aacd95153508d5d89d7"},
- {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b8d1eae0f65441963d805f766c7e9cd092f91e0c600c820c764a4ff71a0764c"},
- {file = "watchfiles-0.21.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1fd9a5205139f3c6bb60d11f6072e0552f0a20b712c85f43d42342d162be1235"},
- {file = "watchfiles-0.21.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a1e3014a625bcf107fbf38eece0e47fa0190e52e45dc6eee5a8265ddc6dc5ea7"},
- {file = "watchfiles-0.21.0-cp312-none-win32.whl", hash = "sha256:9d09869f2c5a6f2d9df50ce3064b3391d3ecb6dced708ad64467b9e4f2c9bef3"},
- {file = "watchfiles-0.21.0-cp312-none-win_amd64.whl", hash = "sha256:18722b50783b5e30a18a8a5db3006bab146d2b705c92eb9a94f78c72beb94094"},
- {file = "watchfiles-0.21.0-cp312-none-win_arm64.whl", hash = "sha256:a3b9bec9579a15fb3ca2d9878deae789df72f2b0fdaf90ad49ee389cad5edab6"},
- {file = "watchfiles-0.21.0-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:4ea10a29aa5de67de02256a28d1bf53d21322295cb00bd2d57fcd19b850ebd99"},
- {file = "watchfiles-0.21.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:40bca549fdc929b470dd1dbfcb47b3295cb46a6d2c90e50588b0a1b3bd98f429"},
- {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9b37a7ba223b2f26122c148bb8d09a9ff312afca998c48c725ff5a0a632145f7"},
- {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec8c8900dc5c83650a63dd48c4d1d245343f904c4b64b48798c67a3767d7e165"},
- {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8ad3fe0a3567c2f0f629d800409cd528cb6251da12e81a1f765e5c5345fd0137"},
- {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d353c4cfda586db2a176ce42c88f2fc31ec25e50212650c89fdd0f560ee507b"},
- {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:83a696da8922314ff2aec02987eefb03784f473281d740bf9170181829133765"},
- {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a03651352fc20975ee2a707cd2d74a386cd303cc688f407296064ad1e6d1562"},
- {file = "watchfiles-0.21.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3ad692bc7792be8c32918c699638b660c0de078a6cbe464c46e1340dadb94c19"},
- {file = "watchfiles-0.21.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06247538e8253975bdb328e7683f8515ff5ff041f43be6c40bff62d989b7d0b0"},
- {file = "watchfiles-0.21.0-cp38-none-win32.whl", hash = "sha256:9a0aa47f94ea9a0b39dd30850b0adf2e1cd32a8b4f9c7aa443d852aacf9ca214"},
- {file = "watchfiles-0.21.0-cp38-none-win_amd64.whl", hash = "sha256:8d5f400326840934e3507701f9f7269247f7c026d1b6cfd49477d2be0933cfca"},
- {file = "watchfiles-0.21.0-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:7f762a1a85a12cc3484f77eee7be87b10f8c50b0b787bb02f4e357403cad0c0e"},
- {file = "watchfiles-0.21.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6e9be3ef84e2bb9710f3f777accce25556f4a71e15d2b73223788d528fcc2052"},
- {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4c48a10d17571d1275701e14a601e36959ffada3add8cdbc9e5061a6e3579a5d"},
- {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c889025f59884423428c261f212e04d438de865beda0b1e1babab85ef4c0f01"},
- {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:66fac0c238ab9a2e72d026b5fb91cb902c146202bbd29a9a1a44e8db7b710b6f"},
- {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b4a21f71885aa2744719459951819e7bf5a906a6448a6b2bbce8e9cc9f2c8128"},
- {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c9198c989f47898b2c22201756f73249de3748e0fc9de44adaf54a8b259cc0c"},
- {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8f57c4461cd24fda22493109c45b3980863c58a25b8bec885ca8bea6b8d4b28"},
- {file = "watchfiles-0.21.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:853853cbf7bf9408b404754b92512ebe3e3a83587503d766d23e6bf83d092ee6"},
- {file = "watchfiles-0.21.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d5b1dc0e708fad9f92c296ab2f948af403bf201db8fb2eb4c8179db143732e49"},
- {file = "watchfiles-0.21.0-cp39-none-win32.whl", hash = "sha256:59137c0c6826bd56c710d1d2bda81553b5e6b7c84d5a676747d80caf0409ad94"},
- {file = "watchfiles-0.21.0-cp39-none-win_amd64.whl", hash = "sha256:6cb8fdc044909e2078c248986f2fc76f911f72b51ea4a4fbbf472e01d14faa58"},
- {file = "watchfiles-0.21.0-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:ab03a90b305d2588e8352168e8c5a1520b721d2d367f31e9332c4235b30b8994"},
- {file = "watchfiles-0.21.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:927c589500f9f41e370b0125c12ac9e7d3a2fd166b89e9ee2828b3dda20bfe6f"},
- {file = "watchfiles-0.21.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bd467213195e76f838caf2c28cd65e58302d0254e636e7c0fca81efa4a2e62c"},
- {file = "watchfiles-0.21.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02b73130687bc3f6bb79d8a170959042eb56eb3a42df3671c79b428cd73f17cc"},
- {file = "watchfiles-0.21.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:08dca260e85ffae975448e344834d765983237ad6dc308231aa16e7933db763e"},
- {file = "watchfiles-0.21.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:3ccceb50c611c433145502735e0370877cced72a6c70fd2410238bcbc7fe51d8"},
- {file = "watchfiles-0.21.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57d430f5fb63fea141ab71ca9c064e80de3a20b427ca2febcbfcef70ff0ce895"},
- {file = "watchfiles-0.21.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dd5fad9b9c0dd89904bbdea978ce89a2b692a7ee8a0ce19b940e538c88a809c"},
- {file = "watchfiles-0.21.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:be6dd5d52b73018b21adc1c5d28ac0c68184a64769052dfeb0c5d9998e7f56a2"},
- {file = "watchfiles-0.21.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:b3cab0e06143768499384a8a5efb9c4dc53e19382952859e4802f294214f36ec"},
- {file = "watchfiles-0.21.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c6ed10c2497e5fedadf61e465b3ca12a19f96004c15dcffe4bd442ebadc2d85"},
- {file = "watchfiles-0.21.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43babacef21c519bc6631c5fce2a61eccdfc011b4bcb9047255e9620732c8097"},
- {file = "watchfiles-0.21.0.tar.gz", hash = "sha256:c76c635fabf542bb78524905718c39f736a98e5ab25b23ec6d4abede1a85a6a3"},
-]
-
-[package.dependencies]
-anyio = ">=3.0.0"
-
-[[package]]
-name = "websockets"
-version = "12.0"
-description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "websockets-12.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d554236b2a2006e0ce16315c16eaa0d628dab009c33b63ea03f41c6107958374"},
- {file = "websockets-12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2d225bb6886591b1746b17c0573e29804619c8f755b5598d875bb4235ea639be"},
- {file = "websockets-12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eb809e816916a3b210bed3c82fb88eaf16e8afcf9c115ebb2bacede1797d2547"},
- {file = "websockets-12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c588f6abc13f78a67044c6b1273a99e1cf31038ad51815b3b016ce699f0d75c2"},
- {file = "websockets-12.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5aa9348186d79a5f232115ed3fa9020eab66d6c3437d72f9d2c8ac0c6858c558"},
- {file = "websockets-12.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6350b14a40c95ddd53e775dbdbbbc59b124a5c8ecd6fbb09c2e52029f7a9f480"},
- {file = "websockets-12.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:70ec754cc2a769bcd218ed8d7209055667b30860ffecb8633a834dde27d6307c"},
- {file = "websockets-12.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6e96f5ed1b83a8ddb07909b45bd94833b0710f738115751cdaa9da1fb0cb66e8"},
- {file = "websockets-12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4d87be612cbef86f994178d5186add3d94e9f31cc3cb499a0482b866ec477603"},
- {file = "websockets-12.0-cp310-cp310-win32.whl", hash = "sha256:befe90632d66caaf72e8b2ed4d7f02b348913813c8b0a32fae1cc5fe3730902f"},
- {file = "websockets-12.0-cp310-cp310-win_amd64.whl", hash = "sha256:363f57ca8bc8576195d0540c648aa58ac18cf85b76ad5202b9f976918f4219cf"},
- {file = "websockets-12.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5d873c7de42dea355d73f170be0f23788cf3fa9f7bed718fd2830eefedce01b4"},
- {file = "websockets-12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3f61726cae9f65b872502ff3c1496abc93ffbe31b278455c418492016e2afc8f"},
- {file = "websockets-12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed2fcf7a07334c77fc8a230755c2209223a7cc44fc27597729b8ef5425aa61a3"},
- {file = "websockets-12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e332c210b14b57904869ca9f9bf4ca32f5427a03eeb625da9b616c85a3a506c"},
- {file = "websockets-12.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5693ef74233122f8ebab026817b1b37fe25c411ecfca084b29bc7d6efc548f45"},
- {file = "websockets-12.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e9e7db18b4539a29cc5ad8c8b252738a30e2b13f033c2d6e9d0549b45841c04"},
- {file = "websockets-12.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6e2df67b8014767d0f785baa98393725739287684b9f8d8a1001eb2839031447"},
- {file = "websockets-12.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bea88d71630c5900690fcb03161ab18f8f244805c59e2e0dc4ffadae0a7ee0ca"},
- {file = "websockets-12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dff6cdf35e31d1315790149fee351f9e52978130cef6c87c4b6c9b3baf78bc53"},
- {file = "websockets-12.0-cp311-cp311-win32.whl", hash = "sha256:3e3aa8c468af01d70332a382350ee95f6986db479ce7af14d5e81ec52aa2b402"},
- {file = "websockets-12.0-cp311-cp311-win_amd64.whl", hash = "sha256:25eb766c8ad27da0f79420b2af4b85d29914ba0edf69f547cc4f06ca6f1d403b"},
- {file = "websockets-12.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0e6e2711d5a8e6e482cacb927a49a3d432345dfe7dea8ace7b5790df5932e4df"},
- {file = "websockets-12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:dbcf72a37f0b3316e993e13ecf32f10c0e1259c28ffd0a85cee26e8549595fbc"},
- {file = "websockets-12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12743ab88ab2af1d17dd4acb4645677cb7063ef4db93abffbf164218a5d54c6b"},
- {file = "websockets-12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b645f491f3c48d3f8a00d1fce07445fab7347fec54a3e65f0725d730d5b99cb"},
- {file = "websockets-12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9893d1aa45a7f8b3bc4510f6ccf8db8c3b62120917af15e3de247f0780294b92"},
- {file = "websockets-12.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f38a7b376117ef7aff996e737583172bdf535932c9ca021746573bce40165ed"},
- {file = "websockets-12.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f764ba54e33daf20e167915edc443b6f88956f37fb606449b4a5b10ba42235a5"},
- {file = "websockets-12.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1e4b3f8ea6a9cfa8be8484c9221ec0257508e3a1ec43c36acdefb2a9c3b00aa2"},
- {file = "websockets-12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9fdf06fd06c32205a07e47328ab49c40fc1407cdec801d698a7c41167ea45113"},
- {file = "websockets-12.0-cp312-cp312-win32.whl", hash = "sha256:baa386875b70cbd81798fa9f71be689c1bf484f65fd6fb08d051a0ee4e79924d"},
- {file = "websockets-12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ae0a5da8f35a5be197f328d4727dbcfafa53d1824fac3d96cdd3a642fe09394f"},
- {file = "websockets-12.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5f6ffe2c6598f7f7207eef9a1228b6f5c818f9f4d53ee920aacd35cec8110438"},
- {file = "websockets-12.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9edf3fc590cc2ec20dc9d7a45108b5bbaf21c0d89f9fd3fd1685e223771dc0b2"},
- {file = "websockets-12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8572132c7be52632201a35f5e08348137f658e5ffd21f51f94572ca6c05ea81d"},
- {file = "websockets-12.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:604428d1b87edbf02b233e2c207d7d528460fa978f9e391bd8aaf9c8311de137"},
- {file = "websockets-12.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a9d160fd080c6285e202327aba140fc9a0d910b09e423afff4ae5cbbf1c7205"},
- {file = "websockets-12.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87b4aafed34653e465eb77b7c93ef058516cb5acf3eb21e42f33928616172def"},
- {file = "websockets-12.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b2ee7288b85959797970114deae81ab41b731f19ebcd3bd499ae9ca0e3f1d2c8"},
- {file = "websockets-12.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7fa3d25e81bfe6a89718e9791128398a50dec6d57faf23770787ff441d851967"},
- {file = "websockets-12.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a571f035a47212288e3b3519944f6bf4ac7bc7553243e41eac50dd48552b6df7"},
- {file = "websockets-12.0-cp38-cp38-win32.whl", hash = "sha256:3c6cc1360c10c17463aadd29dd3af332d4a1adaa8796f6b0e9f9df1fdb0bad62"},
- {file = "websockets-12.0-cp38-cp38-win_amd64.whl", hash = "sha256:1bf386089178ea69d720f8db6199a0504a406209a0fc23e603b27b300fdd6892"},
- {file = "websockets-12.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ab3d732ad50a4fbd04a4490ef08acd0517b6ae6b77eb967251f4c263011a990d"},
- {file = "websockets-12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1d9697f3337a89691e3bd8dc56dea45a6f6d975f92e7d5f773bc715c15dde28"},
- {file = "websockets-12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1df2fbd2c8a98d38a66f5238484405b8d1d16f929bb7a33ed73e4801222a6f53"},
- {file = "websockets-12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23509452b3bc38e3a057382c2e941d5ac2e01e251acce7adc74011d7d8de434c"},
- {file = "websockets-12.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e5fc14ec6ea568200ea4ef46545073da81900a2b67b3e666f04adf53ad452ec"},
- {file = "websockets-12.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46e71dbbd12850224243f5d2aeec90f0aaa0f2dde5aeeb8fc8df21e04d99eff9"},
- {file = "websockets-12.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b81f90dcc6c85a9b7f29873beb56c94c85d6f0dac2ea8b60d995bd18bf3e2aae"},
- {file = "websockets-12.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a02413bc474feda2849c59ed2dfb2cddb4cd3d2f03a2fedec51d6e959d9b608b"},
- {file = "websockets-12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bbe6013f9f791944ed31ca08b077e26249309639313fff132bfbf3ba105673b9"},
- {file = "websockets-12.0-cp39-cp39-win32.whl", hash = "sha256:cbe83a6bbdf207ff0541de01e11904827540aa069293696dd528a6640bd6a5f6"},
- {file = "websockets-12.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc4e7fa5414512b481a2483775a8e8be7803a35b30ca805afa4998a84f9fd9e8"},
- {file = "websockets-12.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:248d8e2446e13c1d4326e0a6a4e9629cb13a11195051a73acf414812700badbd"},
- {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44069528d45a933997a6fef143030d8ca8042f0dfaad753e2906398290e2870"},
- {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c4e37d36f0d19f0a4413d3e18c0d03d0c268ada2061868c1e6f5ab1a6d575077"},
- {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d829f975fc2e527a3ef2f9c8f25e553eb7bc779c6665e8e1d52aa22800bb38b"},
- {file = "websockets-12.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2c71bd45a777433dd9113847af751aae36e448bc6b8c361a566cb043eda6ec30"},
- {file = "websockets-12.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0bee75f400895aef54157b36ed6d3b308fcab62e5260703add87f44cee9c82a6"},
- {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:423fc1ed29f7512fceb727e2d2aecb952c46aa34895e9ed96071821309951123"},
- {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27a5e9964ef509016759f2ef3f2c1e13f403725a5e6a1775555994966a66e931"},
- {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3181df4583c4d3994d31fb235dc681d2aaad744fbdbf94c4802485ececdecf2"},
- {file = "websockets-12.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b067cb952ce8bf40115f6c19f478dc71c5e719b7fbaa511359795dfd9d1a6468"},
- {file = "websockets-12.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:00700340c6c7ab788f176d118775202aadea7602c5cc6be6ae127761c16d6b0b"},
- {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e469d01137942849cff40517c97a30a93ae79917752b34029f0ec72df6b46399"},
- {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffefa1374cd508d633646d51a8e9277763a9b78ae71324183693959cf94635a7"},
- {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba0cab91b3956dfa9f512147860783a1829a8d905ee218a9837c18f683239611"},
- {file = "websockets-12.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2cb388a5bfb56df4d9a406783b7f9dbefb888c09b71629351cc6b036e9259370"},
- {file = "websockets-12.0-py3-none-any.whl", hash = "sha256:dc284bbc8d7c78a6c69e0c7325ab46ee5e40bb4d50e494d8131a07ef47500e9e"},
- {file = "websockets-12.0.tar.gz", hash = "sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b"},
-]
-
-[[package]]
-name = "win32-setctime"
-version = "1.1.0"
-description = "A small Python utility to set file creation time on Windows"
-optional = false
-python-versions = ">=3.5"
-files = [
- {file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"},
- {file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"},
-]
-
-[package.extras]
-dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"]
-
-[[package]]
-name = "yarl"
-version = "1.9.4"
-description = "Yet another URL library"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e"},
- {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2"},
- {file = "yarl-1.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66"},
- {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234"},
- {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392"},
- {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551"},
- {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455"},
- {file = "yarl-1.9.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c"},
- {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53"},
- {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385"},
- {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863"},
- {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b"},
- {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541"},
- {file = "yarl-1.9.4-cp310-cp310-win32.whl", hash = "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d"},
- {file = "yarl-1.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b"},
- {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099"},
- {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c"},
- {file = "yarl-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0"},
- {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525"},
- {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8"},
- {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9"},
- {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42"},
- {file = "yarl-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe"},
- {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce"},
- {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9"},
- {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572"},
- {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958"},
- {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98"},
- {file = "yarl-1.9.4-cp311-cp311-win32.whl", hash = "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31"},
- {file = "yarl-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1"},
- {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"},
- {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"},
- {file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"},
- {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"},
- {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"},
- {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"},
- {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"},
- {file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"},
- {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"},
- {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"},
- {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"},
- {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"},
- {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"},
- {file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"},
- {file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"},
- {file = "yarl-1.9.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f"},
- {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17"},
- {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14"},
- {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5"},
- {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd"},
- {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7"},
- {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e"},
- {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec"},
- {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c"},
- {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead"},
- {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434"},
- {file = "yarl-1.9.4-cp37-cp37m-win32.whl", hash = "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749"},
- {file = "yarl-1.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2"},
- {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be"},
- {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f"},
- {file = "yarl-1.9.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf"},
- {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1"},
- {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57"},
- {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa"},
- {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130"},
- {file = "yarl-1.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559"},
- {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23"},
- {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec"},
- {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78"},
- {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be"},
- {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3"},
- {file = "yarl-1.9.4-cp38-cp38-win32.whl", hash = "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece"},
- {file = "yarl-1.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b"},
- {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27"},
- {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1"},
- {file = "yarl-1.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91"},
- {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b"},
- {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5"},
- {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34"},
- {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136"},
- {file = "yarl-1.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7"},
- {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e"},
- {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4"},
- {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec"},
- {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c"},
- {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0"},
- {file = "yarl-1.9.4-cp39-cp39-win32.whl", hash = "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575"},
- {file = "yarl-1.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15"},
- {file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"},
- {file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"},
-]
-
-[package.dependencies]
-idna = ">=2.0"
-multidict = ">=4.0"
-
-[metadata]
-lock-version = "2.0"
-python-versions = "^3.12"
-content-hash = "0ed7f7d661cf7de2e3d5718340ecfbfc9226a7dd80d1cfb00d4d99c8377d9f1b"
diff --git a/backend/src/tests/api/conftest.py b/backend/src/tests/api/conftest.py
index 0ff62d7e4..6322c1bec 100644
--- a/backend/src/tests/api/conftest.py
+++ b/backend/src/tests/api/conftest.py
@@ -1,8 +1,10 @@
"""Module that defines fixtures for the api tests."""
+
import pytest
+from fastapi import FastAPI
from fastapi.testclient import TestClient
-from kwai.api.app import create_app
+from kwai.api.app import create_api
from kwai.core.settings import get_settings
from kwai.modules.identity.users.user_account import UserAccountEntity
@@ -10,7 +12,8 @@
@pytest.fixture(scope="module")
def client() -> TestClient:
"""Get an HTTP client."""
- app = create_app(get_settings())
+ app = FastAPI(title="kwai API -- TEST")
+ app.mount("/api", create_api(get_settings()))
return TestClient(app)
diff --git a/backend/src/tests/api/v1/auth/endpoints/test_user_invitations.py b/backend/src/tests/api/v1/auth/endpoints/test_user_invitations.py
index 471543ed7..104744520 100644
--- a/backend/src/tests/api/v1/auth/endpoints/test_user_invitations.py
+++ b/backend/src/tests/api/v1/auth/endpoints/test_user_invitations.py
@@ -1,4 +1,5 @@
"""Test the endpoint users."""
+
import json
import pytest
@@ -45,7 +46,7 @@ def test_create_user_invitation(secure_client: TestClient, invitation_data: list
response = secure_client.post(
"api/v1/auth/users/invitations", content=json.dumps(data)
)
- assert response.status_code == status.HTTP_200_OK, response.content
+ assert response.status_code == status.HTTP_201_CREATED, response.content
invitation_data.append(response.json()["data"]["id"])
diff --git a/backend/src/tests/api/v1/club/schemas/conftest.py b/backend/src/tests/api/v1/club/schemas/conftest.py
index 2df39e996..4f75e52eb 100644
--- a/backend/src/tests/api/v1/club/schemas/conftest.py
+++ b/backend/src/tests/api/v1/club/schemas/conftest.py
@@ -7,30 +7,10 @@
from kwai.core.domain.value_objects.date import Date
from kwai.core.domain.value_objects.email_address import EmailAddress
from kwai.core.domain.value_objects.name import Name
-from kwai.modules.club.members.contact import ContactEntity, ContactIdentifier
-from kwai.modules.club.members.country import CountryEntity, CountryIdentifier
-from kwai.modules.club.members.person import PersonEntity, PersonIdentifier
-from kwai.modules.club.members.value_objects import Address, Birthdate, Gender
-
-
-@pytest.fixture
-def country() -> CountryEntity:
- """A fixture for a country."""
- return CountryEntity(
- id_=CountryIdentifier(1), iso_2="JP", iso_3="JPN", name="Japan"
- )
-
-
-@pytest.fixture
-def expected_country_json() -> dict[str, Any]:
- """A fixture for a JSON:API resource of a country."""
- return {
- "data": {
- "id": "1",
- "type": "countries",
- "attributes": {"iso_2": "JP", "iso_3": "JPN", "name": "Japan"},
- }
- }
+from kwai.modules.club.domain.contact import ContactEntity, ContactIdentifier
+from kwai.modules.club.domain.country import CountryEntity
+from kwai.modules.club.domain.person import PersonEntity, PersonIdentifier
+from kwai.modules.club.domain.value_objects import Address, Birthdate, Gender
@pytest.fixture
diff --git a/backend/src/tests/api/v1/club/schemas/test_contact.py b/backend/src/tests/api/v1/club/schemas/test_contact.py
index c0f809337..f995d6182 100644
--- a/backend/src/tests/api/v1/club/schemas/test_contact.py
+++ b/backend/src/tests/api/v1/club/schemas/test_contact.py
@@ -6,7 +6,7 @@
from deepdiff import DeepDiff
from kwai.api.v1.club.schemas.contact import ContactDocument
-from kwai.modules.club.members.contact import ContactEntity
+from kwai.modules.club.domain.contact import ContactEntity
def test_create_contact_document(
diff --git a/backend/src/tests/api/v1/club/schemas/test_member.py b/backend/src/tests/api/v1/club/schemas/test_member.py
index a76d6b58c..c4fda38b5 100644
--- a/backend/src/tests/api/v1/club/schemas/test_member.py
+++ b/backend/src/tests/api/v1/club/schemas/test_member.py
@@ -8,9 +8,9 @@
from kwai.api.v1.club.schemas.member import MemberDocument
from kwai.core.domain.value_objects.date import Date
-from kwai.modules.club.members.member import MemberEntity, MemberIdentifier
-from kwai.modules.club.members.person import PersonEntity
-from kwai.modules.club.members.value_objects import License
+from kwai.modules.club.domain.member import MemberEntity, MemberIdentifier
+from kwai.modules.club.domain.person import PersonEntity
+from kwai.modules.club.domain.value_objects import License
@pytest.fixture
diff --git a/backend/src/tests/api/v1/club/schemas/test_person.py b/backend/src/tests/api/v1/club/schemas/test_person.py
index d27b61684..41d10e737 100644
--- a/backend/src/tests/api/v1/club/schemas/test_person.py
+++ b/backend/src/tests/api/v1/club/schemas/test_person.py
@@ -6,7 +6,7 @@
from deepdiff import DeepDiff
from kwai.api.v1.club.schemas.person import PersonDocument
-from kwai.modules.club.members.person import PersonEntity
+from kwai.modules.club.domain.person import PersonEntity
def test_create_person_document(
diff --git a/backend/src/tests/api/v1/conftest.py b/backend/src/tests/api/v1/conftest.py
new file mode 100644
index 000000000..0f12ef5bc
--- /dev/null
+++ b/backend/src/tests/api/v1/conftest.py
@@ -0,0 +1,27 @@
+"""Module for defining reusable fixtures."""
+
+from typing import Any
+
+import pytest
+
+from kwai.modules.club.domain.country import CountryEntity, CountryIdentifier
+
+
+@pytest.fixture
+def country() -> CountryEntity:
+ """A fixture for a country."""
+ return CountryEntity(
+ id_=CountryIdentifier(1), iso_2="JP", iso_3="JPN", name="Japan"
+ )
+
+
+@pytest.fixture
+def expected_country_json() -> dict[str, Any]:
+ """A fixture for a JSON:API resource of a country."""
+ return {
+ "data": {
+ "id": "1",
+ "type": "countries",
+ "attributes": {"iso_2": "JP", "iso_3": "JPN", "name": "Japan"},
+ }
+ }
diff --git a/backend/src/tests/api/v1/teams/__init__.py b/backend/src/tests/api/v1/teams/__init__.py
new file mode 100644
index 000000000..2a4d512cf
--- /dev/null
+++ b/backend/src/tests/api/v1/teams/__init__.py
@@ -0,0 +1 @@
+"""Package for testing the teams API."""
diff --git a/backend/src/tests/api/v1/teams/conftest.py b/backend/src/tests/api/v1/teams/conftest.py
new file mode 100644
index 000000000..6a1ff2779
--- /dev/null
+++ b/backend/src/tests/api/v1/teams/conftest.py
@@ -0,0 +1,8 @@
+"""Module for defining common fixtures for testing the teams endpoints."""
+
+from tests.fixtures.teams.teams import * # noqa
+from tests.fixtures.teams.team_members import * # noqa
+from tests.fixtures.club.countries import * # noqa
+from tests.fixtures.club.contacts import * # noqa
+from tests.fixtures.club.persons import * # noqa
+from tests.fixtures.club.members import * # noqa
diff --git a/backend/src/tests/api/v1/teams/test_api.py b/backend/src/tests/api/v1/teams/test_api.py
new file mode 100644
index 000000000..639aa0211
--- /dev/null
+++ b/backend/src/tests/api/v1/teams/test_api.py
@@ -0,0 +1,120 @@
+"""Module for testing the teams API."""
+
+import pytest
+from fastapi import status
+from fastapi.testclient import TestClient
+
+pytestmark = pytest.mark.api
+
+
+async def test_get_team(client: TestClient, make_team_in_db):
+ """Test /api/v1/teams endpoint for getting a team."""
+ team = await make_team_in_db()
+ response = client.get(f"/api/v1/teams/{team.id}")
+ assert response.status_code == status.HTTP_200_OK
+
+
+async def test_get_teams(client: TestClient, make_team_in_db):
+ """Test /api/v1/teams endpoint for getting all teams."""
+ await make_team_in_db()
+ response = client.get("/api/v1/teams")
+ assert response.status_code == status.HTTP_200_OK
+
+
+async def test_delete_team(secure_client: TestClient, make_team_in_db):
+ """Test /api/v1/teams endpoint for deleting a team."""
+ team = await make_team_in_db()
+ response = secure_client.delete(f"/api/v1/teams/{team.id}")
+ assert response.status_code == status.HTTP_200_OK
+
+
+async def test_create_team(secure_client: TestClient, make_team):
+ """Test /api/v1/teams endpoint for creating a team."""
+ team = make_team()
+ payload = {
+ "data": {
+ "type": "teams",
+ "attributes": {
+ "name": team.name,
+ "active": team.is_active,
+ "remark": team.remark,
+ },
+ }
+ }
+ response = secure_client.post("/api/v1/teams", json=payload)
+ assert response.status_code == status.HTTP_201_CREATED
+
+
+async def test_update_team(secure_client: TestClient, make_team_in_db):
+ """Test /api/v1/teams endpoint for updating a team."""
+ team = await make_team_in_db()
+ payload = {
+ "data": {
+ "id": str(team.id),
+ "type": "teams",
+ "attributes": {
+ "name": team.name,
+ "active": team.is_active,
+ "remark": "This is a test",
+ },
+ }
+ }
+ response = secure_client.patch(f"/api/v1/teams/{team.id}", json=payload)
+ assert response.status_code == status.HTTP_200_OK
+ assert (
+ response.json()["data"]["attributes"]["remark"] == "This is a test"
+ ), "The team should be updated."
+
+
+async def test_get_members(
+ secure_client: TestClient, make_team_in_db, make_member_in_db
+):
+ """Test /api/v1/teams/members endpoint for getting members."""
+ team = await make_team_in_db()
+ await make_member_in_db()
+ response = secure_client.get(f"/api/v1/teams/members?filter[team]=noteq:{team.id}")
+ assert response.status_code == status.HTTP_200_OK
+
+
+async def test_get_team_members(
+ secure_client: TestClient, make_team_in_db, make_team_member_in_db
+):
+ """Test /api/v1/teams//members endpoint for getting a team's members."""
+ team = await make_team_in_db()
+ await make_team_member_in_db(team=team)
+ response = secure_client.get(f"/api/v1/teams/{team.id}/members")
+ assert response.status_code == status.HTTP_200_OK
+
+
+async def test_create_team_member(
+ secure_client: TestClient, make_team_in_db, make_member_in_db
+):
+ """Test /api/v1/teams//members endpoint for creating a team's member."""
+ team = await make_team_in_db()
+ member = await make_member_in_db()
+ payload = {
+ "data": {
+ "type": "team_members",
+ "id": str(member.uuid),
+ "attributes": {
+ "active": True,
+ "first_name": member.person.name.first_name,
+ "last_name": member.person.name.last_name,
+ "license_number": member.license.number,
+ "license_end_date": str(member.license.end_date),
+ "gender": member.person.gender.value,
+ "birthdate": str(member.person.birthdate),
+ "active_in_club": True,
+ },
+ "relationships": {
+ "nationality": {
+ "data": {
+ "type": "countries",
+ "id": str(member.person.nationality.id),
+ }
+ }
+ },
+ }
+ }
+ response = secure_client.post(f"/api/v1/teams/{team.id}/members", json=payload)
+ assert response.status_code == status.HTTP_201_CREATED, response.json()
diff --git a/backend/src/tests/api/v1/teams/test_schemas.py b/backend/src/tests/api/v1/teams/test_schemas.py
new file mode 100644
index 000000000..13ad2d69d
--- /dev/null
+++ b/backend/src/tests/api/v1/teams/test_schemas.py
@@ -0,0 +1,137 @@
+"""Module for testing teams schemas."""
+
+import json
+from typing import Any
+
+import pytest
+from deepdiff import DeepDiff
+
+from kwai.api.v1.teams.schemas import TeamDocument, TeamMemberDocument
+from kwai.core.domain.value_objects.date import Date
+from kwai.core.domain.value_objects.name import Name
+from kwai.core.domain.value_objects.traceable_time import TraceableTime
+from kwai.core.domain.value_objects.unique_id import UniqueId
+from kwai.modules.club.domain.value_objects import Birthdate, Gender, License
+from kwai.modules.teams.domain.team import TeamEntity, TeamIdentifier
+from kwai.modules.teams.domain.team_member import (
+ MemberEntity,
+ MemberIdentifier,
+ TeamMember,
+)
+from tests.fixtures.club.countries import * # noqa
+
+
+@pytest.fixture
+def team_member(country_japan) -> TeamMember:
+ """A fixture for a team member."""
+ return TeamMember(
+ active=True,
+ member=MemberEntity(
+ id_=MemberIdentifier(1),
+ name=Name(first_name="Jigoro", last_name="Kano"),
+ uuid=UniqueId.generate(),
+ license=License(number="1234", end_date=Date.today().add(years=1)),
+ birthdate=Birthdate(Date.create(year=1860, month=10, day=28)),
+ gender=Gender.MALE,
+ nationality=country_japan,
+ active_in_club=True,
+ ),
+ traceable_time=TraceableTime(),
+ )
+
+
+@pytest.fixture
+def expected_team_member_json(team_member: TeamMember) -> dict[str, Any]:
+ """A fixture for a JSON:API resource of a team member."""
+ return {
+ "data": {
+ "id": str(team_member.member.uuid),
+ "type": "team_members",
+ "meta": {
+ "created_at": str(team_member.traceable_time.created_at),
+ "updated_at": str(team_member.traceable_time.updated_at),
+ },
+ "attributes": {
+ "active": True,
+ "first_name": "Jigoro",
+ "last_name": "Kano",
+ "gender": team_member.member.gender.value,
+ "birthdate": str(team_member.member.birthdate),
+ "license_number": team_member.member.license.number,
+ "license_end_date": str(team_member.member.license.end_date),
+ "active_in_club": True,
+ },
+ "relationships": {
+ "nationality": {
+ "data": {
+ "id": str(team_member.member.nationality.id),
+ "type": "countries",
+ }
+ },
+ "team": None,
+ },
+ },
+ "included": [
+ {
+ "id": str(team_member.member.nationality.id),
+ "type": "countries",
+ "attributes": {"iso_2": "JP", "iso_3": "JPN", "name": "Japan"},
+ }
+ ],
+ }
+
+
+def test_create_team_member_document(
+ team_member: TeamMember, expected_team_member_json: dict[str, Any]
+):
+ """Test the creation of a JSON:API document for a team member resource."""
+ team_member_document = TeamMemberDocument.create(team_member)
+ json_resource = json.loads(team_member_document.json())
+
+ diff = DeepDiff(json_resource, expected_team_member_json, ignore_order=True)
+ assert not diff, f"JSON structure is not expected:{diff}"
+
+
+@pytest.fixture
+def team(team_member: TeamMember) -> TeamEntity:
+ """A fixture for a team entity."""
+ return TeamEntity(
+ id_=TeamIdentifier(1),
+ name="U11",
+ members={team_member.member.uuid: team_member},
+ )
+
+
+@pytest.fixture
+def expected_team_json(team: TeamEntity, expected_team_member_json) -> dict[str, Any]:
+ """A fixture for a JSON:API resource of a team."""
+ return {
+ "data": {
+ "id": "1",
+ "type": "teams",
+ "attributes": {"name": "U11", "remark": "", "active": True},
+ "relationships": {
+ "team_members": {
+ "data": [
+ {
+ "id": expected_team_member_json["data"]["id"],
+ "type": expected_team_member_json["data"]["type"],
+ }
+ ]
+ }
+ },
+ },
+ "included": [
+ expected_team_member_json["data"],
+ *expected_team_member_json["included"],
+ ],
+ }
+
+
+def test_create_team_document(team: TeamEntity, expected_team_json: dict[str, Any]):
+ """Test the creation of a JSON:API document for a team entity."""
+ team_document = TeamDocument.create(team)
+ json_resource = json.loads(team_document.json())
+
+ diff = DeepDiff(json_resource, expected_team_json, ignore_order=True)
+ assert not diff, f"JSON structure is not expected:{diff}"
diff --git a/backend/src/tests/api/v1/club/schemas/test_country.py b/backend/src/tests/api/v1/test_schemas.py
similarity index 73%
rename from backend/src/tests/api/v1/club/schemas/test_country.py
rename to backend/src/tests/api/v1/test_schemas.py
index b7dbcbffd..2bfb21f37 100644
--- a/backend/src/tests/api/v1/club/schemas/test_country.py
+++ b/backend/src/tests/api/v1/test_schemas.py
@@ -1,12 +1,12 @@
-"""Module for testing the country JSON:API resource."""
+"""Module for testing the common JSON:API schemas."""
import json
from typing import Any
from deepdiff import DeepDiff
-from kwai.api.v1.club.schemas.country import CountryDocument
-from kwai.modules.club.members.country import CountryEntity
+from kwai.api.v1.schemas import CountryDocument
+from kwai.modules.club.domain.country import CountryEntity
def test_create_country_document(
diff --git a/backend/src/tests/conftest.py b/backend/src/tests/conftest.py
index 52c27b760..9a8a69057 100644
--- a/backend/src/tests/conftest.py
+++ b/backend/src/tests/conftest.py
@@ -1,4 +1,5 @@
"""Module for sharing fixtures in this module."""
+
import asyncio
from typing import AsyncIterator, Iterator
diff --git a/backend/src/tests/core/test_json_api.py b/backend/src/tests/core/test_json_api.py
index 013b5b1c4..5db6f37ff 100644
--- a/backend/src/tests/core/test_json_api.py
+++ b/backend/src/tests/core/test_json_api.py
@@ -1,4 +1,5 @@
"""Module for testing the JSON:API models."""
+
from types import NoneType
from typing import Literal
@@ -6,7 +7,7 @@
from pydantic import BaseModel
from rich import json
-from kwai.core.json_api import Document, ResourceData, ResourceIdentifier
+from kwai.core.json_api import Document, Error, ResourceData, ResourceIdentifier
class JudokaResourceIdentifier(ResourceIdentifier):
@@ -72,3 +73,19 @@ def test_dump_json(judoka_resource: JudokaResource):
assert (
json_doc["data"]["attributes"]["name"] == "Jigoro Kano"
), "The judoka should have a name."
+
+
+def test_error():
+ """Test the error of a JSON:API document."""
+ json_doc = JudokaDocument(
+ data=[],
+ errors=[
+ Error(
+ title="No judoka selected",
+ detail="There is no judoka selected for this tournament",
+ )
+ ],
+ )
+ json_doc = json.loads(json_doc.model_dump_json())
+ assert "errors" in json_doc, "There should be a 'errors' in the document."
+ assert json_doc["errors"][0]["title"] == "No judoka selected"
diff --git a/backend/src/tests/fixtures/club/coaches.py b/backend/src/tests/fixtures/club/coaches.py
new file mode 100644
index 000000000..b99be4610
--- /dev/null
+++ b/backend/src/tests/fixtures/club/coaches.py
@@ -0,0 +1,52 @@
+"""Module for defining fixtures for coaches."""
+
+import pytest
+
+from kwai.core.db.database import Database
+from kwai.core.db.uow import UnitOfWork
+from kwai.modules.club.domain.coach import CoachEntity
+from kwai.modules.club.domain.member import MemberEntity
+from kwai.modules.club.repositories.coach_db_repository import CoachDbRepository
+
+
+@pytest.fixture
+def make_coach(make_member):
+ """A factory fixture for a coach."""
+
+ def _make_coach(
+ member: MemberEntity | None = None,
+ active: bool = True,
+ ) -> CoachEntity:
+ member = member or make_member()
+ return CoachEntity(member=member or make_member(), active=active)
+
+ return _make_coach
+
+
+@pytest.fixture
+def make_coach_in_db(
+ request, event_loop, database: Database, make_coach, make_member_in_db
+):
+ """A factory fixture for a coach in a database."""
+
+ async def _make_coach_in_db(
+ coach: CoachEntity | None = None, member: MemberEntity | None = None
+ ):
+ member = member or await make_member_in_db()
+ coach = coach or make_coach(member=member)
+ repo = CoachDbRepository(database)
+ async with UnitOfWork(database):
+ coach = await repo.create(coach)
+
+ def cleanup():
+ async def acleanup():
+ async with UnitOfWork(database):
+ await repo.delete(coach)
+
+ event_loop.run_until_complete(acleanup())
+
+ request.addfinalizer(cleanup)
+
+ return coach
+
+ return _make_coach_in_db
diff --git a/backend/src/tests/fixtures/club/contacts.py b/backend/src/tests/fixtures/club/contacts.py
index 05f6e76e2..d94601f8d 100644
--- a/backend/src/tests/fixtures/club/contacts.py
+++ b/backend/src/tests/fixtures/club/contacts.py
@@ -1,40 +1,18 @@
"""Module for defining fixtures for contacts."""
-from typing import (
- Awaitable,
- Callable,
- NotRequired,
- TypeAlias,
- TypedDict,
- Unpack,
-)
-
import pytest
from kwai.core.db.database import Database
from kwai.core.db.uow import UnitOfWork
from kwai.core.domain.value_objects.email_address import EmailAddress
-from kwai.modules.club.members.contact import ContactEntity
-from kwai.modules.club.members.contact_db_repository import ContactDbRepository
-from kwai.modules.club.members.country import CountryEntity
-from kwai.modules.club.members.value_objects import Address
-
-
-class AddressType(TypedDict):
- """Keyword arguments for the Address fixture factory method."""
-
- address: NotRequired[str]
- postal_code: NotRequired[str]
- city: NotRequired[str]
- county: NotRequired[str]
- country: NotRequired[CountryEntity]
-
-
-AddressFixtureFactory: TypeAlias = Callable[[Unpack[AddressType]], Address]
+from kwai.modules.club.domain.contact import ContactEntity
+from kwai.modules.club.domain.country import CountryEntity
+from kwai.modules.club.domain.value_objects import Address
+from kwai.modules.club.repositories.contact_db_repository import ContactDbRepository
@pytest.fixture
-def make_address(country_japan) -> AddressFixtureFactory:
+def make_address(country_japan):
"""A factory fixture for an address."""
def _make_address(
@@ -56,18 +34,8 @@ def _make_address(
return _make_address
-class ContactType(TypedDict):
- """Keyword arguments for the Contact fixture factory method."""
-
- emails: NotRequired[list[EmailAddress]]
- address: NotRequired[Address]
-
-
-ContactFixtureFactory: TypeAlias = Callable[[Unpack[ContactType]], ContactEntity]
-
-
@pytest.fixture
-def make_emails() -> Callable[[str | None], list[EmailAddress]]:
+def make_emails():
"""A factory fixture for a contact email."""
def _make_emails(email: str | None = None) -> list[EmailAddress]:
@@ -79,7 +47,7 @@ def _make_emails(email: str | None = None) -> list[EmailAddress]:
@pytest.fixture
-def make_contact(make_emails, make_address) -> ContactFixtureFactory:
+def make_contact(make_emails, make_address):
"""A factory fixture for a contact."""
def _make_contact(
@@ -93,11 +61,6 @@ def _make_contact(
return _make_contact
-ContactDbFixtureFactory: TypeAlias = Callable[
- [ContactEntity | None], Awaitable[ContactEntity]
-]
-
-
@pytest.fixture
def make_contact_in_db(
request,
@@ -106,7 +69,7 @@ def make_contact_in_db(
make_contact,
make_address,
make_country_in_db,
-) -> ContactDbFixtureFactory:
+):
"""A fixture for a contact in the database."""
async def _make_contact_in_db(
diff --git a/backend/src/tests/fixtures/club/countries.py b/backend/src/tests/fixtures/club/countries.py
index 549d14a72..f23d155c1 100644
--- a/backend/src/tests/fixtures/club/countries.py
+++ b/backend/src/tests/fixtures/club/countries.py
@@ -1,35 +1,16 @@
"""Module for fixtures related to countries."""
-from typing import (
- AsyncGenerator,
- Callable,
- NotRequired,
- TypedDict,
- Unpack,
-)
-
import pytest
from kwai.core.db.database import Database
from kwai.core.db.uow import UnitOfWork
-from kwai.modules.club.members.country import CountryEntity
-from kwai.modules.club.members.country_db_repository import CountryDbRepository
-from kwai.modules.club.members.country_repository import CountryNotFoundException
-
-
-class CountryType(TypedDict):
- """Keyword arguments for the Country fixture factory method."""
-
- iso_2: NotRequired[str]
- iso_3: NotRequired[str]
- name: NotRequired[str]
-
-
-type CountryFixtureFactory = Callable[[Unpack[CountryType]], CountryEntity]
+from kwai.modules.club.domain.country import CountryEntity
+from kwai.modules.club.repositories.country_db_repository import CountryDbRepository
+from kwai.modules.club.repositories.country_repository import CountryNotFoundException
@pytest.fixture
-def make_country() -> CountryFixtureFactory:
+def make_country():
"""A factory fixture for a country."""
def _make_country(iso_2="XX", iso_3="XXX", name="Test Country"):
@@ -39,18 +20,13 @@ def _make_country(iso_2="XX", iso_3="XXX", name="Test Country"):
@pytest.fixture
-def country_japan() -> CountryEntity:
+def country_japan():
"""A factory fixture for the country Japan."""
return CountryEntity(iso_2="JP", iso_3="JPN", name="Japan")
-type CountryDbFixtureFactory = Callable[[], AsyncGenerator[CountryEntity, None]]
-
-
@pytest.fixture
-async def make_country_in_db(
- request, event_loop, database: Database, make_country: CountryFixtureFactory
-) -> CountryDbFixtureFactory:
+async def make_country_in_db(request, event_loop, database: Database, make_country):
"""A fixture for a country in the database.
When the country is already in the database, it will be returned.
diff --git a/backend/src/tests/fixtures/club/members.py b/backend/src/tests/fixtures/club/members.py
index 049782754..8dfbcfbc7 100644
--- a/backend/src/tests/fixtures/club/members.py
+++ b/backend/src/tests/fixtures/club/members.py
@@ -1,22 +1,18 @@
"""Module for defining fixtures of members."""
-from typing import Callable, TypeAlias
-
import pytest
from kwai.core.db.database import Database
from kwai.core.db.uow import UnitOfWork
from kwai.core.domain.value_objects.date import Date
-from kwai.modules.club.members.member import MemberEntity
-from kwai.modules.club.members.member_db_repository import MemberDbRepository
-from kwai.modules.club.members.person import PersonEntity
-from kwai.modules.club.members.value_objects import License
-
-MemberFixtureFactory: TypeAlias = Callable[[License | None], MemberEntity]
+from kwai.modules.club.domain.member import MemberEntity
+from kwai.modules.club.domain.person import PersonEntity
+from kwai.modules.club.domain.value_objects import License
+from kwai.modules.club.repositories.member_db_repository import MemberDbRepository
@pytest.fixture
-def make_member(make_person) -> MemberFixtureFactory:
+def make_member(make_person):
"""A factory fixture for a member."""
def _make_member_entity(
@@ -41,11 +37,22 @@ def make_member_in_db(
database: Database,
make_member,
make_person_in_db,
+ make_person,
+ make_contact_in_db,
+ make_country_in_db,
+ country_japan,
):
"""A fixture for a member in the database."""
async def _make_member_in_db(member: MemberEntity | None = None) -> MemberEntity:
- member = member or make_member(person=await make_person_in_db())
+ member = member or make_member(
+ person=await make_person_in_db(
+ make_person(
+ contact=await make_contact_in_db(),
+ nationality=await make_country_in_db(country_japan),
+ ),
+ )
+ )
repo = MemberDbRepository(database)
async with UnitOfWork(database):
member = await repo.create(member)
diff --git a/backend/src/tests/fixtures/club/persons.py b/backend/src/tests/fixtures/club/persons.py
index 2244cc2e2..be24fe180 100644
--- a/backend/src/tests/fixtures/club/persons.py
+++ b/backend/src/tests/fixtures/club/persons.py
@@ -6,11 +6,11 @@
from kwai.core.db.uow import UnitOfWork
from kwai.core.domain.value_objects.date import Date
from kwai.core.domain.value_objects.name import Name
-from kwai.modules.club.members.contact import ContactEntity
-from kwai.modules.club.members.country import CountryEntity
-from kwai.modules.club.members.person import PersonEntity
-from kwai.modules.club.members.person_db_repository import PersonDbRepository
-from kwai.modules.club.members.value_objects import Birthdate, Gender
+from kwai.modules.club.domain.contact import ContactEntity
+from kwai.modules.club.domain.country import CountryEntity
+from kwai.modules.club.domain.person import PersonEntity
+from kwai.modules.club.domain.value_objects import Birthdate, Gender
+from kwai.modules.club.repositories.person_db_repository import PersonDbRepository
@pytest.fixture
diff --git a/backend/src/tests/fixtures/teams/__init__.py b/backend/src/tests/fixtures/teams/__init__.py
new file mode 100644
index 000000000..533b46b01
--- /dev/null
+++ b/backend/src/tests/fixtures/teams/__init__.py
@@ -0,0 +1 @@
+"""Package for defining recurring fixtures for the teams bounded context."""
diff --git a/backend/src/tests/fixtures/teams/team_members.py b/backend/src/tests/fixtures/teams/team_members.py
new file mode 100644
index 000000000..1ba087c82
--- /dev/null
+++ b/backend/src/tests/fixtures/teams/team_members.py
@@ -0,0 +1,50 @@
+"""Module for defining factory fixtures for team members."""
+
+import pytest
+
+from kwai.core.db.database import Database
+from kwai.core.domain.value_objects.traceable_time import TraceableTime
+from kwai.modules.teams.domain.team import TeamEntity
+from kwai.modules.teams.domain.team_member import MemberEntity, TeamMember
+from kwai.modules.teams.repositories.team_db_repository import TeamDbRepository
+
+
+@pytest.fixture
+def make_team_member(make_member):
+ """A factory fixture for a team member."""
+
+ def _make_team_member(member: MemberEntity | None = None) -> TeamMember:
+ member = member or make_member()
+ return TeamMember(
+ active=True,
+ member=MemberEntity(
+ id_=member.id,
+ uuid=member.uuid,
+ name=member.name,
+ license=member.license,
+ birthdate=member.person.birthdate,
+ nationality=member.person.nationality,
+ gender=member.person.gender,
+ ),
+ traceable_time=TraceableTime(),
+ )
+
+ return _make_team_member
+
+
+@pytest.fixture
+def make_team_member_in_db(
+ database: Database, make_team_member, make_member_in_db, make_team_in_db
+):
+ """A factory fixture for a team member in a database."""
+
+ async def _make_team_member_in_db(
+ member: MemberEntity | None = None, team: TeamEntity | None = None
+ ) -> TeamMember:
+ member = member or make_team_member(await make_member_in_db())
+ team = team or await make_team_in_db()
+ if team is not None:
+ await TeamDbRepository(database).add_team_member(team, member)
+ return member
+
+ return _make_team_member_in_db
diff --git a/backend/src/tests/fixtures/teams/teams.py b/backend/src/tests/fixtures/teams/teams.py
new file mode 100644
index 000000000..599ef9db7
--- /dev/null
+++ b/backend/src/tests/fixtures/teams/teams.py
@@ -0,0 +1,42 @@
+"""Module for defining factory fixtures for teams."""
+
+import pytest
+
+from kwai.core.db.database import Database
+from kwai.core.db.uow import UnitOfWork
+from kwai.modules.teams.domain.team import TeamEntity
+from kwai.modules.teams.repositories.team_db_repository import TeamDbRepository
+
+
+@pytest.fixture
+def make_team():
+ """A factory fixture for creating a team."""
+
+ def _make_team(name: str | None = None) -> TeamEntity:
+ return TeamEntity(name=name or "U11")
+
+ return _make_team
+
+
+@pytest.fixture
+def make_team_in_db(request, event_loop, database: Database, make_team):
+ """A factory fixture for creating a team in database."""
+
+ async def _make_team_in_db(team: TeamEntity | None = None) -> TeamEntity:
+ team = team or make_team()
+ repo = TeamDbRepository(database)
+ async with UnitOfWork(database):
+ team = await repo.create(team)
+
+ def cleanup():
+ async def acleanup():
+ async with UnitOfWork(database):
+ await repo.delete(team)
+
+ event_loop.run_until_complete(acleanup())
+
+ request.addfinalizer(cleanup)
+
+ return team
+
+ return _make_team_in_db
diff --git a/backend/src/tests/fixtures/training/__init__.py b/backend/src/tests/fixtures/training/__init__.py
new file mode 100644
index 000000000..f79555c49
--- /dev/null
+++ b/backend/src/tests/fixtures/training/__init__.py
@@ -0,0 +1 @@
+"""Package for defining recurring fixtures for the training bounded context."""
diff --git a/backend/src/tests/fixtures/training/training_definitions.py b/backend/src/tests/fixtures/training/training_definitions.py
new file mode 100644
index 000000000..0d00cc1fa
--- /dev/null
+++ b/backend/src/tests/fixtures/training/training_definitions.py
@@ -0,0 +1,63 @@
+"""Module for defining fixture factories for training definitions."""
+
+import pytest
+
+from kwai.core.db.database import Database
+from kwai.core.db.uow import UnitOfWork
+from kwai.core.domain.value_objects.owner import Owner
+from kwai.core.domain.value_objects.time_period import TimePeriod
+from kwai.core.domain.value_objects.weekday import Weekday
+from kwai.modules.training.trainings.training_definition import TrainingDefinitionEntity
+from kwai.modules.training.trainings.training_definition_db_repository import (
+ TrainingDefinitionDbRepository,
+)
+
+
+@pytest.fixture
+def make_training_definition(owner: Owner):
+ """A factory fixture for creating a training definition."""
+
+ def _make_training_definition(
+ name: str | None = None,
+ description: str | None = None,
+ weekday: Weekday | None = None,
+ period: TimePeriod | None = None,
+ ) -> TrainingDefinitionEntity:
+ return TrainingDefinitionEntity(
+ name=name or "A training",
+ description=description or "A training definition",
+ weekday=weekday or Weekday.MONDAY,
+ period=period
+ or TimePeriod.create_from_string("18:00", "19:00", "Europe/Brussels"),
+ owner=owner,
+ )
+
+ return _make_training_definition
+
+
+@pytest.fixture
+def make_training_definition_in_db(
+ request, event_loop, database: Database, make_training_definition
+):
+ """A fixture factory for a training definition in the database."""
+
+ async def _make_training_definition_in_db(
+ training_definition: TrainingDefinitionEntity | None = None,
+ ) -> TrainingDefinitionEntity:
+ training_definition = training_definition or make_training_definition()
+ repo = TrainingDefinitionDbRepository(database)
+ async with UnitOfWork(database):
+ training_definition = await repo.create(training_definition)
+
+ def cleanup():
+ async def acleanup():
+ async with UnitOfWork(database):
+ await repo.delete(training_definition)
+
+ event_loop.run_until_complete(acleanup())
+
+ request.addfinalizer(cleanup)
+
+ return training_definition
+
+ return _make_training_definition_in_db
diff --git a/backend/src/tests/fixtures/training/trainings.py b/backend/src/tests/fixtures/training/trainings.py
new file mode 100644
index 000000000..fcb9990ae
--- /dev/null
+++ b/backend/src/tests/fixtures/training/trainings.py
@@ -0,0 +1,98 @@
+"""Module for defining factory fixtures for trainings."""
+
+import pytest
+
+from kwai.core.db.database import Database
+from kwai.core.db.uow import UnitOfWork
+from kwai.core.domain.value_objects.owner import Owner
+from kwai.core.domain.value_objects.period import Period
+from kwai.core.domain.value_objects.text import DocumentFormat, Locale, LocaleText
+from kwai.modules.training.coaches.coach import CoachEntity
+from kwai.modules.training.trainings.training import TrainingEntity
+from kwai.modules.training.trainings.training_db_repository import TrainingDbRepository
+from kwai.modules.training.trainings.value_objects import TrainingCoach
+
+
+@pytest.fixture
+def make_text(
+ *,
+ locale: Locale | None = None,
+ format_: DocumentFormat | None = None,
+ title: str = "Training Test",
+ content: str = "This is a test training",
+ summary: str = "Test",
+ owner: Owner,
+):
+ """A factory fixture for a text."""
+
+ def _make_text() -> LocaleText:
+ return LocaleText(
+ title=title,
+ content=content,
+ summary=summary,
+ locale=locale or Locale.NL,
+ format=format_ or DocumentFormat.MARKDOWN,
+ author=owner,
+ )
+
+ return _make_text
+
+
+@pytest.fixture
+def make_training_coach(make_coach, owner: Owner):
+ """A factory fixture for a training coach."""
+
+ def _make_training_coach(coach: CoachEntity | None = None) -> TrainingCoach:
+ if coach is None:
+ # make_coach returns a coach entity from the club module, so we need
+ # to convert it to one for the training module.
+ club_coach = make_coach()
+ coach = CoachEntity(
+ id_=club_coach.id, name=club_coach.name, active=club_coach.is_active
+ )
+ return TrainingCoach(coach=coach, owner=owner)
+
+ return _make_training_coach
+
+
+@pytest.fixture
+def make_training(make_text, make_training_coach):
+ """A factory fixture for a training."""
+
+ def _make_training(
+ text: LocaleText | None = None,
+ coach: TrainingCoach | None = None,
+ period: Period | None = None,
+ ) -> TrainingEntity:
+ coach = coach or make_training_coach()
+ text = text or make_text()
+ period = period or Period.create_from_delta(hours=2)
+ return TrainingEntity(texts=[text], coaches=[coach], season=None, period=period)
+
+ return _make_training
+
+
+@pytest.fixture
+def make_training_in_db(request, event_loop, database: Database, make_training):
+ """A factory fixture for a training in the database."""
+
+ async def _make_training_in_db(
+ training: TrainingEntity | None = None,
+ ) -> TrainingEntity:
+ training = training or make_training()
+ repo = TrainingDbRepository(database)
+ async with UnitOfWork(database):
+ training = await repo.create(training)
+
+ def cleanup():
+ async def acleanup():
+ async with UnitOfWork(database):
+ await repo.delete(training)
+
+ event_loop.run_until_complete(acleanup())
+
+ request.addfinalizer(cleanup)
+
+ return training
+
+ return _make_training_in_db
diff --git a/backend/src/tests/frontend/__init__.py b/backend/src/tests/frontend/__init__.py
new file mode 100644
index 000000000..cfbb3982c
--- /dev/null
+++ b/backend/src/tests/frontend/__init__.py
@@ -0,0 +1 @@
+"""Package containing frontend tests."""
diff --git a/backend/src/tests/frontend/conftest.py b/backend/src/tests/frontend/conftest.py
new file mode 100644
index 000000000..b0d6d6123
--- /dev/null
+++ b/backend/src/tests/frontend/conftest.py
@@ -0,0 +1,19 @@
+"""Module for pytest fixtures for testing the frontend module.."""
+
+from pathlib import Path
+
+import pytest
+
+from kwai.frontend.manifest import Manifest
+
+
+@pytest.fixture
+def manifest_path() -> Path:
+ """Load a manifest file from the data folder."""
+ return Path(__file__).parent / "data" / "manifest.json"
+
+
+@pytest.fixture
+def manifest(manifest_path) -> Manifest:
+ """Load a manifest file from the data folder."""
+ return Manifest.load_from_file(manifest_path)
diff --git a/backend/src/tests/frontend/data/manifest.json b/backend/src/tests/frontend/data/manifest.json
new file mode 100644
index 000000000..2d070f0a0
--- /dev/null
+++ b/backend/src/tests/frontend/data/manifest.json
@@ -0,0 +1,114 @@
+{
+ "_vendor-97e41b2b.js": {
+ "file": "assets/vendor-97e41b2b.js"
+ },
+ "images/hero.jpg": {
+ "file": "assets/hero-7d6583ab.jpg",
+ "src": "images/hero.jpg"
+ },
+ "images/hero_club.jpg": {
+ "file": "assets/hero_club-163a0a1d.jpg",
+ "src": "images/hero_club.jpg"
+ },
+ "images/hero_judo.jpg": {
+ "file": "assets/hero_judo-98309ea4.jpg",
+ "src": "images/hero_judo.jpg"
+ },
+ "images/hero_news.jpg": {
+ "file": "assets/hero_news-7e409a2c.jpg",
+ "src": "images/hero_news.jpg"
+ },
+ "images/hero_shop.jpg": {
+ "file": "assets/hero_shop-b55abed0.jpg",
+ "src": "images/hero_shop.jpg"
+ },
+ "images/hero_tournaments.jpg": {
+ "file": "assets/hero_tournaments-59e5271e.jpg",
+ "src": "images/hero_tournaments.jpg"
+ },
+ "images/hero_trainings.jpg": {
+ "file": "assets/hero_trainings-47dcea06.jpg",
+ "src": "images/hero_trainings.jpg"
+ },
+ "src/components/icons/FacebookIcon.vue": {
+ "file": "assets/FacebookIcon-44b697a2.js",
+ "imports": [
+ "src/index.ts",
+ "_vendor-97e41b2b.js"
+ ],
+ "isDynamicEntry": true,
+ "src": "src/components/icons/FacebookIcon.vue"
+ },
+ "src/components/icons/InstagramIcon.vue": {
+ "file": "assets/InstagramIcon-ce6d9dfa.js",
+ "imports": [
+ "src/index.ts",
+ "_vendor-97e41b2b.js"
+ ],
+ "isDynamicEntry": true,
+ "src": "src/components/icons/InstagramIcon.vue"
+ },
+ "src/components/icons/LoadingIcon.vue": {
+ "file": "assets/LoadingIcon-3b690cc8.js",
+ "imports": [
+ "src/index.ts",
+ "_vendor-97e41b2b.js"
+ ],
+ "isDynamicEntry": true,
+ "src": "src/components/icons/LoadingIcon.vue"
+ },
+ "src/components/icons/NextIcon.vue": {
+ "file": "assets/NextIcon-771d3f7f.js",
+ "imports": [
+ "src/index.ts",
+ "_vendor-97e41b2b.js"
+ ],
+ "isDynamicEntry": true,
+ "src": "src/components/icons/NextIcon.vue"
+ },
+ "src/components/icons/PrevIcon.vue": {
+ "file": "assets/PrevIcon-41277b2b.js",
+ "imports": [
+ "src/index.ts",
+ "_vendor-97e41b2b.js"
+ ],
+ "isDynamicEntry": true,
+ "src": "src/components/icons/PrevIcon.vue"
+ },
+ "src/index.css": {
+ "file": "assets/index-ace45c09.css",
+ "src": "src/index.css"
+ },
+ "src/index.ts": {
+ "assets": [
+ "assets/hero-7d6583ab.jpg",
+ "assets/hero_club-163a0a1d.jpg",
+ "assets/hero_judo-98309ea4.jpg",
+ "assets/hero_news-7e409a2c.jpg",
+ "assets/hero_shop-b55abed0.jpg",
+ "assets/hero_tournaments-59e5271e.jpg",
+ "assets/hero_trainings-47dcea06.jpg"
+ ],
+ "css": [
+ "assets/index-ace45c09.css"
+ ],
+ "dynamicImports": [
+ "src/components/icons/FacebookIcon.vue",
+ "src/components/icons/InstagramIcon.vue",
+ "src/components/icons/LoadingIcon.vue",
+ "src/components/icons/NextIcon.vue",
+ "src/components/icons/PrevIcon.vue",
+ "src/components/icons/FacebookIcon.vue",
+ "src/components/icons/InstagramIcon.vue",
+ "src/components/icons/LoadingIcon.vue",
+ "src/components/icons/NextIcon.vue",
+ "src/components/icons/PrevIcon.vue"
+ ],
+ "file": "assets/index-533fa9ea.js",
+ "imports": [
+ "_vendor-97e41b2b.js"
+ ],
+ "isEntry": true,
+ "src": "src/index.ts"
+ }
+}
diff --git a/backend/src/tests/frontend/test_development_vite.py b/backend/src/tests/frontend/test_development_vite.py
new file mode 100644
index 000000000..57301d246
--- /dev/null
+++ b/backend/src/tests/frontend/test_development_vite.py
@@ -0,0 +1,31 @@
+"""Module for testing the development vite class."""
+
+import pytest
+
+from kwai.frontend.vite import DevelopmentVite, Vite
+
+
+@pytest.fixture
+def vite() -> Vite:
+ """A fixture for vite development."""
+ vite = DevelopmentVite("http://localhost:5173", "")
+ vite.init("src/index.ts")
+ return vite
+
+
+def test_development_vite_scripts(vite: Vite):
+ """Test the development version of the Vite class for script tags."""
+ scripts = vite.get_scripts("")
+ assert len(scripts) == 2, "There should be 2 script tags"
+ assert scripts[0] == "http://localhost:5173/@vite/client"
+ assert scripts[1] == "http://localhost:5173/src/index.ts"
+
+
+def test_development_vite_css(vite: Vite):
+ """Test the development version of the Vite class for css tags."""
+ assert len(vite.get_css("")) == 0, "There should be no css in development"
+
+
+def test_development_vite_preload(vite: Vite):
+ """Test the development version of the Vite class for preload tags."""
+ assert len(vite.get_preloads("")) == 0, "There should be no preload in development"
diff --git a/backend/src/tests/frontend/test_etag_file_response.py b/backend/src/tests/frontend/test_etag_file_response.py
new file mode 100644
index 000000000..f66470909
--- /dev/null
+++ b/backend/src/tests/frontend/test_etag_file_response.py
@@ -0,0 +1,31 @@
+"""Test the EtagFileResponse."""
+
+from pathlib import Path
+
+from fastapi import FastAPI
+from fastapi.testclient import TestClient
+
+from kwai.frontend.etag_file_response import EtagFileResponse
+
+
+def test_etag_file_response(tmp_path: Path) -> None:
+ """Test the ETag file response."""
+ app = FastAPI(title="kwai API -- TEST")
+
+ @app.get("/")
+ def get_file():
+ return EtagFileResponse(tmp_path / "test_file.txt")
+
+ client = TestClient(app)
+
+ test_file_path = Path(tmp_path / "test_file.txt")
+ with open(test_file_path, "w") as f:
+ f.write("This is a test file.")
+
+ response = client.get("/")
+ assert response.status_code == 200
+ assert response.headers["Etag"] is not None
+
+ etag = response.headers["Etag"]
+ response = client.get("/", headers={"if-none-match": etag})
+ assert response.status_code == 304
diff --git a/backend/src/tests/frontend/test_manifest.py b/backend/src/tests/frontend/test_manifest.py
new file mode 100644
index 000000000..9bd0e96d8
--- /dev/null
+++ b/backend/src/tests/frontend/test_manifest.py
@@ -0,0 +1,47 @@
+"""Module for testing the Manifest class."""
+
+from kwai.frontend.manifest import Manifest
+
+
+def test_load_manifest_from_string():
+ """Test loading the manifest from a string."""
+ manifest = Manifest.load_from_string(
+ """
+ {
+ "src/index.ts": {
+ "isEntry": true,
+ "file": "assets/index-8a61960c.js",
+ "src": "src/index.ts"
+ }
+ }
+ """
+ )
+ assert len(manifest.chunks) > 0, "There should be a chunk in the manifest."
+ assert manifest.has_chunk("src/index.ts") is not None, "The chunk should exist."
+ assert manifest.get_chunk("src/index.ts") is not None, "The chunk should exist."
+
+
+def test_chunks(manifest: Manifest):
+ """Test the chunks property."""
+ chunks = manifest.chunks
+ assert len(chunks) > 0, "There should be chunks in the manifest."
+
+
+def test_has_chunk(manifest: Manifest):
+ """Test the has_chunk method."""
+ assert manifest.has_chunk("src/index.ts") is True, "The chunk should exist."
+ assert manifest.has_chunk("images/hero.jpg") is True, "The chunk should exist."
+
+
+def test_chunk(manifest: Manifest):
+ """Test the get_chunk method."""
+ chunk = manifest.get_chunk("src/index.ts")
+ assert chunk is not None, "The chunk should exist."
+ assert chunk.src == "src/index.ts", "The src should be 'src/index.ts'"
+ assert chunk.file == "assets/index-533fa9ea.js"
+ assert len(chunk.imports) > 0
+ assert chunk.entry is True
+ assert len(chunk.assets) > 0
+ assert len(chunk.css) > 0
+ assert len(chunk.dynamic_imports) > 0
+ assert chunk.dynamic_entry is False
diff --git a/backend/src/tests/frontend/test_production_vite.py b/backend/src/tests/frontend/test_production_vite.py
new file mode 100644
index 000000000..027e8a85d
--- /dev/null
+++ b/backend/src/tests/frontend/test_production_vite.py
@@ -0,0 +1,69 @@
+"""Module for testing the production vite class."""
+
+from pathlib import Path
+
+import pytest
+
+from kwai.frontend.vite import ProductionVite, Vite
+
+
+@pytest.fixture
+def vite(manifest_path: Path, tmp_path: Path) -> Vite:
+ """A fixture for vite production."""
+ vite = ProductionVite(manifest_path, tmp_path)
+ vite.init("src/index.ts")
+ return vite
+
+
+def test_production_vite_scripts(vite: Vite):
+ """Test the production version of the Vite class for script tags."""
+ scripts = vite.get_scripts("http://localhost:8000/apps/portal/")
+ assert len(scripts) == 1, "There should be one script tag"
+ assert scripts[0] == "http://localhost:8000/apps/portal/assets/index-533fa9ea.js"
+
+
+def test_production_vite_css(vite: Vite):
+ """Test the production of the Vite class for css tags."""
+ css = vite.get_css("")
+ assert len(css) == 1, "There should be a css link"
+ assert css[0] == "assets/index-ace45c09.css"
+
+
+def test_production_vite_preload(vite: Vite):
+ """Test the production version of the Vite class for preload tags."""
+ preload = vite.get_preloads("")
+ assert len(preload) == 1, "There should be a preload"
+ assert preload[0] == "assets/vendor-97e41b2b.js"
+
+
+def test_production_vite_get_asset_path(vite: Vite, tmp_path: Path):
+ """Test getting the path of an asset."""
+ dist_path = tmp_path / "dist"
+ dist_path.mkdir(exist_ok=True)
+ with open(dist_path / "test_file.txt", "w") as f:
+ f.write("This is a test file.")
+
+ asset_file = vite.get_asset_path(Path("test_file.txt"))
+ assert asset_file is not None
+
+
+def test_production_vite_get_public_path(vite: Vite, tmp_path: Path):
+ """Test getting the path of a public file."""
+ dist_path = tmp_path / "dist"
+ dist_path.mkdir(exist_ok=True)
+ with open(dist_path / "test_file.txt", "w") as f:
+ f.write("This is a test file.")
+
+ asset_file = vite.get_asset_path(Path("test_file.txt"))
+ assert asset_file is not None
+
+
+def test_production_vite_get_asset_path_with_relative(vite: Vite, tmp_path: Path):
+ """Test if a relative path fails."""
+ dist_path = tmp_path / "dist"
+ dist_path.mkdir(exist_ok=True)
+ with open(dist_path / "test_file.txt", "w") as f:
+ f.write("This is a test file.")
+
+ asset_file = vite.get_asset_path(Path("../../test_file.txt"))
+ assert asset_file is None
diff --git a/backend/src/tests/modules/club/conftest.py b/backend/src/tests/modules/club/conftest.py
index 4824b39d3..f79f4fa28 100644
--- a/backend/src/tests/modules/club/conftest.py
+++ b/backend/src/tests/modules/club/conftest.py
@@ -1,6 +1,7 @@
-"""Module for defining common fixtures for testing code related to members."""
+"""Module for common fixtures used for testing code of the club module."""
from tests.fixtures.club.countries import * # noqa
from tests.fixtures.club.contacts import * # noqa
from tests.fixtures.club.persons import * # noqa
from tests.fixtures.club.members import * # noqa
+from tests.fixtures.club.coaches import * # noqa
diff --git a/backend/src/tests/modules/club/domain/__init__.py b/backend/src/tests/modules/club/domain/__init__.py
new file mode 100644
index 000000000..b862f7c7d
--- /dev/null
+++ b/backend/src/tests/modules/club/domain/__init__.py
@@ -0,0 +1 @@
+"""Package for testing the club domain package."""
diff --git a/backend/src/tests/modules/club/members/test_birthdate.py b/backend/src/tests/modules/club/domain/test_birthdate.py
similarity index 92%
rename from backend/src/tests/modules/club/members/test_birthdate.py
rename to backend/src/tests/modules/club/domain/test_birthdate.py
index d22d22af6..272cd2e99 100644
--- a/backend/src/tests/modules/club/members/test_birthdate.py
+++ b/backend/src/tests/modules/club/domain/test_birthdate.py
@@ -3,7 +3,7 @@
import pendulum
from kwai.core.domain.value_objects.date import Date
-from kwai.modules.club.members.value_objects import Birthdate
+from kwai.modules.club.domain.value_objects import Birthdate
def test_age():
diff --git a/backend/src/tests/modules/club/members/test_contact.py b/backend/src/tests/modules/club/domain/test_contact.py
similarity index 87%
rename from backend/src/tests/modules/club/members/test_contact.py
rename to backend/src/tests/modules/club/domain/test_contact.py
index 2d0735faa..80ebcf4fe 100644
--- a/backend/src/tests/modules/club/members/test_contact.py
+++ b/backend/src/tests/modules/club/domain/test_contact.py
@@ -3,9 +3,9 @@
import pytest
from kwai.core.domain.value_objects.email_address import EmailAddress
-from kwai.modules.club.members.contact import ContactEntity
-from kwai.modules.club.members.country import CountryEntity, CountryIdentifier
-from kwai.modules.club.members.value_objects import Address
+from kwai.modules.club.domain.contact import ContactEntity
+from kwai.modules.club.domain.country import CountryEntity, CountryIdentifier
+from kwai.modules.club.domain.value_objects import Address
@pytest.fixture
diff --git a/backend/src/tests/modules/club/repositories/__init__.py b/backend/src/tests/modules/club/repositories/__init__.py
new file mode 100644
index 000000000..b36b28844
--- /dev/null
+++ b/backend/src/tests/modules/club/repositories/__init__.py
@@ -0,0 +1 @@
+"""Package for testing the club repositories."""
diff --git a/backend/src/tests/modules/club/members/data/flemish_members_test.csv b/backend/src/tests/modules/club/repositories/data/flemish_members_test.csv
similarity index 100%
rename from backend/src/tests/modules/club/members/data/flemish_members_test.csv
rename to backend/src/tests/modules/club/repositories/data/flemish_members_test.csv
diff --git a/backend/src/tests/modules/club/repositories/test_coach_db_repository.py b/backend/src/tests/modules/club/repositories/test_coach_db_repository.py
new file mode 100644
index 000000000..b3ab0c46c
--- /dev/null
+++ b/backend/src/tests/modules/club/repositories/test_coach_db_repository.py
@@ -0,0 +1,12 @@
+"""Module for testing the coach database repository."""
+
+import pytest
+
+pytestmark = pytest.mark.db
+
+
+async def test_create_coach(make_coach_in_db, make_member_in_db):
+ """Test creating a coach."""
+ coach = await make_coach_in_db()
+ assert coach is not None, "There should be a coach."
+ assert coach.id is not None, "Coach id should be provided."
diff --git a/backend/src/tests/modules/club/members/test_contact_db_repository.py b/backend/src/tests/modules/club/repositories/test_contact_db_repository.py
similarity index 92%
rename from backend/src/tests/modules/club/members/test_contact_db_repository.py
rename to backend/src/tests/modules/club/repositories/test_contact_db_repository.py
index 39f7b2d08..b42c360dc 100644
--- a/backend/src/tests/modules/club/members/test_contact_db_repository.py
+++ b/backend/src/tests/modules/club/repositories/test_contact_db_repository.py
@@ -5,8 +5,8 @@
from kwai.core.db.database import Database
from kwai.core.db.uow import UnitOfWork
from kwai.core.domain.entity import Entity
-from kwai.modules.club.members.contact_db_repository import ContactDbRepository
-from kwai.modules.club.members.contact_repository import (
+from kwai.modules.club.repositories.contact_db_repository import ContactDbRepository
+from kwai.modules.club.repositories.contact_repository import (
ContactNotFoundException,
ContactRepository,
)
diff --git a/backend/src/tests/modules/club/members/test_country_db_repository.py b/backend/src/tests/modules/club/repositories/test_country_db_repository.py
similarity index 86%
rename from backend/src/tests/modules/club/members/test_country_db_repository.py
rename to backend/src/tests/modules/club/repositories/test_country_db_repository.py
index ae594a096..e101e7519 100644
--- a/backend/src/tests/modules/club/members/test_country_db_repository.py
+++ b/backend/src/tests/modules/club/repositories/test_country_db_repository.py
@@ -3,9 +3,9 @@
import pytest
from kwai.core.db.database import Database
-from kwai.modules.club.members.country import CountryEntity
-from kwai.modules.club.members.country_db_repository import CountryDbRepository
-from kwai.modules.club.members.country_repository import (
+from kwai.modules.club.domain.country import CountryEntity
+from kwai.modules.club.repositories.country_db_repository import CountryDbRepository
+from kwai.modules.club.repositories.country_repository import (
CountryNotFoundException,
CountryRepository,
)
diff --git a/backend/src/tests/modules/club/members/test_file_upload_db_repository.py b/backend/src/tests/modules/club/repositories/test_file_upload_db_repository.py
similarity index 75%
rename from backend/src/tests/modules/club/members/test_file_upload_db_repository.py
rename to backend/src/tests/modules/club/repositories/test_file_upload_db_repository.py
index 797285b59..376f84813 100644
--- a/backend/src/tests/modules/club/members/test_file_upload_db_repository.py
+++ b/backend/src/tests/modules/club/repositories/test_file_upload_db_repository.py
@@ -4,8 +4,10 @@
from kwai.core.db.database import Database
from kwai.core.domain.value_objects.owner import Owner
-from kwai.modules.club.members.file_upload import FileUploadEntity
-from kwai.modules.club.members.file_upload_db_repository import FileUploadDbRepository
+from kwai.modules.club.domain.file_upload import FileUploadEntity
+from kwai.modules.club.repositories.file_upload_db_repository import (
+ FileUploadDbRepository,
+)
pytestmark = pytest.mark.db
diff --git a/backend/src/tests/modules/club/members/test_flemish_member_importer.py b/backend/src/tests/modules/club/repositories/test_flemish_member_importer.py
similarity index 79%
rename from backend/src/tests/modules/club/members/test_flemish_member_importer.py
rename to backend/src/tests/modules/club/repositories/test_flemish_member_importer.py
index 6eb572298..d80b78ecc 100644
--- a/backend/src/tests/modules/club/members/test_flemish_member_importer.py
+++ b/backend/src/tests/modules/club/repositories/test_flemish_member_importer.py
@@ -6,10 +6,10 @@
from kwai.core.db.database import Database
from kwai.core.domain.value_objects.owner import Owner
-from kwai.modules.club.members.country_db_repository import CountryDbRepository
-from kwai.modules.club.members.flemish_member_importer import FlemishMemberImporter
-from kwai.modules.club.members.member_importer import Result
-from kwai.modules.club.members.value_objects import Gender
+from kwai.modules.club.domain.value_objects import Gender
+from kwai.modules.club.repositories.country_db_repository import CountryDbRepository
+from kwai.modules.club.repositories.flemish_member_importer import FlemishMemberImporter
+from kwai.modules.club.repositories.member_importer import Result
pytestmark = pytest.mark.db
diff --git a/backend/src/tests/modules/club/members/test_member_db_query.py b/backend/src/tests/modules/club/repositories/test_member_db_query.py
similarity index 89%
rename from backend/src/tests/modules/club/members/test_member_db_query.py
rename to backend/src/tests/modules/club/repositories/test_member_db_query.py
index 37db0a439..cc02cb6ea 100644
--- a/backend/src/tests/modules/club/members/test_member_db_query.py
+++ b/backend/src/tests/modules/club/repositories/test_member_db_query.py
@@ -4,9 +4,9 @@
from kwai.core.db.database import Database
from kwai.core.domain.value_objects.unique_id import UniqueId
-from kwai.modules.club.members.member import MemberIdentifier
-from kwai.modules.club.members.member_db_query import MemberDbQuery
-from kwai.modules.club.members.member_query import MemberQuery
+from kwai.modules.club.domain.member import MemberIdentifier
+from kwai.modules.club.repositories.member_db_query import MemberDbQuery
+from kwai.modules.club.repositories.member_query import MemberQuery
pytestmark = pytest.mark.db
diff --git a/backend/src/tests/modules/club/members/test_member_db_repository.py b/backend/src/tests/modules/club/repositories/test_member_db_repository.py
similarity index 62%
rename from backend/src/tests/modules/club/members/test_member_db_repository.py
rename to backend/src/tests/modules/club/repositories/test_member_db_repository.py
index a1c461224..6405571ba 100644
--- a/backend/src/tests/modules/club/members/test_member_db_repository.py
+++ b/backend/src/tests/modules/club/repositories/test_member_db_repository.py
@@ -5,8 +5,10 @@
from kwai.core.db.database import Database
from kwai.core.db.uow import UnitOfWork
from kwai.core.domain.entity import Entity
-from kwai.modules.club.members.member_db_repository import MemberDbRepository
-from kwai.modules.club.members.member_repository import (
+from kwai.core.domain.value_objects.owner import Owner
+from kwai.modules.club.domain.file_upload import FileUploadEntity, FileUploadIdentifier
+from kwai.modules.club.repositories.member_db_repository import MemberDbRepository
+from kwai.modules.club.repositories.member_repository import (
MemberNotFoundException,
MemberRepository,
)
@@ -57,3 +59,29 @@ async def test_delete(
await member_repo.delete(member)
with pytest.raises(MemberNotFoundException):
await member_repo.get(member_repo.create_query().filter_by_id(member.id))
+
+
+async def test_activate_members(
+ member_repo: MemberRepository, database: Database, owner: Owner
+):
+ """Test activate members."""
+ async with UnitOfWork(database):
+ upload_entity = FileUploadEntity(
+ id_=FileUploadIdentifier(1),
+ filename="test.txt",
+ owner=owner,
+ )
+ await member_repo.activate_members(upload_entity)
+
+
+async def test_deactivate_members(
+ member_repo: MemberRepository, database: Database, owner: Owner
+):
+ """Test activate members."""
+ async with UnitOfWork(database):
+ upload_entity = FileUploadEntity(
+ id_=FileUploadIdentifier(1),
+ filename="test.txt",
+ owner=owner,
+ )
+ await member_repo.deactivate_members(upload_entity)
diff --git a/backend/src/tests/modules/club/members/test_person_db_repository.py b/backend/src/tests/modules/club/repositories/test_person_db_repository.py
similarity index 92%
rename from backend/src/tests/modules/club/members/test_person_db_repository.py
rename to backend/src/tests/modules/club/repositories/test_person_db_repository.py
index 40885d214..77a29a884 100644
--- a/backend/src/tests/modules/club/members/test_person_db_repository.py
+++ b/backend/src/tests/modules/club/repositories/test_person_db_repository.py
@@ -5,8 +5,8 @@
from kwai.core.db.database import Database
from kwai.core.db.uow import UnitOfWork
from kwai.core.domain.entity import Entity
-from kwai.modules.club.members.person_db_repository import PersonDbRepository
-from kwai.modules.club.members.person_repository import (
+from kwai.modules.club.repositories.person_db_repository import PersonDbRepository
+from kwai.modules.club.repositories.person_repository import (
PersonNotFoundException,
PersonRepository,
)
diff --git a/backend/src/tests/modules/club/test_get_member.py b/backend/src/tests/modules/club/test_get_member.py
index 5ddf16454..7df4a25ba 100644
--- a/backend/src/tests/modules/club/test_get_member.py
+++ b/backend/src/tests/modules/club/test_get_member.py
@@ -3,9 +3,28 @@
import pytest
from kwai.core.db.database import Database
+from kwai.core.domain.presenter import Presenter
+from kwai.modules.club.domain.member import MemberEntity
from kwai.modules.club.get_member import GetMember, GetMemberCommand
-from kwai.modules.club.members.member_db_repository import MemberDbRepository
-from kwai.modules.club.members.member_repository import MemberRepository
+from kwai.modules.club.repositories.member_db_repository import MemberDbRepository
+from kwai.modules.club.repositories.member_repository import MemberRepository
+
+
+class TestPresenter(Presenter[MemberEntity]):
+ """A dummy presenter for checking the use case result."""
+
+ def __init__(self):
+ super().__init__()
+ self._entity = None
+
+ @property
+ def entity(self):
+ """Return the entity."""
+ return self._entity
+
+ def present(self, use_case_result: MemberEntity) -> None:
+ """Process the result of the use case."""
+ self._entity = use_case_result
@pytest.fixture
@@ -17,6 +36,8 @@ def member_repo(database: Database) -> MemberRepository:
async def test_get_member(member_repo: MemberRepository, make_member_in_db):
"""Test the get member use case."""
member = await make_member_in_db()
+ presenter = TestPresenter()
command = GetMemberCommand(uuid=str(member.uuid))
- result = await GetMember(member_repo).execute(command)
- assert result.uuid == member.uuid, "The member should be found"
+ await GetMember(member_repo, presenter).execute(command)
+ assert presenter.entity is not None, "The member should exist"
+ assert presenter.entity.uuid == member.uuid, "The member should be found"
diff --git a/backend/src/tests/modules/club/test_get_members.py b/backend/src/tests/modules/club/test_get_members.py
index 9d29f7210..8b7a00ad4 100644
--- a/backend/src/tests/modules/club/test_get_members.py
+++ b/backend/src/tests/modules/club/test_get_members.py
@@ -3,11 +3,30 @@
import pytest
from kwai.core.db.database import Database
+from kwai.core.domain.presenter import AsyncPresenter, IterableResult
from kwai.core.domain.value_objects.date import Date
+from kwai.modules.club.domain.member import MemberEntity
+from kwai.modules.club.domain.value_objects import License
from kwai.modules.club.get_members import GetMembers, GetMembersCommand
-from kwai.modules.club.members.member_db_repository import MemberDbRepository
-from kwai.modules.club.members.member_repository import MemberRepository
-from kwai.modules.club.members.value_objects import License
+from kwai.modules.club.repositories.member_db_repository import MemberDbRepository
+from kwai.modules.club.repositories.member_repository import MemberRepository
+
+
+class DummyPresenter(AsyncPresenter[IterableResult[MemberEntity]]):
+ """A dummy presenter for checking the use case result."""
+
+ def __init__(self):
+ super().__init__()
+ self._count = 0
+
+ @property
+ def count(self):
+ """Return count."""
+ return self._count
+
+ async def present(self, use_case_result: IterableResult[MemberEntity]) -> None:
+ """Process the result of the use case."""
+ self._count += 1
@pytest.fixture
@@ -20,8 +39,9 @@ async def test_get_members(member_repo: MemberRepository, make_member_in_db):
"""Test get members."""
await make_member_in_db()
command = GetMembersCommand()
- result = await GetMembers(member_repo).execute(command)
- assert result.count > 0, "There should be at least one member"
+ presenter = DummyPresenter()
+ await GetMembers(member_repo, presenter).execute(command)
+ assert presenter.count > 0, "There should be at least one member"
async def test_get_members_with_license_date(
@@ -35,8 +55,9 @@ async def test_get_members_with_license_date(
)
)
command = GetMembersCommand(license_end_year=2023, license_end_month=2)
- result = await GetMembers(member_repo).execute(command)
- assert result.count == 1, "There should only be one member"
+ presenter = DummyPresenter()
+ await GetMembers(member_repo, presenter).execute(command)
+ assert presenter.count == 1, "There should only be one member"
async def test_get_all_members(
@@ -50,5 +71,6 @@ async def test_get_all_members(
)
)
command = GetMembersCommand(active=False)
- result = await GetMembers(member_repo).execute(command)
- assert result.count > 0, "There should be at least one inactive member"
+ presenter = DummyPresenter()
+ await GetMembers(member_repo, presenter).execute(command)
+ assert presenter.count > 0, "There should be at least one inactive member"
diff --git a/backend/src/tests/modules/club/test_import_members.py b/backend/src/tests/modules/club/test_import_members.py
index ceceaca0b..b9aa474bf 100644
--- a/backend/src/tests/modules/club/test_import_members.py
+++ b/backend/src/tests/modules/club/test_import_members.py
@@ -3,24 +3,51 @@
from pathlib import Path
from kwai.core.db.database import Database
+from kwai.core.domain.presenter import Presenter
from kwai.core.domain.value_objects.owner import Owner
from kwai.modules.club.import_members import ImportMembers, ImportMembersCommand
-from kwai.modules.club.members.country_db_repository import CountryDbRepository
-from kwai.modules.club.members.file_upload_db_repository import FileUploadDbRepository
-from kwai.modules.club.members.flemish_member_importer import FlemishMemberImporter
-from kwai.modules.club.members.member_db_repository import MemberDbRepository
+from kwai.modules.club.repositories.country_db_repository import CountryDbRepository
+from kwai.modules.club.repositories.file_upload_db_repository import (
+ FileUploadDbRepository,
+)
+from kwai.modules.club.repositories.flemish_member_importer import FlemishMemberImporter
+from kwai.modules.club.repositories.member_db_repository import MemberDbRepository
+
+
+class DummyPresenter[MemberImportResult](Presenter):
+ """A dummy presenter."""
+
+ def __init__(self):
+ super().__init__()
+ self._count = 0
+
+ @property
+ def count(self):
+ """Return the count."""
+ return self._count
+
+ def present(self, use_case_result: MemberImportResult) -> None:
+ """Process the result of the use case."""
+ self._count += 1
async def test_import_members(database: Database, owner: Owner):
"""Test the use case Import Members."""
- filename = Path(__file__).parent / "members" / "data" / "flemish_members_test.csv"
+ filename = (
+ Path(__file__).parent / "repositories" / "data" / "flemish_members_test.csv"
+ )
importer = FlemishMemberImporter(
str(filename), owner, CountryDbRepository(database)
)
command = ImportMembersCommand()
- async for result in ImportMembers(
- importer, FileUploadDbRepository(database), MemberDbRepository(database)
- ).execute(command):
- assert result.file_upload is not None, "There should be a fileupload result"
+ presenter = DummyPresenter()
+ await ImportMembers(
+ importer,
+ FileUploadDbRepository(database),
+ MemberDbRepository(database),
+ presenter,
+ ).execute(command)
+
+ assert presenter.count > 0, "There should be a member uploaded."
diff --git a/backend/src/tests/modules/identity/tokens/conftest.py b/backend/src/tests/modules/identity/tokens/conftest.py
index e59dfc783..06215103f 100644
--- a/backend/src/tests/modules/identity/tokens/conftest.py
+++ b/backend/src/tests/modules/identity/tokens/conftest.py
@@ -1,9 +1,9 @@
"""Module that defines fixtures for testing identity tokens."""
-from datetime import datetime
import pytest
from kwai.core.db.database import Database
+from kwai.core.domain.value_objects.timestamp import Timestamp
from kwai.modules.identity.tokens.access_token import (
AccessTokenEntity,
)
@@ -33,7 +33,7 @@ async def access_token(
"""Fixture for creating an access token."""
token = AccessTokenEntity(
identifier=TokenIdentifier.generate(),
- expiration=datetime.utcnow(),
+ expiration=Timestamp.create_now(),
user_account=user_account,
)
@@ -53,7 +53,7 @@ async def refresh_token(
"""Fixture for creating a refresh token."""
token = RefreshTokenEntity(
identifier=TokenIdentifier.generate(),
- expiration=datetime.utcnow(),
+ expiration=Timestamp.create_now(),
access_token=access_token,
)
return await refresh_token_repo.create(token)
diff --git a/backend/src/tests/modules/identity/tokens/test_access_token.py b/backend/src/tests/modules/identity/tokens/test_access_token.py
index 16b21da4b..d82507c42 100644
--- a/backend/src/tests/modules/identity/tokens/test_access_token.py
+++ b/backend/src/tests/modules/identity/tokens/test_access_token.py
@@ -1,9 +1,9 @@
"""Module for testing the access token entity."""
-from datetime import datetime
from kwai.core.domain.value_objects.email_address import EmailAddress
from kwai.core.domain.value_objects.name import Name
from kwai.core.domain.value_objects.password import Password
+from kwai.core.domain.value_objects.timestamp import Timestamp
from kwai.core.domain.value_objects.unique_id import UniqueId
from kwai.modules.identity.tokens.access_token import AccessTokenEntity
from kwai.modules.identity.tokens.token_identifier import TokenIdentifier
@@ -23,7 +23,7 @@ def test_create():
)
token = AccessTokenEntity(
identifier=TokenIdentifier.generate(),
- expiration=datetime.utcnow(),
+ expiration=Timestamp.create_now(),
user_account=account,
)
diff --git a/backend/src/tests/modules/identity/user_recoveries/test_user_recovery_db_repository.py b/backend/src/tests/modules/identity/user_recoveries/test_user_recovery_db_repository.py
index b1ae88ebf..912097e8f 100644
--- a/backend/src/tests/modules/identity/user_recoveries/test_user_recovery_db_repository.py
+++ b/backend/src/tests/modules/identity/user_recoveries/test_user_recovery_db_repository.py
@@ -1,7 +1,5 @@
"""Module that defines tests for user recovery database."""
-from datetime import datetime
-
import pytest
from kwai.core.db.database import Database
@@ -31,7 +29,7 @@ async def user_recovery(
) -> UserRecoveryEntity:
"""Fixture for creating a user recovery entity."""
user_recovery = UserRecoveryEntity(
- expiration=Timestamp(timestamp=datetime.utcnow()),
+ expiration=Timestamp.create_now(),
user=user,
)
return await repo.create(user_recovery)
diff --git a/backend/src/tests/modules/identity/user_recoveries/test_user_recovery_mailer.py b/backend/src/tests/modules/identity/user_recoveries/test_user_recovery_mailer.py
index bb36356aa..c2fa072af 100644
--- a/backend/src/tests/modules/identity/user_recoveries/test_user_recovery_mailer.py
+++ b/backend/src/tests/modules/identity/user_recoveries/test_user_recovery_mailer.py
@@ -1,7 +1,5 @@
"""Module with tests for the user recovery mailer."""
-from datetime import datetime
-
import pytest
from kwai.core.domain.value_objects.email_address import EmailAddress
@@ -23,7 +21,7 @@
def user_recovery() -> UserRecoveryEntity:
"""Fixture creating a user recovery entity."""
return UserRecoveryEntity(
- expiration=Timestamp(timestamp=datetime.utcnow()),
+ expiration=Timestamp.create_now(),
user=UserEntity(
email=EmailAddress("jigoro.kano@kwai.com"),
name=Name(first_name="Jigoro", last_name="Kano"),
diff --git a/backend/src/tests/modules/teams/__init__.py b/backend/src/tests/modules/teams/__init__.py
new file mode 100644
index 000000000..f2ba449e1
--- /dev/null
+++ b/backend/src/tests/modules/teams/__init__.py
@@ -0,0 +1 @@
+"""Package for testing the teams module."""
diff --git a/backend/src/tests/modules/teams/conftest.py b/backend/src/tests/modules/teams/conftest.py
new file mode 100644
index 000000000..ce1a6084e
--- /dev/null
+++ b/backend/src/tests/modules/teams/conftest.py
@@ -0,0 +1,36 @@
+"""Module for common fixtures used for testing code of the club module."""
+
+import pytest
+
+from kwai.core.domain.presenter import Presenter
+from kwai.modules.teams.domain.team import TeamEntity
+from tests.fixtures.club.coaches import * # noqa
+from tests.fixtures.club.contacts import * # noqa
+from tests.fixtures.club.countries import * # noqa
+from tests.fixtures.club.members import * # noqa
+from tests.fixtures.club.persons import * # noqa
+from tests.fixtures.teams.team_members import * # noqa
+from tests.fixtures.teams.teams import * # noqa
+
+
+class DummyPresenter(Presenter[TeamEntity]):
+ """A dummy presenter for checking the use case result."""
+
+ def __init__(self):
+ super().__init__()
+ self._entity = None
+
+ @property
+ def entity(self):
+ """Return the entity."""
+ return self._entity
+
+ def present(self, use_case_result: TeamEntity) -> None:
+ """Process the result of the use case."""
+ self._entity = use_case_result
+
+
+@pytest.fixture
+def team_presenter() -> DummyPresenter:
+ """A fixture for a team presenter."""
+ return DummyPresenter()
diff --git a/backend/src/tests/modules/teams/domain/__init__.py b/backend/src/tests/modules/teams/domain/__init__.py
new file mode 100644
index 000000000..216cf9d5b
--- /dev/null
+++ b/backend/src/tests/modules/teams/domain/__init__.py
@@ -0,0 +1 @@
+"""Package for testing teams domain models."""
diff --git a/backend/src/tests/modules/teams/repositories/__init__.py b/backend/src/tests/modules/teams/repositories/__init__.py
new file mode 100644
index 000000000..2dde9a550
--- /dev/null
+++ b/backend/src/tests/modules/teams/repositories/__init__.py
@@ -0,0 +1 @@
+"""Package for testing the repositories of the teams module."""
diff --git a/backend/src/tests/modules/teams/repositories/test_member_db_query.py b/backend/src/tests/modules/teams/repositories/test_member_db_query.py
new file mode 100644
index 000000000..5b00e7704
--- /dev/null
+++ b/backend/src/tests/modules/teams/repositories/test_member_db_query.py
@@ -0,0 +1,73 @@
+"""Module for testing the team member query for a database."""
+
+import pytest
+
+from kwai.core.db.database import Database
+from kwai.core.domain.value_objects.date import Date
+from kwai.core.domain.value_objects.unique_id import UniqueId
+from kwai.modules.teams.domain.team import TeamIdentifier
+from kwai.modules.teams.domain.team_member import MemberIdentifier
+from kwai.modules.teams.repositories.member_db_repository import MemberDbQuery
+from kwai.modules.teams.repositories.member_repository import MemberQuery
+
+pytestmark = pytest.mark.db
+
+
+@pytest.fixture
+def query(database: Database) -> MemberQuery:
+ """A fixture for a team member query."""
+ return MemberDbQuery(database)
+
+
+async def test_filter_by_id(query: MemberQuery):
+ """Test filtering by id."""
+ query.filter_by_id(MemberIdentifier(1))
+ try:
+ await query.fetch_one()
+ except Exception as exc:
+ pytest.fail(f"An exception occurred: {exc}")
+
+
+async def test_filter_by_uuid(query: MemberQuery):
+ """Test filtering by uuid."""
+ query.filter_by_uuid(UniqueId.generate())
+ try:
+ await query.fetch_one()
+ except Exception as exc:
+ pytest.fail(f"An exception occurred: {exc}")
+
+
+async def test_filter_by_birthdate_without_end_date(query: MemberQuery):
+ """Test filtering by birthdate."""
+ query.filter_by_birthdate(Date.create(2015, 1, 1))
+ try:
+ await query.fetch_one()
+ except Exception as exc:
+ pytest.fail(f"An exception occurred: {exc}")
+
+
+async def test_filter_by_birthdate(query: MemberQuery):
+ """Test filtering by birthdate between two dates."""
+ query.filter_by_birthdate(Date.create(2015, 1, 1), Date.create(2015, 1, 31))
+ try:
+ await query.fetch_one()
+ except Exception as exc:
+ pytest.fail(f"An exception occurred: {exc}")
+
+
+async def test_filter_by_team(query: MemberQuery):
+ """Test filtering by not part of the team."""
+ query.filter_by_team(TeamIdentifier(1))
+ try:
+ await query.fetch_one()
+ except Exception as exc:
+ pytest.fail(f"An exception occurred: {exc}")
+
+
+async def test_filter_by_not_in_team(query: MemberQuery):
+ """Test filtering by not part of the team."""
+ query.filter_by_team(TeamIdentifier(1))
+ try:
+ await query.fetch_one()
+ except Exception as exc:
+ pytest.fail(f"An exception occurred: {exc}")
diff --git a/backend/src/tests/modules/teams/repositories/test_member_db_repository.py b/backend/src/tests/modules/teams/repositories/test_member_db_repository.py
new file mode 100644
index 000000000..8826da3c4
--- /dev/null
+++ b/backend/src/tests/modules/teams/repositories/test_member_db_repository.py
@@ -0,0 +1,94 @@
+"""Module for testing the team member repository for a database."""
+
+import pytest
+
+from kwai.core.db.database import Database
+from kwai.core.domain.value_objects.date import Date
+from kwai.modules.club.domain.value_objects import Birthdate
+from kwai.modules.teams.repositories.member_db_repository import (
+ MemberDbRepository,
+)
+
+pytestmark = pytest.mark.db
+
+
+async def test_get_all(database: Database, make_member_in_db):
+ """Test getting all members."""
+ member = await make_member_in_db()
+ repo = MemberDbRepository(database)
+ members = {member.id: member async for member in repo.get_all()}
+ assert members is not None
+ assert member.id in members, "The member should be returned."
+
+
+async def test_get_by_id(database: Database, make_member_in_db):
+ """Test get member by its ids."""
+ member = await make_member_in_db()
+ repo = MemberDbRepository(database)
+ query = repo.create_query()
+ query.filter_by_id(member.id)
+ member = await repo.get(query)
+ assert member is not None
+
+
+async def test_get_by_birthdate(
+ database: Database,
+ make_member,
+ make_member_in_db,
+ make_person_in_db,
+ make_person,
+ make_contact_in_db,
+ make_country_in_db,
+ country_japan,
+):
+ """Test get a member by its birthdate."""
+ birthdate = Birthdate(Date.create(year=2000, month=12, day=31))
+ await make_member_in_db(
+ make_member(
+ person=await make_person_in_db(
+ make_person(
+ birthdate=birthdate,
+ contact=await make_contact_in_db(),
+ nationality=await make_country_in_db(country_japan),
+ )
+ )
+ )
+ )
+
+ repo = MemberDbRepository(database)
+ query = repo.create_query()
+ query.filter_by_birthdate(birthdate.date)
+ member = await repo.get(query)
+ assert member is not None
+
+
+async def test_get_by_birthdate_between_dates(
+ database: Database,
+ make_member,
+ make_member_in_db,
+ make_person_in_db,
+ make_person,
+ make_contact_in_db,
+ make_country_in_db,
+ country_japan,
+):
+ """Test get a member by its birthdate between two dates."""
+ birthdate = Birthdate(Date.create(year=1990, month=1, day=1))
+ await make_member_in_db(
+ make_member(
+ person=await make_person_in_db(
+ make_person(
+ birthdate=birthdate,
+ contact=await make_contact_in_db(),
+ nationality=await make_country_in_db(country_japan),
+ )
+ )
+ )
+ )
+ repo = MemberDbRepository(database)
+ query = repo.create_query()
+ start_date = Date.create(year=1990, month=1, day=1)
+ end_date = Date.create(year=1990, month=12, day=31)
+ query.filter_by_birthdate(start_date, end_date)
+ member = await repo.get(query)
+ assert member is not None
diff --git a/backend/src/tests/modules/teams/repositories/test_team_db_repository.py b/backend/src/tests/modules/teams/repositories/test_team_db_repository.py
new file mode 100644
index 000000000..ec5120ede
--- /dev/null
+++ b/backend/src/tests/modules/teams/repositories/test_team_db_repository.py
@@ -0,0 +1,64 @@
+"""Module for testing the team db repository."""
+
+import pytest
+
+from kwai.core.db.database import Database
+from kwai.core.domain.entity import Entity
+from kwai.modules.teams.repositories.team_db_repository import TeamDbRepository
+from kwai.modules.teams.repositories.team_repository import TeamNotFoundException
+
+pytestmark = pytest.mark.db
+
+
+async def test_create_team(make_team_in_db):
+ """Test creating a team in the database."""
+ team = await make_team_in_db()
+ assert team is not None, "There should be a team in the database."
+
+
+async def test_get_team(database: Database, make_team_in_db):
+ """Test getting a team from the database."""
+ team = await make_team_in_db()
+ repo = TeamDbRepository(database)
+ team = await repo.get(repo.create_query().filter_by_id(team.id))
+ assert team is not None, "There should be a team in the database."
+
+
+async def test_get_all_teams(database: Database):
+ """Test getting all teams in the database."""
+ teams_iterator = TeamDbRepository(database).get_all()
+ assert teams_iterator is not None, "There should be a team in the database."
+ assert (
+ await anext(teams_iterator) is not None
+ ), "There should be a team in the database."
+
+
+async def test_delete_team(database: Database, make_team_in_db):
+ """Test deleting a team in the database."""
+ team_repo = TeamDbRepository(database)
+ team = await make_team_in_db()
+ await team_repo.delete(team)
+
+ with pytest.raises(TeamNotFoundException):
+ await team_repo.get(team_repo.create_query().filter_by_id(team.id))
+
+
+async def test_update_team(database: Database, make_team_in_db):
+ """Test updating a team in the database."""
+ team_repo = TeamDbRepository(database)
+ team = await make_team_in_db()
+
+ team = Entity.replace(team, remark="This is a test.")
+ await team_repo.update(team)
+
+ team = await team_repo.get(team_repo.create_query().filter_by_id(team.id))
+ assert team.remark == "This is a test.", "The team should be updated."
+
+
+async def test_add_team_member(database: Database, make_team_in_db, make_team_member):
+ """Test adding a team member to a team."""
+ team_repo = TeamDbRepository(database)
+ team = await make_team_in_db()
+ team_member = make_team_member()
+
+ await team_repo.add_team_member(team, team_member)
diff --git a/backend/src/tests/modules/teams/repositories/test_team_member_db_query.py b/backend/src/tests/modules/teams/repositories/test_team_member_db_query.py
new file mode 100644
index 000000000..c4884bd1a
--- /dev/null
+++ b/backend/src/tests/modules/teams/repositories/test_team_member_db_query.py
@@ -0,0 +1,22 @@
+"""Module for testing the TeamMemberDbQuery class."""
+
+import pytest
+
+from kwai.core.db.database import Database
+from kwai.modules.teams.domain.team import TeamIdentifier
+from kwai.modules.teams.repositories.team_member_db_query import TeamMemberDbQuery
+
+
+@pytest.fixture
+def query(database: Database) -> TeamMemberDbQuery:
+ """A fixture for a team member database query."""
+ return TeamMemberDbQuery(database)
+
+
+async def test_filter_by_teams(query: TeamMemberDbQuery):
+ """Test filter by teams."""
+ query.filter_by_teams(TeamIdentifier(1))
+ try:
+ await query.fetch_team_members()
+ except Exception as exc:
+ pytest.fail(f"An exception occurred: f{exc}")
diff --git a/backend/src/tests/modules/teams/test_create_team.py b/backend/src/tests/modules/teams/test_create_team.py
new file mode 100644
index 000000000..a92f74c68
--- /dev/null
+++ b/backend/src/tests/modules/teams/test_create_team.py
@@ -0,0 +1,21 @@
+"""Module that tests the Create Team use case."""
+
+import pytest
+
+from kwai.core.db.database import Database
+from kwai.modules.teams.create_team import CreateTeam, CreateTeamCommand
+from kwai.modules.teams.repositories.team_db_repository import TeamDbRepository
+
+pytestmark = pytest.mark.db
+
+
+async def test_create_team(database: Database, make_team, team_presenter) -> None:
+ """Test the use case 'Create Team'."""
+ team = make_team()
+ command = CreateTeamCommand(
+ name=team.name,
+ active=team.is_active,
+ remark=team.remark,
+ )
+ await CreateTeam(TeamDbRepository(database), team_presenter).execute((command))
+ assert team_presenter.entity is not None, "The team should be created"
diff --git a/backend/src/tests/modules/teams/test_create_team_member.py b/backend/src/tests/modules/teams/test_create_team_member.py
new file mode 100644
index 000000000..90aca808b
--- /dev/null
+++ b/backend/src/tests/modules/teams/test_create_team_member.py
@@ -0,0 +1,58 @@
+"""Module for testing the use case 'Create Team Member."""
+
+import pytest
+
+from kwai.core.db.database import Database
+from kwai.core.domain.presenter import Presenter
+from kwai.modules.teams.create_team_member import (
+ CreateTeamMember,
+ CreateTeamMemberCommand,
+)
+from kwai.modules.teams.domain.team import TeamEntity
+from kwai.modules.teams.domain.team_member import TeamMember
+from kwai.modules.teams.repositories.member_db_repository import MemberDbRepository
+from kwai.modules.teams.repositories.team_db_repository import TeamDbRepository
+
+pytestmark = pytest.mark.db
+
+
+class DummyPresenter(Presenter[tuple[TeamMember, TeamEntity]]):
+ """A dummy presenter for checking the use case result."""
+
+ def __init__(self):
+ super().__init__()
+ self._team_member = None
+ self._team = None
+
+ @property
+ def team(self) -> TeamEntity:
+ """Return the team entity."""
+ return self._team
+
+ @property
+ def team_member(self) -> TeamMember:
+ """Return the team member."""
+ return self._team_member
+
+ def present(self, use_case_result: tuple[TeamMember, TeamEntity]) -> None:
+ """Handle use case result."""
+ self._team_member = use_case_result[0]
+ self._team = use_case_result[1]
+
+
+async def test_create_team_member(
+ database: Database, make_team_in_db, make_team_member_in_db
+) -> None:
+ """Test the use case 'Create Team Member'."""
+ presenter = DummyPresenter()
+ team = await make_team_in_db()
+ team_member = await make_team_member_in_db()
+
+ command = CreateTeamMemberCommand(
+ team_id=team.id.value, member_id=str(team_member.member.uuid)
+ )
+ await CreateTeamMember(
+ TeamDbRepository(database), MemberDbRepository(database), presenter
+ ).execute(command)
+ assert presenter.team is not None, "The team should be available"
+ assert presenter.team_member is not None, "There should be a member"
diff --git a/backend/src/tests/modules/teams/test_delete_team.py b/backend/src/tests/modules/teams/test_delete_team.py
new file mode 100644
index 000000000..0c9a61857
--- /dev/null
+++ b/backend/src/tests/modules/teams/test_delete_team.py
@@ -0,0 +1,21 @@
+"""Module for testing the Delete Team use case."""
+
+import pytest
+
+from kwai.core.db.database import Database
+from kwai.modules.teams.delete_team import DeleteTeam, DeleteTeamCommand
+from kwai.modules.teams.repositories.team_db_repository import TeamDbRepository
+from kwai.modules.teams.repositories.team_repository import TeamNotFoundException
+
+pytestmark = pytest.mark.db
+
+
+async def test_delete_team(database: Database, make_team_in_db):
+ """Test deleting a team."""
+ team = await make_team_in_db()
+ command = DeleteTeamCommand(id=team.id.value)
+ team_repo = TeamDbRepository(database)
+ await DeleteTeam(team_repo).execute(command)
+
+ with pytest.raises(TeamNotFoundException):
+ await team_repo.get(team_repo.create_query().filter_by_id(team.id))
diff --git a/backend/src/tests/modules/teams/test_get_members.py b/backend/src/tests/modules/teams/test_get_members.py
new file mode 100644
index 000000000..077d4829e
--- /dev/null
+++ b/backend/src/tests/modules/teams/test_get_members.py
@@ -0,0 +1,61 @@
+"""Module for testing the use case 'Get Team Members'."""
+
+import pytest
+
+from kwai.core.db.database import Database
+from kwai.core.domain.presenter import AsyncPresenter, IterableResult
+from kwai.modules.teams.domain.team_member import MemberEntity
+from kwai.modules.teams.get_members import GetMembers, GetMembersCommand
+from kwai.modules.teams.repositories.member_db_repository import MemberDbRepository
+
+pytestmark = pytest.mark.db
+
+
+class DummyPresenter(AsyncPresenter[IterableResult[MemberEntity]]):
+ """A dummy presenter for checking the use case result."""
+
+ def __init__(self):
+ super().__init__()
+ self._count = 0
+
+ @property
+ def count(self):
+ """Return the count."""
+ return self._count
+
+ async def present(self, use_case_result: IterableResult[MemberEntity]) -> None:
+ """Count the number of members."""
+ async for _ in use_case_result.iterator:
+ self._count += 1
+
+
+@pytest.fixture
+def team_member_presenter() -> DummyPresenter:
+ """A fixture for a team member presenter."""
+ return DummyPresenter()
+
+
+async def test_get_members_not_in_team(
+ database: Database, make_team_in_db, make_member_in_db, team_member_presenter
+):
+ """Test get team members."""
+ team = await make_team_in_db()
+ await make_member_in_db()
+ command = GetMembersCommand(team_id=team.id.value, in_team=False)
+ await GetMembers(MemberDbRepository(database), team_member_presenter).execute(
+ command
+ )
+ assert team_member_presenter.count > 0
+
+
+async def test_get_members_in_team(
+ database: Database, make_team_in_db, make_team_member_in_db, team_member_presenter
+):
+ """Test get team members from a team."""
+ team = await make_team_in_db()
+ await make_team_member_in_db(team=team)
+ command = GetMembersCommand(team_id=team.id.value)
+ await GetMembers(MemberDbRepository(database), team_member_presenter).execute(
+ command
+ )
+ assert team_member_presenter.count == 1
diff --git a/backend/src/tests/modules/teams/test_get_team.py b/backend/src/tests/modules/teams/test_get_team.py
new file mode 100644
index 000000000..e8c82800a
--- /dev/null
+++ b/backend/src/tests/modules/teams/test_get_team.py
@@ -0,0 +1,18 @@
+"""Module for defining tests for the use case 'Get Teams'."""
+
+import pytest
+
+from kwai.core.db.database import Database
+from kwai.modules.teams.get_team import GetTeam, GetTeamCommand
+from kwai.modules.teams.repositories.team_db_repository import TeamDbRepository
+
+pytestmark = pytest.mark.db
+
+
+async def test_get_teams(database: Database, make_team_in_db, team_presenter):
+ """Test get teams."""
+ team = await make_team_in_db()
+ command = GetTeamCommand(id=team.id.value)
+ await GetTeam(TeamDbRepository(database), team_presenter).execute(command)
+ assert team_presenter.entity is not None, "The team should exist"
+ assert team_presenter.entity.id == team.id, "The team should be found"
diff --git a/backend/src/tests/modules/teams/test_get_teams.py b/backend/src/tests/modules/teams/test_get_teams.py
new file mode 100644
index 000000000..bccef39b0
--- /dev/null
+++ b/backend/src/tests/modules/teams/test_get_teams.py
@@ -0,0 +1,39 @@
+"""Module for defining tests for the use case 'Get Teams'."""
+
+import pytest
+
+from kwai.core.db.database import Database
+from kwai.core.domain.presenter import AsyncPresenter, IterableResult
+from kwai.modules.teams.domain.team import TeamEntity
+from kwai.modules.teams.get_teams import GetTeams, GetTeamsCommand
+from kwai.modules.teams.repositories.team_db_repository import TeamDbRepository
+
+pytestmark = pytest.mark.db
+
+
+class DummyPresenter(AsyncPresenter[IterableResult[TeamEntity]]):
+ """A dummy presenter for checking the use case result."""
+
+ def __init__(self):
+ super().__init__()
+ self._count = 0
+
+ @property
+ def count(self):
+ """Return the count."""
+ return self._count
+
+ async def present(self, use_case_result: IterableResult[TeamEntity]) -> None:
+ """Count the teams."""
+ async for _ in use_case_result.iterator:
+ self._count += 1
+
+
+async def test_get_teams(database: Database, make_team_in_db):
+ """Test get teams."""
+ await make_team_in_db()
+ command = GetTeamsCommand()
+ presenter = DummyPresenter()
+ await GetTeams(TeamDbRepository(database), presenter).execute(command)
+ print(presenter.count)
+ assert presenter.count > 0, "There should be at least one team."
diff --git a/backend/src/tests/modules/teams/test_update_team.py b/backend/src/tests/modules/teams/test_update_team.py
new file mode 100644
index 000000000..5f88cce41
--- /dev/null
+++ b/backend/src/tests/modules/teams/test_update_team.py
@@ -0,0 +1,24 @@
+"""Module for testing the 'Update Team' use case."""
+
+import pytest
+
+from kwai.core.db.database import Database
+from kwai.modules.teams.repositories.team_db_repository import TeamDbRepository
+from kwai.modules.teams.update_team import UpdateTeam, UpdateTeamCommand
+
+pytestmark = pytest.mark.db
+
+
+async def test_update_team(database: Database, make_team_in_db, team_presenter):
+ """Test the use case 'Update Team'."""
+ team = await make_team_in_db()
+ command = UpdateTeamCommand(
+ id=team.id.value,
+ name=team.name,
+ active=team.is_active,
+ remark="This is a test.",
+ )
+ await UpdateTeam(TeamDbRepository(database), team_presenter).execute(command)
+ assert (
+ team_presenter.entity.remark == "This is a test."
+ ), "The team should be updated."
diff --git a/backend/src/tests/modules/training/coaches/test_coaches_db_repository.py b/backend/src/tests/modules/training/coaches/test_coaches_db_repository.py
index aabcc80a1..402ca72ed 100644
--- a/backend/src/tests/modules/training/coaches/test_coaches_db_repository.py
+++ b/backend/src/tests/modules/training/coaches/test_coaches_db_repository.py
@@ -1,40 +1,38 @@
"""Module for testing the coach database repository."""
+
import pytest
from kwai.core.db.database import Database
from kwai.core.db.exceptions import QueryException
-from kwai.modules.training.coaches.coach import CoachIdentifier
from kwai.modules.training.coaches.coach_db_repository import CoachDbRepository
-from kwai.modules.training.coaches.coach_repository import CoachNotFoundException
-async def test_get_by_id(database: Database):
+async def test_get_by_id(database: Database, make_coach_in_db):
"""Test get_by_id method."""
+ coach = await make_coach_in_db()
repo = CoachDbRepository(database)
try:
- await repo.get_by_id(CoachIdentifier(1))
- except CoachNotFoundException:
- pass # Ok
+ await repo.get_by_id(coach.id)
except QueryException as qe:
pytest.fail(str(qe))
-async def test_get_by_ids(database: Database):
+async def test_get_by_ids(database: Database, make_coach_in_db):
"""Test get_by_ids method."""
repo = CoachDbRepository(database)
+ coach_1 = await make_coach_in_db()
+ coach_2 = await make_coach_in_db()
try:
- {
- coach.id: coach
- async for coach in repo.get_by_ids(CoachIdentifier(1), CoachIdentifier(2))
- }
+ {coach.id: coach async for coach in repo.get_by_ids(coach_1.id, coach_2.id)}
except QueryException as qe:
pytest.fail(str(qe))
-async def test_get_all(database: Database):
+async def test_get_all(database: Database, make_coach_in_db):
"""Test get_all method."""
+ await make_coach_in_db()
repo = CoachDbRepository(database)
try:
diff --git a/backend/src/tests/modules/training/conftest.py b/backend/src/tests/modules/training/conftest.py
index f1384b1a4..48c653366 100644
--- a/backend/src/tests/modules/training/conftest.py
+++ b/backend/src/tests/modules/training/conftest.py
@@ -1,125 +1,10 @@
"""Module with fixtures for the training bounded context."""
-import dataclasses
-from collections import defaultdict
-from datetime import datetime, time
-from typing import Any
-
-import pytest
-
-from kwai.core.db.database import Database
-from kwai.core.domain.value_objects.owner import Owner
-from kwai.core.domain.value_objects.period import Period
-from kwai.core.domain.value_objects.text import DocumentFormat, Locale, LocaleText
-from kwai.core.domain.value_objects.time_period import TimePeriod
-from kwai.core.domain.value_objects.timestamp import Timestamp
-from kwai.core.domain.value_objects.weekday import Weekday
-from kwai.modules.training.coaches.coach_tables import (
- CoachesTable,
- CoachRow,
- PersonRow,
- PersonsTable,
-)
-from kwai.modules.training.teams.team_tables import TeamRow, TeamsTable
-from kwai.modules.training.trainings.training import TrainingEntity
-from kwai.modules.training.trainings.training_definition import TrainingDefinitionEntity
-
-Context = dict[str, list[Any]]
-
-
-@pytest.fixture(scope="module")
-def context() -> Context:
- """A fixture for creating a context.
-
- This context is a dictionary for collecting data.
- """
- return defaultdict(list)
-
-
-@pytest.fixture(scope="module")
-def person_row() -> PersonRow:
- """Fixture for creating a person row."""
- return PersonRow(id=0, firstname="Jigoro", lastname="Kano")
-
-
-@pytest.fixture(scope="module", autouse=True)
-async def seed_persons(database: Database, person_row: PersonRow, context: Context):
- """Seed the database with persons."""
- # For now, we create the query, in the future a repository from the members
- # bounded context can be used.
- query = database.create_query_factory().insert(PersonsTable.table_name)
- person_dict = dataclasses.asdict(person_row)
- del person_dict["id"]
- person_dict["gender"] = 1
- person_dict["birthdate"] = datetime(year=1860, month=12, day=10)
- person_dict["nationality_id"] = 1
- query.columns(*person_dict.keys()).values(*person_dict.values())
- context["persons"].append(
- dataclasses.replace(person_row, id=await database.execute(query))
- )
- await database.commit()
-
-
-@pytest.fixture(scope="module")
-def coach_row(seed_persons, context: Context) -> CoachRow:
- """Fixture for creating a coach row."""
- return CoachRow(id=0, person_id=context["persons"][0].id, active=True)
-
-
-@pytest.fixture(scope="module", autouse=True)
-async def seed_coaches(database: Database, coach_row: CoachRow, context: Context):
- """Seed the database with coaches."""
- query = database.create_query_factory().insert(CoachesTable.table_name)
- coach_dict = dataclasses.asdict(coach_row)
- del coach_dict["id"]
- query.columns(*coach_dict.keys()).values(*coach_dict.values())
- context["coaches"].append(
- dataclasses.replace(coach_row, id=await database.execute(query))
- )
- await database.commit()
-
-
-@pytest.fixture(scope="module", autouse=True)
-async def seed_teams(database: Database, context: Context):
- """Seed the database with teams."""
- query = database.create_query_factory().insert(TeamsTable.table_name)
- team_row = TeamRow(id=0, name="U18")
- team_dict = dataclasses.asdict(team_row)
- del team_dict["id"]
- query.columns(*team_dict.keys()).values(*team_dict.values())
- context["teams"].append(
- dataclasses.replace(team_row, id=await database.execute(query))
- )
- await database.commit()
-
-
-@pytest.fixture
-async def training_entity(owner: Owner) -> TrainingEntity:
- """A fixture for a training entity."""
- start_date = Timestamp.create_now()
- training = TrainingEntity(
- texts=[
- LocaleText(
- locale=Locale.NL,
- format=DocumentFormat.MARKDOWN,
- title="Test Training",
- content="This is a test training",
- summary="This is a test training",
- author=owner,
- )
- ],
- period=Period(start_date=start_date, end_date=start_date.add_delta(hours=1)),
- )
- return training
-
-
-@pytest.fixture
-async def training_definition(owner: Owner) -> TrainingDefinitionEntity:
- """A fixture for a training definition entity."""
- return TrainingDefinitionEntity(
- name="U11 Training Monday",
- description="Training for U11 on each monday",
- weekday=Weekday.MONDAY,
- owner=owner,
- period=TimePeriod(start=time(hour=20), end=time(hour=21)),
- )
+from tests.fixtures.club.coaches import * # noqa
+from tests.fixtures.club.contacts import * # noqa
+from tests.fixtures.club.countries import * # noqa
+from tests.fixtures.club.members import * # noqa
+from tests.fixtures.club.persons import * # noqa
+from tests.fixtures.teams.teams import * # noqa
+from tests.fixtures.training.training_definitions import * # noqa
+from tests.fixtures.training.trainings import * # noqa
diff --git a/backend/src/tests/modules/training/teams/test_team_db_repository.py b/backend/src/tests/modules/training/teams/test_team_db_repository.py
index 68e69e9b3..d87e8b089 100644
--- a/backend/src/tests/modules/training/teams/test_team_db_repository.py
+++ b/backend/src/tests/modules/training/teams/test_team_db_repository.py
@@ -1,4 +1,5 @@
"""Module for testing the team database repository."""
+
import pytest
from kwai.core.db.database import Database
diff --git a/backend/src/tests/modules/training/test_create_training.py b/backend/src/tests/modules/training/test_create_training.py
index 1944ed699..783651e79 100644
--- a/backend/src/tests/modules/training/test_create_training.py
+++ b/backend/src/tests/modules/training/test_create_training.py
@@ -6,11 +6,10 @@
from kwai.core.domain.use_case import TextCommand
from kwai.core.domain.value_objects.owner import Owner
from kwai.core.domain.value_objects.timestamp import Timestamp
-from kwai.modules.training.coaches.coach import CoachEntity, CoachIdentifier
+from kwai.modules.training.coaches.coach import CoachEntity
from kwai.modules.training.coaches.coach_db_repository import CoachDbRepository
from kwai.modules.training.coaches.coach_repository import CoachRepository
from kwai.modules.training.create_training import CreateTraining, CreateTrainingCommand
-from kwai.modules.training.teams.team import TeamEntity, TeamIdentifier
from kwai.modules.training.teams.team_db_repository import TeamDbRepository
from kwai.modules.training.teams.team_repository import TeamRepository
from kwai.modules.training.training_command import Coach
@@ -22,7 +21,6 @@
TrainingDefinitionRepository,
)
from kwai.modules.training.trainings.training_repository import TrainingRepository
-from tests.modules.training.conftest import Context
@pytest.fixture
@@ -50,25 +48,16 @@ def team_repo(database: Database) -> TeamRepository:
@pytest.fixture
-async def coach(
- database: Database, context: Context, coach_repo: CoachRepository
-) -> CoachEntity:
+async def coach(make_coach_in_db) -> CoachEntity:
"""A fixture for a coach."""
- return await coach_repo.get_by_id(CoachIdentifier(context.get("coaches")[0].id))
+ return await make_coach_in_db()
@pytest.fixture
-async def team(
- database: Database, context: Context, team_repo: TeamRepository
-) -> TeamEntity:
- """A fixture for a team repository."""
- teams_iterator = team_repo.get_by_ids(TeamIdentifier(context.get("teams")[0].id))
- return await anext(teams_iterator)
-
-
-@pytest.fixture
-async def command(coach: CoachEntity, team: TeamEntity) -> CreateTrainingCommand:
+async def command(make_coach_in_db, make_team_in_db) -> CreateTrainingCommand:
"""A fixture for a training entity."""
+ coach = await make_coach_in_db()
+ team = await make_team_in_db()
start_date = Timestamp.create_now()
return CreateTrainingCommand(
start_date=str(start_date),
diff --git a/backend/src/tests/modules/training/test_create_training_definition.py b/backend/src/tests/modules/training/test_create_training_definition.py
index c7425d4f4..43158fe8b 100644
--- a/backend/src/tests/modules/training/test_create_training_definition.py
+++ b/backend/src/tests/modules/training/test_create_training_definition.py
@@ -31,8 +31,9 @@ def team_repo(database: Database) -> TeamRepository:
@pytest.fixture
-def command():
+async def command(make_team_in_db):
"""A fixture for a create command."""
+ team = await make_team_in_db()
return CreateTrainingDefinitionCommand(
name="U11 Monday Training",
description="Training for U11 on Monday",
@@ -43,7 +44,7 @@ def command():
active=True,
location="Sports Hall",
remark="Test",
- team_id=None,
+ team_id=team.id.value,
)
diff --git a/backend/src/tests/modules/training/test_delete_training.py b/backend/src/tests/modules/training/test_delete_training.py
index 6434430e5..979726474 100644
--- a/backend/src/tests/modules/training/test_delete_training.py
+++ b/backend/src/tests/modules/training/test_delete_training.py
@@ -4,7 +4,6 @@
from kwai.core.db.database import Database
from kwai.modules.training.delete_training import DeleteTraining, DeleteTrainingCommand
-from kwai.modules.training.trainings.training import TrainingEntity
from kwai.modules.training.trainings.training_db_repository import TrainingDbRepository
from kwai.modules.training.trainings.training_repository import (
TrainingNotFoundException,
@@ -18,23 +17,14 @@ def training_repo(database: Database) -> TrainingRepository:
return TrainingDbRepository(database)
-@pytest.fixture
-async def saved_training_entity(
- training_repo: TrainingRepository, training_entity: TrainingEntity
-):
- """A fixture for a training in the repository."""
- return await training_repo.create(training_entity)
-
-
-async def test_delete_training(
- training_repo: TrainingRepository, saved_training_entity
-):
+async def test_delete_training(training_repo: TrainingRepository, make_training_in_db):
"""Test the use case "Delete Training"."""
- command = DeleteTrainingCommand(id=saved_training_entity.id.value)
+ training = await make_training_in_db()
+ command = DeleteTrainingCommand(id=training.id.value)
try:
await DeleteTraining(training_repo).execute(command)
except TrainingNotFoundException as ex:
pytest.fail(str(ex))
with pytest.raises(TrainingNotFoundException):
- await training_repo.get_by_id(saved_training_entity.id)
+ await training_repo.get_by_id(training.id)
diff --git a/backend/src/tests/modules/training/test_get_coaches.py b/backend/src/tests/modules/training/test_get_coaches.py
index a1fccfad1..4bf47a502 100644
--- a/backend/src/tests/modules/training/test_get_coaches.py
+++ b/backend/src/tests/modules/training/test_get_coaches.py
@@ -1,12 +1,18 @@
"""Module for testing the GetCoaches use case."""
+
from kwai.core.db.database import Database
from kwai.modules.training.coaches.coach_db_repository import CoachDbRepository
from kwai.modules.training.get_coaches import GetCoaches, GetCoachesCommand
-async def test_get_coaches(database: Database):
+async def test_get_coaches(database: Database, make_coach_in_db):
"""Test the get coaches use case."""
- coach_repo = CoachDbRepository(database)
+ coach = await make_coach_in_db()
+
command = GetCoachesCommand(active=True)
+ coach_repo = CoachDbRepository(database)
count, iterator = await GetCoaches(coach_repo).execute(command)
- assert count is not None, "There should be result"
+ assert count > 0, "There should be at least one result"
+
+ coaches = {coach.id: coach async for coach in iterator}
+ assert coach.id in coaches, "The coach should be retrieved"
diff --git a/backend/src/tests/modules/training/test_get_teams.py b/backend/src/tests/modules/training/test_get_teams.py
index d90d1ce4f..daef148bd 100644
--- a/backend/src/tests/modules/training/test_get_teams.py
+++ b/backend/src/tests/modules/training/test_get_teams.py
@@ -1,11 +1,14 @@
"""Module for tests of the get teams use case."""
+
from kwai.core.db.database import Database
from kwai.modules.training.get_teams import GetTeams
from kwai.modules.training.teams.team_db_repository import TeamDbRepository
-async def test_get_teams(database: Database):
+async def test_get_teams(database: Database, make_team_in_db):
"""Test use case get teams."""
- result = await GetTeams(TeamDbRepository(database)).execute()
- assert result is not None
- assert result.count > 0, "There should be a team"
+ team = await make_team_in_db()
+ count, iterator = await GetTeams(TeamDbRepository(database)).execute()
+ assert count > 0, "There should be a team"
+ teams = {team.id: team async for team in iterator}
+ assert team.id in teams, "The team should be in the result"
diff --git a/backend/src/tests/modules/training/test_get_training.py b/backend/src/tests/modules/training/test_get_training.py
index 0c61c0030..f20a228b2 100644
--- a/backend/src/tests/modules/training/test_get_training.py
+++ b/backend/src/tests/modules/training/test_get_training.py
@@ -1,11 +1,11 @@
"""Module for testing the use case "Get Training"."""
+
import pytest
from kwai.core.db.database import Database
from kwai.modules.training.get_training import GetTraining, GetTrainingCommand
from kwai.modules.training.trainings.training_db_repository import TrainingDbRepository
from kwai.modules.training.trainings.training_repository import (
- TrainingNotFoundException,
TrainingRepository,
)
@@ -16,11 +16,9 @@ def training_repo(database: Database) -> TrainingRepository:
return TrainingDbRepository(database)
-async def test_get_training(training_repo: TrainingRepository):
+async def test_get_training(training_repo: TrainingRepository, make_training_in_db):
"""Test the use case "Get Training"."""
- command = GetTrainingCommand(id=1)
- try:
- training = await GetTraining(training_repo).execute(command)
- assert training is not None, "There should be a training."
- except TrainingNotFoundException:
- pass
+ training = await make_training_in_db()
+ command = GetTrainingCommand(id=training.id.value)
+ training = await GetTraining(training_repo).execute(command)
+ assert training is not None, "There should be a training."
diff --git a/backend/src/tests/modules/training/test_get_training_definition.py b/backend/src/tests/modules/training/test_get_training_definition.py
index 059e8719b..9b3b4b8aa 100644
--- a/backend/src/tests/modules/training/test_get_training_definition.py
+++ b/backend/src/tests/modules/training/test_get_training_definition.py
@@ -1,4 +1,5 @@
"""Module for testing the use case "Get Training Definition"."""
+
import pytest
from kwai.core.db.database import Database
@@ -6,7 +7,6 @@
GetTrainingDefinition,
GetTrainingDefinitionCommand,
)
-from kwai.modules.training.trainings.training_definition import TrainingDefinitionEntity
from kwai.modules.training.trainings.training_definition_db_repository import (
TrainingDefinitionDbRepository,
)
@@ -21,21 +21,13 @@ def training_definition_repo(database: Database) -> TrainingDefinitionRepository
return TrainingDefinitionDbRepository(database)
-@pytest.fixture
-async def saved_training_definition(
- training_definition_repo: TrainingDefinitionRepository,
- training_definition: TrainingDefinitionEntity,
-) -> TrainingDefinitionEntity:
- """A fixture for a training definition in the database."""
- return await training_definition_repo.create(training_definition)
-
-
async def test_get_training_definition(
training_definition_repo: TrainingDefinitionRepository,
- saved_training_definition: TrainingDefinitionEntity,
+ make_training_definition_in_db,
):
"""Test a successful execution of the use case."""
- command = GetTrainingDefinitionCommand(id=saved_training_definition.id.value)
+ definition = await make_training_definition_in_db()
+ command = GetTrainingDefinitionCommand(id=definition.id.value)
training_definition = await GetTrainingDefinition(training_definition_repo).execute(
command
)
diff --git a/backend/src/tests/modules/training/test_get_training_definitions.py b/backend/src/tests/modules/training/test_get_training_definitions.py
index b872a3ecf..ef8ebebad 100644
--- a/backend/src/tests/modules/training/test_get_training_definitions.py
+++ b/backend/src/tests/modules/training/test_get_training_definitions.py
@@ -1,5 +1,4 @@
"""Module for testing the use case "Get Training Definitions"."""
-from typing import AsyncIterator
import pytest
@@ -10,7 +9,6 @@
)
from kwai.modules.training.trainings.training_definition import (
TrainingDefinitionEntity,
- TrainingDefinitionIdentifier,
)
from kwai.modules.training.trainings.training_definition_db_repository import (
TrainingDefinitionDbRepository,
@@ -20,14 +18,6 @@
)
-async def _find(iterator: AsyncIterator, id_: TrainingDefinitionIdentifier):
- """Search for an entity with the given id."""
- async for entity in iterator:
- if entity.id == id_:
- return entity
- return None
-
-
@pytest.fixture(scope="module")
def training_definition_repo(database: Database) -> TrainingDefinitionRepository:
"""A fixture for a training definition repository."""
@@ -45,14 +35,15 @@ async def saved_training_definition(
async def test_get_training_definitions(
training_definition_repo: TrainingDefinitionRepository,
- saved_training_definition: TrainingDefinitionEntity,
+ make_training_definition_in_db,
):
"""Test a successful execution of the use case."""
+ definition = await make_training_definition_in_db()
command = GetTrainingDefinitionsCommand()
count, iterator = await GetTrainingDefinitions(training_definition_repo).execute(
command
)
assert count >= 1, "There should be at least a training definition"
- entity = await _find(iterator, saved_training_definition.id)
- assert entity is not None, "The definition should be part of the data"
+ definitions = {definition.id: definition async for definition in iterator}
+ assert definition.id in definitions, "The definition should be part of the data"
diff --git a/backend/src/tests/modules/training/test_get_trainings.py b/backend/src/tests/modules/training/test_get_trainings.py
index 7ad9da7c4..521dff9c1 100644
--- a/backend/src/tests/modules/training/test_get_trainings.py
+++ b/backend/src/tests/modules/training/test_get_trainings.py
@@ -1,7 +1,10 @@
"""Module for testing the use case "Get Trainings"."""
+
import pytest
from kwai.core.db.database import Database
+from kwai.core.domain.value_objects.period import Period
+from kwai.core.domain.value_objects.timestamp import Timestamp
from kwai.modules.training.coaches.coach_db_repository import CoachDbRepository
from kwai.modules.training.coaches.coach_repository import CoachRepository
from kwai.modules.training.get_trainings import GetTrainings, GetTrainingsCommand
@@ -37,27 +40,36 @@ async def test_get_active_trainings(
training_repo: TrainingRepository,
coach_repo: CoachRepository,
definition_repo: TrainingDefinitionRepository,
+ make_training_in_db,
):
"""Test the use case "Get Trainings"."""
- command = GetTrainingsCommand(active=True, limit=10)
+ training = await make_training_in_db()
+ command = GetTrainingsCommand(active=True)
count, iterator = await GetTrainings(
training_repo, coach_repo, definition_repo
).execute(command)
- entities = {entity.id: entity async for entity in iterator}
+ assert count > 0, "There should be at least one active training"
- assert entities is not None, "There should be a result"
+ entities = {entity.id: entity async for entity in iterator}
+ assert training.id in entities, "The training should be returned"
async def test_get_year_month_trainings(
training_repo: TrainingRepository,
coach_repo: CoachRepository,
definition_repo: TrainingDefinitionRepository,
+ make_training_in_db,
+ make_training,
):
"""Test the use case "Get Trainings"."""
- command = GetTrainingsCommand(limit=10, year=2023, month=1)
+ start_date = Timestamp.create_from_string("2024-01-01 19:00:00")
+ training = await make_training_in_db(
+ make_training(period=Period.create_from_delta(start_date, hours=2))
+ )
+ command = GetTrainingsCommand(limit=10, year=2024, month=1)
count, iterator = await GetTrainings(
training_repo, coach_repo, definition_repo
).execute(command)
+ assert count > 0, "There should be at least one training in 01/2023."
entities = {entity.id: entity async for entity in iterator}
-
- assert entities is not None, "There should be a result"
+ assert training.id in entities, "The training should be returned in the result."
diff --git a/backend/src/tests/modules/training/test_update_training.py b/backend/src/tests/modules/training/test_update_training.py
index bc857841b..42b4ce277 100644
--- a/backend/src/tests/modules/training/test_update_training.py
+++ b/backend/src/tests/modules/training/test_update_training.py
@@ -5,17 +5,12 @@
from kwai.core.db.database import Database
from kwai.core.domain.use_case import TextCommand
from kwai.core.domain.value_objects.owner import Owner
-from kwai.core.domain.value_objects.period import Period
-from kwai.core.domain.value_objects.text import DocumentFormat, Locale, LocaleText
from kwai.core.domain.value_objects.timestamp import Timestamp
-from kwai.modules.training.coaches.coach import CoachEntity, CoachIdentifier
from kwai.modules.training.coaches.coach_db_repository import CoachDbRepository
from kwai.modules.training.coaches.coach_repository import CoachRepository
-from kwai.modules.training.teams.team import TeamEntity, TeamIdentifier
from kwai.modules.training.teams.team_db_repository import TeamDbRepository
from kwai.modules.training.teams.team_repository import TeamRepository
from kwai.modules.training.training_command import Coach
-from kwai.modules.training.trainings.training import TrainingEntity
from kwai.modules.training.trainings.training_db_repository import TrainingDbRepository
from kwai.modules.training.trainings.training_definition_db_repository import (
TrainingDefinitionDbRepository,
@@ -24,9 +19,7 @@
TrainingDefinitionRepository,
)
from kwai.modules.training.trainings.training_repository import TrainingRepository
-from kwai.modules.training.trainings.value_objects import TrainingCoach
from kwai.modules.training.update_training import UpdateTraining, UpdateTrainingCommand
-from tests.modules.training.conftest import Context
@pytest.fixture
@@ -53,71 +46,25 @@ def team_repo(database: Database) -> TeamRepository:
return TeamDbRepository(database)
-@pytest.fixture
-async def coach(
- database: Database, context: Context, coach_repo: CoachRepository
-) -> CoachEntity:
- """A fixture for a coach."""
- return await coach_repo.get_by_id(CoachIdentifier(context.get("coaches")[0].id))
-
-
-@pytest.fixture
-async def team(
- database: Database, context: Context, team_repo: TeamRepository
-) -> TeamEntity:
- """A fixture for a team repository."""
- teams_iterator = team_repo.get_by_ids(TeamIdentifier(context.get("teams")[0].id))
- return await anext(teams_iterator)
-
-
-@pytest.fixture
-async def training_entity(
- training_repo: TrainingRepository,
- coach: CoachEntity,
- team: TeamEntity,
- owner: Owner,
-) -> TrainingEntity:
- """A fixture for a training entity."""
- start_date = Timestamp.create_now()
- return await training_repo.create(
- TrainingEntity(
- texts=[
- LocaleText(
- locale=Locale.EN,
- format=DocumentFormat.MARKDOWN,
- title="Test training",
- content="This is a test",
- summary="This is a test",
- author=owner,
- )
- ],
- coaches=[TrainingCoach(coach=coach, owner=owner)],
- teams=[team],
- period=Period(
- start_date=start_date, end_date=start_date.add_delta(hours=1)
- ),
- )
- )
-
-
async def test_update_training(
- training_entity: TrainingEntity,
training_repo: TrainingRepository,
definition_repo: TrainingDefinitionRepository,
coach_repo: CoachRepository,
team_repo: TeamRepository,
+ make_training_in_db,
owner: Owner,
):
"""Test the use case "Update Training"."""
+ training = await make_training_in_db()
start_date = Timestamp.create_now().add_delta(hours=1)
end_date = start_date.add_delta(hours=1)
command = UpdateTrainingCommand(
- id=training_entity.id.value,
+ id=training.id.value,
start_date=str(start_date),
end_date=str(end_date),
- active=training_entity.active,
- cancelled=training_entity.cancelled,
- location=training_entity.location,
+ active=training.active,
+ cancelled=training.cancelled,
+ location=training.location,
texts=[
TextCommand(
locale="en",
@@ -130,14 +77,14 @@ async def test_update_training(
remark="This is a test",
coaches=[
Coach(
- id=training_coach.coach.id.value,
+ id=training.coaches[0].coach.id.value,
head=training_coach.type == 1,
present=training_coach.present,
payed=training_coach.payed,
)
- for training_coach in training_entity.coaches
+ for training_coach in training.coaches
],
- teams=[team.id.value for team in training_entity.teams],
+ teams=[team.id.value for team in training.teams],
definition=None,
)
@@ -146,3 +93,4 @@ async def test_update_training(
).execute(command)
assert training is not None, "There should be a training"
+ assert training.texts[0].title == "Updated Test Training"
diff --git a/backend/src/tests/modules/training/test_update_training_definition.py b/backend/src/tests/modules/training/test_update_training_definition.py
index 26bc27e65..340cd71f9 100644
--- a/backend/src/tests/modules/training/test_update_training_definition.py
+++ b/backend/src/tests/modules/training/test_update_training_definition.py
@@ -4,11 +4,8 @@
from kwai.core.db.database import Database
from kwai.core.domain.value_objects.owner import Owner
-from kwai.core.domain.value_objects.time_period import TimePeriod
-from kwai.core.domain.value_objects.weekday import Weekday
from kwai.modules.training.teams.team_db_repository import TeamDbRepository
from kwai.modules.training.teams.team_repository import TeamRepository
-from kwai.modules.training.trainings.training_definition import TrainingDefinitionEntity
from kwai.modules.training.trainings.training_definition_db_repository import (
TrainingDefinitionDbRepository,
)
@@ -33,40 +30,24 @@ def team_repo(database: Database) -> TeamRepository:
return TeamDbRepository(database)
-@pytest.fixture
-async def training_definition_entity(
- training_definition_repo: TrainingDefinitionRepository,
- owner: Owner,
-) -> TrainingDefinitionEntity:
- """A fixture for a training definition entity."""
- return await training_definition_repo.create(
- TrainingDefinitionEntity(
- name="U9 Training",
- description="Test Training Definition",
- weekday=Weekday.MONDAY,
- period=TimePeriod.create_from_string("19:00", "20:00"),
- owner=owner,
- )
- )
-
-
async def test_update_training_definition(
- training_definition_entity: TrainingDefinitionEntity,
training_definition_repo: TrainingDefinitionRepository,
team_repo: TeamRepository,
+ make_training_definition_in_db,
owner: Owner,
):
"""Test the use case "Update Training"."""
+ definition = await make_training_definition_in_db()
command = UpdateTrainingDefinitionCommand(
- id=training_definition_entity.id.value,
- name=training_definition_entity.name,
- description=training_definition_entity.description,
- weekday=training_definition_entity.weekday.value,
+ id=definition.id.value,
+ name=definition.name,
+ description=definition.description,
+ weekday=definition.weekday.value,
start_time="20:00",
end_time="21:00",
timezone="Europe/Brussels",
- active=training_definition_entity.active,
- location=training_definition_entity.location,
+ active=definition.active,
+ location=definition.location,
remark="This is an update test",
team_id=None,
)
diff --git a/backend/src/tests/modules/training/trainings/test_training_db_query.py b/backend/src/tests/modules/training/trainings/test_training_db_query.py
index b73153c18..180514988 100644
--- a/backend/src/tests/modules/training/trainings/test_training_db_query.py
+++ b/backend/src/tests/modules/training/trainings/test_training_db_query.py
@@ -1,5 +1,6 @@
"""Module for testing TrainingDbQuery."""
-from datetime import datetime, time, timedelta
+
+from datetime import time
import pytest
@@ -8,6 +9,7 @@
from kwai.core.domain.value_objects.name import Name
from kwai.core.domain.value_objects.owner import Owner
from kwai.core.domain.value_objects.time_period import TimePeriod
+from kwai.core.domain.value_objects.timestamp import Timestamp
from kwai.core.domain.value_objects.unique_id import UniqueId
from kwai.core.domain.value_objects.weekday import Weekday
from kwai.modules.training.coaches.coach import CoachEntity
@@ -52,7 +54,7 @@ async def test_filter_by_year_month(database: Database):
async def test_filter_by_dates(database: Database):
"""Test filtering on dates."""
query = TrainingDbQuery(database)
- query.filter_by_dates(datetime.utcnow(), datetime.utcnow() + timedelta(days=1))
+ query.filter_by_dates(Timestamp.create_now(), Timestamp.create_with_delta(days=1))
count = await query.count()
assert count >= 0, "There should be 0 or more trainings."
diff --git a/backend/src/tests/modules/training/trainings/test_training_db_repository.py b/backend/src/tests/modules/training/trainings/test_training_db_repository.py
index cb9b7ec84..17dc29a11 100644
--- a/backend/src/tests/modules/training/trainings/test_training_db_repository.py
+++ b/backend/src/tests/modules/training/trainings/test_training_db_repository.py
@@ -5,25 +5,10 @@
from kwai.core.db.database import Database
from kwai.core.db.exceptions import QueryException
from kwai.core.domain.entity import Entity
-from kwai.core.domain.value_objects.name import Name
-from kwai.core.domain.value_objects.owner import Owner
-from kwai.core.domain.value_objects.period import Period
-from kwai.core.domain.value_objects.text import DocumentFormat, Locale, LocaleText
-from kwai.modules.training.coaches.coach import CoachEntity, CoachIdentifier
-from kwai.modules.training.trainings.training import TrainingEntity
from kwai.modules.training.trainings.training_db_repository import TrainingDbRepository
-from kwai.modules.training.trainings.training_definition import TrainingDefinitionEntity
-from kwai.modules.training.trainings.training_definition_db_repository import (
- TrainingDefinitionDbRepository,
-)
-from kwai.modules.training.trainings.training_definition_repository import (
- TrainingDefinitionRepository,
-)
from kwai.modules.training.trainings.training_repository import (
TrainingRepository,
)
-from kwai.modules.training.trainings.value_objects import TrainingCoach
-from tests.modules.training.conftest import Context
pytestmark = pytest.mark.db
@@ -34,52 +19,15 @@ def repo(database: Database) -> TrainingRepository:
return TrainingDbRepository(database)
-@pytest.fixture(scope="module")
-def training(user, context: Context, owner: Owner) -> TrainingEntity:
- """A fixture for a training."""
- coach = context["coaches"][0]
- person = context["persons"][0]
-
- text = [
- LocaleText(
- locale=Locale.EN,
- format=DocumentFormat.MARKDOWN,
- title="Training U13",
- summary="Training for U13",
- content="",
- author=owner,
- )
- ]
- return TrainingEntity(
- texts=text,
- period=Period.create_from_delta(hours=1),
- coaches=[
- TrainingCoach(
- coach=CoachEntity(
- id_=CoachIdentifier(coach.id),
- name=Name(first_name=person.firstname, last_name=person.lastname),
- active=True,
- ),
- owner=owner,
- remark="Test Training Coach",
- )
- ],
- )
-
-
-async def test_create(
- repo: TrainingRepository, context: Context, training: TrainingEntity
-):
+async def test_create(make_training_in_db):
"""Test create a training."""
- new_training = await repo.create(training)
- assert new_training is not None, "There should be a training."
- context["trainings"] = [new_training]
+ training = await make_training_in_db()
+ assert training is not None, "There should be a training."
-async def test_update(repo: TrainingRepository, context: Context):
+async def test_update(repo: TrainingRepository, make_training_in_db):
"""Test update of a training."""
- assert len(context["trainings"]) > 0, "There should be a training"
- training = context["trainings"][0]
+ training = await make_training_in_db()
updated_training = Entity.replace(training, remark="This training is updated.")
try:
await repo.update(updated_training)
@@ -87,45 +35,31 @@ async def test_update(repo: TrainingRepository, context: Context):
pytest.fail(str(qe))
-async def test_get_all(repo: TrainingRepository):
+async def test_get_all(repo: TrainingRepository, make_training_in_db):
"""Test get all trainings."""
+ training = await make_training_in_db()
trainings = {entity.id: entity async for entity in repo.get_all()}
- assert trainings is not None, "There should be a result"
+ assert training.id in trainings, "The training should be returned in the list"
-async def test_get_by_id(repo: TrainingRepository, context: Context):
+async def test_get_by_id(repo: TrainingRepository, make_training_in_db):
"""Test get training by id."""
- assert len(context["trainings"]) > 0, "There should be a training"
- training = context["trainings"][0]
+ training = await make_training_in_db()
training = await repo.get_by_id(training.id)
assert training is not None, "There should be a result"
-async def test_delete(repo: TrainingRepository, context: Context):
+async def test_delete(repo: TrainingRepository, make_training_in_db):
"""Test delete of a training."""
- assert len(context["trainings"]) > 0, "There should be a training"
- training = context["trainings"][0]
+ training = await make_training_in_db()
try:
await repo.delete(training)
except QueryException as qe:
pytest.fail(str(qe))
-@pytest.fixture(scope="module")
-def training_definition_repo(database: Database) -> TrainingDefinitionRepository:
- """Fixture for a training definition repository."""
- return TrainingDefinitionDbRepository(database)
-
-
-@pytest.fixture
-async def saved_training_definition(
- training_definition_repo: TrainingDefinitionRepository,
- training_definition: TrainingDefinitionEntity,
-) -> TrainingDefinitionEntity:
- """A fixture for a training definition in the database."""
- return await training_definition_repo.create(training_definition)
-
-
-async def test_reset_definition(repo: TrainingRepository, saved_training_definition):
+async def test_reset_definition(database: Database, make_training_definition_in_db):
"""Test reset definition."""
- await repo.reset_definition(saved_training_definition, False)
+ definition = await make_training_definition_in_db()
+ repo = TrainingDbRepository(database)
+ await repo.reset_definition(definition, False)
diff --git a/backend/src/tests/modules/training/trainings/test_training_definition_db_repository.py b/backend/src/tests/modules/training/trainings/test_training_definition_db_repository.py
index c4181f600..2f687687f 100644
--- a/backend/src/tests/modules/training/trainings/test_training_definition_db_repository.py
+++ b/backend/src/tests/modules/training/trainings/test_training_definition_db_repository.py
@@ -3,78 +3,69 @@
import pytest
from kwai.core.db.database import Database
+from kwai.core.db.exceptions import QueryException
from kwai.core.domain.entity import Entity
-from kwai.modules.training.trainings.training_definition import (
- TrainingDefinitionEntity,
-)
from kwai.modules.training.trainings.training_definition_db_repository import (
TrainingDefinitionDbRepository,
)
from kwai.modules.training.trainings.training_definition_repository import (
TrainingDefinitionNotFoundException,
- TrainingDefinitionRepository,
)
pytestmark = pytest.mark.db
-@pytest.fixture(scope="module")
-def repo(database: Database) -> TrainingDefinitionRepository:
- """Fixture for a training definition repository."""
- return TrainingDefinitionDbRepository(database)
-
-
-@pytest.fixture
-async def saved_training_definition(
- repo: TrainingDefinitionRepository,
- training_definition: TrainingDefinitionEntity,
-) -> TrainingDefinitionEntity:
- """A fixture for a training definition in the database."""
- return await repo.create(training_definition)
-
-
-def test_create(saved_training_definition: TrainingDefinitionEntity):
+async def test_create(make_training_definition_in_db):
"""Test if the training definition was created."""
- assert (
- not saved_training_definition.id.is_empty()
- ), "There should be a training definition created"
+ definition = await make_training_definition_in_db()
+ assert definition is not None, "There should be a training definition created"
async def test_get_by_id(
- repo: TrainingDefinitionRepository,
- saved_training_definition: TrainingDefinitionEntity,
+ database: Database,
+ make_training_definition_in_db,
):
"""Test if the training definition can be found with the id."""
- entity = await repo.get_by_id(saved_training_definition.id)
+ repo = TrainingDefinitionDbRepository(database)
+ definition = await make_training_definition_in_db()
+ entity = await repo.get_by_id(definition.id)
- assert (
- entity.id == saved_training_definition.id
- ), "The training definition should be found"
+ assert entity.id == definition.id, "The training definition should be found"
-async def test_get_all(repo: TrainingDefinitionRepository):
+async def test_get_all(
+ database: Database,
+ make_training_definition_in_db,
+):
"""Test if all training definitions can be loaded."""
+ repo = TrainingDefinitionDbRepository(database)
+ definition = await make_training_definition_in_db()
entities = {entity.id: entity async for entity in repo.get_all()}
- assert entities is not None, "There should be a result"
+ assert definition.id in entities, "Definition should be in the list."
async def test_update(
- repo: TrainingDefinitionRepository,
- saved_training_definition: TrainingDefinitionEntity,
+ database: Database,
+ make_training_definition_in_db,
):
"""Test update of training definition."""
- training_definition = Entity.replace(
- saved_training_definition, remark="Training definition updated"
- )
- await repo.update(training_definition)
+ repo = TrainingDefinitionDbRepository(database)
+ definition = await make_training_definition_in_db()
+ definition = Entity.replace(definition, remark="Training definition updated")
+ try:
+ await repo.update(definition)
+ except QueryException as qe:
+ pytest.fail(str(qe))
async def test_delete(
- repo: TrainingDefinitionRepository,
- saved_training_definition: TrainingDefinitionEntity,
+ database: Database,
+ make_training_definition_in_db,
):
"""Test if the training definition can be deleted."""
- await repo.delete(saved_training_definition)
+ repo = TrainingDefinitionDbRepository(database)
+ definition = await make_training_definition_in_db()
+ await repo.delete(definition)
with pytest.raises(TrainingDefinitionNotFoundException):
- await repo.get_by_id(saved_training_definition.id)
+ await repo.get_by_id(definition.id)
diff --git a/backend/templates/index.jinja2 b/backend/templates/index.jinja2
new file mode 100644
index 000000000..b1d1a4483
--- /dev/null
+++ b/backend/templates/index.jinja2
@@ -0,0 +1,22 @@
+
+{% do vite.init("src/index.ts") %}
+
+
+
+
+ Portal
+ {% for preload in vite.get_preloads(application.url) %}
+
+ {% endfor %}
+ {% for css in vite.get_css(application.url) %}
+
+ {% endfor %}
+
+
+
+
+ {% for js in vite.get_scripts(application.url) %}
+
+ {% endfor %}
+
+
diff --git a/backend/vagrant/test/Vagrant.provision.sh b/backend/vagrant/test/Vagrant.provision.sh
index 5efe1d090..186829bbf 100644
--- a/backend/vagrant/test/Vagrant.provision.sh
+++ b/backend/vagrant/test/Vagrant.provision.sh
@@ -109,8 +109,8 @@ TEST_SCRIPT=$(cat < "$VAGRANT_HOME/kwai_test.sh"
diff --git a/docs/index.md b/docs/index.md
index 251462e03..82788acb3 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,14 +1,21 @@
# KWAI
> The sports club management system.
+KWAI is a project for managing a sports club.
+
+!!! note
+ KWAI is a work in progress. The current focus is judo, therefore the name KWAI which means club in Japanese.
+ Our judo club is already using it for managing the website with news, pages and trainings.
+
+The system can be divided in two parts: a backend and a frontend.
## Backend
-Unlike the [other version](https://github.com/fbraem/kwai-api) which is written in PHP, this backend is written in
+Unlike the [other version](https://github.com/fbraem/kwai-api) which was written in PHP, this backend is written in
Python and uses [FastAPI](https://fastapi.tiangolo.com/) as web framework to provide an API for Kwai.
[Backend documentation](./kwai-backend/index.md)
## Frontend
-The frontend consists of several single page applications. [Vue](https://vuejs.org) is used as JavaScript framework.
+The frontend consists of several single page applications. [Vue](https://vuejs.org) is used as JavaScript framework.
[Frontend documentation](./kwai-frontend/index.md)
diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css
index 5b497cb39..70641308e 100644
--- a/docs/stylesheets/extra.css
+++ b/docs/stylesheets/extra.css
@@ -1,3 +1,38 @@
:root {
--md-primary-fg-color: rgb(220 38 38);
}
+
+.doc-heading {
+ display: flex;
+ align-items: center;
+}
+
+.badge {
+ display: inline-block;
+ padding: 2px 6px;
+ font-size: 12px;
+ font-weight: bold;
+ color: #fff;
+ border-radius: 2px;
+ text-align: center;
+ white-space: nowrap;
+ background-color: #49cc90;
+ text-transform: uppercase;
+ margin-left: 6px;
+}
+
+.badge-post {
+ background-color: #49cc90;
+}
+
+.badge-get {
+ background-color: #61affe;
+}
+
+.badge-delete {
+ background-color: #f93e3e;
+}
+
+.badge-patch {
+ background-color: #fb923c;
+}
diff --git a/frontend/.eslintrc.cjs b/frontend/.eslintrc.cjs
index fe6deb674..727bcd018 100644
--- a/frontend/.eslintrc.cjs
+++ b/frontend/.eslintrc.cjs
@@ -1,13 +1,13 @@
module.exports = {
- root: true,
- // This tells ESLint to load the config from the package `eslint-config-kwai`
- extends: ['kwai'],
- settings: {
- next: {
- rootDir: [
- 'apps/*/',
- 'packages/*/'
- ],
- },
+ root: true,
+ // This tells ESLint to load the config from the package `eslint-config-kwai`
+ extends: ['kwai'],
+ settings: {
+ next: {
+ rootDir: [
+ 'apps/*/',
+ 'packages/*/',
+ ],
},
-};
\ No newline at end of file
+ },
+};
diff --git a/frontend/Taskfile.yml b/frontend/Taskfile.yml
new file mode 100644
index 000000000..26470522c
--- /dev/null
+++ b/frontend/Taskfile.yml
@@ -0,0 +1,109 @@
+version: '3'
+
+tasks:
+ # Internal task to clean the dist folder of a package.
+ _npm_clean_package:
+ internal: true
+ requires:
+ vars: [PACKAGE]
+ cmds:
+ - rm -rf packages/{{.PACKAGE}}/dist
+
+ # Internal task to run npm build for a package.
+ _npm_build_package:
+ internal: true
+ label: build_package_{{.PACKAGE}}
+ requires:
+ vars: [PACKAGE]
+ sources:
+ - packages/{{.PACKAGE}}/src/**/*
+ - packages/{{.PACKAGE}}/package.json
+ - packages/{{.PACKAGE}}/tailwind.config.js
+ generates:
+ - packages/{{.PACKAGE}}/dist/**/*
+ cmds:
+ - task: _npm_clean_package
+ vars: { PACKAGE: '{{.PACKAGE}}' }
+ - npm run build -w packages/{{.PACKAGE}}
+
+ # @kwai/config package is a dependency for all other packages.
+ _npm_build_config_package:
+ internal: true
+ run: once
+ cmds:
+ - task: _npm_build_package
+ vars: { PACKAGE: 'kwai-config' }
+
+ # Build a package.
+ build_package:
+ desc: Build a package
+ requires:
+ vars: [PACKAGE]
+ deps: [_npm_build_config_package]
+ cmds:
+ - task: _npm_build_package
+ vars: { PACKAGE: '{{.PACKAGE}}' }
+
+ # Build all packages.
+ build_packages:
+ desc: Build all packages
+ run: once # When used as a dependency, one run is enough.
+ deps:
+ - task: build_package
+ vars: { PACKAGE: 'kwai-types' }
+ - task: build_package
+ vars: { PACKAGE: 'kwai-date' }
+ - task: build_package
+ vars: { PACKAGE: 'kwai-api' }
+ - task: build_package
+ vars: { PACKAGE: 'kwai-ui' }
+
+ # Build and start a development server for an application.
+ # All packages will be built before starting the application.
+ dev_app:
+ desc: Build and start a development server for this application
+ requires:
+ vars: [APP]
+ deps: [build_packages]
+ cmds:
+ - npm run dev -w apps/{{.APP}}
+
+ # Build and start a development server for all applications.
+ dev_apps:
+ desc: Build and start a development server for all applications
+ deps:
+ - task: dev_app
+ vars: { APP: 'auth' }
+ - task: dev_app
+ vars: { APP: 'author' }
+ - task: dev_app
+ vars: { APP: 'club' }
+ - task: dev_app
+ vars: { APP: 'coach' }
+ - task: dev_app
+ vars: { APP: 'portal' }
+
+ # Build an application.
+ build_app:
+ desc: Build an application
+ requires:
+ vars: [APP]
+ deps: [build_packages]
+ cmds:
+ - rm -rf apps/{{.APP}}/dist
+ - npm run build -w apps/{{.APP}}
+
+ # Build all applications.
+ build:
+ desc: Build all applications of the frontend
+ deps:
+ - task: build_app
+ vars: { APP: 'auth' }
+ - task: build_app
+ vars: { APP: 'author' }
+ - task: build_app
+ vars: { APP: 'club' }
+ - task: build_app
+ vars: { APP: 'coach' }
+ - task: build_app
+ vars: { APP: 'portal' }
diff --git a/frontend/apps/auth/package.json b/frontend/apps/auth/package.json
index 91920f85a..8fbd57a0c 100644
--- a/frontend/apps/auth/package.json
+++ b/frontend/apps/auth/package.json
@@ -2,12 +2,14 @@
"name": "@kwai/auth",
"description": "The authentication application for kwai",
"version": "1.0.0",
+ "type": "module",
"dependencies": {
"@kwai/api": "*",
"@kwai/config": "*",
"@kwai/ui": "*",
- "@vueuse/core": "^10.9.0",
+ "@vueuse/core": "11.0.3",
"pinia": "^2.1.7",
+ "tailwindcss-primeui": "^0.3.4",
"vee-validate": "^4.12.6",
"vue": "^3.4.25",
"vue-i18n": "^9.13.1",
@@ -15,12 +17,12 @@
},
"devDependencies": {
"@intlify/unplugin-vue-i18n": "^1.4.0",
- "@vitejs/plugin-vue": "^4.5.0",
+ "@vitejs/plugin-vue": "^5.2.1",
"@vue/tsconfig": "^0.4.0",
"autoprefixer": "^10.4.16",
- "postcss": "^8.4.31",
- "tailwindcss": "^3.4.3",
- "vue-tsc": "^1.8.24"
+ "postcss": "^8.4.49",
+ "tailwindcss": "^3.4.15",
+ "vue-tsc": "^1.8.27"
},
"private": true,
"scripts": {
diff --git a/frontend/apps/auth/postcss.config.cjs b/frontend/apps/auth/postcss.config.cjs
new file mode 100644
index 000000000..f0f6868e8
--- /dev/null
+++ b/frontend/apps/auth/postcss.config.cjs
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: [
+ require('tailwindcss'),
+ require('autoprefixer'),
+ ],
+};
diff --git a/frontend/apps/auth/postcss.config.js b/frontend/apps/auth/postcss.config.js
deleted file mode 100644
index 12a703d90..000000000
--- a/frontend/apps/auth/postcss.config.js
+++ /dev/null
@@ -1,6 +0,0 @@
-module.exports = {
- plugins: {
- tailwindcss: {},
- autoprefixer: {},
- },
-};
diff --git a/frontend/apps/auth/src/index.css b/frontend/apps/auth/src/index.css
index b5c61c956..efcef79ef 100644
--- a/frontend/apps/auth/src/index.css
+++ b/frontend/apps/auth/src/index.css
@@ -1,3 +1,6 @@
+@import '@root/style.css';
+@import '@kwai/ui/index.css';
+
@tailwind base;
@tailwind components;
@tailwind utilities;
diff --git a/frontend/apps/auth/src/index.ts b/frontend/apps/auth/src/index.ts
index 44f4738fb..b38b0a4bb 100644
--- a/frontend/apps/auth/src/index.ts
+++ b/frontend/apps/auth/src/index.ts
@@ -1,7 +1,7 @@
import { createApp } from 'vue';
// Create app
import App from './App.vue';
-import './index.css';
+import '@root/index.css';
// Setup i18n
import { createI18n } from 'vue-i18n';
@@ -10,6 +10,8 @@ import messages from '@intlify/unplugin-vue-i18n/messages';
// Setup pinia store
import { createPinia } from 'pinia';
+import { init } from '@kwai/ui';
+
// Setup router
import { createRouter, createWebHistory } from 'vue-router';
import { routes } from './routes';
@@ -30,5 +32,6 @@ const router = createRouter({
routes,
});
app.use(router);
+init(app);
app.mount('#app');
diff --git a/frontend/apps/auth/src/pages/ChangePasswordPage.vue b/frontend/apps/auth/src/pages/ChangePasswordPage.vue
index 7b84ccd52..3e565cdab 100644
--- a/frontend/apps/auth/src/pages/ChangePasswordPage.vue
+++ b/frontend/apps/auth/src/pages/ChangePasswordPage.vue
@@ -1,77 +1,6 @@
-
-
-
- {{ t('change_password.notifications.password_changed') }}
-
-
-
-
-
+
+
+
+
+ {{ t('change_password.notifications.password_changed') }}
+
+
+
+
diff --git a/frontend/apps/auth/src/pages/InvitedPage.vue b/frontend/apps/auth/src/pages/InvitedPage.vue
index 481db2e7c..180288744 100644
--- a/frontend/apps/auth/src/pages/InvitedPage.vue
+++ b/frontend/apps/auth/src/pages/InvitedPage.vue
@@ -1,3 +1,102 @@
+
+
-
+
-
-
diff --git a/frontend/apps/auth/src/pages/LoginPage.vue b/frontend/apps/auth/src/pages/LoginPage.vue
index 45dfc549f..c52bce140 100644
--- a/frontend/apps/auth/src/pages/LoginPage.vue
+++ b/frontend/apps/auth/src/pages/LoginPage.vue
@@ -1,5 +1,5 @@
+
+
+
+
+
diff --git a/frontend/apps/auth/src/pages/ResetPasswordPage.vue b/frontend/apps/auth/src/pages/ResetPasswordPage.vue
index 61d27c5c0..95a34fcf4 100644
--- a/frontend/apps/auth/src/pages/ResetPasswordPage.vue
+++ b/frontend/apps/auth/src/pages/ResetPasswordPage.vue
@@ -1,3 +1,91 @@
+
+
-
+
-
-
diff --git a/frontend/apps/auth/src/style.css b/frontend/apps/auth/src/style.css
new file mode 100644
index 000000000..acc685709
--- /dev/null
+++ b/frontend/apps/auth/src/style.css
@@ -0,0 +1,75 @@
+
+/* Primary and Surface Palettes */
+:root {
+ --p-primary-50: #fef2f2;
+ --p-primary-100: #fee2e2;
+ --p-primary-200: #fecaca;
+ --p-primary-300: #fca5a5;
+ --p-primary-400: #f87171;
+ --p-primary-500: #ef4444;
+ --p-primary-600: #dc2626;
+ --p-primary-700: #b91c1c;
+ --p-primary-800: #991b1b;
+ --p-primary-900: #7f1d1d;
+ --p-primary-950: #451a03;
+ --p-surface-0: #ffffff;
+ --p-surface-50: #fafafa;
+ --p-surface-100: #f4f4f5;
+ --p-surface-200: #e4e4e7;
+ --p-surface-300: #d4d4d8;
+ --p-surface-400: #a1a1aa;
+ --p-surface-500: #71717a;
+ --p-surface-600: #52525b;
+ --p-surface-700: #3f3f46;
+ --p-surface-800: #27272a;
+ --p-surface-900: #18181b;
+ --p-surface-950: #09090b;
+ --p-content-border-radius: 6px;
+}
+
+/* Light */
+:root {
+ --p-primary-color: var(--p-surface-600);
+ --p-primary-contrast-color: var(--p-surface-0);
+ --p-primary-hover-color: var(--p-surface-900);
+ --p-primary-active-color: var(--p-primary-700);
+ --p-content-border-color: var(--p-surface-200);
+ --p-content-hover-background: var(--p-surface-100);
+ --p-content-hover-color: var(--p-surface-800);
+ --p-highlight-background: var(--p-primary-50);
+ --p-highlight-color: var(--p-primary-700);
+ --p-highlight-focus-background: var(--p-primary-100);
+ --p-highlight-focus-color: var(--p-primary-800);
+ --p-text-color: var(--p-surface-700);
+ --p-text-hover-color: var(--p-surface-800);
+ --p-text-muted-color: var(--p-surface-500);
+ --p-text-hover-muted-color: var(--p-surface-600);
+}
+
+/*
+ * Dark Mode
+ * Defaults to system, change the selector to match the darkMode in tailwind.config.
+ * For example;
+ * darkMode: ['selector', '[class*="app-dark"]']
+ * should be;
+ * :root[class="app-dark"] {
+*/
+@media (prefers-color-scheme: dark) {
+ :root {
+ --p-primary-color: var(--p-primary-400);
+ --p-primary-contrast-color: var(--p-surface-900);
+ --p-primary-hover-color: var(--p-primary-300);
+ --p-primary-active-color: var(--p-primary-200);
+ --p-content-border-color: var(--p-surface-700);
+ --p-content-hover-background: var(--p-surface-800);
+ --p-content-hover-color: var(--p-surface-0);
+ --p-highlight-background: color-mix(in srgb, var(--p-primary-400), transparent 84%);
+ --p-highlight-color: rgba(255, 255, 255, 0.87);
+ --p-highlight-focus-background: color-mix(in srgb, var(--p-primary-400), transparent 76%);
+ --p-highlight-focus-color: rgba(255, 255, 255, 0.87);
+ --p-text-color: var(--p-surface-0);
+ --p-text-hover-color: var(--p-surface-0);
+ --p-text-muted-color: var(--p-surface-400);
+ --p-text-hover-muted-color: var(--p-surface-300);
+ }
+}
diff --git a/frontend/apps/auth/tailwind.config.js b/frontend/apps/auth/tailwind.config.js
index f2a53ce40..a56b03390 100644
--- a/frontend/apps/auth/tailwind.config.js
+++ b/frontend/apps/auth/tailwind.config.js
@@ -1,12 +1,13 @@
/** @type {import('tailwindcss').Config} */
+import primeui from 'tailwindcss-primeui';
+
module.exports = {
content: [
- './index.html',
'./src/**/*.{html,js,ts,vue,jsx,tsx}',
'../../packages/kwai-ui/src/**/*.{html,js,ts,vue,jsx,tsx}',
],
theme: {
extend: {},
},
- plugins: [],
+ plugins: [primeui],
};
diff --git a/frontend/apps/auth/vite.config.ts b/frontend/apps/auth/vite.config.ts
index aac1990b4..3fa4bea01 100644
--- a/frontend/apps/auth/vite.config.ts
+++ b/frontend/apps/auth/vite.config.ts
@@ -1,4 +1,4 @@
-import { defineConfig, splitVendorChunkPlugin } from 'vite';
+import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import toml from '@fbraem/rollup-plugin-toml';
import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite';
@@ -21,13 +21,23 @@ const resolveTheme = (path: string) => {
return original;
};
-export default defineConfig(() => {
+export default defineConfig(({ mode }) => {
return {
base: '/apps/auth/',
+ esbuild: {
+ pure: mode === 'production' ? ['console.log'] : [],
+ },
server: {
+ origin: 'http://localhost:3002',
host: '0.0.0.0',
port: 3002,
},
+ build: {
+ manifest: true,
+ rollupOptions: {
+ input: 'src/index.ts',
+ },
+ },
plugins: [
vue(),
toml(),
@@ -35,7 +45,6 @@ export default defineConfig(() => {
include: resolve(__dirname, './src/locales/**'),
compositionOnly: true,
}),
- splitVendorChunkPlugin(),
visualizer(),
],
resolve: {
@@ -45,6 +54,12 @@ export default defineConfig(() => {
replacement: '',
customResolver: resolveTheme,
},
+ {
+ find: '@kwai/ui',
+ replacement: mode === 'production'
+ ? '@kwai/ui'
+ : resolve(__dirname, '../../packages/kwai-ui/src/'),
+ },
{
find: /^@root\/(.*)/,
replacement: `${resolve(__dirname)}/src/$1`,
diff --git a/frontend/apps/author/package.json b/frontend/apps/author/package.json
index 958902293..87073403d 100644
--- a/frontend/apps/author/package.json
+++ b/frontend/apps/author/package.json
@@ -2,6 +2,7 @@
"name": "@kwai/author",
"description": "The author application for Kwai",
"version": "1.0.0",
+ "type": "module",
"dependencies": {
"@intlify/unplugin-vue-i18n": "4.0.0",
"@kwai/api": "*",
@@ -10,6 +11,7 @@
"@kwai/types": "*",
"@kwai/ui": "*",
"@tanstack/vue-query": "^5.32.0",
+ "tailwindcss-primeui": "^0.3.4",
"vee-validate": "^4.12.6",
"vue": "^3.4.25",
"vue-i18n": "^9.13.1",
@@ -17,12 +19,12 @@
"zod": "^3.23.4"
},
"devDependencies": {
- "@vitejs/plugin-vue": "^4.5.0",
+ "@vitejs/plugin-vue": "^5.2.1",
"@vue/tsconfig": "^0.4.0",
"autoprefixer": "^10.4.16",
- "postcss": "^8.4.31",
- "tailwindcss": "^3.4.3",
- "vue-tsc": "^1.8.24"
+ "postcss": "^8.4.49",
+ "tailwindcss": "^3.4.15",
+ "vue-tsc": "^1.8.27"
},
"private": true,
"scripts": {
diff --git a/frontend/apps/author/postcss.config.cjs b/frontend/apps/author/postcss.config.cjs
new file mode 100644
index 000000000..f0f6868e8
--- /dev/null
+++ b/frontend/apps/author/postcss.config.cjs
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: [
+ require('tailwindcss'),
+ require('autoprefixer'),
+ ],
+};
diff --git a/frontend/apps/author/postcss.config.js b/frontend/apps/author/postcss.config.js
deleted file mode 100644
index 12a703d90..000000000
--- a/frontend/apps/author/postcss.config.js
+++ /dev/null
@@ -1,6 +0,0 @@
-module.exports = {
- plugins: {
- tailwindcss: {},
- autoprefixer: {},
- },
-};
diff --git a/frontend/apps/author/src/components/AuthorToolbar.vue b/frontend/apps/author/src/components/AuthorToolbar.vue
index 0161ae59b..d151bde37 100644
--- a/frontend/apps/author/src/components/AuthorToolbar.vue
+++ b/frontend/apps/author/src/components/AuthorToolbar.vue
@@ -2,25 +2,16 @@
// eslint-disable-next-line import/no-absolute-path
import logoUrl from '/logo.png';
import { website } from '@kwai/config';
-import type { MenuItem } from '@kwai/ui';
-import { ToolbarLogo, ToolbarMenu } from '@kwai/ui';
-import { useRouter } from 'vue-router';
-import { computed } from 'vue';
-import PrimaryButton from '@root/components/PrimaryButton.vue';
+import { useMenu, KwaiMenubar, KwaiButton, ToolbarLogo } from '@kwai/ui';
+import { isLoggedIn, useHttpLogout } from '@kwai/api';
-const router = useRouter();
-const menuItems = computed(() : MenuItem[] => {
- const result: MenuItem[] = [];
- for (const route of router.getRoutes()) {
- if (route.meta.title) {
- result.push({
- title: route.meta.title as string,
- route,
- });
- }
- }
- return result;
-});
+const menuItems = useMenu();
+
+const loggedIn = isLoggedIn;
+const logout = () => {
+ useHttpLogout();
+ window.location.reload();
+};
@@ -42,18 +33,22 @@ const menuItems = computed(() : MenuItem[] => {
-
-
+
+
+ Logout
+
+
+
+
Login
-
+
-
diff --git a/frontend/apps/author/src/components/PrimaryButton.vue b/frontend/apps/author/src/components/PrimaryButton.vue
deleted file mode 100644
index fbfc30c00..000000000
--- a/frontend/apps/author/src/components/PrimaryButton.vue
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/frontend/apps/author/src/index.css b/frontend/apps/author/src/index.css
index b5c61c956..efcef79ef 100644
--- a/frontend/apps/author/src/index.css
+++ b/frontend/apps/author/src/index.css
@@ -1,3 +1,6 @@
+@import '@root/style.css';
+@import '@kwai/ui/index.css';
+
@tailwind base;
@tailwind components;
@tailwind utilities;
diff --git a/frontend/apps/author/src/index.ts b/frontend/apps/author/src/index.ts
index 89886a948..6952f0e60 100644
--- a/frontend/apps/author/src/index.ts
+++ b/frontend/apps/author/src/index.ts
@@ -1,16 +1,16 @@
import { createApp } from 'vue';
-import App from './App.vue';
-import './index.css';
-import '@kwai/ui/index.css';
+import App from '@root/App.vue';
+import '@root/index.css';
-import { VueQueryPlugin } from '@tanstack/vue-query';
import { createRouter, createWebHistory } from 'vue-router';
+import routes from '@root/routes';
-// Setup i18n
import { createI18n } from 'vue-i18n';
import messages from '@intlify/unplugin-vue-i18n/messages';
-import routes from './routes';
+import { VueQueryPlugin } from '@tanstack/vue-query';
+
+import { init } from '@kwai/ui';
const app = createApp(App);
app.use(VueQueryPlugin);
@@ -28,4 +28,5 @@ const router = createRouter({
});
app.use(router);
+init(app);
app.mount('#app');
diff --git a/frontend/apps/author/src/pages/HomePage.vue b/frontend/apps/author/src/pages/HomePage.vue
index 7c9ab94c2..31675c35f 100644
--- a/frontend/apps/author/src/pages/HomePage.vue
+++ b/frontend/apps/author/src/pages/HomePage.vue
@@ -1,6 +1,5 @@
@@ -20,12 +19,12 @@ import PrimaryButton from '@root/components/PrimaryButton.vue';
@@ -40,12 +39,12 @@ import PrimaryButton from '@root/components/PrimaryButton.vue';
@@ -60,12 +59,12 @@ import PrimaryButton from '@root/components/PrimaryButton.vue';
diff --git a/frontend/apps/author/src/pages/applications/ApplicationEditPage.vue b/frontend/apps/author/src/pages/applications/ApplicationEditPage.vue
index b158a28d7..ed2574f0b 100644
--- a/frontend/apps/author/src/pages/applications/ApplicationEditPage.vue
+++ b/frontend/apps/author/src/pages/applications/ApplicationEditPage.vue
@@ -1,5 +1,5 @@
@@ -50,9 +49,9 @@ const { data: applications } = useApplications();
-
- Wijzig
-
+
+ Wijzig
+
diff --git a/frontend/apps/author/src/pages/news/NewsPage.vue b/frontend/apps/author/src/pages/news/NewsPage.vue
index 7d433ec71..1237f3ee6 100644
--- a/frontend/apps/author/src/pages/news/NewsPage.vue
+++ b/frontend/apps/author/src/pages/news/NewsPage.vue
@@ -8,12 +8,12 @@ import {
CancelIcon,
CheckIcon,
EditIcon,
+ KwaiButton,
OffsetPagination,
usePagination,
} from '@kwai/ui';
import { useNewsItems } from '@root/composables/useNewsItem';
-import PrimaryButton from '@root/components/PrimaryButton.vue';
import { useI18n } from 'vue-i18n';
import PromotedIcon from '@root/components/icons/PromotedIcon.vue';
@@ -37,13 +37,10 @@ const { data: newsItems } = useNewsItems({ offset, limit });
-
+
{{ t('news.home.toolbar.button') }}
-
+
-
+
-
+
diff --git a/frontend/apps/author/src/pages/news/components/NewsForm.vue b/frontend/apps/author/src/pages/news/components/NewsForm.vue
index eb1d49d58..c22f5e5e3 100644
--- a/frontend/apps/author/src/pages/news/components/NewsForm.vue
+++ b/frontend/apps/author/src/pages/news/components/NewsForm.vue
@@ -1,14 +1,14 @@
-
-
-
-
-
-
-
-
diff --git a/frontend/apps/club/src/components/icons/AddMemberIcon.vue b/frontend/apps/club/src/components/icons/AddMemberIcon.vue
new file mode 100644
index 000000000..8945c90eb
--- /dev/null
+++ b/frontend/apps/club/src/components/icons/AddMemberIcon.vue
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
diff --git a/frontend/apps/club/src/components/icons/MemberIcon.vue b/frontend/apps/club/src/components/icons/MemberIcon.vue
new file mode 100644
index 000000000..855986afb
--- /dev/null
+++ b/frontend/apps/club/src/components/icons/MemberIcon.vue
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
diff --git a/frontend/apps/club/src/composables/useCountry.ts b/frontend/apps/club/src/composables/useCountry.ts
new file mode 100644
index 000000000..9bc6cfa95
--- /dev/null
+++ b/frontend/apps/club/src/composables/useCountry.ts
@@ -0,0 +1,12 @@
+import { JsonApiData } from '@kwai/api';
+import { z } from 'zod';
+
+export const CountryResourceSchema = JsonApiData.extend({
+ type: z.literal('countries'),
+ attributes: z.object({
+ iso_2: z.string(),
+ iso_3: z.string(),
+ name: z.string(),
+ }),
+});
+export type CountryResource = z.infer;
diff --git a/frontend/apps/club/src/composables/useMember.e2e.test.ts b/frontend/apps/club/src/composables/useMember.e2e.test.ts
new file mode 100644
index 000000000..27c3f24d7
--- /dev/null
+++ b/frontend/apps/club/src/composables/useMember.e2e.test.ts
@@ -0,0 +1,37 @@
+import { describe, expect, it, vi } from 'vitest';
+import { defineComponent } from 'vue';
+import { useMembers } from '@root/composables/useMember';
+import { mount } from '@vue/test-utils';
+import { VueQueryPlugin } from '@tanstack/vue-query';
+import { useHttpLogin } from '@kwai/api';
+import * as process from 'node:process';
+
+const noUser = process.env.KWAI_USER === undefined;
+
+describe('useMember e2e tests', () => {
+ it.skipIf(noUser)('can get members', async() => {
+ await useHttpLogin(
+ {
+ username: process.env.KWAI_USER as string,
+ password: process.env.KWAI_PASSWORD as string,
+ }
+ );
+
+ const TestComponent = defineComponent({
+ setup() {
+ return useMembers({});
+ },
+ template: 'Test Component',
+ });
+ const wrapper = mount(TestComponent, {
+ global: {
+ plugins: [VueQueryPlugin],
+ },
+ });
+ await vi.waitFor(() => {
+ expect(wrapper.vm.isPending).toBeFalsy();
+ }, { timeout: 1000 });
+ const members = wrapper.vm.data;
+ expect(members).toBeDefined();
+ });
+});
diff --git a/frontend/apps/club/src/composables/useMember.test.ts b/frontend/apps/club/src/composables/useMember.test.ts
new file mode 100644
index 000000000..b4e79359f
--- /dev/null
+++ b/frontend/apps/club/src/composables/useMember.test.ts
@@ -0,0 +1,104 @@
+import { describe, expect, it } from 'vitest';
+import { MemberDocumentSchema } from '@root/composables/useMember';
+
+const memberJson = {
+ data: {
+ type: 'members',
+ id: '1',
+ attributes: {
+ license_number: '123456',
+ license_end_date: '2024-31-01',
+ active: true,
+ competition: false,
+ remark: '',
+ },
+ relationships: {
+ person: {
+ data: {
+ type: 'persons',
+ id: '1',
+ },
+ },
+ },
+ },
+ included: [
+ {
+ type: 'persons',
+ id: '1',
+ attributes: {
+ first_name: 'Jigoro',
+ last_name: 'Kano',
+ gender: 1,
+ birthdate: '18',
+ remark: '',
+ },
+ relationships: {
+ contact: {
+ data: {
+ type: 'contacts',
+ id: '1',
+ },
+ },
+ nationality: {
+ data: {
+ type: 'countries',
+ id: '1',
+ },
+ },
+ },
+ },
+ {
+ type: 'contacts',
+ id: '1',
+ attributes: {
+ emails: [],
+ tel: '',
+ mobile: '',
+ address: '',
+ postal_code: '',
+ city: '',
+ county: '',
+ remark: '',
+ },
+ relationships: {
+ country: {
+ data: {
+ type: 'countries',
+ id: '1',
+ },
+ },
+ },
+ },
+ {
+ type: 'countries',
+ id: '1',
+ attributes: {
+ iso_2: 'JP',
+ iso_3: 'JPN',
+ name: 'Japan',
+ },
+ },
+ ],
+};
+
+const parse = (json: unknown) => {
+ const result = MemberDocumentSchema.safeParse(json);
+ if (!result.success) {
+ console.log(result.error);
+ }
+ return result;
+};
+
+describe('useMember tests', () => {
+ it('can handle a member document', () => {
+ const { data: document, success } = parse(memberJson);
+ expect(success).toBeTruthy();
+ expect(document).toHaveProperty('data.type', 'members');
+ });
+ it('can handle a member array document', () => {
+ const { data: document, success } = parse({ data: [memberJson.data] });
+ expect(success).toBeTruthy();
+ expect(document!.data).toHaveLength(1);
+ expect(document).toHaveProperty('data.0.type', 'members');
+ });
+});
diff --git a/frontend/apps/club/src/composables/useMember.ts b/frontend/apps/club/src/composables/useMember.ts
index 6b47f6ada..51e40d3f1 100644
--- a/frontend/apps/club/src/composables/useMember.ts
+++ b/frontend/apps/club/src/composables/useMember.ts
@@ -1,50 +1,10 @@
-import type { DateType } from '@kwai/date';
+import { createDateFromString } from '@kwai/date';
import { JsonApiData, JsonApiDocument, JsonResourceIdentifier, useHttpApi } from '@kwai/api';
import { type Ref, ref, toValue } from 'vue';
import { useQuery } from '@tanstack/vue-query';
import { z } from 'zod';
-import { createDateFromString } from '@kwai/date';
-
-interface Country {
- iso2: string,
- iso3: string,
- name: string
-}
-interface Contact {
- emails: string[],
- tel: string,
- mobile: string,
- address: string,
- postalCode: string,
- city: string,
- county: string,
- country: Country
-}
-
-interface Person {
- firstName: string,
- lastName: string,
- gender: number,
- birthdate: DateType,
- remark: string,
- contact: Contact,
- nationality: Country
-}
-
-interface License {
- number: string,
- end_date: DateType
-}
-
-export interface Member {
- id?: string,
- license: License,
- remark: string,
- active: boolean,
- competition: boolean,
- person: Person,
- new: boolean
-}
+import { type CountryResource, CountryResourceSchema } from '@root/composables/useCountry';
+import type { Member } from '@root/types/member';
export interface Members {
meta: { count: number, offset: number, limit: number },
@@ -108,16 +68,6 @@ const ContactResourceSchema = JsonApiData.extend({
});
type ContactResource = z.infer;
-const CountryResourceSchema = JsonApiData.extend({
- type: z.literal('countries'),
- attributes: z.object({
- iso_2: z.string(),
- iso_3: z.string(),
- name: z.string(),
- }),
-});
-type CountryResource = z.infer;
-
export const MemberDocumentSchema = JsonApiDocument.extend({
data: z.union([
MemberResourceSchema,
@@ -130,7 +80,10 @@ export const MemberDocumentSchema = JsonApiDocument.extend({
CountryResourceSchema,
])
).default([]),
-}).transform(doc => {
+});
+type MemberDocument = z.infer;
+
+export const transform = (doc: MemberDocument) : Member | Members => {
const mapModel = (data: MemberResource): Member => {
const person = doc.included.find(included => included.type === PersonResourceSchema.shape.type.value && included.id === data.relationships.person.data.id) as PersonResource;
const nationality = doc.included.find(included => included.type === CountryResourceSchema.shape.type.value && included.id === person.relationships.nationality.data.id) as CountryResource;
@@ -145,7 +98,7 @@ export const MemberDocumentSchema = JsonApiDocument.extend({
remark: data.attributes.remark,
license: {
number: data.attributes.license_number,
- end_date: createDateFromString(data.attributes.license_end_date),
+ endDate: createDateFromString(data.attributes.license_end_date),
},
person: {
birthdate: createDateFromString(person.attributes.birthdate),
@@ -153,6 +106,7 @@ export const MemberDocumentSchema = JsonApiDocument.extend({
address: contact.attributes.address,
city: contact.attributes.city,
country: {
+ id: country.id as string,
name: country.attributes.name,
iso2: country.attributes.iso_2,
iso3: country.attributes.iso_3,
@@ -168,6 +122,7 @@ export const MemberDocumentSchema = JsonApiDocument.extend({
lastName: person.attributes.last_name,
gender: person.attributes.gender,
nationality: {
+ id: nationality.id as string,
name: nationality.attributes.name,
iso2: nationality.attributes.iso_2,
iso3: nationality.attributes.iso_3,
@@ -186,8 +141,7 @@ export const MemberDocumentSchema = JsonApiDocument.extend({
};
}
return mapModel(doc.data);
-});
-type MemberDocument = z.input;
+};
const getMembers = async({
offset = null,
@@ -208,7 +162,7 @@ const getMembers = async({
return api.get().json().then(json => {
const result = MemberDocumentSchema.safeParse(json);
if (result.success) {
- return result.data as Members;
+ return transform(result.data) as Members;
}
console.log(result.error);
throw result.error;
diff --git a/frontend/apps/club/src/composables/useTeam.e2e.test.ts b/frontend/apps/club/src/composables/useTeam.e2e.test.ts
new file mode 100644
index 000000000..2c11e7b05
--- /dev/null
+++ b/frontend/apps/club/src/composables/useTeam.e2e.test.ts
@@ -0,0 +1,27 @@
+import { describe, expect, it, vi } from 'vitest';
+import { useTeam } from '@root/composables/useTeam';
+import { defineComponent, toRef } from 'vue';
+import { VueQueryPlugin } from '@tanstack/vue-query';
+import { mount } from '@vue/test-utils';
+
+describe('useTeam e2e tests', () => {
+ it('can get a team', async() => {
+ const TestComponent = defineComponent({
+ setup() {
+ return useTeam(toRef('1'));
+ },
+ template: 'Test Component',
+ });
+ const wrapper = mount(TestComponent, {
+ global: {
+ plugins: [VueQueryPlugin],
+ },
+ });
+ await vi.waitFor(() => {
+ expect(wrapper.vm.isPending).toBeFalsy();
+ }, { timeout: 1000 });
+ const team = wrapper.vm.data;
+ expect(team).toBeDefined();
+ expect(team!.id).toBe('1');
+ });
+});
diff --git a/frontend/apps/club/src/composables/useTeam.test.ts b/frontend/apps/club/src/composables/useTeam.test.ts
new file mode 100644
index 000000000..79f26ff33
--- /dev/null
+++ b/frontend/apps/club/src/composables/useTeam.test.ts
@@ -0,0 +1,107 @@
+import { describe, expect, it } from 'vitest';
+import { type TeamDocument, TeamDocumentSchema, transform } from '@root/composables/useTeam';
+import type { TeamResource } from '@kwai/coach/src/composables/useTeam';
+import type { Team } from '@root/types/team';
+
+const teamWithoutMembersJson = {
+ data: {
+ type: 'teams',
+ id: '1',
+ attributes: { name: 'U11', active: true, remark: '' },
+ relationships: { team_members: { data: [] } },
+ },
+};
+
+const teamWithMembersJson = {
+ data: {
+ type: 'teams',
+ id: '1',
+ attributes: { name: 'U11', active: true, remark: '' },
+ relationships: {
+ team_members: {
+ data: [
+ { type: 'team_members', id: '1' },
+ ],
+ },
+ },
+ },
+ included: [{
+ type: 'team_members',
+ id: '1',
+ attributes: {
+ active: true,
+ first_name: 'Jigoro',
+ last_name: 'Kano',
+ license_number: '1234',
+ license_end_date: '2025-01-31',
+ gender: 1,
+ birthdate: '1860-10-28',
+ },
+ relationships: {
+ nationality: {
+ data: { type: 'countries', id: '1' },
+ },
+ },
+ }, {
+ type: 'countries',
+ id: '1',
+ attributes: { iso_2: 'JP', iso_3: 'JPN', name: 'Japan' },
+ },
+ ],
+};
+
+const parse = (json: unknown) => {
+ const result = TeamDocumentSchema.safeParse(json);
+ if (!result.success) {
+ console.log(result.error);
+ }
+ return result;
+};
+
+describe('useTeam tests', () => {
+ it('can handle a team document', () => {
+ const { data: document, success } = parse(teamWithoutMembersJson);
+
+ expect(success).toBeTruthy();
+ expect(document).toHaveProperty('data.type', 'teams');
+ expect(document).toHaveProperty('data.id', '1');
+ expect(document).toHaveProperty('data.attributes.name', 'U11');
+ });
+
+ it('can handle a team document with team members', () => {
+ const { data: document, success } = parse(teamWithMembersJson);
+
+ expect(success).toBeTruthy();
+ expect(document).toHaveProperty('data.type', 'teams');
+ expect(document).toHaveProperty('data.id', '1');
+ expect(document).toHaveProperty('data.relationships.team_members.data');
+ const teamData = document!.data as TeamResource;
+ expect(teamData.relationships!.team_members.data).toHaveLength(1);
+ expect(document!.included).toHaveLength(2);
+ expect(document).toHaveProperty('included.0.type', 'team_members');
+ expect(document).toHaveProperty('included.0.id', '1');
+ expect(document).toHaveProperty('included.0.attributes.first_name', 'Jigoro');
+ expect(document).toHaveProperty('included.0.attributes.last_name', 'Kano');
+ });
+
+ it('can transform a document with a team', () => {
+ const { data: document } = parse(teamWithoutMembersJson);
+
+ const team = transform(document as TeamDocument) as Team;
+ expect(team).not.toBeNull();
+ expect(team).toHaveProperty('id', '1');
+ expect(team).toHaveProperty('name', 'U11');
+ expect(team.members).toHaveLength(0);
+ });
+
+ it('can transform a document with a team and members', () => {
+ const { data: document } = parse(teamWithMembersJson);
+ const team = transform(document as TeamDocument) as Team;
+ expect(team).not.toBeNull();
+ expect(team).toHaveProperty('id', '1');
+ expect(team).toHaveProperty('name', 'U11');
+ expect(team).toHaveProperty('members.0.firstName', 'Jigoro');
+ expect(team).toHaveProperty('members.0.lastName', 'Kano');
+ expect(team).toHaveProperty('members.0.nationality.name', 'Japan');
+ });
+});
diff --git a/frontend/apps/club/src/composables/useTeam.ts b/frontend/apps/club/src/composables/useTeam.ts
new file mode 100644
index 000000000..7af8d2735
--- /dev/null
+++ b/frontend/apps/club/src/composables/useTeam.ts
@@ -0,0 +1,229 @@
+import type { Team, TeamMember } from '@root/types/team';
+import {
+ JsonApiData,
+ JsonApiDocument,
+ JsonResourceIdentifier,
+ type JsonResourceIdentifierType,
+ transformResourceArrayToObject,
+ useHttpApi,
+} from '@kwai/api';
+import { z } from 'zod';
+import { type Ref, ref, toValue } from 'vue';
+import { useMutation, useQuery, useQueryClient } from '@tanstack/vue-query';
+import { CountryResourceSchema } from '@root/composables/useCountry';
+import { TeamMemberResourceSchema } from '@root/composables/useTeamMember';
+import { createDateFromString } from '@kwai/date';
+
+export interface Teams {
+ meta: {
+ count: number,
+ offset: number,
+ limit: number
+ },
+ items: Team[]
+}
+
+const TeamResourceSchema = JsonApiData.extend({
+ type: z.literal('teams'),
+ attributes: z.object({
+ name: z.string(),
+ active: z.boolean(),
+ remark: z.string(),
+ }),
+ relationships: z.object({
+ team_members: z.object({
+ data: z.array(JsonResourceIdentifier).default([]),
+ }),
+ }),
+});
+
+type TeamResource = z.infer;
+
+export const TeamDocumentSchema = JsonApiDocument.extend({
+ data: z.union([
+ TeamResourceSchema,
+ z.array(TeamResourceSchema),
+ ]),
+ included: z.array(z.union([TeamMemberResourceSchema, CountryResourceSchema])).default([]),
+});
+export type TeamDocument = z.infer;
+
+export const transform = (doc: TeamDocument) : Team | Teams => {
+ const included = transformResourceArrayToObject(doc.included);
+ const mapModel = (teamResource: TeamResource): Team => {
+ const teamMembers: TeamMember[] = [];
+ for (const teamMemberIdentifier of teamResource.relationships.team_members.data) {
+ const teamMember = included[teamMemberIdentifier.type][teamMemberIdentifier.id as string];
+ const countryResourceId = teamMember.relationships!.nationality.data as JsonResourceIdentifierType;
+ const nationality = included[countryResourceId.type][countryResourceId.id as string];
+ teamMembers.push(
+ {
+ id: teamMemberIdentifier.id as string,
+ active: teamMember.attributes.active,
+ firstName: teamMember.attributes.first_name,
+ lastName: teamMember.attributes.last_name,
+ license: {
+ number: teamMember.attributes.license_number,
+ endDate: createDateFromString(teamMember.attributes.license_end_date),
+ },
+ gender: teamMember.attributes.gender,
+ birthdate: createDateFromString(teamMember.attributes.birthdate),
+ nationality: {
+ id: nationality.id as string,
+ iso2: nationality.attributes.iso_2,
+ iso3: nationality.attributes.iso_3,
+ name: nationality.attributes.name,
+ },
+ activeInClub: teamMember.attributes.active_in_club,
+ }
+ );
+ }
+
+ return {
+ id: teamResource.id,
+ name: teamResource.attributes.name,
+ active: teamResource.attributes.active,
+ remark: teamResource.attributes.remark,
+ members: teamMembers,
+ };
+ };
+ if (Array.isArray(doc.data)) {
+ return {
+ meta: {
+ count: doc.meta?.count || 0,
+ offset: doc.meta?.offset || 0,
+ limit: doc.meta?.limit || 0,
+ },
+ items: doc.data.map(mapModel),
+ };
+ }
+ return mapModel(doc.data);
+};
+
+const getTeams = async({
+ offset = null,
+ limit = null,
+} : {
+ offset?: number | null,
+ limit?: number | null,
+}) => {
+ let api = useHttpApi().url('/v1/teams');
+ if (offset) {
+ api = api.query({ 'page[offset]': offset });
+ }
+ if (limit) {
+ api = api.query({ 'page[limit]': limit });
+ }
+ return api.get().json().then(json => {
+ const result = TeamDocumentSchema.safeParse(json);
+ if (result.success) {
+ return transform(result.data) as Teams;
+ }
+ console.log(result.error);
+ throw result.error;
+ });
+};
+
+export const useTeams = ({ offset = ref(0), limit = ref(0) } : { offset?: Ref, limit?: Ref}) => {
+ const queryKey : { offset: Ref, limit: Ref } = { offset, limit };
+ return useQuery({
+ queryKey: ['club/teams', queryKey],
+ queryFn: () => getTeams({
+ offset: toValue(offset),
+ limit: toValue(limit),
+ }),
+ });
+};
+
+const getTeam = (id: string) : Promise => {
+ return useHttpApi()
+ .url(`/v1/teams/${id}`)
+ .get()
+ .json()
+ .then(json => {
+ const result = TeamDocumentSchema.safeParse(json);
+ if (result.success) {
+ return transform(result.data) as Team;
+ }
+ throw result.error;
+ });
+};
+
+export const useTeam = (id: Ref) => {
+ return useQuery({
+ queryKey: ['club/teams', id],
+ queryFn: () => getTeam(toValue(id)),
+ });
+};
+
+const mutateTeam = (team: Team): Promise => {
+ const payload: TeamDocument = {
+ data: {
+ id: team.id,
+ type: 'teams',
+ attributes: {
+ name: team.name,
+ active: team.active,
+ remark: team.remark,
+ },
+ relationships: {
+ team_members: {
+ data: [],
+ },
+ },
+ },
+ included: [],
+ };
+ if (team.id) { // Update
+ return useHttpApi()
+ .url(`/v1/teams/${team.id}`)
+ .patch(payload)
+ .json(json => {
+ const result = TeamDocumentSchema.safeParse(json);
+ if (result.success) {
+ return transform(result.data) as Team;
+ }
+ throw result.error;
+ })
+ ;
+ }
+ // Create
+ return useHttpApi()
+ .url('/v1/teams')
+ .post(payload)
+ .json(json => {
+ const result = TeamDocumentSchema.safeParse(json);
+ if (result.success) {
+ return transform(result.data) as Team;
+ }
+ throw result.error;
+ });
+};
+
+type OnSuccessCallback = () => void;
+type OnSuccessAsyncCallback = () => Promise;
+interface MutationOptions {
+ onSuccess?: OnSuccessCallback | OnSuccessAsyncCallback
+}
+
+export const useTeamMutation = ({ onSuccess }: MutationOptions = {}) => {
+ const queryClient = useQueryClient();
+
+ return useMutation({
+ mutationFn: (data: Team) => mutateTeam(data),
+ onSuccess: async(data: Team) => {
+ queryClient.setQueryData(['club/teams', data.id], data);
+ if (onSuccess) {
+ if (onSuccess.constructor.name === 'AsyncFunction') {
+ await onSuccess();
+ } else {
+ onSuccess();
+ }
+ }
+ },
+ onSettled: () => queryClient.invalidateQueries({
+ queryKey: ['club/teams'],
+ exact: true,
+ }),
+ });
+};
diff --git a/frontend/apps/club/src/composables/useTeamMember.e2e.test.ts b/frontend/apps/club/src/composables/useTeamMember.e2e.test.ts
new file mode 100644
index 000000000..07e6115b2
--- /dev/null
+++ b/frontend/apps/club/src/composables/useTeamMember.e2e.test.ts
@@ -0,0 +1,26 @@
+import { defineComponent } from 'vue';
+import { mount } from '@vue/test-utils';
+import { VueQueryPlugin } from '@tanstack/vue-query';
+import { expect, vi } from 'vitest';
+import { useTeamMembers } from '@root/composables/useTeamMember';
+
+describe('useTeamMembers e2e tests', () => {
+ it('can get team members', async() => {
+ const TestComponent = defineComponent({
+ setup() {
+ return useTeamMembers({});
+ },
+ template: 'Test Component',
+ });
+ const wrapper = mount(TestComponent, {
+ global: {
+ plugins: [VueQueryPlugin],
+ },
+ });
+ await vi.waitFor(() => {
+ expect(wrapper.vm.isPending).toBeFalsy();
+ }, { timeout: 1000 });
+ const teamMembers = wrapper.vm.data;
+ expect(teamMembers).toBeDefined();
+ });
+});
diff --git a/frontend/apps/club/src/composables/useTeamMember.ts b/frontend/apps/club/src/composables/useTeamMember.ts
new file mode 100644
index 000000000..9a0ba7b5d
--- /dev/null
+++ b/frontend/apps/club/src/composables/useTeamMember.ts
@@ -0,0 +1,209 @@
+import type { TeamMember } from '@root/types/team';
+import {
+ JsonApiData,
+ JsonApiDocument,
+ JsonResourceIdentifier,
+ type JsonResourceIdentifierType,
+ type ResourceItems,
+ transformResourceArrayToObject,
+ useHttpApi,
+} from '@kwai/api';
+import { useMutation, useQuery, useQueryClient } from '@tanstack/vue-query';
+import { z } from 'zod';
+import { CountryResourceSchema } from '@root/composables/useCountry';
+import { type Ref, ref, toValue } from 'vue';
+import { createDateFromString } from '@kwai/date';
+
+export const TeamMemberResourceSchema = JsonApiData.extend({
+ type: z.literal('team_members'),
+ attributes: z.object({
+ active: z.boolean(),
+ first_name: z.string(),
+ last_name: z.string(),
+ license_number: z.string(),
+ license_end_date: z.string(),
+ gender: z.number(),
+ birthdate: z.string(),
+ active_in_club: z.boolean(),
+ }),
+ relationships: z.object({
+ nationality: z.object({
+ data: JsonResourceIdentifier,
+ }),
+ }),
+});
+type TeamMemberResource = z.infer;
+
+export const TeamMemberDocumentSchema = JsonApiDocument.extend({
+ data: z.union([
+ TeamMemberResourceSchema,
+ z.array(TeamMemberResourceSchema),
+ ]),
+ included: z.array(CountryResourceSchema).default([]),
+});
+export type TeamMemberDocument = z.infer;
+
+type TeamMembers = ResourceItems;
+
+export const transform = (doc: TeamMemberDocument) : TeamMember | TeamMembers => {
+ const included = transformResourceArrayToObject(doc.included);
+ const mapModel = (teamMemberResource: TeamMemberResource): TeamMember => {
+ const countryResourceId = teamMemberResource.relationships!.nationality.data as JsonResourceIdentifierType;
+ const nationality = included[countryResourceId.type][countryResourceId.id as string];
+ return {
+ id: teamMemberResource.id as string,
+ active: teamMemberResource.attributes.active,
+ firstName: teamMemberResource.attributes.first_name,
+ lastName: teamMemberResource.attributes.last_name,
+ license: {
+ number: teamMemberResource.attributes.license_number,
+ endDate: createDateFromString(teamMemberResource.attributes.license_end_date),
+ },
+ gender: teamMemberResource.attributes.gender,
+ birthdate: createDateFromString(teamMemberResource.attributes.birthdate),
+ nationality: {
+ id: nationality.id as string,
+ iso2: nationality.attributes.iso_2,
+ iso3: nationality.attributes.iso_3,
+ name: nationality.attributes.name,
+ },
+ activeInClub: teamMemberResource.attributes.active_in_club,
+ };
+ };
+ if (Array.isArray(doc.data)) {
+ return {
+ meta: {
+ count: doc.meta?.count || 0,
+ offset: doc.meta?.offset || 0,
+ limit: doc.meta?.limit || 0,
+ },
+ items: doc.data.map(mapModel),
+ };
+ }
+ return mapModel(doc.data);
+};
+
+export interface TeamFilter {
+ id: string,
+ inTeam: boolean,
+}
+
+const getTeamMembers = async({
+ offset = null,
+ limit = null,
+ team = null,
+} : {
+ offset?: number | null,
+ limit?: number | null,
+ team?: TeamFilter | null,
+}) => {
+ let api = useHttpApi().url('/v1/teams/members');
+ if (offset) {
+ api = api.query({ 'page[offset]': offset });
+ }
+ if (limit) {
+ api = api.query({ 'page[limit]': limit });
+ }
+ if (team) {
+ if (team.inTeam) {
+ api = api.query({ 'filter[team]': team.id });
+ } else {
+ api = api.query({ 'filter[team]': `noteq:${team.id}` });
+ }
+ }
+ return api
+ .get()
+ .json()
+ .then(json => {
+ const result = TeamMemberDocumentSchema.safeParse(json);
+ if (result.success) {
+ return transform(result.data) as TeamMembers;
+ }
+ throw result.error;
+ });
+};
+
+export const useTeamMembers = ({
+ offset = ref(0),
+ limit = ref(0),
+ team = ref(null),
+} : {
+ offset?: Ref,
+ limit?: Ref,
+ team?: Ref,
+}) => {
+ const queryKey = ['club/team_members'];
+ if (team.value) {
+ queryKey.push(team.value.id);
+ }
+ return useQuery({
+ queryKey,
+ queryFn: () => getTeamMembers({
+ offset: toValue(offset),
+ limit: toValue(limit),
+ team: toValue(team),
+ }),
+ });
+};
+
+export interface TeamMemberData {
+ team_id: string,
+ member: TeamMemberDocument,
+}
+
+const mutateAddTeamMember = (data: TeamMemberData): Promise => {
+ const payload = data.member;
+ return useHttpApi()
+ .url(`/v1/teams/${data.team_id}/members`)
+ .post(payload)
+ .json(json => {
+ const result = TeamMemberDocumentSchema.safeParse(json);
+ if (result.success) {
+ return transform(result.data) as TeamMember;
+ }
+ throw result.error;
+ });
+};
+
+interface MutationOptions {
+ onSuccess?: (data: TeamMember, variables: TeamMemberData) => Promise | void
+}
+
+export const useAddTeamMemberMutation = ({ onSuccess }: MutationOptions = {}) => {
+ const queryClient = useQueryClient();
+
+ return useMutation({
+ mutationFn: (variables: TeamMemberData) => mutateAddTeamMember(variables),
+ onSuccess: (data: TeamMember, variables: TeamMemberData) => {
+ if (onSuccess) {
+ return onSuccess(data, variables);
+ }
+ },
+ onSettled: (data, error, variables) => {
+ queryClient.invalidateQueries({
+ queryKey: ['club/teams', variables.team_id],
+ exact: true,
+ });
+ },
+ });
+};
+
+/**
+ * Returns a function that can be used to remove the team member
+ * from the club/team_members/ cache.
+ */
+export const useUpdateTeamMemberCache = () => {
+ const queryClient = useQueryClient();
+
+ return (teamMember: TeamMember, variables: TeamMemberData) => {
+ queryClient.setQueryData(
+ ['club/team_members', variables.team_id],
+ (oldData: ResourceItems) => {
+ return {
+ ...oldData,
+ items: oldData.items.filter(item => item.id !== teamMember.id),
+ };
+ }
+ );
+ };
+};
diff --git a/frontend/apps/club/src/index.css b/frontend/apps/club/src/index.css
index b5c61c956..d9d0534e9 100644
--- a/frontend/apps/club/src/index.css
+++ b/frontend/apps/club/src/index.css
@@ -1,3 +1,6 @@
+@import './style.css';
+@import '@kwai/ui/index.css';
+
@tailwind base;
@tailwind components;
@tailwind utilities;
diff --git a/frontend/apps/club/src/index.ts b/frontend/apps/club/src/index.ts
index 6d79d8a3a..4df7905d1 100644
--- a/frontend/apps/club/src/index.ts
+++ b/frontend/apps/club/src/index.ts
@@ -1,7 +1,6 @@
import { createApp } from 'vue';
import App from './App.vue';
-import './index.css';
-import '@kwai/ui/index.css';
+import '@root/index.css';
import { VueQueryPlugin } from '@tanstack/vue-query';
import { createRouter, createWebHistory } from 'vue-router';
diff --git a/frontend/apps/club/src/locales/nl.yaml b/frontend/apps/club/src/locales/nl.yaml
index d91279bb5..fb1aec34b 100644
--- a/frontend/apps/club/src/locales/nl.yaml
+++ b/frontend/apps/club/src/locales/nl.yaml
@@ -7,7 +7,68 @@ not_allowed:
Om deze applicatie te kunnen gebruiken moet je ingelogd zijn.
members:
title: Alle Actieve Leden
+ count: Er zijn {count} leden.
members_upload:
title: Opladen Leden
description: |
Via deze pagina kan u een bestand opladen met nieuwe of gewijzigde leden.
+ preview_description: |
+ Met preview kan je eerst controleren of het bestand correct verwerkt kan worden.
+ preview: Preview
+ error:
+ message: |
+ Opgelet er zijn fouten gevonden in het opgeladen bestand!
+ row: Rij
+ description: Omschrijving
+teams:
+ title: Teams
+ error: Er is een fout gebeurd tijdens het ophalen van de teams.
+ name: Naam
+ remark: Opmerking
+ members: Leden
+ form:
+ sections:
+ team:
+ title: Team
+ description: De naam van het team
+ fields:
+ name:
+ label: Naam
+ placeholder: Geef een naam in
+ remark:
+ title: Opmerking
+ description: Een opmerking over het team.
+ fields:
+ remark:
+ label: Opmerking
+ placeholder: Geef een opmerking in
+ submit:
+ fields:
+ active:
+ label: Actief?
+ help: Is dit team actief?
+ button:
+ label: Bewaar
+ validations:
+ required: Dit is een verplicht veld.
+team:
+ edit:
+ title: Wijzig Team
+ create:
+ title: Maak Team
+ members:
+ title: Leden
+ no_members: Er zijn nog geen leden in de club.
+ no_team_members: Dit team heeft nog geen leden.
+ add: Toevoegen
+ member_add:
+ title: Leden Toevoegen
+ birthdate: Geboortedatum
+ nationality: Nationaliteit
+ filter:
+ title: Filter Leden
+ name: Naam
+ age: Leeftijd
+ age_invalid: Geen geldige waarde
+ valid_license: Geldige Licentie
+ number_of_members: Er zijn geen leden die voldoen aan de filter. | Er is 1 lid dat voldoet aan de filter. | Er zijn {count} leden die voldoen aan de filter.
diff --git a/frontend/apps/club/src/pages/members/MembersPage.vue b/frontend/apps/club/src/pages/members/MembersPage.vue
index 60166e2ac..a4eac1968 100644
--- a/frontend/apps/club/src/pages/members/MembersPage.vue
+++ b/frontend/apps/club/src/pages/members/MembersPage.vue
@@ -6,11 +6,12 @@ import {
KwaiButton,
KwaiButtonGroup,
} from '@kwai/ui';
-import { type Member, useMembers } from '@root/composables/useMember';
+import { useMembers } from '@root/composables/useMember';
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { breakpointsTailwind, useBreakpoints } from '@vueuse/core';
+import type { Member } from '@root/types/member';
const breakpoints = useBreakpoints(breakpointsTailwind);
const largerThanLg = breakpoints.greater('lg');
@@ -18,6 +19,7 @@ const largerThanLg = breakpoints.greater('lg');
const { t } = useI18n({ useScope: 'global' });
const { data: members } = useMembers({});
+
const sortedMembers = computed(() => {
const result: Record = {};
if (!members.value) return result;
@@ -49,6 +51,9 @@ const alphabet = [...Array(26)].map((_, i) => String.fromCharCode(65 + i));
{{ t('members.title') }}
+
+ {{ t('members.count', { count: members.meta.count }) }}
+
diff --git a/frontend/apps/club/src/pages/members/MembersUploadPage.vue b/frontend/apps/club/src/pages/members/MembersUploadPage.vue
index dc4b9210c..5721f72a4 100644
--- a/frontend/apps/club/src/pages/members/MembersUploadPage.vue
+++ b/frontend/apps/club/src/pages/members/MembersUploadPage.vue
@@ -6,27 +6,31 @@ import {
ContainerSectionTitle,
KwaiFileUpload,
KwaiCheckbox,
+ KwaiTag,
+ ErrorAlert,
} from '@kwai/ui';
import { type Ref, ref } from 'vue';
-import { useHttpApi } from '@kwai/api';
-import { MemberDocumentSchema, type Members } from '@root/composables/useMember';
+import { useHttpApi, type JsonApiErrorType } from '@kwai/api';
+import { MemberDocumentSchema, type Members, transform } from '@root/composables/useMember';
const { t } = useI18n({ useScope: 'global' });
const useMemberUpload = (files: File[]) => {
- const members: Ref = ref(null);
(async() => {
const formData = new FormData();
formData.append('member_file', files[0]);
await useHttpApi()
.url('/v1/club/members/upload')
+ .query({ preview: preview.value })
.body(formData)
.post()
.json()
.then(json => {
const result = MemberDocumentSchema.safeParse(json);
if (result.success) {
- members.value = result.data as Members;
+ errors.value = result.data.errors ?? [];
+ count.value = result.data.meta?.count ?? 0;
+ members.value = transform(result.data) as Members;
} else {
console.log(result.error);
throw result.error;
@@ -39,6 +43,8 @@ const useMemberUpload = (files: File[]) => {
const members = ref();
const preview: Ref = ref(true);
+const errors: Ref = ref([]);
+const count = ref(0);
const upload = (files: File[]) => {
members.value = useMemberUpload(files);
@@ -46,24 +52,105 @@ const upload = (files: File[]) => {
-
+
{{ t('members_upload.title') }}
- {{ t('members_upload.description') }}
-
+
+ {{ t('members_upload.description') }}
+
+
+
+
+
+
+
+ {{ t('members_upload.preview_description') }}
+
+
+
+ {{ t('members_upload.preview') }}
+
+
+
+
+
+
+
+ {{ t('members_upload.error.message') }}
+
+
+
+
+
+ {{ t('members_upload.error.row') }}
+ |
+
+ {{ t('members_upload.error.description') }}
+ |
+
+
+
+
+
+ {{ error.source!.pointer }}
+ |
+
+ {{ error.detail }}
+ |
+
+
+
+
+
+
+
+ Er zijn {{ members.meta.count }} leden gevonden in dit bestand.
+
+
+
+
+
+
+ {{ t('members_upload.error.row') }}
+ |
+
+ {{ t('members_upload.error.description') }}
+ |
+
+
+
+
+
+ {{ index + 1 }}
+ |
+
+ {{ member.person.lastName }} {{ member.person.firstName }}
+
+ |
+
+
+
-
-
- Preview
-
-
- {{ members }}
diff --git a/frontend/apps/club/src/pages/members/components/MemberCard.vue b/frontend/apps/club/src/pages/members/components/MemberCard.vue
deleted file mode 100644
index f56c61349..000000000
--- a/frontend/apps/club/src/pages/members/components/MemberCard.vue
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
diff --git a/frontend/apps/club/src/pages/teams/TeamCreatePage.vue b/frontend/apps/club/src/pages/teams/TeamCreatePage.vue
new file mode 100644
index 000000000..8a2499188
--- /dev/null
+++ b/frontend/apps/club/src/pages/teams/TeamCreatePage.vue
@@ -0,0 +1,24 @@
+
+
+
+
+ {{ t('team.create.title') }}
+
+
+
+
+
+
+
diff --git a/frontend/apps/club/src/pages/teams/TeamEditPage.vue b/frontend/apps/club/src/pages/teams/TeamEditPage.vue
new file mode 100644
index 000000000..7eb98ccc3
--- /dev/null
+++ b/frontend/apps/club/src/pages/teams/TeamEditPage.vue
@@ -0,0 +1,34 @@
+
+
+
+
+ {{ t('team.edit.title') }}
+
+
+
+
+
+
+
diff --git a/frontend/apps/club/src/pages/teams/TeamMembersPage.vue b/frontend/apps/club/src/pages/teams/TeamMembersPage.vue
new file mode 100644
index 000000000..7972187f8
--- /dev/null
+++ b/frontend/apps/club/src/pages/teams/TeamMembersPage.vue
@@ -0,0 +1,99 @@
+
+
+
+
+
+ {{ t('team.members.title') }} {{ team.name }}
+
+
+
+
+
+
+ {{ t('teams.error') }}
+
+
+
+ {{ t('team.members.no_team_members') }}
+
+
+
+
+
+
+ Naam
+
+
+ Geboortedatum
+
+
+ Licensie
+
+
+
+
+
+
+ {{ team_member.lastName }} {{ team_member.firstName }}
+
+
+ {{ team_member.birthdate.format('L') }} ({{ year - team_member.birthdate.year() }})
+
+
+
+ {{ team_member.license.number }}
+
+
+ {{ team_member.license.endDate.format('L') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/apps/club/src/pages/teams/TeamsPage.vue b/frontend/apps/club/src/pages/teams/TeamsPage.vue
new file mode 100644
index 000000000..47e95739b
--- /dev/null
+++ b/frontend/apps/club/src/pages/teams/TeamsPage.vue
@@ -0,0 +1,122 @@
+
+
+
+
+
+ {{ t('teams.title') }}
+
+
+
+
+
+
+ {{ t('teams.error') }}
+
+
+
+
+ |
+
+ {{ t('teams.name') }}
+ |
+
+ {{ t('teams.members') }}
+ |
+
+ {{ t('teams.remark') }}
+ |
+ |
+
+
+
+
+
+
+
+ |
+
+ {{ team.name }}
+ |
+
+ {{ team.members.length }}
+ |
+
+ {{ team.remark }}
+ |
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+ Nieuw Team
+
+
+
+
+
+
+
diff --git a/frontend/apps/club/src/pages/teams/components/MemberCard.vue b/frontend/apps/club/src/pages/teams/components/MemberCard.vue
new file mode 100644
index 000000000..fe28c350d
--- /dev/null
+++ b/frontend/apps/club/src/pages/teams/components/MemberCard.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
+ {{ member.lastName }} {{ member.firstName }}
+
+
+
+
Geboortedatum:
+
{{ member.birthdate.format('L') }} ({{ age }})
+
Licentie
+
+ {{ member.license.number }} ({{ member.license.endDate.format('L') }})
+
+
+
Nationaliteit:
+
{{ member.nationality.iso3 }}
+
+
+
+
+
+
+
+
+
diff --git a/frontend/apps/club/src/pages/teams/components/TeamForm.vue b/frontend/apps/club/src/pages/teams/components/TeamForm.vue
new file mode 100644
index 000000000..704de0e75
--- /dev/null
+++ b/frontend/apps/club/src/pages/teams/components/TeamForm.vue
@@ -0,0 +1,152 @@
+
+
+
+
+
+
+
diff --git a/frontend/apps/club/src/pages/teams/components/TeamMemberAdd.vue b/frontend/apps/club/src/pages/teams/components/TeamMemberAdd.vue
new file mode 100644
index 000000000..f02a46bc8
--- /dev/null
+++ b/frontend/apps/club/src/pages/teams/components/TeamMemberAdd.vue
@@ -0,0 +1,179 @@
+
+
+
+
+ {{ t('team.member_add.title') }}
+
+
+
+
+
+ {{ t('teams.error') }}
+
+
+
+ {{ t('team.members.no_members') }}
+
+
+
+
+ {{ t('team.member_add.filter.title') }}
+
+
+
+
+
+ {{ t('team.member_add.filter.name') }}
+
+
+
+
+
+
+ {{ t('team.member_add.filter.age') }}
+
+
+
+
+
+
+ {{ t('team.member_add.filter.valid_license') }}
+
+
+
+
+
+
+ {{ t('team.member_add.filter.number_of_members', filteredMembers.length ) }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/apps/club/src/pages/teams/components/TeamMemberButtonAdd.vue b/frontend/apps/club/src/pages/teams/components/TeamMemberButtonAdd.vue
new file mode 100644
index 000000000..5efb229a9
--- /dev/null
+++ b/frontend/apps/club/src/pages/teams/components/TeamMemberButtonAdd.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+ {{ t('team.members.add') }}
+
+
+
+
+
+
diff --git a/frontend/apps/club/src/routes.ts b/frontend/apps/club/src/routes.ts
index f15f80687..8221feb8e 100644
--- a/frontend/apps/club/src/routes.ts
+++ b/frontend/apps/club/src/routes.ts
@@ -5,6 +5,12 @@ import NotAllowedPage from '@root/pages/not_allowed/NotAllowedPage.vue';
import MembersPage from '@root/pages/members/MembersPage.vue';
import ClubToolbar from '@root/components/ClubToolbar.vue';
import UploadMembersPage from '@root/pages/members/MembersUploadPage.vue';
+import TeamsPage from '@root/pages/teams/TeamsPage.vue';
+import TeamEditPage from '@root/pages/teams/TeamEditPage.vue';
+import TeamCreatePage from '@root/pages/teams/TeamCreatePage.vue';
+import TeamMembersPage from '@root/pages/teams/TeamMembersPage.vue';
+import TeamMemberButtonAdd from '@root/pages/teams/components/TeamMemberButtonAdd.vue';
+import TeamMemberAdd from '@root/pages/teams/components/TeamMemberAdd.vue';
const routes: RouteRecordRaw[] = [
{
@@ -40,6 +46,9 @@ const routes: RouteRecordRaw[] = [
toolbar: ClubToolbar,
main: MembersPage,
},
+ meta: {
+ title: 'Leden',
+ },
},
{
name: 'club.upload',
@@ -49,6 +58,62 @@ const routes: RouteRecordRaw[] = [
main: UploadMembersPage,
},
},
+ {
+ name: 'club.teams',
+ path: '/teams',
+ components: {
+ toolbar: ClubToolbar,
+ main: TeamsPage,
+ },
+ meta: {
+ title: 'Teams',
+ },
+ },
+ {
+ name: 'club.teams.edit',
+ path: '/teams/edit/:id',
+ components: {
+ toolbar: ClubToolbar,
+ main: TeamEditPage,
+ },
+ props: {
+ toolbar: false,
+ main: true,
+ },
+ },
+ {
+ name: 'club.teams.create',
+ path: '/teams/create',
+ components: {
+ toolbar: ClubToolbar,
+ main: TeamCreatePage,
+ },
+ },
+ {
+ path: '/teams/:id/members',
+ components: {
+ toolbar: ClubToolbar,
+ main: TeamMembersPage,
+ },
+ props: {
+ toolbar: false,
+ main: true,
+ },
+ children: [
+ {
+ name: 'club.teams.members',
+ path: '',
+ component: TeamMemberButtonAdd,
+ props: true,
+ },
+ {
+ name: 'club.teams.members.add',
+ path: 'add',
+ component: TeamMemberAdd,
+ props: true,
+ },
+ ],
+ },
],
},
];
diff --git a/frontend/apps/club/src/style.css b/frontend/apps/club/src/style.css
new file mode 100644
index 000000000..a885cd482
--- /dev/null
+++ b/frontend/apps/club/src/style.css
@@ -0,0 +1,73 @@
+/* Primary and Surface Palettes */
+:root {
+ --p-primary-50: #f0fdf4;
+ --p-primary-100: #dcfce7;
+ --p-primary-200: #bbf7d0;
+ --p-primary-300: #86efac;
+ --p-primary-400: #4ade80;
+ --p-primary-500: #22c55e;
+ --p-primary-600: #16a34a;
+ --p-primary-700: #15803d;
+ --p-primary-800: #166534;
+ --p-primary-900: #14532d;
+ --p-surface-0: #ffffff;
+ --p-surface-50: #fafafa;
+ --p-surface-100: #f4f4f5;
+ --p-surface-200: #e4e4e7;
+ --p-surface-300: #d4d4d8;
+ --p-surface-400: #a1a1aa;
+ --p-surface-500: #71717a;
+ --p-surface-600: #52525b;
+ --p-surface-700: #3f3f46;
+ --p-surface-800: #27272a;
+ --p-surface-900: #18181b;
+ --p-surface-950: #09090b;
+ --p-content-border-radius: 6px;
+}
+
+/* Light */
+:root {
+ --p-primary-color: var(--p-primary-500);
+ --p-primary-contrast-color: var(--p-surface-0);
+ --p-primary-hover-color: var(--p-primary-600);
+ --p-primary-active-color: var(--p-primary-700);
+ --p-content-border-color: var(--p-surface-200);
+ --p-content-hover-background: var(--p-surface-100);
+ --p-content-hover-color: var(--p-surface-800);
+ --p-highlight-background: var(--p-primary-50);
+ --p-highlight-color: var(--p-primary-700);
+ --p-highlight-focus-background: var(--p-primary-100);
+ --p-highlight-focus-color: var(--p-primary-800);
+ --p-text-color: var(--p-surface-700);
+ --p-text-hover-color: var(--p-surface-800);
+ --p-text-muted-color: var(--p-surface-500);
+ --p-text-hover-muted-color: var(--p-surface-600);
+}
+
+/*
+ * Dark Mode
+ * Defaults to system, change the selector to match the darkMode in tailwind.config.
+ * For example;
+ * darkMode: ['selector', '[class*="app-dark"]']
+ * should be;
+ * :root[class="app-dark"] {
+*/
+@media (prefers-color-scheme: dark) {
+ :root {
+ --p-primary-color: var(--p-primary-400);
+ --p-primary-contrast-color: var(--p-surface-900);
+ --p-primary-hover-color: var(--p-primary-300);
+ --p-primary-active-color: var(--p-primary-200);
+ --p-content-border-color: var(--p-surface-700);
+ --p-content-hover-background: var(--p-surface-800);
+ --p-content-hover-color: var(--p-surface-0);
+ --p-highlight-background: color-mix(in srgb, var(--p-primary-400), transparent 84%);
+ --p-highlight-color: rgba(255, 255, 255, 0.87);
+ --p-highlight-focus-background: color-mix(in srgb, var(--p-primary-400), transparent 76%);
+ --p-highlight-focus-color: rgba(255, 255, 255, 0.87);
+ --p-text-color: var(--p-surface-0);
+ --p-text-hover-color: var(--p-surface-0);
+ --p-text-muted-color: var(--p-surface-400);
+ --p-text-hover-muted-color: var(--p-surface-300);
+ }
+}
diff --git a/frontend/apps/club/src/types/contact.ts b/frontend/apps/club/src/types/contact.ts
new file mode 100644
index 000000000..9f0106505
--- /dev/null
+++ b/frontend/apps/club/src/types/contact.ts
@@ -0,0 +1,12 @@
+import type { Country } from './country';
+
+export interface Contact {
+ emails: string[],
+ tel: string,
+ mobile: string,
+ address: string,
+ postalCode: string,
+ city: string,
+ county: string,
+ country: Country
+}
diff --git a/frontend/apps/club/src/types/country.ts b/frontend/apps/club/src/types/country.ts
new file mode 100644
index 000000000..897963f17
--- /dev/null
+++ b/frontend/apps/club/src/types/country.ts
@@ -0,0 +1,6 @@
+export interface Country {
+ id: string,
+ iso2: string,
+ iso3: string,
+ name: string
+}
diff --git a/frontend/apps/club/src/types/member.ts b/frontend/apps/club/src/types/member.ts
new file mode 100644
index 000000000..1f41251cc
--- /dev/null
+++ b/frontend/apps/club/src/types/member.ts
@@ -0,0 +1,17 @@
+import type { DateType } from '@kwai/date';
+import type { Person } from './person';
+
+export interface License {
+ number: string,
+ endDate: DateType
+}
+
+export interface Member {
+ id?: string,
+ license: License,
+ remark: string,
+ active: boolean,
+ competition: boolean,
+ person: Person,
+ new: boolean
+}
diff --git a/frontend/apps/club/src/types/person.ts b/frontend/apps/club/src/types/person.ts
new file mode 100644
index 000000000..a5a13e279
--- /dev/null
+++ b/frontend/apps/club/src/types/person.ts
@@ -0,0 +1,13 @@
+import type { DateType } from '@kwai/date';
+import type { Contact } from './contact';
+import type { Country } from './country';
+
+export interface Person {
+ firstName: string,
+ lastName: string,
+ gender: number,
+ birthdate: DateType,
+ remark: string,
+ contact: Contact,
+ nationality: Country
+}
diff --git a/frontend/apps/club/src/types/team.ts b/frontend/apps/club/src/types/team.ts
new file mode 100644
index 000000000..f1a18ced2
--- /dev/null
+++ b/frontend/apps/club/src/types/team.ts
@@ -0,0 +1,23 @@
+import type { License } from '@root/types/member';
+import type { Country } from '@root/types/country';
+import type { DateType } from '@kwai/date';
+
+export interface TeamMember {
+ id: string,
+ active: boolean,
+ firstName: string,
+ lastName: string,
+ license: License,
+ gender: number,
+ birthdate: DateType,
+ nationality: Country,
+ activeInClub: boolean
+}
+
+export interface Team {
+ id?: string,
+ name: string,
+ active: boolean,
+ remark: string,
+ members: TeamMember[],
+}
diff --git a/frontend/apps/club/tailwind.config.js b/frontend/apps/club/tailwind.config.js
index 9a0d5e6a4..b2e8213e9 100644
--- a/frontend/apps/club/tailwind.config.js
+++ b/frontend/apps/club/tailwind.config.js
@@ -1,19 +1,14 @@
/** @type {import('tailwindcss').Config} */
-import colors from 'tailwindcss/colors';
+import primeui from 'tailwindcss-primeui';
+
module.exports = {
content: [
- './index.html',
'./src/**/*.{html,js,ts,vue,jsx,tsx}',
'../../packages/kwai-ui/src/**/*.{html,js,ts,vue,jsx,tsx}',
- 'node_modules/@indielayer/ui/{lib,src}/**/*',
],
theme: {
extend: {
- colors: {
- primary: colors.green,
- 'primary-text': colors.white,
- },
},
},
- plugins: [],
+ plugins: [primeui],
};
diff --git a/frontend/apps/club/vite.config.ts b/frontend/apps/club/vite.config.ts
index 8c732f193..8380a0f28 100644
--- a/frontend/apps/club/vite.config.ts
+++ b/frontend/apps/club/vite.config.ts
@@ -1,4 +1,4 @@
-import { defineConfig, splitVendorChunkPlugin } from 'vite';
+import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { resolve } from 'path';
import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite';
@@ -9,9 +9,16 @@ export default defineConfig(({ mode }) => {
return {
base: '/apps/club/',
server: {
+ origin: 'http://localhost:3004',
host: '0.0.0.0',
port: 3004,
},
+ build: {
+ manifest: true,
+ rollupOptions: {
+ input: 'src/index.ts',
+ },
+ },
esbuild: {
pure: mode === 'production' ? ['console.log'] : [],
},
@@ -21,7 +28,6 @@ export default defineConfig(({ mode }) => {
include: resolve(__dirname, './src/locales/**'),
compositionOnly: true,
}),
- splitVendorChunkPlugin(),
visualizer(),
],
resolve: {
@@ -39,5 +45,9 @@ export default defineConfig(({ mode }) => {
],
dedupe: ['vue'],
},
+ test: {
+ global: true,
+ environment: 'jsdom',
+ },
};
});
diff --git a/frontend/apps/club/vitest.config.ts b/frontend/apps/club/vitest.config.ts
new file mode 100644
index 000000000..caf993c29
--- /dev/null
+++ b/frontend/apps/club/vitest.config.ts
@@ -0,0 +1,19 @@
+import { resolve } from 'path';
+import { loadEnv } from 'vite';
+import { defineConfig } from 'vitest/config';
+
+export default defineConfig(({ mode }) => ({
+ test: {
+ globals: true,
+ environment: 'jsdom',
+ env: loadEnv(mode, '../../', ''),
+ },
+ resolve: {
+ alias: [
+ {
+ find: /^@root\/(.*)/,
+ replacement: `${resolve(__dirname)}/src/$1`,
+ },
+ ],
+ },
+}));
diff --git a/frontend/apps/coach/package.json b/frontend/apps/coach/package.json
index b10c35af7..e29573542 100644
--- a/frontend/apps/coach/package.json
+++ b/frontend/apps/coach/package.json
@@ -2,6 +2,7 @@
"name": "@kwai/coach",
"description": "The coach application of kwai",
"version": "1.0.0",
+ "type": "module",
"dependencies": {
"@intlify/unplugin-vue-i18n": "4.0.0",
"@kwai/api": "*",
@@ -10,8 +11,9 @@
"@kwai/types": "*",
"@kwai/ui": "*",
"@tanstack/vue-query": "^5.32.0",
- "@vuepic/vue-datepicker": "8.4.0",
- "@vueuse/core": "^10.9.0",
+ "@vuepic/vue-datepicker": "9.0.3",
+ "@vueuse/core": "11.0.3",
+ "tailwindcss-primeui": "^0.3.4",
"vee-validate": "^4.12.6",
"vue": "^3.4.25",
"vue-i18n": "^9.13.1",
@@ -19,12 +21,12 @@
"zod": "^3.23.4"
},
"devDependencies": {
- "@vitejs/plugin-vue": "^4.5.0",
+ "@vitejs/plugin-vue": "^5.2.1",
"@vue/tsconfig": "^0.4.0",
"autoprefixer": "^10.4.16",
- "postcss": "^8.4.31",
- "tailwindcss": "^3.4.3",
- "vue-tsc": "^1.8.24"
+ "postcss": "^8.4.49",
+ "tailwindcss": "^3.4.15",
+ "vue-tsc": "^1.8.27"
},
"scripts": {
"build": "vue-tsc --noEmit && vite build --config ./vite.config.ts",
diff --git a/frontend/apps/coach/postcss.config.cjs b/frontend/apps/coach/postcss.config.cjs
new file mode 100644
index 000000000..f0f6868e8
--- /dev/null
+++ b/frontend/apps/coach/postcss.config.cjs
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: [
+ require('tailwindcss'),
+ require('autoprefixer'),
+ ],
+};
diff --git a/frontend/apps/coach/postcss.config.js b/frontend/apps/coach/postcss.config.js
deleted file mode 100644
index 12a703d90..000000000
--- a/frontend/apps/coach/postcss.config.js
+++ /dev/null
@@ -1,6 +0,0 @@
-module.exports = {
- plugins: {
- tailwindcss: {},
- autoprefixer: {},
- },
-};
diff --git a/frontend/apps/coach/src/components/CoachToolbar.vue b/frontend/apps/coach/src/components/CoachToolbar.vue
index af7733a3e..bcd8b6282 100644
--- a/frontend/apps/coach/src/components/CoachToolbar.vue
+++ b/frontend/apps/coach/src/components/CoachToolbar.vue
@@ -1,11 +1,17 @@
@@ -27,20 +33,21 @@ const menuItems = useMenu();
-
-
+
+
+ Logout
+
+
+
+
Login
-
+
-
+
diff --git a/frontend/apps/coach/src/index.css b/frontend/apps/coach/src/index.css
index b5c61c956..efcef79ef 100644
--- a/frontend/apps/coach/src/index.css
+++ b/frontend/apps/coach/src/index.css
@@ -1,3 +1,6 @@
+@import '@root/style.css';
+@import '@kwai/ui/index.css';
+
@tailwind base;
@tailwind components;
@tailwind utilities;
diff --git a/frontend/apps/coach/src/index.ts b/frontend/apps/coach/src/index.ts
index 271ef479d..6952f0e60 100644
--- a/frontend/apps/coach/src/index.ts
+++ b/frontend/apps/coach/src/index.ts
@@ -1,7 +1,6 @@
import { createApp } from 'vue';
import App from '@root/App.vue';
import '@root/index.css';
-import '@kwai/ui/index.css';
import { createRouter, createWebHistory } from 'vue-router';
import routes from '@root/routes';
@@ -11,6 +10,8 @@ import messages from '@intlify/unplugin-vue-i18n/messages';
import { VueQueryPlugin } from '@tanstack/vue-query';
+import { init } from '@kwai/ui';
+
const app = createApp(App);
app.use(VueQueryPlugin);
@@ -27,4 +28,5 @@ const router = createRouter({
});
app.use(router);
+init(app);
app.mount('#app');
diff --git a/frontend/apps/coach/src/pages/home/HomePage.vue b/frontend/apps/coach/src/pages/home/HomePage.vue
index cdd899439..e74c318d3 100644
--- a/frontend/apps/coach/src/pages/home/HomePage.vue
+++ b/frontend/apps/coach/src/pages/home/HomePage.vue
@@ -1,7 +1,6 @@
@@ -24,12 +23,12 @@ const { t } = useI18n({ useScope: 'global' });
-
+
{{ t('home.trainings.list') }}
-
+
diff --git a/frontend/apps/coach/src/pages/home/components/TrainingDefinitionsCard.vue b/frontend/apps/coach/src/pages/home/components/TrainingDefinitionsCard.vue
index 47e919d98..fe34a4aae 100644
--- a/frontend/apps/coach/src/pages/home/components/TrainingDefinitionsCard.vue
+++ b/frontend/apps/coach/src/pages/home/components/TrainingDefinitionsCard.vue
@@ -1,6 +1,5 @@
@@ -17,12 +16,12 @@ const { t } = useI18n({ useScope: 'global' });
-
+
{{ t('home.training_definitions.list') }}
-
+
diff --git a/frontend/apps/coach/src/pages/home/components/TrainingsCard.vue b/frontend/apps/coach/src/pages/home/components/TrainingsCard.vue
index e7036e8da..dbf1f90af 100644
--- a/frontend/apps/coach/src/pages/home/components/TrainingsCard.vue
+++ b/frontend/apps/coach/src/pages/home/components/TrainingsCard.vue
@@ -1,6 +1,5 @@
@@ -17,12 +16,12 @@ const { t } = useI18n({ useScope: 'global' });
-
+
{{ t('home.trainings.list') }}
-
+
diff --git a/frontend/apps/coach/src/pages/training_definitions/GenerateTrainingsPage.vue b/frontend/apps/coach/src/pages/training_definitions/GenerateTrainingsPage.vue
index 66c46427b..bc56f8fb4 100644
--- a/frontend/apps/coach/src/pages/training_definitions/GenerateTrainingsPage.vue
+++ b/frontend/apps/coach/src/pages/training_definitions/GenerateTrainingsPage.vue
@@ -6,14 +6,14 @@ import {
ContainerSectionBanner,
ContainerSectionContent,
ContainerSectionTitle,
- DateRangePicker,
+ KwaiDateRangePicker,
DeleteIcon,
InfoAlert,
+ KwaiButton,
LinkTag,
NewIcon,
} from '@kwai/ui';
import { useI18n } from 'vue-i18n';
-import PrimaryButton from '@root/components/PrimaryButton.vue';
import TrainingDefinitionCard from '@root/pages/training_definitions/components/TrainingDefinitionCard.vue';
import { ref, toRef } from 'vue';
import { useForm } from 'vee-validate';
@@ -94,17 +94,14 @@ const saveTrainings = () => {
-
-
+
{{ t('generate_trainings.banner.button') }}
-
+
@@ -171,13 +168,10 @@ const saveTrainings = () => {
v-if="trainings.length > 0"
class="w-full flex flex-col"
>
-
+
{{ t('generate_trainings.save') }}
-
+
diff --git a/frontend/apps/coach/src/pages/training_definitions/TrainingDefinitionsPage.vue b/frontend/apps/coach/src/pages/training_definitions/TrainingDefinitionsPage.vue
index 288135388..c2831b81b 100644
--- a/frontend/apps/coach/src/pages/training_definitions/TrainingDefinitionsPage.vue
+++ b/frontend/apps/coach/src/pages/training_definitions/TrainingDefinitionsPage.vue
@@ -4,11 +4,12 @@ import {
ContainerSection,
ContainerSectionBanner,
ContainerSectionContent,
- ContainerSectionTitle, EditIcon,
+ ContainerSectionTitle,
+ EditIcon,
+ KwaiButton,
NewIcon,
} from '@kwai/ui';
import { useI18n } from 'vue-i18n';
-import PrimaryButton from '@root/components/PrimaryButton.vue';
import TrainingDefinitionCard from '@root/pages/training_definitions/components/TrainingDefinitionCard.vue';
import AddCalendarIcon from '@root/components/icons/AddCalendarIcon.vue';
@@ -33,13 +34,10 @@ const { data: trainingDefinitions } = useTrainingDefinitions();
-
+
{{ t('training_definitions.banner.button') }}
-
+
@@ -50,9 +48,8 @@ const { data: trainingDefinitions } = useTrainingDefinitions();
-
{{ t('training_definitions.card.buttons.generate') }}
-
-
{{ t('training_definitions.card.buttons.edit') }}
-
+
diff --git a/frontend/apps/coach/src/pages/training_definitions/components/TrainingDefinitionForm.vue b/frontend/apps/coach/src/pages/training_definitions/components/TrainingDefinitionForm.vue
index b3346be2f..60c216970 100644
--- a/frontend/apps/coach/src/pages/training_definitions/components/TrainingDefinitionForm.vue
+++ b/frontend/apps/coach/src/pages/training_definitions/components/TrainingDefinitionForm.vue
@@ -5,7 +5,7 @@ import { useI18n } from 'vue-i18n';
import { useForm } from 'vee-validate';
import {
- Button,
+ KwaiButton,
CheckBox,
ErrorAlert,
FormSection,
@@ -13,7 +13,7 @@ import {
InputField,
SelectOption,
TextareaField,
- TimePicker,
+ KwaiTimePicker,
isStringRequired,
} from '@kwai/ui';
import type { Option, TimeModel } from '@kwai/ui';
@@ -225,7 +225,7 @@ watch(definition, nv => {
-
{
{{ t('training_definition.form.sections.period.fields.start_time.label') }} :
-
-
+ {
{{ t('training_definition.form.sections.period.fields.end_time.label') }} :
-
+
@@ -278,13 +278,12 @@ watch(definition, nv => {
-
+
{{ t('training_definition.form.error') }}
diff --git a/frontend/apps/coach/src/pages/trainings/TrainingsPage.vue b/frontend/apps/coach/src/pages/trainings/TrainingsPage.vue
index 9e0dd4f33..6de01927a 100644
--- a/frontend/apps/coach/src/pages/trainings/TrainingsPage.vue
+++ b/frontend/apps/coach/src/pages/trainings/TrainingsPage.vue
@@ -12,9 +12,9 @@ import {
CancelIcon,
CheckIcon,
EditIcon,
+ KwaiButton,
TextBadge,
} from '@kwai/ui';
-import PrimaryButton from '@root/components/PrimaryButton.vue';
import { createDate, createFromDate, now } from '@kwai/date';
import { computed, ref, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
@@ -103,16 +103,13 @@ const setToCurrent = () => {
:format="format"
auto-apply
/>
-
+
-
-
+
+
{{ t('trainings.banner.button') }}
-
+
@@ -188,12 +185,9 @@ const setToCurrent = () => {
/>
-
+
-
+
|
diff --git a/frontend/apps/coach/src/pages/trainings/components/TrainingForm.vue b/frontend/apps/coach/src/pages/trainings/components/TrainingForm.vue
index f398bf667..98926f3e4 100644
--- a/frontend/apps/coach/src/pages/trainings/components/TrainingForm.vue
+++ b/frontend/apps/coach/src/pages/trainings/components/TrainingForm.vue
@@ -1,12 +1,12 @@
-
-
-
-
-
-
-
-
diff --git a/frontend/apps/portal/src/components/toolbar/ToolbarUser.vue b/frontend/apps/portal/src/components/toolbar/ToolbarUser.vue
index 193d17d15..d773d4570 100644
--- a/frontend/apps/portal/src/components/toolbar/ToolbarUser.vue
+++ b/frontend/apps/portal/src/components/toolbar/ToolbarUser.vue
@@ -1,16 +1,26 @@
-
diff --git a/frontend/apps/portal/src/index.css b/frontend/apps/portal/src/index.css
index bd6213e1d..efcef79ef 100644
--- a/frontend/apps/portal/src/index.css
+++ b/frontend/apps/portal/src/index.css
@@ -1,3 +1,6 @@
+@import '@root/style.css';
+@import '@kwai/ui/index.css';
+
@tailwind base;
@tailwind components;
-@tailwind utilities;
\ No newline at end of file
+@tailwind utilities;
diff --git a/frontend/apps/portal/src/index.ts b/frontend/apps/portal/src/index.ts
index ea40e77d9..5161feb88 100644
--- a/frontend/apps/portal/src/index.ts
+++ b/frontend/apps/portal/src/index.ts
@@ -1,8 +1,9 @@
import { createApp } from 'vue';
-
+// Create app
import App from './App.vue';
-import './index.css';
+import '@root/index.css';
+import { init } from '@kwai/ui';
import { createRouter, createWebHistory } from 'vue-router';
import routes from './routes';
import { VueQueryPlugin } from '@tanstack/vue-query';
@@ -12,7 +13,7 @@ const app = createApp(App);
app.use(VueQueryPlugin);
const router = createRouter({
- history: createWebHistory(),
+ history: createWebHistory(import.meta.env.BASE_URL),
routes: [],
});
router.beforeEach((to, from, next) => {
@@ -26,5 +27,6 @@ router.beforeEach((to, from, next) => {
});
routes.forEach(route => router.addRoute(route));
app.use(router);
+init(app);
app.mount('#app');
diff --git a/frontend/apps/portal/src/pages/ApplicationPage.vue b/frontend/apps/portal/src/pages/ApplicationPage.vue
index 4fd191b4a..ceb76522d 100644
--- a/frontend/apps/portal/src/pages/ApplicationPage.vue
+++ b/frontend/apps/portal/src/pages/ApplicationPage.vue
@@ -2,25 +2,35 @@
import { useRoute, useRouter } from 'vue-router';
import IntroSection from '@root/components/IntroSection.vue';
import { useApplications } from '@root/composables/useApplication';
-import { computed, ref, toRef } from 'vue';
+import { computed, ref, toRef, watch } from 'vue';
import { usePages } from '@root/composables/usePage';
import FullArticle from '@root/components/FullArticle.vue';
const route = useRoute();
-const applicationName = route.meta.application as string;
-const heroImageUrl = route.meta.heroImageUrl as string;
+
+const applicationName = toRef(route.meta.application as string);
+const heroImageUrl = toRef(route.meta.heroImageUrl as string);
+
+watch(route, (nv) => {
+ if (nv.meta.application) {
+ applicationName.value = nv.meta.application as string;
+ }
+ if (nv.meta.heroImageUrl) {
+ heroImageUrl.value = nv.meta.heroImageUrl as string;
+ }
+});
// Application
const { data: applications } = useApplications();
const application = computed(() => {
if (applications.value) {
- return applications.value.find(application => application.name === applicationName);
+ return applications.value.find(application => application.name === applicationName.value);
}
return null;
});
// Pages
-const { data: pages } = usePages(toRef(applicationName));
+const { data: pages } = usePages(applicationName);
const sortedPages = computed(() => {
return [...pages.value || []].sort((a, b) => b.priority - a.priority);
});
@@ -41,7 +51,10 @@ const currentPage = computed(() => {
if (articleSection.value) articleSection.value.scrollIntoView(true);
return sortedPages.value.find(page => page.id === route.query.page);
}
- return sortedPages.value[0];
+ if (sortedPages.value.length > 0) {
+ return sortedPages.value[0];
+ }
+ return null;
});
const router = useRouter();
diff --git a/frontend/apps/portal/src/pages/TrainingsPage.vue b/frontend/apps/portal/src/pages/TrainingsPage.vue
index 04b5f8232..ba791280e 100644
--- a/frontend/apps/portal/src/pages/TrainingsPage.vue
+++ b/frontend/apps/portal/src/pages/TrainingsPage.vue
@@ -7,12 +7,12 @@ import { useRoute, useRouter } from 'vue-router';
import { useApplications } from '@root/composables/useApplication';
import { usePages } from '@root/composables/usePage';
import { createDate, now } from '@kwai/date';
+import { KwaiButton } from '@kwai/ui';
import { useTrainingDays, useTrainings } from '@root/composables/useTraining';
import TrainingTimeline from '@root/pages/trainings/components/TrainingTimeline.vue';
import SectionTitle from '@root/components/SectionTitle.vue';
import LeftArrowIcon from '@root/components/icons/LeftArrowIcon.vue';
import RightArrowIcon from '@root/components/icons/RightArrowIcon.vue';
-import PrimaryButton from '@root/components/PrimaryButton.vue';
import FullArticle from '@root/components/FullArticle.vue';
import CoachList from '@root/pages/trainings/components/CoachList.vue';
@@ -176,24 +176,15 @@ const showNextMonth = () => {
Trainingsrooster
-
+
Vorige Maand
-
-
+
+
Deze Maand
-
-
+
+
Volgende Maand
-
+
{{ start.format("MMMM") }} {{ start.format("YYYY") }}
diff --git a/frontend/apps/portal/src/style.css b/frontend/apps/portal/src/style.css
new file mode 100644
index 000000000..688d24c35
--- /dev/null
+++ b/frontend/apps/portal/src/style.css
@@ -0,0 +1,75 @@
+
+/* Primary and Surface Palettes */
+:root {
+ --p-primary-50: #fef2f2;
+ --p-primary-100: #fee2e2;
+ --p-primary-200: #fecaca;
+ --p-primary-300: #fca5a5;
+ --p-primary-400: #f87171;
+ --p-primary-500: #ef4444;
+ --p-primary-600: #dc2626;
+ --p-primary-700: #b91c1c;
+ --p-primary-800: #991b1b;
+ --p-primary-900: #7f1d1d;
+ --p-primary-950: #451a03;
+ --p-surface-0: #ffffff;
+ --p-surface-50: #fafafa;
+ --p-surface-100: #f4f4f5;
+ --p-surface-200: #e4e4e7;
+ --p-surface-300: #d4d4d8;
+ --p-surface-400: #a1a1aa;
+ --p-surface-500: #71717a;
+ --p-surface-600: #52525b;
+ --p-surface-700: #3f3f46;
+ --p-surface-800: #27272a;
+ --p-surface-900: #18181b;
+ --p-surface-950: #09090b;
+ --p-content-border-radius: 6px;
+}
+
+/* Light */
+:root {
+ --p-primary-color: var(--p-primary-600);
+ --p-primary-contrast-color: var(--p-surface-0);
+ --p-primary-hover-color: var(--p-primary-700);
+ --p-primary-active-color: var(--p-primary-800);
+ --p-content-border-color: var(--p-surface-200);
+ --p-content-hover-background: var(--p-surface-100);
+ --p-content-hover-color: var(--p-surface-800);
+ --p-highlight-background: var(--p-primary-50);
+ --p-highlight-color: var(--p-primary-800);
+ --p-highlight-focus-background: var(--p-primary-200);
+ --p-highlight-focus-color: var(--p-primary-900);
+ --p-text-color: var(--p-surface-700);
+ --p-text-hover-color: var(--p-surface-800);
+ --p-text-muted-color: var(--p-surface-500);
+ --p-text-hover-muted-color: var(--p-surface-600);
+}
+
+/*
+ * Dark Mode
+ * Defaults to system, change the selector to match the darkMode in tailwind.config.
+ * For example;
+ * darkMode: ['selector', '[class*="app-dark"]']
+ * should be;
+ * :root[class="app-dark"] {
+*/
+@media (prefers-color-scheme: dark) {
+ :root {
+ --p-primary-color: var(--p-primary-400);
+ --p-primary-contrast-color: var(--p-surface-900);
+ --p-primary-hover-color: var(--p-primary-300);
+ --p-primary-active-color: var(--p-primary-200);
+ --p-content-border-color: var(--p-surface-700);
+ --p-content-hover-background: var(--p-surface-800);
+ --p-content-hover-color: var(--p-surface-0);
+ --p-highlight-background: color-mix(in srgb, var(--p-primary-400), transparent 84%);
+ --p-highlight-color: rgba(255, 255, 255, 0.87);
+ --p-highlight-focus-background: color-mix(in srgb, var(--p-primary-400), transparent 76%);
+ --p-highlight-focus-color: rgba(255, 255, 255, 0.87);
+ --p-text-color: var(--p-surface-0);
+ --p-text-hover-color: var(--p-surface-0);
+ --p-text-muted-color: var(--p-surface-400);
+ --p-text-hover-muted-color: var(--p-surface-300);
+ }
+}
diff --git a/frontend/apps/portal/tailwind.config.js b/frontend/apps/portal/tailwind.config.js
index f2a53ce40..a56b03390 100644
--- a/frontend/apps/portal/tailwind.config.js
+++ b/frontend/apps/portal/tailwind.config.js
@@ -1,12 +1,13 @@
/** @type {import('tailwindcss').Config} */
+import primeui from 'tailwindcss-primeui';
+
module.exports = {
content: [
- './index.html',
'./src/**/*.{html,js,ts,vue,jsx,tsx}',
'../../packages/kwai-ui/src/**/*.{html,js,ts,vue,jsx,tsx}',
],
theme: {
extend: {},
},
- plugins: [],
+ plugins: [primeui],
};
diff --git a/frontend/apps/portal/vite.config.ts b/frontend/apps/portal/vite.config.ts
index 36692f45d..5e9b1942c 100644
--- a/frontend/apps/portal/vite.config.ts
+++ b/frontend/apps/portal/vite.config.ts
@@ -1,4 +1,4 @@
-import { defineConfig, splitVendorChunkPlugin } from 'vite';
+import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { existsSync } from 'fs';
@@ -19,18 +19,32 @@ const resolveTheme = (path: string) => {
return original;
};
-export default defineConfig(() => {
+export default defineConfig(({ mode }) => {
return {
- base: '/',
+ base: '/apps/portal/',
server: {
+ origin: 'http://localhost:3000',
host: '0.0.0.0',
port: 3000,
},
+ build: {
+ manifest: true,
+ rollupOptions: {
+ input: 'src/index.ts',
+ },
+ },
plugins: [
- vue(), splitVendorChunkPlugin(), visualizer(),
+ vue(),
+ visualizer(),
],
resolve: {
alias: [
+ {
+ find: '@kwai/ui',
+ replacement: mode === 'production'
+ ? '@kwai/ui'
+ : resolve(__dirname, '../../packages/kwai-ui/src/'),
+ },
{
find: '@theme',
replacement: '',
diff --git a/frontend/docs/index.md b/frontend/docs/index.md
index d1d4ca39e..1b9bd98bc 100644
--- a/frontend/docs/index.md
+++ b/frontend/docs/index.md
@@ -3,8 +3,7 @@
The frontend consists of several single page applications. [Vue](https://vuejs.org) is used as JavaScript framework.
The frontend code is written with [Typescript](https://www.typescriptlang.org/).
-The code is structured as a mono repository. It contains applications
-and libraries.
+The code is structured as a mono repository. It contains applications and libraries.
## Install
@@ -15,53 +14,28 @@ Clone the repository to your system.
[npm](https://www.npmjs.com/) is used as packaging and dependency management tool.
Make sure it is available.
-Use npm to install all dependencies:
+Make `frontend` the current directory and use npm to install all dependencies:
`npm install`
+[Task](https://taskfile.dev/) can be used as runner and build tool.
+
### Configuration
The frontend uses a config package.
## Development
-A development version of the frontend can be started:
+A development version of the frontend can be started. Make `frontend` the current directory
+and run the `dev_apps` task. This task will build all the packages from the monorepo
+and build and serve the applications.
-`npm run dev`
+`task dev_apps`
[Vite](https://vitejs.dev/) is the local development server.
-Each application will have a vite server. To serve all applications
-from one url, Nginx can be used as reverse proxy. Use the following
-configuration for Nginx:
-
-````
-server {
- listen 80;
- include /etc/nginx/mime.types;
-
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade; # allow websockets
- proxy_set_header Connection "upgrade";
- proxy_set_header Host $http_host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
- proxy_set_header X-Forwarded-Host $host:$server_port;
-
- location /apps/author {
- proxy_pass http://localhost:3001/apps/author;
- }
- location /apps/coach {
- proxy_pass http://localhost:3003/apps/coach;
- }
- location /apps/auth {
- proxy_pass http://localhost:3002/apps/auth;
- }
- location / {
- proxy_pass http://localhost:3000/;
- }
-}
-````
+Each application will have a vite server.
+
+The FastAPI backend is used to serve all applications.
## Build
@@ -69,4 +43,8 @@ To create a production version of the frontend:
`npm run build`
+or
+
+`task build_apps`
+
This will create dist folders in each application.
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index c5c836e13..bded0bb77 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -12,14 +12,15 @@
"packages/*"
],
"devDependencies": {
+ "@go-task/cli": "^3.39.0",
"@vue/test-utils": "^2.4.3",
"eslint-config-kwai": "*",
"msw": "^2.0.11",
"rollup-plugin-visualizer": "^5.11.0",
"syncpack": "^12.3.2",
- "turbo": "^1.13.2",
"typescript": "^5.2.2",
- "vite": "^4.5.3"
+ "vite": "^5.4.11",
+ "vitest": "^2.0.5"
},
"engines": {
"node": ">=18.0.0"
@@ -32,8 +33,9 @@
"@kwai/api": "*",
"@kwai/config": "*",
"@kwai/ui": "*",
- "@vueuse/core": "^10.9.0",
+ "@vueuse/core": "11.0.3",
"pinia": "^2.1.7",
+ "tailwindcss-primeui": "^0.3.4",
"vee-validate": "^4.12.6",
"vue": "^3.4.25",
"vue-i18n": "^9.13.1",
@@ -41,12 +43,12 @@
},
"devDependencies": {
"@intlify/unplugin-vue-i18n": "^1.4.0",
- "@vitejs/plugin-vue": "^4.5.0",
+ "@vitejs/plugin-vue": "^5.2.1",
"@vue/tsconfig": "^0.4.0",
"autoprefixer": "^10.4.16",
- "postcss": "^8.4.31",
- "tailwindcss": "^3.4.3",
- "vue-tsc": "^1.8.24"
+ "postcss": "^8.4.49",
+ "tailwindcss": "^3.4.15",
+ "vue-tsc": "^1.8.27"
}
},
"apps/author": {
@@ -60,6 +62,7 @@
"@kwai/types": "*",
"@kwai/ui": "*",
"@tanstack/vue-query": "^5.32.0",
+ "tailwindcss-primeui": "^0.3.4",
"vee-validate": "^4.12.6",
"vue": "^3.4.25",
"vue-i18n": "^9.13.1",
@@ -67,12 +70,12 @@
"zod": "^3.23.4"
},
"devDependencies": {
- "@vitejs/plugin-vue": "^4.5.0",
+ "@vitejs/plugin-vue": "^5.2.1",
"@vue/tsconfig": "^0.4.0",
"autoprefixer": "^10.4.16",
- "postcss": "^8.4.31",
- "tailwindcss": "^3.4.3",
- "vue-tsc": "^1.8.24"
+ "postcss": "^8.4.49",
+ "tailwindcss": "^3.4.15",
+ "vue-tsc": "^1.8.27"
}
},
"apps/author/node_modules/@intlify/unplugin-vue-i18n": {
@@ -124,7 +127,8 @@
"@kwai/types": "*",
"@kwai/ui": "*",
"@tanstack/vue-query": "^5.32.0",
- "@vueuse/core": "^10.9.0",
+ "@vueuse/core": "11.0.3",
+ "tailwindcss-primeui": "^0.3.4",
"vee-validate": "^4.12.6",
"vue": "^3.4.25",
"vue-i18n": "^9.13.1",
@@ -132,11 +136,12 @@
"zod": "^3.23.4"
},
"devDependencies": {
- "@vitejs/plugin-vue": "^4.5.0",
+ "@vitejs/plugin-vue": "^5.2.1",
"@vue/tsconfig": "^0.4.0",
"autoprefixer": "^10.4.16",
- "postcss": "^8.4.31",
- "tailwindcss": "^3.4.3",
+ "jsdom": "^25.0.0",
+ "postcss": "^8.4.49",
+ "tailwindcss": "^3.4.15",
"vue-tsc": "^1.8.27"
}
},
@@ -189,8 +194,9 @@
"@kwai/types": "*",
"@kwai/ui": "*",
"@tanstack/vue-query": "^5.32.0",
- "@vuepic/vue-datepicker": "8.4.0",
- "@vueuse/core": "^10.9.0",
+ "@vuepic/vue-datepicker": "9.0.3",
+ "@vueuse/core": "11.0.3",
+ "tailwindcss-primeui": "^0.3.4",
"vee-validate": "^4.12.6",
"vue": "^3.4.25",
"vue-i18n": "^9.13.1",
@@ -198,12 +204,12 @@
"zod": "^3.23.4"
},
"devDependencies": {
- "@vitejs/plugin-vue": "^4.5.0",
+ "@vitejs/plugin-vue": "^5.2.1",
"@vue/tsconfig": "^0.4.0",
"autoprefixer": "^10.4.16",
- "postcss": "^8.4.31",
- "tailwindcss": "^3.4.3",
- "vue-tsc": "^1.8.24"
+ "postcss": "^8.4.49",
+ "tailwindcss": "^3.4.15",
+ "vue-tsc": "^1.8.27"
}
},
"apps/coach/node_modules/@intlify/unplugin-vue-i18n": {
@@ -254,18 +260,19 @@
"@kwai/types": "*",
"@kwai/ui": "*",
"@tanstack/vue-query": "^5.32.0",
- "@vueuse/core": "^10.9.0",
- "@vueuse/router": "^10.6.1",
+ "@vueuse/core": "11.0.3",
+ "@vueuse/router": "11.0.3",
+ "tailwindcss-primeui": "^0.3.4",
"vue": "^3.4.25",
"vue-router": "^4.3.2"
},
"devDependencies": {
- "@vitejs/plugin-vue": "^4.5.0",
+ "@vitejs/plugin-vue": "^5.2.1",
"@vue/tsconfig": "^0.4.0",
"autoprefixer": "^10.4.16",
- "postcss": "^8.4.31",
- "tailwindcss": "^3.4.3",
- "vue-tsc": "^1.8.24"
+ "postcss": "^8.4.49",
+ "tailwindcss": "^3.4.15",
+ "vue-tsc": "^1.8.27"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
@@ -280,7 +287,6 @@
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
"integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
- "dev": true,
"engines": {
"node": ">=10"
},
@@ -399,12 +405,12 @@
}
},
"node_modules/@bundled-es-modules/cookie": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.0.tgz",
- "integrity": "sha512-Or6YHg/kamKHpxULAdSqhGqnWFneIXu1NKvvfBBzKGwpVsYuFIQ5aBPHDnnoR3ghW1nvSkALd+EF9iMtY7Vjxw==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.1.tgz",
+ "integrity": "sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==",
"dev": true,
"dependencies": {
- "cookie": "^0.5.0"
+ "cookie": "^0.7.2"
}
},
"node_modules/@bundled-es-modules/statuses": {
@@ -416,6 +422,16 @@
"statuses": "^2.0.1"
}
},
+ "node_modules/@bundled-es-modules/tough-cookie": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/@bundled-es-modules/tough-cookie/-/tough-cookie-0.1.6.tgz",
+ "integrity": "sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==",
+ "dev": true,
+ "dependencies": {
+ "@types/tough-cookie": "^4.0.5",
+ "tough-cookie": "^4.1.4"
+ }
+ },
"node_modules/@effect/schema": {
"version": "0.66.5",
"resolved": "https://registry.npmjs.org/@effect/schema/-/schema-0.66.5.tgz",
@@ -426,10 +442,26 @@
"fast-check": "^3.13.2"
}
},
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/@esbuild/android-arm": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
- "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
+ "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
"cpu": [
"arm"
],
@@ -443,9 +475,9 @@
}
},
"node_modules/@esbuild/android-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz",
- "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
+ "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
"cpu": [
"arm64"
],
@@ -459,9 +491,9 @@
}
},
"node_modules/@esbuild/android-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz",
- "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
+ "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
"cpu": [
"x64"
],
@@ -475,9 +507,9 @@
}
},
"node_modules/@esbuild/darwin-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz",
- "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
+ "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
"cpu": [
"arm64"
],
@@ -491,9 +523,9 @@
}
},
"node_modules/@esbuild/darwin-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz",
- "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
+ "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
"cpu": [
"x64"
],
@@ -507,9 +539,9 @@
}
},
"node_modules/@esbuild/freebsd-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz",
- "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
+ "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
"cpu": [
"arm64"
],
@@ -523,9 +555,9 @@
}
},
"node_modules/@esbuild/freebsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz",
- "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
+ "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
"cpu": [
"x64"
],
@@ -539,9 +571,9 @@
}
},
"node_modules/@esbuild/linux-arm": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz",
- "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
+ "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
"cpu": [
"arm"
],
@@ -555,9 +587,9 @@
}
},
"node_modules/@esbuild/linux-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz",
- "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
+ "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
"cpu": [
"arm64"
],
@@ -571,9 +603,9 @@
}
},
"node_modules/@esbuild/linux-ia32": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz",
- "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
+ "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
"cpu": [
"ia32"
],
@@ -587,9 +619,9 @@
}
},
"node_modules/@esbuild/linux-loong64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz",
- "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
+ "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
"cpu": [
"loong64"
],
@@ -603,9 +635,9 @@
}
},
"node_modules/@esbuild/linux-mips64el": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz",
- "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
+ "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
"cpu": [
"mips64el"
],
@@ -619,9 +651,9 @@
}
},
"node_modules/@esbuild/linux-ppc64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz",
- "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
"cpu": [
"ppc64"
],
@@ -635,9 +667,9 @@
}
},
"node_modules/@esbuild/linux-riscv64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz",
- "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
+ "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
"cpu": [
"riscv64"
],
@@ -651,9 +683,9 @@
}
},
"node_modules/@esbuild/linux-s390x": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz",
- "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
+ "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
"cpu": [
"s390x"
],
@@ -667,9 +699,9 @@
}
},
"node_modules/@esbuild/linux-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz",
- "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
+ "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
"cpu": [
"x64"
],
@@ -683,9 +715,9 @@
}
},
"node_modules/@esbuild/netbsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz",
- "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
"cpu": [
"x64"
],
@@ -699,9 +731,9 @@
}
},
"node_modules/@esbuild/openbsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz",
- "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
"cpu": [
"x64"
],
@@ -715,9 +747,9 @@
}
},
"node_modules/@esbuild/sunos-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz",
- "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
+ "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
"cpu": [
"x64"
],
@@ -731,9 +763,9 @@
}
},
"node_modules/@esbuild/win32-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz",
- "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
+ "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
"cpu": [
"arm64"
],
@@ -747,9 +779,9 @@
}
},
"node_modules/@esbuild/win32-ia32": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz",
- "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
+ "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
"cpu": [
"ia32"
],
@@ -763,9 +795,9 @@
}
},
"node_modules/@esbuild/win32-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz",
- "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
+ "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
"cpu": [
"x64"
],
@@ -873,6 +905,25 @@
"node": ">= 8.0.0"
}
},
+ "node_modules/@go-task/cli": {
+ "version": "3.39.0",
+ "resolved": "https://registry.npmjs.org/@go-task/cli/-/cli-3.39.0.tgz",
+ "integrity": "sha512-KhJ3Ao0ZR9JmmA5ad8ovFwr2mJmSLVqd0Y7hJBI130MZ9JXPmxavkoDc10d4oul/TCKG6nGwypru/OmFqkHTTw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "dependencies": {
+ "@go-task/go-npm": "^0.2.0"
+ }
+ },
+ "node_modules/@go-task/go-npm": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/@go-task/go-npm/-/go-npm-0.2.0.tgz",
+ "integrity": "sha512-vQbdtBvesHm8EUFHX8QKg4rbBodmu9VsAXH1ozpbiN5jdTMOYHTCMM31EurAYmY+rNNtxJQ4JGy6t383RPlqbw==",
+ "dev": true,
+ "bin": {
+ "go-npm": "bin/index.js"
+ }
+ },
"node_modules/@humanwhocodes/config-array": {
"version": "0.11.14",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
@@ -930,37 +981,36 @@
"dev": true
},
"node_modules/@inquirer/confirm": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.1.5.tgz",
- "integrity": "sha512-6+dwZrpko5vr5EFEQmUbfBVhtu6IsnB8lQNsLHgO9S9fbfS5J6MuUj+NY0h98pPpYZXEazLR7qzypEDqVzf6aQ==",
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.0.2.tgz",
+ "integrity": "sha512-KJLUHOaKnNCYzwVbryj3TNBxyZIrr56fR5N45v6K9IPrbT6B7DcudBMfylkV1A8PUdJE15mybkEQyp2/ZUpxUA==",
"dev": true,
"dependencies": {
- "@inquirer/core": "^8.0.1",
- "@inquirer/type": "^1.3.0"
+ "@inquirer/core": "^10.1.0",
+ "@inquirer/type": "^3.0.1"
},
"engines": {
"node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/node": ">=18"
}
},
"node_modules/@inquirer/core": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-8.0.1.tgz",
- "integrity": "sha512-qJRk1y51Os2ARc11Bg2N6uIwiQ9qBSrmZeuMonaQ/ntFpb4+VlcQ8Gl1TFH67mJLz3HA2nvuave0nbv6Lu8pbg==",
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.0.tgz",
+ "integrity": "sha512-I+ETk2AL+yAVbvuKx5AJpQmoaWhpiTFOg/UJb7ZkMAK4blmtG8ATh5ct+T/8xNld0CZG/2UhtkdMwpgvld92XQ==",
"dev": true,
"dependencies": {
- "@inquirer/figures": "^1.0.1",
- "@inquirer/type": "^1.3.0",
- "@types/mute-stream": "^0.0.4",
- "@types/node": "^20.12.7",
- "@types/wrap-ansi": "^3.0.0",
+ "@inquirer/figures": "^1.0.8",
+ "@inquirer/type": "^3.0.1",
"ansi-escapes": "^4.3.2",
- "chalk": "^4.1.2",
- "cli-spinners": "^2.9.2",
"cli-width": "^4.1.0",
- "mute-stream": "^1.0.0",
+ "mute-stream": "^2.0.0",
"signal-exit": "^4.1.0",
"strip-ansi": "^6.0.1",
- "wrap-ansi": "^6.2.0"
+ "wrap-ansi": "^6.2.0",
+ "yoctocolors-cjs": "^2.1.2"
},
"engines": {
"node": ">=18"
@@ -1022,21 +1072,24 @@
}
},
"node_modules/@inquirer/figures": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.1.tgz",
- "integrity": "sha512-mtup3wVKia3ZwULPHcbs4Mor8Voi+iIXEWD7wCNbIO6lYR62oPCTQyrddi5OMYVXHzeCSoneZwJuS8sBvlEwDw==",
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.8.tgz",
+ "integrity": "sha512-tKd+jsmhq21AP1LhexC0pPwsCxEhGgAkg28byjJAd+xhmIs8LUX8JbUc3vBf3PhLxWiB5EvyBE5X7JSPAqMAqg==",
"dev": true,
"engines": {
"node": ">=18"
}
},
"node_modules/@inquirer/type": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.3.0.tgz",
- "integrity": "sha512-RW4Zf6RCTnInRaOZuRHTqAUl+v6VJuQGglir7nW2BkT3OXOphMhkIFhvFRjorBx2l0VwtC/M4No8vYR65TdN9Q==",
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.1.tgz",
+ "integrity": "sha512-+ksJMIy92sOAiAccGpcKZUc3bYO07cADnscIxHBknEm3uNts3movSmBofc1908BNy5edKscxYeAdaX1NXkHS6A==",
"dev": true,
"engines": {
"node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/node": ">=18"
}
},
"node_modules/@intlify/bundle-utils": {
@@ -1179,7 +1232,6 @@
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
- "dev": true,
"dependencies": {
"string-width": "^5.1.2",
"string-width-cjs": "npm:string-width@^4.2.0",
@@ -1192,23 +1244,10 @@
"node": ">=12"
}
},
- "node_modules/@jest/schemas": {
- "version": "29.6.3",
- "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
- "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
- "dev": true,
- "dependencies": {
- "@sinclair/typebox": "^0.27.8"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
"integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
- "dev": true,
"dependencies": {
"@jridgewell/set-array": "^1.2.1",
"@jridgewell/sourcemap-codec": "^1.4.10",
@@ -1222,7 +1261,6 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
- "dev": true,
"engines": {
"node": ">=6.0.0"
}
@@ -1231,21 +1269,19 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
- "dev": true,
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.4.15",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
- "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
+ "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.25",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
- "dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
@@ -1428,26 +1464,17 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/@mswjs/cookies": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@mswjs/cookies/-/cookies-1.1.0.tgz",
- "integrity": "sha512-0ZcCVQxifZmhwNBoQIrystCb+2sWBY2Zw8lpfJBPCHGCA/HWqehITeCRVIv4VMy8MPlaHo2w2pTHFV2pFfqKPw==",
- "dev": true,
- "engines": {
- "node": ">=18"
- }
- },
"node_modules/@mswjs/interceptors": {
- "version": "0.26.15",
- "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.26.15.tgz",
- "integrity": "sha512-HM47Lu1YFmnYHKMBynFfjCp0U/yRskHj/8QEJW0CBEPOlw8Gkmjfll+S9b8M7V5CNDw2/ciRxjjnWeaCiblSIQ==",
+ "version": "0.37.1",
+ "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.37.1.tgz",
+ "integrity": "sha512-SvE+tSpcX884RJrPCskXxoS965Ky/pYABDEhWW6oeSRhpUDLrS5nTvT5n1LLSDVDYvty4imVmXsy+3/ROVuknA==",
"dev": true,
"dependencies": {
"@open-draft/deferred-promise": "^2.2.0",
"@open-draft/logger": "^0.3.0",
"@open-draft/until": "^2.0.0",
"is-node-process": "^1.2.0",
- "outvariant": "^1.2.1",
+ "outvariant": "^1.4.3",
"strict-event-emitter": "^0.5.1"
},
"engines": {
@@ -1518,7 +1545,6 @@
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
- "dev": true,
"optional": true,
"engines": {
"node": ">=14"
@@ -1535,6 +1561,52 @@
"url": "https://opencollective.com/unts"
}
},
+ "node_modules/@primeuix/styled": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@primeuix/styled/-/styled-0.3.2.tgz",
+ "integrity": "sha512-ColZes0+/WKqH4ob2x8DyNYf1NENpe5ZguOvx5yCLxaP8EIMVhLjWLO/3umJiDnQU4XXMLkn2mMHHw+fhTX/mw==",
+ "dependencies": {
+ "@primeuix/utils": "^0.3.2"
+ },
+ "engines": {
+ "node": ">=12.11.0"
+ }
+ },
+ "node_modules/@primeuix/utils": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@primeuix/utils/-/utils-0.3.2.tgz",
+ "integrity": "sha512-B+nphqTQeq+i6JuICLdVWnDMjONome2sNz0xI65qIOyeB4EF12CoKRiCsxuZ5uKAkHi/0d1LqlQ9mIWRSdkavw==",
+ "engines": {
+ "node": ">=12.11.0"
+ }
+ },
+ "node_modules/@primevue/core": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/@primevue/core/-/core-4.2.4.tgz",
+ "integrity": "sha512-QFvPcGSvyIhZPLdnjJnYrwbDtwbA1/FyGLI7VYDgYv4twsgtLw0kgKDyWB1uwM0xdJhv8CCmu7hfxcsPaLuIFg==",
+ "dependencies": {
+ "@primeuix/styled": "^0.3.2",
+ "@primeuix/utils": "^0.3.2"
+ },
+ "engines": {
+ "node": ">=12.11.0"
+ },
+ "peerDependencies": {
+ "vue": "^3.3.0"
+ }
+ },
+ "node_modules/@primevue/icons": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/@primevue/icons/-/icons-4.2.4.tgz",
+ "integrity": "sha512-vteUFM7qvWiDJWxhBbDRgc2VY6kQQyJ91yOukqfWHy4gAgfTz1jiUXMAzc7j269oh4CNFpTNhCe9riS7402HGg==",
+ "dependencies": {
+ "@primeuix/utils": "^0.3.2",
+ "@primevue/core": "4.2.4"
+ },
+ "engines": {
+ "node": ">=12.11.0"
+ }
+ },
"node_modules/@rollup/pluginutils": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz",
@@ -1556,6 +1628,240 @@
}
}
},
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.27.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.27.4.tgz",
+ "integrity": "sha512-2Y3JT6f5MrQkICUyRVCw4oa0sutfAsgaSsb0Lmmy1Wi2y7X5vT9Euqw4gOsCyy0YfKURBg35nhUKZS4mDcfULw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.27.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.27.4.tgz",
+ "integrity": "sha512-wzKRQXISyi9UdCVRqEd0H4cMpzvHYt1f/C3CoIjES6cG++RHKhrBj2+29nPF0IB5kpy9MS71vs07fvrNGAl/iA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.27.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.27.4.tgz",
+ "integrity": "sha512-PlNiRQapift4LNS8DPUHuDX/IdXiLjf8mc5vdEmUR0fF/pyy2qWwzdLjB+iZquGr8LuN4LnUoSEvKRwjSVYz3Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.27.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.27.4.tgz",
+ "integrity": "sha512-o9bH2dbdgBDJaXWJCDTNDYa171ACUdzpxSZt+u/AAeQ20Nk5x+IhA+zsGmrQtpkLiumRJEYef68gcpn2ooXhSQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.27.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.27.4.tgz",
+ "integrity": "sha512-NBI2/i2hT9Q+HySSHTBh52da7isru4aAAo6qC3I7QFVsuhxi2gM8t/EI9EVcILiHLj1vfi+VGGPaLOUENn7pmw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.27.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.27.4.tgz",
+ "integrity": "sha512-wYcC5ycW2zvqtDYrE7deary2P2UFmSh85PUpAx+dwTCO9uw3sgzD6Gv9n5X4vLaQKsrfTSZZ7Z7uynQozPVvWA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.27.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.27.4.tgz",
+ "integrity": "sha512-9OwUnK/xKw6DyRlgx8UizeqRFOfi9mf5TYCw1uolDaJSbUmBxP85DE6T4ouCMoN6pXw8ZoTeZCSEfSaYo+/s1w==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.27.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.27.4.tgz",
+ "integrity": "sha512-Vgdo4fpuphS9V24WOV+KwkCVJ72u7idTgQaBoLRD0UxBAWTF9GWurJO9YD9yh00BzbkhpeXtm6na+MvJU7Z73A==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.27.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.27.4.tgz",
+ "integrity": "sha512-pleyNgyd1kkBkw2kOqlBx+0atfIIkkExOTiifoODo6qKDSpnc6WzUY5RhHdmTdIJXBdSnh6JknnYTtmQyobrVg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.27.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.27.4.tgz",
+ "integrity": "sha512-caluiUXvUuVyCHr5DxL8ohaaFFzPGmgmMvwmqAITMpV/Q+tPoaHZ/PWa3t8B2WyoRcIIuu1hkaW5KkeTDNSnMA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
+ "version": "4.27.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.27.4.tgz",
+ "integrity": "sha512-FScrpHrO60hARyHh7s1zHE97u0KlT/RECzCKAdmI+LEoC1eDh/RDji9JgFqyO+wPDb86Oa/sXkily1+oi4FzJQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.27.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.27.4.tgz",
+ "integrity": "sha512-qyyprhyGb7+RBfMPeww9FlHwKkCXdKHeGgSqmIXw9VSUtvyFZ6WZRtnxgbuz76FK7LyoN8t/eINRbPUcvXB5fw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.27.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.27.4.tgz",
+ "integrity": "sha512-PFz+y2kb6tbh7m3A7nA9++eInGcDVZUACulf/KzDtovvdTizHpZaJty7Gp0lFwSQcrnebHOqxF1MaKZd7psVRg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.27.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.27.4.tgz",
+ "integrity": "sha512-Ni8mMtfo+o/G7DVtweXXV/Ol2TFf63KYjTtoZ5f078AUgJTmaIJnj4JFU7TK/9SVWTaSJGxPi5zMDgK4w+Ez7Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.27.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.27.4.tgz",
+ "integrity": "sha512-5AeeAF1PB9TUzD+3cROzFTnAJAcVUGLuR8ng0E0WXGkYhp6RD6L+6szYVX+64Rs0r72019KHZS1ka1q+zU/wUw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.27.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.27.4.tgz",
+ "integrity": "sha512-yOpVsA4K5qVwu2CaS3hHxluWIK5HQTjNV4tWjQXluMiiiu4pJj4BN98CvxohNCpcjMeTXk/ZMJBRbgRg8HBB6A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.27.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.27.4.tgz",
+ "integrity": "sha512-KtwEJOaHAVJlxV92rNYiG9JQwQAdhBlrjNRp7P9L8Cb4Rer3in+0A+IPhJC9y68WAi9H0sX4AiG2NTsVlmqJeQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.27.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.27.4.tgz",
+ "integrity": "sha512-3j4jx1TppORdTAoBJRd+/wJRGCPC0ETWkXOecJ6PPZLj6SptXkrXcNqdj0oclbKML6FkQltdz7bBA3rUSirZug==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
"node_modules/@rushstack/node-core-library": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-4.0.2.tgz",
@@ -1669,12 +1975,6 @@
"sprintf-js": "~1.0.2"
}
},
- "node_modules/@sinclair/typebox": {
- "version": "0.27.8",
- "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
- "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
- "dev": true
- },
"node_modules/@sindresorhus/merge-streams": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz",
@@ -1688,15 +1988,15 @@
}
},
"node_modules/@tailwindcss/forms": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.7.tgz",
- "integrity": "sha512-QE7X69iQI+ZXwldE+rzasvbJiyV/ju1FGHH0Qn2W3FKbuYtqp8LKcy6iSw79fVUT5/Vvf+0XgLCeYVG+UV6hOw==",
+ "version": "0.5.9",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.9.tgz",
+ "integrity": "sha512-tM4XVr2+UVTxXJzey9Twx48c1gcxFStqn1pQz0tRsX8o3DvxhN5oY5pvyAbUx7VTaZxpej4Zzvc6h+1RJBzpIg==",
"dev": true,
"dependencies": {
"mini-svg-data-uri": "^1.2.3"
},
"peerDependencies": {
- "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1"
+ "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20"
}
},
"node_modules/@tanstack/match-sorter-utils": {
@@ -1778,21 +2078,6 @@
"integrity": "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==",
"dev": true
},
- "node_modules/@types/chai": {
- "version": "4.3.14",
- "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.14.tgz",
- "integrity": "sha512-Wj71sXE4Q4AkGdG9Tvq1u/fquNz9EdG4LIJMwVVII7ashjD/8cf8fyIfJAjRr6YcsXnSE8cOGQPq1gqeR8z+3w==",
- "dev": true
- },
- "node_modules/@types/chai-subset": {
- "version": "1.3.5",
- "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.5.tgz",
- "integrity": "sha512-c2mPnw+xHtXDoHmdtcCXGwyLMiauiAyxWMzhGpqHC4nqI/Y5G2XhTampslK2rb59kpcuHon03UH8W6iYUzw88A==",
- "dev": true,
- "dependencies": {
- "@types/chai": "*"
- }
- },
"node_modules/@types/cookie": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
@@ -1800,9 +2085,9 @@
"dev": true
},
"node_modules/@types/estree": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
- "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
+ "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="
},
"node_modules/@types/json-schema": {
"version": "7.0.15",
@@ -1815,20 +2100,12 @@
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
"peer": true
},
- "node_modules/@types/mute-stream": {
- "version": "0.0.4",
- "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz",
- "integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==",
- "dev": true,
- "dependencies": {
- "@types/node": "*"
- }
- },
"node_modules/@types/node": {
"version": "20.12.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz",
"integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==",
"dev": true,
+ "peer": true,
"dependencies": {
"undici-types": "~5.26.4"
}
@@ -1844,17 +2121,17 @@
"integrity": "sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==",
"dev": true
},
+ "node_modules/@types/tough-cookie": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz",
+ "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==",
+ "dev": true
+ },
"node_modules/@types/web-bluetooth": {
"version": "0.0.20",
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz",
"integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow=="
},
- "node_modules/@types/wrap-ansi": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz",
- "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==",
- "dev": true
- },
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "7.7.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.7.1.tgz",
@@ -2084,108 +2361,128 @@
"integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ=="
},
"node_modules/@vitejs/plugin-vue": {
- "version": "4.6.2",
- "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.6.2.tgz",
- "integrity": "sha512-kqf7SGFoG+80aZG6Pf+gsZIVvGSCKE98JbiWqcCV9cThtg91Jav0yvYFC9Zb+jKetNGF6ZKeoaxgZfND21fWKw==",
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.1.tgz",
+ "integrity": "sha512-cxh314tzaWwOLqVes2gnnCtvBDcM1UMdn+iFR+UjAn411dPT3tOmqrJjbMd7koZpMAmBM/GqeV4n9ge7JSiJJQ==",
"dev": true,
"engines": {
- "node": "^14.18.0 || >=16.0.0"
+ "node": "^18.0.0 || >=20.0.0"
},
"peerDependencies": {
- "vite": "^4.0.0 || ^5.0.0",
+ "vite": "^5.0.0 || ^6.0.0",
"vue": "^3.2.25"
}
},
"node_modules/@vitest/expect": {
- "version": "0.34.6",
- "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.6.tgz",
- "integrity": "sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==",
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.6.tgz",
+ "integrity": "sha512-9M1UR9CAmrhJOMoSwVnPh2rELPKhYo0m/CSgqw9PyStpxtkwhmdM6XYlXGKeYyERY1N6EIuzkQ7e3Lm1WKCoUg==",
"dev": true,
"dependencies": {
- "@vitest/spy": "0.34.6",
- "@vitest/utils": "0.34.6",
- "chai": "^4.3.10"
+ "@vitest/spy": "2.1.6",
+ "@vitest/utils": "2.1.6",
+ "chai": "^5.1.2",
+ "tinyrainbow": "^1.2.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
}
},
- "node_modules/@vitest/runner": {
- "version": "0.34.6",
- "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.6.tgz",
- "integrity": "sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==",
+ "node_modules/@vitest/mocker": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.6.tgz",
+ "integrity": "sha512-MHZp2Z+Q/A3am5oD4WSH04f9B0T7UvwEb+v5W0kCYMhtXGYbdyl2NUk1wdSMqGthmhpiThPDp/hEoVwu16+u1A==",
"dev": true,
"dependencies": {
- "@vitest/utils": "0.34.6",
- "p-limit": "^4.0.0",
- "pathe": "^1.1.1"
+ "@vitest/spy": "2.1.6",
+ "estree-walker": "^3.0.3",
+ "magic-string": "^0.30.12"
},
"funding": {
"url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "msw": "^2.4.9",
+ "vite": "^5.0.0 || ^6.0.0"
+ },
+ "peerDependenciesMeta": {
+ "msw": {
+ "optional": true
+ },
+ "vite": {
+ "optional": true
+ }
}
},
- "node_modules/@vitest/runner/node_modules/p-limit": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz",
- "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==",
+ "node_modules/@vitest/mocker/node_modules/estree-walker": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
+ "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
"dev": true,
"dependencies": {
- "yocto-queue": "^1.0.0"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ "@types/estree": "^1.0.0"
+ }
+ },
+ "node_modules/@vitest/pretty-format": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.6.tgz",
+ "integrity": "sha512-exZyLcEnHgDMKc54TtHca4McV4sKT+NKAe9ix/yhd/qkYb/TP8HTyXRFDijV19qKqTZM0hPL4753zU/U8L/gAA==",
+ "dev": true,
+ "dependencies": {
+ "tinyrainbow": "^1.2.0"
},
"funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "url": "https://opencollective.com/vitest"
}
},
- "node_modules/@vitest/runner/node_modules/yocto-queue": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz",
- "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==",
+ "node_modules/@vitest/runner": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.6.tgz",
+ "integrity": "sha512-SjkRGSFyrA82m5nz7To4CkRSEVWn/rwQISHoia/DB8c6IHIhaE/UNAo+7UfeaeJRE979XceGl00LNkIz09RFsA==",
"dev": true,
- "engines": {
- "node": ">=12.20"
+ "dependencies": {
+ "@vitest/utils": "2.1.6",
+ "pathe": "^1.1.2"
},
"funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "url": "https://opencollective.com/vitest"
}
},
"node_modules/@vitest/snapshot": {
- "version": "0.34.6",
- "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.6.tgz",
- "integrity": "sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==",
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.6.tgz",
+ "integrity": "sha512-5JTWHw8iS9l3v4/VSuthCndw1lN/hpPB+mlgn1BUhFbobeIUj1J1V/Bj2t2ovGEmkXLTckFjQddsxS5T6LuVWw==",
"dev": true,
"dependencies": {
- "magic-string": "^0.30.1",
- "pathe": "^1.1.1",
- "pretty-format": "^29.5.0"
+ "@vitest/pretty-format": "2.1.6",
+ "magic-string": "^0.30.12",
+ "pathe": "^1.1.2"
},
"funding": {
"url": "https://opencollective.com/vitest"
}
},
"node_modules/@vitest/spy": {
- "version": "0.34.6",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.6.tgz",
- "integrity": "sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==",
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.6.tgz",
+ "integrity": "sha512-oTFObV8bd4SDdRka5O+mSh5w9irgx5IetrD5i+OsUUsk/shsBoHifwCzy45SAORzAhtNiprUVaK3hSCCzZh1jQ==",
"dev": true,
"dependencies": {
- "tinyspy": "^2.1.1"
+ "tinyspy": "^3.0.2"
},
"funding": {
"url": "https://opencollective.com/vitest"
}
},
"node_modules/@vitest/utils": {
- "version": "0.34.6",
- "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.6.tgz",
- "integrity": "sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==",
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.6.tgz",
+ "integrity": "sha512-ixNkFy3k4vokOUTU2blIUvOgKq/N2PW8vKIjZZYsGJCMX69MRa9J2sKqX5hY/k5O5Gty3YJChepkqZ3KM9LyIQ==",
"dev": true,
"dependencies": {
- "diff-sequences": "^29.4.3",
- "loupe": "^2.3.6",
- "pretty-format": "^29.5.0"
+ "@vitest/pretty-format": "2.1.6",
+ "loupe": "^3.1.2",
+ "tinyrainbow": "^1.2.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
@@ -2394,9 +2691,9 @@
"dev": true
},
"node_modules/@vuepic/vue-datepicker": {
- "version": "8.4.0",
- "resolved": "https://registry.npmjs.org/@vuepic/vue-datepicker/-/vue-datepicker-8.4.0.tgz",
- "integrity": "sha512-Twgvqwd5GrQf3JT2DvAQ/Ku0+sM51zsH1OkQKoRwYqJyF+EugItS8I0CveYmcI3Gbu92RZ9C3DMutvkaiuDzAQ==",
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/@vuepic/vue-datepicker/-/vue-datepicker-9.0.3.tgz",
+ "integrity": "sha512-OtCAKG+CkVBpCwnPx7/BGRF+/z+jDzNl2cMBpcr8j2NkAN+13xkUt7sctbOVKbG/jhuXtKoUSedI69e0cDXPXw==",
"dependencies": {
"date-fns": "^3.6.0"
},
@@ -2408,23 +2705,23 @@
}
},
"node_modules/@vueuse/core": {
- "version": "10.9.0",
- "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.9.0.tgz",
- "integrity": "sha512-/1vjTol8SXnx6xewDEKfS0Ra//ncg4Hb0DaZiwKf7drgfMsKFExQ+FnnENcN6efPen+1kIzhLQoGSy0eDUVOMg==",
+ "version": "11.0.3",
+ "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-11.0.3.tgz",
+ "integrity": "sha512-RENlh64+SYA9XMExmmH1a3TPqeIuJBNNB/63GT35MZI+zpru3oMRUA6cEFr9HmGqEgUisurwGwnIieF6qu3aXw==",
"dependencies": {
"@types/web-bluetooth": "^0.0.20",
- "@vueuse/metadata": "10.9.0",
- "@vueuse/shared": "10.9.0",
- "vue-demi": ">=0.14.7"
+ "@vueuse/metadata": "11.0.3",
+ "@vueuse/shared": "11.0.3",
+ "vue-demi": ">=0.14.10"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/core/node_modules/vue-demi": {
- "version": "0.14.7",
- "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz",
- "integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==",
+ "version": "0.14.10",
+ "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
+ "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
@@ -2447,20 +2744,20 @@
}
},
"node_modules/@vueuse/metadata": {
- "version": "10.9.0",
- "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.9.0.tgz",
- "integrity": "sha512-iddNbg3yZM0X7qFY2sAotomgdHK7YJ6sKUvQqbvwnf7TmaVPxS4EJydcNsVejNdS8iWCtDk+fYXr7E32nyTnGA==",
+ "version": "11.0.3",
+ "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-11.0.3.tgz",
+ "integrity": "sha512-+FtbO4SD5WpsOcQTcC0hAhNlOid6QNLzqedtquTtQ+CRNBoAt9GuV07c6KNHK1wCmlq8DFPwgiLF2rXwgSHX5Q==",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/router": {
- "version": "10.9.0",
- "resolved": "https://registry.npmjs.org/@vueuse/router/-/router-10.9.0.tgz",
- "integrity": "sha512-MOmrCMQlRuPS4PExE1hy8T0XbZUXaNbEuh7CAG5mC8kdvdgANQMkdvJ7vIEOP27n5mXK/4YjvXJOZSsur4E0QQ==",
+ "version": "11.0.3",
+ "resolved": "https://registry.npmjs.org/@vueuse/router/-/router-11.0.3.tgz",
+ "integrity": "sha512-Sa8wNATd4DoAWkO5NgV+sfTU9dOtC8pi+GEbtzOdC7/99fWK8k5/dfbfkt+OWcpwXoToNidBqnAZafknlYb2ig==",
"dependencies": {
- "@vueuse/shared": "10.9.0",
- "vue-demi": ">=0.14.7"
+ "@vueuse/shared": "11.0.3",
+ "vue-demi": ">=0.14.10"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
@@ -2470,9 +2767,9 @@
}
},
"node_modules/@vueuse/router/node_modules/vue-demi": {
- "version": "0.14.7",
- "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz",
- "integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==",
+ "version": "0.14.10",
+ "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
+ "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
@@ -2495,20 +2792,20 @@
}
},
"node_modules/@vueuse/shared": {
- "version": "10.9.0",
- "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.9.0.tgz",
- "integrity": "sha512-Uud2IWncmAfJvRaFYzv5OHDli+FbOzxiVEQdLCKQKLyhz94PIyFC3CHcH7EDMwIn8NPtD06+PNbC/PiO0LGLtw==",
+ "version": "11.0.3",
+ "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-11.0.3.tgz",
+ "integrity": "sha512-0rY2m6HS5t27n/Vp5cTDsKTlNnimCqsbh/fmT2LgE+aaU42EMfXo8+bNX91W9I7DDmxfuACXMmrd7d79JxkqWA==",
"dependencies": {
- "vue-demi": ">=0.14.7"
+ "vue-demi": ">=0.14.10"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/shared/node_modules/vue-demi": {
- "version": "0.14.7",
- "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz",
- "integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==",
+ "version": "0.14.10",
+ "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
+ "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
@@ -2558,13 +2855,16 @@
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
- "node_modules/acorn-walk": {
- "version": "8.3.2",
- "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz",
- "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==",
+ "node_modules/agent-base": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
+ "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
"dev": true,
+ "dependencies": {
+ "debug": "^4.3.4"
+ },
"engines": {
- "node": ">=0.4.0"
+ "node": ">= 14"
}
},
"node_modules/ajv": {
@@ -2622,7 +2922,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
- "dev": true,
"engines": {
"node": ">=12"
},
@@ -2647,8 +2946,7 @@
"node_modules/any-promise": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
- "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
- "dev": true
+ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="
},
"node_modules/anymatch": {
"version": "3.1.3",
@@ -2665,8 +2963,7 @@
"node_modules/arg": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
- "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
- "dev": true
+ "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="
},
"node_modules/argparse": {
"version": "2.0.1",
@@ -2796,14 +3093,20 @@
}
},
"node_modules/assertion-error": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
- "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
+ "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
"dev": true,
"engines": {
- "node": "*"
+ "node": ">=12"
}
},
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "dev": true
+ },
"node_modules/autoprefixer": {
"version": "10.4.19",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz",
@@ -2886,11 +3189,11 @@
}
},
"node_modules/braces": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dependencies": {
- "fill-range": "^7.0.1"
+ "fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
@@ -2988,15 +3291,14 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
"integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
- "dev": true,
"engines": {
"node": ">= 6"
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001612",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001612.tgz",
- "integrity": "sha512-lFgnZ07UhaCcsSZgWW0K5j4e69dK1u/ltrL9lTUiFOwNHs12S3UMIEYgBV0Z6C6hRDev7iRnMzzYmKabYdXF9g==",
+ "version": "1.0.30001684",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001684.tgz",
+ "integrity": "sha512-G1LRwLIQjBQoyq0ZJGqGIJUXzJ8irpbjHLpVRXDvBEScFJ9b17sgK6vlx0GAJFE21okD7zXl08rRRUfq6HdoEQ==",
"dev": true,
"funding": [
{
@@ -3014,21 +3316,19 @@
]
},
"node_modules/chai": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz",
- "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==",
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.2.tgz",
+ "integrity": "sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==",
"dev": true,
"dependencies": {
- "assertion-error": "^1.1.0",
- "check-error": "^1.0.3",
- "deep-eql": "^4.1.3",
- "get-func-name": "^2.0.2",
- "loupe": "^2.3.6",
- "pathval": "^1.1.1",
- "type-detect": "^4.0.8"
+ "assertion-error": "^2.0.1",
+ "check-error": "^2.1.1",
+ "deep-eql": "^5.0.1",
+ "loupe": "^3.1.0",
+ "pathval": "^2.0.0"
},
"engines": {
- "node": ">=4"
+ "node": ">=12"
}
},
"node_modules/chalk": {
@@ -3074,15 +3374,12 @@
}
},
"node_modules/check-error": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz",
- "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==",
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz",
+ "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==",
"dev": true,
- "dependencies": {
- "get-func-name": "^2.0.2"
- },
"engines": {
- "node": "*"
+ "node": ">= 16"
}
},
"node_modules/chokidar": {
@@ -3232,6 +3529,18 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/commander": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
@@ -3268,9 +3577,9 @@
}
},
"node_modules/cookie": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
- "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
+ "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
"dev": true,
"engines": {
"node": ">= 0.6"
@@ -3303,9 +3612,9 @@
}
},
"node_modules/cross-spawn": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dependencies": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
@@ -3326,11 +3635,36 @@
"node": ">=4"
}
},
+ "node_modules/cssstyle": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz",
+ "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==",
+ "dev": true,
+ "dependencies": {
+ "rrweb-cssom": "^0.7.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
},
+ "node_modules/data-urls": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz",
+ "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==",
+ "dev": true,
+ "dependencies": {
+ "whatwg-mimetype": "^4.0.0",
+ "whatwg-url": "^14.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/data-view-buffer": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz",
@@ -3403,11 +3737,11 @@
"dev": true
},
"node_modules/debug": {
- "version": "4.3.4",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
- "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
"dependencies": {
- "ms": "2.1.2"
+ "ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
@@ -3418,14 +3752,17 @@
}
}
},
+ "node_modules/decimal.js": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz",
+ "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==",
+ "dev": true
+ },
"node_modules/deep-eql": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz",
- "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==",
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz",
+ "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==",
"dev": true,
- "dependencies": {
- "type-detect": "^4.0.0"
- },
"engines": {
"node": ">=6"
}
@@ -3478,21 +3815,20 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/didyoumean": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
- "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
- "dev": true
- },
- "node_modules/diff-sequences": {
- "version": "29.6.3",
- "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
- "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"dev": true,
"engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ "node": ">=0.4.0"
}
},
+ "node_modules/didyoumean": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
+ "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="
+ },
"node_modules/dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@@ -3515,8 +3851,7 @@
"node_modules/dlv": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
- "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
- "dev": true
+ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
},
"node_modules/doctrine": {
"version": "3.0.0",
@@ -3532,8 +3867,7 @@
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
- "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
- "dev": true
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
},
"node_modules/editorconfig": {
"version": "1.0.4",
@@ -3568,8 +3902,7 @@
"node_modules/emoji-regex": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
- "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
- "dev": true
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
},
"node_modules/enquirer": {
"version": "2.4.1",
@@ -3715,6 +4048,12 @@
"node": ">= 0.4"
}
},
+ "node_modules/es-module-lexer": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz",
+ "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==",
+ "dev": true
+ },
"node_modules/es-object-atoms": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz",
@@ -3768,9 +4107,9 @@
}
},
"node_modules/esbuild": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
- "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
+ "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
"dev": true,
"hasInstallScript": true,
"bin": {
@@ -3780,28 +4119,29 @@
"node": ">=12"
},
"optionalDependencies": {
- "@esbuild/android-arm": "0.18.20",
- "@esbuild/android-arm64": "0.18.20",
- "@esbuild/android-x64": "0.18.20",
- "@esbuild/darwin-arm64": "0.18.20",
- "@esbuild/darwin-x64": "0.18.20",
- "@esbuild/freebsd-arm64": "0.18.20",
- "@esbuild/freebsd-x64": "0.18.20",
- "@esbuild/linux-arm": "0.18.20",
- "@esbuild/linux-arm64": "0.18.20",
- "@esbuild/linux-ia32": "0.18.20",
- "@esbuild/linux-loong64": "0.18.20",
- "@esbuild/linux-mips64el": "0.18.20",
- "@esbuild/linux-ppc64": "0.18.20",
- "@esbuild/linux-riscv64": "0.18.20",
- "@esbuild/linux-s390x": "0.18.20",
- "@esbuild/linux-x64": "0.18.20",
- "@esbuild/netbsd-x64": "0.18.20",
- "@esbuild/openbsd-x64": "0.18.20",
- "@esbuild/sunos-x64": "0.18.20",
- "@esbuild/win32-arm64": "0.18.20",
- "@esbuild/win32-ia32": "0.18.20",
- "@esbuild/win32-x64": "0.18.20"
+ "@esbuild/aix-ppc64": "0.21.5",
+ "@esbuild/android-arm": "0.21.5",
+ "@esbuild/android-arm64": "0.21.5",
+ "@esbuild/android-x64": "0.21.5",
+ "@esbuild/darwin-arm64": "0.21.5",
+ "@esbuild/darwin-x64": "0.21.5",
+ "@esbuild/freebsd-arm64": "0.21.5",
+ "@esbuild/freebsd-x64": "0.21.5",
+ "@esbuild/linux-arm": "0.21.5",
+ "@esbuild/linux-arm64": "0.21.5",
+ "@esbuild/linux-ia32": "0.21.5",
+ "@esbuild/linux-loong64": "0.21.5",
+ "@esbuild/linux-mips64el": "0.21.5",
+ "@esbuild/linux-ppc64": "0.21.5",
+ "@esbuild/linux-riscv64": "0.21.5",
+ "@esbuild/linux-s390x": "0.21.5",
+ "@esbuild/linux-x64": "0.21.5",
+ "@esbuild/netbsd-x64": "0.21.5",
+ "@esbuild/openbsd-x64": "0.21.5",
+ "@esbuild/sunos-x64": "0.21.5",
+ "@esbuild/win32-arm64": "0.21.5",
+ "@esbuild/win32-ia32": "0.21.5",
+ "@esbuild/win32-x64": "0.21.5"
}
},
"node_modules/escalade": {
@@ -4382,6 +4722,15 @@
"node": ">=0.10.0"
}
},
+ "node_modules/expect-type": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.1.0.tgz",
+ "integrity": "sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
"node_modules/fast-check": {
"version": "3.17.2",
"resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.17.2.tgz",
@@ -4459,9 +4808,9 @@
}
},
"node_modules/fill-range": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
- "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dependencies": {
"to-regex-range": "^5.0.1"
},
@@ -4515,7 +4864,6 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
"integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
- "dev": true,
"dependencies": {
"cross-spawn": "^7.0.0",
"signal-exit": "^4.0.1"
@@ -4527,6 +4875,20 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "dev": true,
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/fraction.js": {
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
@@ -4628,15 +4990,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/get-func-name": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz",
- "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==",
- "dev": true,
- "engines": {
- "node": "*"
- }
- },
"node_modules/get-intrinsic": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
@@ -4689,7 +5042,6 @@
"version": "10.3.12",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz",
"integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==",
- "dev": true,
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^2.3.6",
@@ -4916,6 +5268,56 @@
"node": "^16.14.0 || >=18.0.0"
}
},
+ "node_modules/html-encoding-sniffer": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz",
+ "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==",
+ "dev": true,
+ "dependencies": {
+ "whatwg-encoding": "^3.1.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/http-proxy-agent": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
+ "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
+ "dev": true,
+ "dependencies": {
+ "agent-base": "^7.1.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz",
+ "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==",
+ "dev": true,
+ "dependencies": {
+ "agent-base": "^7.0.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "dev": true,
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/ignore": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
@@ -5146,7 +5548,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -5223,6 +5624,12 @@
"node": ">=8"
}
},
+ "node_modules/is-potential-custom-element-name": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
+ "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
+ "dev": true
+ },
"node_modules/is-regex": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
@@ -5350,7 +5757,6 @@
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
"integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
- "dev": true,
"dependencies": {
"@isaacs/cliui": "^8.0.2"
},
@@ -5365,10 +5771,9 @@
}
},
"node_modules/jiti": {
- "version": "1.21.0",
- "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz",
- "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==",
- "dev": true,
+ "version": "1.21.6",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz",
+ "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==",
"bin": {
"jiti": "bin/jiti.js"
}
@@ -5426,6 +5831,55 @@
"js-yaml": "bin/js-yaml.js"
}
},
+ "node_modules/jsdom": {
+ "version": "25.0.0",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.0.tgz",
+ "integrity": "sha512-OhoFVT59T7aEq75TVw9xxEfkXgacpqAhQaYgP9y/fDqWQCMB/b1H66RfmPm/MaeaAIU9nDwMOVTlPN51+ao6CQ==",
+ "dev": true,
+ "dependencies": {
+ "cssstyle": "^4.0.1",
+ "data-urls": "^5.0.0",
+ "decimal.js": "^10.4.3",
+ "form-data": "^4.0.0",
+ "html-encoding-sniffer": "^4.0.0",
+ "http-proxy-agent": "^7.0.2",
+ "https-proxy-agent": "^7.0.5",
+ "is-potential-custom-element-name": "^1.0.1",
+ "nwsapi": "^2.2.12",
+ "parse5": "^7.1.2",
+ "rrweb-cssom": "^0.7.1",
+ "saxes": "^6.0.0",
+ "symbol-tree": "^3.2.4",
+ "tough-cookie": "^4.1.4",
+ "w3c-xmlserializer": "^5.0.0",
+ "webidl-conversions": "^7.0.0",
+ "whatwg-encoding": "^3.1.1",
+ "whatwg-mimetype": "^4.0.0",
+ "whatwg-url": "^14.0.0",
+ "ws": "^8.18.0",
+ "xml-name-validator": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "canvas": "^2.11.2"
+ },
+ "peerDependenciesMeta": {
+ "canvas": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jsdom/node_modules/xml-name-validator": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz",
+ "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/json-buffer": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
@@ -5523,7 +5977,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
"integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
- "dev": true,
"engines": {
"node": ">=10"
}
@@ -5531,20 +5984,7 @@
"node_modules/lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
- "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
- "dev": true
- },
- "node_modules/local-pkg": {
- "version": "0.4.3",
- "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz",
- "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==",
- "dev": true,
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/antfu"
- }
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
},
"node_modules/locate-path": {
"version": "6.0.0",
@@ -5623,29 +6063,25 @@
}
},
"node_modules/loupe": {
- "version": "2.3.7",
- "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz",
- "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==",
- "dev": true,
- "dependencies": {
- "get-func-name": "^2.0.1"
- }
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz",
+ "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==",
+ "dev": true
},
"node_modules/lru-cache": {
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz",
"integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==",
- "dev": true,
"engines": {
"node": "14 || >=16.14"
}
},
"node_modules/magic-string": {
- "version": "0.30.10",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz",
- "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==",
+ "version": "0.30.14",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.14.tgz",
+ "integrity": "sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==",
"dependencies": {
- "@jridgewell/sourcemap-codec": "^1.4.15"
+ "@jridgewell/sourcemap-codec": "^1.5.0"
}
},
"node_modules/merge2": {
@@ -5657,17 +6093,38 @@
}
},
"node_modules/micromatch": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
- "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"dependencies": {
- "braces": "^3.0.2",
+ "braces": "^3.0.3",
"picomatch": "^2.3.1"
},
"engines": {
"node": ">=8.6"
}
},
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dev": true,
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/mimic-fn": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
@@ -5690,7 +6147,6 @@
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz",
"integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==",
- "dev": true,
"dependencies": {
"brace-expansion": "^2.0.1"
},
@@ -5714,7 +6170,6 @@
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
"integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
- "dev": true,
"engines": {
"node": ">=16 || 14 >=14.17"
}
@@ -5731,22 +6186,23 @@
}
},
"node_modules/ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"node_modules/msw": {
- "version": "2.2.14",
- "resolved": "https://registry.npmjs.org/msw/-/msw-2.2.14.tgz",
- "integrity": "sha512-64i8rNCa1xzDK8ZYsTrVMli05D687jty8+Th+PU5VTbJ2/4P7fkQFVyDQ6ZFT5FrNR8z2BHhbY47fKNvfHrumA==",
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/msw/-/msw-2.6.6.tgz",
+ "integrity": "sha512-npfIIVRHKQX3Lw4aLWX4wBh+lQwpqdZNyJYB5K/+ktK8NhtkdsTxGK7WDrgknozcVyRI7TOqY6yBS9j2FTR+YQ==",
"dev": true,
"hasInstallScript": true,
"dependencies": {
- "@bundled-es-modules/cookie": "^2.0.0",
+ "@bundled-es-modules/cookie": "^2.0.1",
"@bundled-es-modules/statuses": "^1.0.1",
- "@inquirer/confirm": "^3.0.0",
- "@mswjs/cookies": "^1.1.0",
- "@mswjs/interceptors": "^0.26.14",
+ "@bundled-es-modules/tough-cookie": "^0.1.6",
+ "@inquirer/confirm": "^5.0.0",
+ "@mswjs/interceptors": "^0.37.0",
+ "@open-draft/deferred-promise": "^2.2.0",
"@open-draft/until": "^2.1.0",
"@types/cookie": "^0.6.0",
"@types/statuses": "^2.0.4",
@@ -5754,10 +6210,10 @@
"graphql": "^16.8.1",
"headers-polyfill": "^4.0.2",
"is-node-process": "^1.2.0",
- "outvariant": "^1.4.2",
- "path-to-regexp": "^6.2.0",
+ "outvariant": "^1.4.3",
+ "path-to-regexp": "^6.3.0",
"strict-event-emitter": "^0.5.1",
- "type-fest": "^4.9.0",
+ "type-fest": "^4.26.1",
"yargs": "^17.7.2"
},
"bin": {
@@ -5770,7 +6226,7 @@
"url": "https://github.com/sponsors/mswjs"
},
"peerDependencies": {
- "typescript": ">= 4.7.x"
+ "typescript": ">= 4.8.x"
},
"peerDependenciesMeta": {
"typescript": {
@@ -5785,19 +6241,18 @@
"dev": true
},
"node_modules/mute-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz",
- "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz",
+ "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==",
"dev": true,
"engines": {
- "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ "node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/mz": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
"integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
- "dev": true,
"dependencies": {
"any-promise": "^1.0.0",
"object-assign": "^4.0.1",
@@ -5890,11 +6345,16 @@
"url": "https://github.com/fb55/nth-check?sponsor=1"
}
},
+ "node_modules/nwsapi": {
+ "version": "2.2.12",
+ "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz",
+ "integrity": "sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==",
+ "dev": true
+ },
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -5903,7 +6363,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
"integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
- "dev": true,
"engines": {
"node": ">= 6"
}
@@ -6108,9 +6567,9 @@
}
},
"node_modules/outvariant": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.2.tgz",
- "integrity": "sha512-Ou3dJ6bA/UJ5GVHxah4LnqDwZRwAmWxrG3wtrHrbGnP4RnLCtA64A4F+ae7Y8ww660JaddSoArUR5HjipWSHAQ==",
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz",
+ "integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==",
"dev": true
},
"node_modules/p-limit": {
@@ -6170,6 +6629,18 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/parse5": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
+ "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
+ "dev": true,
+ "dependencies": {
+ "entities": "^4.4.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
"node_modules/path-browserify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
@@ -6209,7 +6680,6 @@
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz",
"integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==",
- "dev": true,
"dependencies": {
"lru-cache": "^10.2.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
@@ -6222,9 +6692,9 @@
}
},
"node_modules/path-to-regexp": {
- "version": "6.2.2",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz",
- "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==",
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz",
+ "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==",
"dev": true
},
"node_modules/path-type": {
@@ -6245,18 +6715,18 @@
"integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="
},
"node_modules/pathval": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
- "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz",
+ "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==",
"dev": true,
"engines": {
- "node": "*"
+ "node": ">= 14.16"
}
},
"node_modules/picocolors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
- "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
},
"node_modules/picomatch": {
"version": "2.3.1",
@@ -6273,7 +6743,6 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -6332,7 +6801,6 @@
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
"integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
- "dev": true,
"engines": {
"node": ">= 6"
}
@@ -6357,9 +6825,9 @@
}
},
"node_modules/postcss": {
- "version": "8.4.38",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
- "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
+ "version": "8.4.49",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz",
+ "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==",
"funding": [
{
"type": "opencollective",
@@ -6376,8 +6844,8 @@
],
"dependencies": {
"nanoid": "^3.3.7",
- "picocolors": "^1.0.0",
- "source-map-js": "^1.2.0"
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
},
"engines": {
"node": "^10 || ^12 || >=14"
@@ -6387,7 +6855,6 @@
"version": "15.1.0",
"resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
"integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
- "dev": true,
"dependencies": {
"postcss-value-parser": "^4.0.0",
"read-cache": "^1.0.0",
@@ -6404,7 +6871,6 @@
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
"integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
- "dev": true,
"dependencies": {
"camelcase-css": "^2.0.1"
},
@@ -6423,7 +6889,6 @@
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
"integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
- "dev": true,
"funding": [
{
"type": "opencollective",
@@ -6458,7 +6923,6 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz",
"integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==",
- "dev": true,
"engines": {
"node": ">=14"
},
@@ -6467,28 +6931,33 @@
}
},
"node_modules/postcss-nested": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz",
- "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==",
- "dev": true,
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
+ "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
"dependencies": {
- "postcss-selector-parser": "^6.0.11"
+ "postcss-selector-parser": "^6.1.1"
},
"engines": {
"node": ">=12.0"
},
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
"peerDependencies": {
"postcss": "^8.2.14"
}
},
"node_modules/postcss-selector-parser": {
- "version": "6.0.16",
- "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz",
- "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==",
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
+ "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
@@ -6500,8 +6969,7 @@
"node_modules/postcss-value-parser": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
- "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
- "dev": true
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
},
"node_modules/prelude-ls": {
"version": "1.2.1",
@@ -6537,38 +7005,18 @@
"node": ">=6.0.0"
}
},
- "node_modules/pretty-format": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
- "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
- "dev": true,
+ "node_modules/primevue": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/primevue/-/primevue-4.2.4.tgz",
+ "integrity": "sha512-aMQymoO489isReSF/bScypswOnLBU29qkeTulGj3Wntb9plvzTIWjA4+iyDOsyxGmV5GVIvD+DuTw5FNCDWgSw==",
"dependencies": {
- "@jest/schemas": "^29.6.3",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
+ "@primeuix/styled": "^0.3.2",
+ "@primeuix/utils": "^0.3.2",
+ "@primevue/core": "4.2.4",
+ "@primevue/icons": "4.2.4"
},
"engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/pretty-format/node_modules/ansi-styles": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
- "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/primevue": {
- "version": "3.51.0",
- "resolved": "https://registry.npmjs.org/primevue/-/primevue-3.51.0.tgz",
- "integrity": "sha512-BdMveidLSr0fNJ5+mxuke8mMCHyiXwvfDP4iwPr6R98rl3E0Wcm1u4/RKVrL7o0Iq606SXyhPQL3LGyAfXngcA==",
- "peerDependencies": {
- "vue": "^3.0.0"
+ "node": ">=12.11.0"
}
},
"node_modules/proc-log": {
@@ -6599,6 +7047,12 @@
"integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==",
"dev": true
},
+ "node_modules/psl": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
+ "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==",
+ "dev": true
+ },
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
@@ -6623,6 +7077,12 @@
}
]
},
+ "node_modules/querystringify": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
+ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
+ "dev": true
+ },
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@@ -6642,17 +7102,10 @@
}
]
},
- "node_modules/react-is": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
- "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
- "dev": true
- },
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
"integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
- "dev": true,
"dependencies": {
"pify": "^2.3.0"
}
@@ -6713,6 +7166,12 @@
"node": ">=0.10.0"
}
},
+ "node_modules/requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
+ "dev": true
+ },
"node_modules/resolve": {
"version": "1.22.8",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
@@ -6831,18 +7290,39 @@
}
},
"node_modules/rollup": {
- "version": "3.29.4",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz",
- "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==",
+ "version": "4.27.4",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.27.4.tgz",
+ "integrity": "sha512-RLKxqHEMjh/RGLsDxAEsaLO3mWgyoU6x9w6n1ikAzet4B3gI2/3yP6PWY2p9QzRTh6MfEIXB3MwsOY0Iv3vNrw==",
"devOptional": true,
+ "dependencies": {
+ "@types/estree": "1.0.6"
+ },
"bin": {
"rollup": "dist/bin/rollup"
},
"engines": {
- "node": ">=14.18.0",
+ "node": ">=18.0.0",
"npm": ">=8.0.0"
},
"optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.27.4",
+ "@rollup/rollup-android-arm64": "4.27.4",
+ "@rollup/rollup-darwin-arm64": "4.27.4",
+ "@rollup/rollup-darwin-x64": "4.27.4",
+ "@rollup/rollup-freebsd-arm64": "4.27.4",
+ "@rollup/rollup-freebsd-x64": "4.27.4",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.27.4",
+ "@rollup/rollup-linux-arm-musleabihf": "4.27.4",
+ "@rollup/rollup-linux-arm64-gnu": "4.27.4",
+ "@rollup/rollup-linux-arm64-musl": "4.27.4",
+ "@rollup/rollup-linux-powerpc64le-gnu": "4.27.4",
+ "@rollup/rollup-linux-riscv64-gnu": "4.27.4",
+ "@rollup/rollup-linux-s390x-gnu": "4.27.4",
+ "@rollup/rollup-linux-x64-gnu": "4.27.4",
+ "@rollup/rollup-linux-x64-musl": "4.27.4",
+ "@rollup/rollup-win32-arm64-msvc": "4.27.4",
+ "@rollup/rollup-win32-ia32-msvc": "4.27.4",
+ "@rollup/rollup-win32-x64-msvc": "4.27.4",
"fsevents": "~2.3.2"
}
},
@@ -6872,6 +7352,12 @@
}
}
},
+ "node_modules/rrweb-cssom": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz",
+ "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==",
+ "dev": true
+ },
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -6929,6 +7415,24 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true
+ },
+ "node_modules/saxes": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
+ "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==",
+ "dev": true,
+ "dependencies": {
+ "xmlchars": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=v12.22.7"
+ }
+ },
"node_modules/semver": {
"version": "7.6.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
@@ -7033,7 +7537,6 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
- "dev": true,
"engines": {
"node": ">=14"
},
@@ -7069,9 +7572,9 @@
}
},
"node_modules/source-map-js": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
- "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"engines": {
"node": ">=0.10.0"
}
@@ -7098,9 +7601,9 @@
}
},
"node_modules/std-env": {
- "version": "3.7.0",
- "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz",
- "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==",
+ "version": "3.8.0",
+ "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz",
+ "integrity": "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==",
"dev": true
},
"node_modules/stdin-discarder": {
@@ -7134,7 +7637,6 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
- "dev": true,
"dependencies": {
"eastasianwidth": "^0.2.0",
"emoji-regex": "^9.2.2",
@@ -7152,7 +7654,6 @@
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@@ -7166,7 +7667,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -7174,14 +7674,12 @@
"node_modules/string-width-cjs/node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"node_modules/string-width-cjs/node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
@@ -7242,7 +7740,6 @@
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
- "dev": true,
"dependencies": {
"ansi-regex": "^6.0.1"
},
@@ -7258,7 +7755,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
@@ -7270,7 +7766,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -7295,23 +7790,10 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/strip-literal": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.3.0.tgz",
- "integrity": "sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==",
- "dev": true,
- "dependencies": {
- "acorn": "^8.10.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/antfu"
- }
- },
"node_modules/sucrase": {
"version": "3.35.0",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
"integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
- "dev": true,
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.2",
"commander": "^4.0.0",
@@ -7333,7 +7815,6 @@
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
- "dev": true,
"engines": {
"node": ">= 6"
}
@@ -7360,6 +7841,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/symbol-tree": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
+ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
+ "dev": true
+ },
"node_modules/synckit": {
"version": "0.8.8",
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz",
@@ -7452,33 +7939,32 @@
}
},
"node_modules/tailwindcss": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz",
- "integrity": "sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==",
- "dev": true,
+ "version": "3.4.15",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.15.tgz",
+ "integrity": "sha512-r4MeXnfBmSOuKUWmXe6h2CcyfzJCEk4F0pptO5jlnYSIViUkVmsawj80N5h2lO3gwcmSb4n3PuN+e+GC1Guylw==",
"dependencies": {
"@alloc/quick-lru": "^5.2.0",
"arg": "^5.0.2",
- "chokidar": "^3.5.3",
+ "chokidar": "^3.6.0",
"didyoumean": "^1.2.2",
"dlv": "^1.1.3",
- "fast-glob": "^3.3.0",
+ "fast-glob": "^3.3.2",
"glob-parent": "^6.0.2",
"is-glob": "^4.0.3",
- "jiti": "^1.21.0",
+ "jiti": "^1.21.6",
"lilconfig": "^2.1.0",
- "micromatch": "^4.0.5",
+ "micromatch": "^4.0.8",
"normalize-path": "^3.0.0",
"object-hash": "^3.0.0",
- "picocolors": "^1.0.0",
- "postcss": "^8.4.23",
+ "picocolors": "^1.1.1",
+ "postcss": "^8.4.47",
"postcss-import": "^15.1.0",
"postcss-js": "^4.0.1",
- "postcss-load-config": "^4.0.1",
- "postcss-nested": "^6.0.1",
- "postcss-selector-parser": "^6.0.11",
- "resolve": "^1.22.2",
- "sucrase": "^3.32.0"
+ "postcss-load-config": "^4.0.2",
+ "postcss-nested": "^6.2.0",
+ "postcss-selector-parser": "^6.1.2",
+ "resolve": "^1.22.8",
+ "sucrase": "^3.35.0"
},
"bin": {
"tailwind": "lib/cli.js",
@@ -7488,11 +7974,18 @@
"node": ">=14.0.0"
}
},
+ "node_modules/tailwindcss-primeui": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/tailwindcss-primeui/-/tailwindcss-primeui-0.3.4.tgz",
+ "integrity": "sha512-5+Qfoe5Kpq2Iwrd6umBUb3rQH6b7+pL4jxJUId0Su5agUM6TwCyH5Pyl9R0y3QQB3IRuTxBNmeS11B41f+30zw==",
+ "peerDependencies": {
+ "tailwindcss": ">=3.1.0"
+ }
+ },
"node_modules/tailwindcss/node_modules/glob-parent": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "dev": true,
"dependencies": {
"is-glob": "^4.0.3"
},
@@ -7509,7 +8002,6 @@
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
"integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
- "dev": true,
"dependencies": {
"any-promise": "^1.0.0"
}
@@ -7518,7 +8010,6 @@
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
"integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
- "dev": true,
"dependencies": {
"thenify": ">= 3.1.0 < 4"
},
@@ -7536,24 +8027,39 @@
}
},
"node_modules/tinybench": {
- "version": "2.8.0",
- "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.8.0.tgz",
- "integrity": "sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==",
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
+ "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==",
+ "dev": true
+ },
+ "node_modules/tinyexec": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.1.tgz",
+ "integrity": "sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==",
"dev": true
},
"node_modules/tinypool": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.7.0.tgz",
- "integrity": "sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.1.tgz",
+ "integrity": "sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==",
+ "dev": true,
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ }
+ },
+ "node_modules/tinyrainbow": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz",
+ "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==",
"dev": true,
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/tinyspy": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz",
- "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==",
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz",
+ "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==",
"dev": true,
"engines": {
"node": ">=14.0.0"
@@ -7570,6 +8076,42 @@
"node": ">=8.0"
}
},
+ "node_modules/tough-cookie": {
+ "version": "4.1.4",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz",
+ "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==",
+ "dev": true,
+ "dependencies": {
+ "psl": "^1.1.33",
+ "punycode": "^2.1.1",
+ "universalify": "^0.2.0",
+ "url-parse": "^1.5.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/tough-cookie/node_modules/universalify": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
+ "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/tr46": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz",
+ "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/ts-api-utils": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz",
@@ -7584,8 +8126,7 @@
"node_modules/ts-interface-checker": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
- "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
- "dev": true
+ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="
},
"node_modules/ts-toolbelt": {
"version": "9.6.0",
@@ -7631,101 +8172,6 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
},
- "node_modules/turbo": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/turbo/-/turbo-1.13.2.tgz",
- "integrity": "sha512-rX/d9f4MgRT3yK6cERPAkfavIxbpBZowDQpgvkYwGMGDQ0Nvw1nc0NVjruE76GrzXQqoxR1UpnmEP54vBARFHQ==",
- "dev": true,
- "bin": {
- "turbo": "bin/turbo"
- },
- "optionalDependencies": {
- "turbo-darwin-64": "1.13.2",
- "turbo-darwin-arm64": "1.13.2",
- "turbo-linux-64": "1.13.2",
- "turbo-linux-arm64": "1.13.2",
- "turbo-windows-64": "1.13.2",
- "turbo-windows-arm64": "1.13.2"
- }
- },
- "node_modules/turbo-darwin-64": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-1.13.2.tgz",
- "integrity": "sha512-CCSuD8CfmtncpohCuIgq7eAzUas0IwSbHfI8/Q3vKObTdXyN8vAo01gwqXjDGpzG9bTEVedD0GmLbD23dR0MLA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/turbo-darwin-arm64": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-1.13.2.tgz",
- "integrity": "sha512-0HySm06/D2N91rJJ89FbiI/AodmY8B3WDSFTVEpu2+8spUw7hOJ8okWOT0e5iGlyayUP9gr31eOeL3VFZkpfCw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/turbo-linux-64": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-1.13.2.tgz",
- "integrity": "sha512-7HnibgbqZrjn4lcfIouzlPu8ZHSBtURG4c7Bedu7WJUDeZo+RE1crlrQm8wuwO54S0siYqUqo7GNHxu4IXbioQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/turbo-linux-arm64": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-1.13.2.tgz",
- "integrity": "sha512-sUq4dbpk6SNKg/Hkwn256Vj2AEYSQdG96repio894h5/LEfauIK2QYiC/xxAeW3WBMc6BngmvNyURIg7ltrePg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/turbo-windows-64": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-1.13.2.tgz",
- "integrity": "sha512-DqzhcrciWq3dpzllJR2VVIyOhSlXYCo4mNEWl98DJ3FZ08PEzcI3ceudlH6F0t/nIcfSItK1bDP39cs7YoZHEA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/turbo-windows-arm64": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-1.13.2.tgz",
- "integrity": "sha512-WnPMrwfCXxK69CdDfS1/j2DlzcKxSmycgDAqV0XCYpK/812KB0KlvsVAt5PjEbZGXkY88pCJ1BLZHAjF5FcbqA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ]
- },
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -7737,19 +8183,10 @@
"node": ">= 0.8.0"
}
},
- "node_modules/type-detect": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
- "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/type-fest": {
- "version": "4.17.0",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.17.0.tgz",
- "integrity": "sha512-9flrz1zkfLRH3jO3bLflmTxryzKMxVa7841VeMgBaNQGY6vH4RCcpN/sQLB7mQQYh1GZ5utT2deypMuCy4yicw==",
+ "version": "4.29.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.29.0.tgz",
+ "integrity": "sha512-RPYt6dKyemXJe7I6oNstcH24myUGSReicxcHTvCLgzm4e0n8y05dGvcGB15/SoPRBmhlMthWQ9pvKyL81ko8nQ==",
"engines": {
"node": ">=16"
},
@@ -7866,7 +8303,8 @@
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
- "dev": true
+ "dev": true,
+ "peer": true
},
"node_modules/unicorn-magic": {
"version": "0.1.0",
@@ -7941,6 +8379,16 @@
"punycode": "^2.1.0"
}
},
+ "node_modules/url-parse": {
+ "version": "1.5.10",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
+ "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
+ "dev": true,
+ "dependencies": {
+ "querystringify": "^2.1.1",
+ "requires-port": "^1.0.0"
+ }
+ },
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -7980,32 +8428,33 @@
}
},
"node_modules/vite": {
- "version": "4.5.3",
- "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.3.tgz",
- "integrity": "sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg==",
+ "version": "5.4.11",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz",
+ "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==",
"dev": true,
"dependencies": {
- "esbuild": "^0.18.10",
- "postcss": "^8.4.27",
- "rollup": "^3.27.1"
+ "esbuild": "^0.21.3",
+ "postcss": "^8.4.43",
+ "rollup": "^4.20.0"
},
"bin": {
"vite": "bin/vite.js"
},
"engines": {
- "node": "^14.18.0 || >=16.0.0"
+ "node": "^18.0.0 || >=20.0.0"
},
"funding": {
"url": "https://github.com/vitejs/vite?sponsor=1"
},
"optionalDependencies": {
- "fsevents": "~2.3.2"
+ "fsevents": "~2.3.3"
},
"peerDependencies": {
- "@types/node": ">= 14",
+ "@types/node": "^18.0.0 || >=20.0.0",
"less": "*",
"lightningcss": "^1.21.0",
"sass": "*",
+ "sass-embedded": "*",
"stylus": "*",
"sugarss": "*",
"terser": "^5.4.0"
@@ -8023,6 +8472,9 @@
"sass": {
"optional": true
},
+ "sass-embedded": {
+ "optional": true
+ },
"stylus": {
"optional": true
},
@@ -8035,32 +8487,31 @@
}
},
"node_modules/vite-node": {
- "version": "0.34.6",
- "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.34.6.tgz",
- "integrity": "sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==",
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.6.tgz",
+ "integrity": "sha512-DBfJY0n9JUwnyLxPSSUmEePT21j8JZp/sR9n+/gBwQU6DcQOioPdb8/pibWfXForbirSagZCilseYIwaL3f95A==",
"dev": true,
"dependencies": {
"cac": "^6.7.14",
- "debug": "^4.3.4",
- "mlly": "^1.4.0",
- "pathe": "^1.1.1",
- "picocolors": "^1.0.0",
- "vite": "^3.0.0 || ^4.0.0 || ^5.0.0-0"
+ "debug": "^4.3.7",
+ "es-module-lexer": "^1.5.4",
+ "pathe": "^1.1.2",
+ "vite": "^5.0.0 || ^6.0.0"
},
"bin": {
"vite-node": "vite-node.mjs"
},
"engines": {
- "node": ">=v14.18.0"
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
}
},
"node_modules/vite-plugin-dts": {
- "version": "3.9.0",
- "resolved": "https://registry.npmjs.org/vite-plugin-dts/-/vite-plugin-dts-3.9.0.tgz",
- "integrity": "sha512-pwFIEYQ3LZvMafkEGvNnileb6af5JuyZsBfYQrTDYxdeGEy0OS4B4hCsLPo5YGnhK5k9EzyO6BXVO6y+Lt5T2A==",
+ "version": "3.9.1",
+ "resolved": "https://registry.npmjs.org/vite-plugin-dts/-/vite-plugin-dts-3.9.1.tgz",
+ "integrity": "sha512-rVp2KM9Ue22NGWB8dNtWEr+KekN3rIgz1tWD050QnRGlriUCmaDwa7qA5zDEjbXg5lAXhYMSBJtx3q3hQIJZSg==",
"dev": true,
"dependencies": {
"@microsoft/api-extractor": "7.43.0",
@@ -8085,59 +8536,56 @@
}
},
"node_modules/vitest": {
- "version": "0.34.6",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.34.6.tgz",
- "integrity": "sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==",
- "dev": true,
- "dependencies": {
- "@types/chai": "^4.3.5",
- "@types/chai-subset": "^1.3.3",
- "@types/node": "*",
- "@vitest/expect": "0.34.6",
- "@vitest/runner": "0.34.6",
- "@vitest/snapshot": "0.34.6",
- "@vitest/spy": "0.34.6",
- "@vitest/utils": "0.34.6",
- "acorn": "^8.9.0",
- "acorn-walk": "^8.2.0",
- "cac": "^6.7.14",
- "chai": "^4.3.10",
- "debug": "^4.3.4",
- "local-pkg": "^0.4.3",
- "magic-string": "^0.30.1",
- "pathe": "^1.1.1",
- "picocolors": "^1.0.0",
- "std-env": "^3.3.3",
- "strip-literal": "^1.0.1",
- "tinybench": "^2.5.0",
- "tinypool": "^0.7.0",
- "vite": "^3.1.0 || ^4.0.0 || ^5.0.0-0",
- "vite-node": "0.34.6",
- "why-is-node-running": "^2.2.2"
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.6.tgz",
+ "integrity": "sha512-isUCkvPL30J4c5O5hgONeFRsDmlw6kzFEdLQHLezmDdKQHy8Ke/B/dgdTMEgU0vm+iZ0TjW8GuK83DiahBoKWQ==",
+ "dev": true,
+ "dependencies": {
+ "@vitest/expect": "2.1.6",
+ "@vitest/mocker": "2.1.6",
+ "@vitest/pretty-format": "^2.1.6",
+ "@vitest/runner": "2.1.6",
+ "@vitest/snapshot": "2.1.6",
+ "@vitest/spy": "2.1.6",
+ "@vitest/utils": "2.1.6",
+ "chai": "^5.1.2",
+ "debug": "^4.3.7",
+ "expect-type": "^1.1.0",
+ "magic-string": "^0.30.12",
+ "pathe": "^1.1.2",
+ "std-env": "^3.8.0",
+ "tinybench": "^2.9.0",
+ "tinyexec": "^0.3.1",
+ "tinypool": "^1.0.1",
+ "tinyrainbow": "^1.2.0",
+ "vite": "^5.0.0 || ^6.0.0",
+ "vite-node": "2.1.6",
+ "why-is-node-running": "^2.3.0"
},
"bin": {
"vitest": "vitest.mjs"
},
"engines": {
- "node": ">=v14.18.0"
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
},
"peerDependencies": {
"@edge-runtime/vm": "*",
- "@vitest/browser": "*",
- "@vitest/ui": "*",
+ "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
+ "@vitest/browser": "2.1.6",
+ "@vitest/ui": "2.1.6",
"happy-dom": "*",
- "jsdom": "*",
- "playwright": "*",
- "safaridriver": "*",
- "webdriverio": "*"
+ "jsdom": "*"
},
"peerDependenciesMeta": {
"@edge-runtime/vm": {
"optional": true
},
+ "@types/node": {
+ "optional": true
+ },
"@vitest/browser": {
"optional": true
},
@@ -8149,15 +8597,6 @@
},
"jsdom": {
"optional": true
- },
- "playwright": {
- "optional": true
- },
- "safaridriver": {
- "optional": true
- },
- "webdriverio": {
- "optional": true
}
}
},
@@ -8270,6 +8709,36 @@
"typescript": "*"
}
},
+ "node_modules/w3c-xmlserializer": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz",
+ "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==",
+ "dev": true,
+ "dependencies": {
+ "xml-name-validator": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/w3c-xmlserializer/node_modules/xml-name-validator": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz",
+ "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/webidl-conversions": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
+ "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/webpack-sources": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
@@ -8283,6 +8752,40 @@
"resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.1.tgz",
"integrity": "sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg=="
},
+ "node_modules/whatwg-encoding": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
+ "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
+ "dev": true,
+ "dependencies": {
+ "iconv-lite": "0.6.3"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/whatwg-mimetype": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
+ "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/whatwg-url": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz",
+ "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==",
+ "dev": true,
+ "dependencies": {
+ "tr46": "^5.0.0",
+ "webidl-conversions": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -8333,9 +8836,9 @@
}
},
"node_modules/why-is-node-running": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz",
- "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==",
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
+ "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==",
"dev": true,
"dependencies": {
"siginfo": "^2.0.0",
@@ -8352,7 +8855,6 @@
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
- "dev": true,
"dependencies": {
"ansi-styles": "^6.1.0",
"string-width": "^5.0.1",
@@ -8370,7 +8872,6 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "dev": true,
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
@@ -8387,7 +8888,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -8395,14 +8895,12 @@
"node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"node_modules/wrap-ansi-cjs/node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@@ -8416,7 +8914,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
@@ -8428,7 +8925,6 @@
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
- "dev": true,
"engines": {
"node": ">=12"
},
@@ -8449,6 +8945,27 @@
"node": ">=14"
}
},
+ "node_modules/ws": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
+ "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
"node_modules/xml-name-validator": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz",
@@ -8457,6 +8974,12 @@
"node": ">=12"
}
},
+ "node_modules/xmlchars": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
+ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
+ "dev": true
+ },
"node_modules/y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
@@ -8577,6 +9100,18 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/yoctocolors-cjs": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz",
+ "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/z-schema": {
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz",
@@ -8636,13 +9171,13 @@
"license": "MIT",
"dependencies": {
"@kwai/config": "*",
- "@vueuse/core": "^10.9.0",
+ "@vueuse/core": "11.0.3",
"wretch": "^2.7.0",
"zod": "^3.23.4"
},
"devDependencies": {
"vite-plugin-dts": "^3.6.3",
- "vitest": "^0.34.6"
+ "vitest": "^2.0.5"
}
},
"packages/kwai-config": {
@@ -8661,7 +9196,7 @@
"dayjs": "^1.11.10"
},
"devDependencies": {
- "vitest": "^0.34.6"
+ "vitest": "^2.0.5"
}
},
"packages/kwai-types": {
@@ -8679,15 +9214,17 @@
"license": "MIT",
"dependencies": {
"@kwai/date": "*",
- "@vuepic/vue-datepicker": "8.4.0",
- "primevue": "^3.51.0"
+ "@vuepic/vue-datepicker": "9.0.3",
+ "primevue": "4.2.4"
},
"devDependencies": {
- "@tailwindcss/forms": "^0.5.6",
- "@vitejs/plugin-vue": "^4.5.0",
+ "@tailwindcss/forms": "^0.5.9",
+ "@vitejs/plugin-vue": "^5.2.1",
"autoprefixer": "^10.4.16",
- "postcss": "^8.4.31",
- "tailwindcss": "^3.4.3",
+ "postcss": "^8.4.49",
+ "postcss-import": "^16.1.0",
+ "tailwindcss": "^3.4.15",
+ "tailwindcss-primeui": "^0.3.4",
"vite-plugin-dts": "^3.6.3",
"vue": "3.4.25"
},
@@ -8695,6 +9232,23 @@
"vee-validate": "^4.9.6",
"vue-router": "^4.2.2"
}
+ },
+ "packages/kwai-ui/node_modules/postcss-import": {
+ "version": "16.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-16.1.0.tgz",
+ "integrity": "sha512-7hsAZ4xGXl4MW+OKEWCnF6T5jqBw80/EE9aXg1r2yyn1RsVEU8EtKXbijEODa+rg7iih4bKf7vlvTGYR4CnPNg==",
+ "dev": true,
+ "dependencies": {
+ "postcss-value-parser": "^4.0.0",
+ "read-cache": "^1.0.0",
+ "resolve": "^1.1.7"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.0.0"
+ }
}
}
}
diff --git a/frontend/package.json b/frontend/package.json
index 5ff6e4b14..c08571e87 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,26 +1,28 @@
{
"name": "kwai",
"version": "1.0.0",
- "devDependencies": {
- "@vue/test-utils": "^2.4.3",
- "eslint-config-kwai": "*",
- "msw": "^2.0.11",
- "rollup-plugin-visualizer": "^5.11.0",
- "syncpack": "^12.3.2",
- "turbo": "^1.13.2",
- "typescript": "^5.2.2",
- "vite": "^4.5.3"
- },
"engines": {
"node": ">=18.0.0"
},
"private": true,
"scripts": {
- "build": "turbo run build --force",
- "dev": "turbo run dev --parallel --continue"
+ "test": "vitest",
+ "prebuild": "npm run build -w packages/kwai-types && npm run build -w packages/kwai-config && npm run build -w packages/kwai-date && npm run build -w packages/kwai-api && npm run build -w packages/kwai-ui",
+ "build": "npm run build --workspaces --if-present"
},
"workspaces": [
"apps/*",
"packages/*"
- ]
+ ],
+ "devDependencies": {
+ "@go-task/cli": "^3.39.0",
+ "@vue/test-utils": "^2.4.3",
+ "eslint-config-kwai": "*",
+ "msw": "^2.0.11",
+ "rollup-plugin-visualizer": "^5.11.0",
+ "syncpack": "^12.3.2",
+ "typescript": "^5.2.2",
+ "vite": "^5.4.11",
+ "vitest": "^2.0.5"
+ }
}
diff --git a/frontend/packages/kwai-api/package.json b/frontend/packages/kwai-api/package.json
index 005d63691..f70e0259b 100644
--- a/frontend/packages/kwai-api/package.json
+++ b/frontend/packages/kwai-api/package.json
@@ -4,13 +4,13 @@
"version": "0.0.1",
"dependencies": {
"@kwai/config": "*",
- "@vueuse/core": "^10.9.0",
+ "@vueuse/core": "11.0.3",
"wretch": "^2.7.0",
"zod": "^3.23.4"
},
"devDependencies": {
"vite-plugin-dts": "^3.6.3",
- "vitest": "^0.34.6"
+ "vitest": "^2.0.5"
},
"exports": {
".": {
diff --git a/frontend/packages/kwai-api/src/index.ts b/frontend/packages/kwai-api/src/index.ts
index dc1f566d3..170790ee7 100644
--- a/frontend/packages/kwai-api/src/index.ts
+++ b/frontend/packages/kwai-api/src/index.ts
@@ -11,6 +11,7 @@ export const JsonResourceIdentifier = z.object({
id: z.optional(z.string()),
type: z.string(),
});
+export type JsonResourceIdentifierType = z.infer;
export const JsonApiRelationship = z.object({
data: z.union([JsonResourceIdentifier, z.array(JsonResourceIdentifier)]),
@@ -29,6 +30,16 @@ export const JsonApiData = JsonResourceIdentifier.extend({
});
export type JsonApiDataType = z.infer;
+export const JsonApiError = z.object({
+ status: z.string().default(''),
+ source: z.object({
+ pointer: z.string(),
+ }).optional(),
+ title: z.string().default(''),
+ detail: z.string().default(''),
+});
+export type JsonApiErrorType = z.infer;
+
export const JsonApiDocument = z.object({
meta: z.object({
count: z.number().optional(),
@@ -37,9 +48,70 @@ export const JsonApiDocument = z.object({
}).optional(),
data: z.union([JsonApiData, z.array(JsonApiData)]),
included: z.array(JsonApiData).optional(),
+ errors: z.array(JsonApiError).optional(),
});
export type JsonApiDocumentType = z.infer;
+/**
+ * Transforms an array of resources in a nested object.
+ *
+ * This object makes it easier to lookup included resources. When, for example, a team resource
+ * has team members, the included array will contain resources for the team members but also
+ * country resources for the nationality of these team members. In this example, the returned
+ * object will have two properties: team_members and countries. The value of these properties will
+ * be another object with all the resources. The property for each resource will be the id of the resource.
+ *
+ * {
+ * team_members: {
+ * '1': {
+ * type: 'team_members',
+ * id: '1',
+ * attributes: {
+ * name: 'Jigoro Kano',
+ * },
+ * relationships: {
+ * nationality: {
+ * data: { type: 'countries', 'id': '1' }
+ * }
+ * }
+ * }
+ * },
+ * countries: {
+ * '1': {
+ * type: 'countries',
+ * id: '1',
+ * attributes: {
+ * name: 'Japan'
+ * }
+ * }
+ * }
+ * }
+ *
+ * @param resources
+ */
+export const transformResourceArrayToObject = (resources: JsonApiDataType[]): Record> => {
+ return resources.reduce((acc: Record>, current) => {
+ if (!acc[current.type]) {
+ acc[current.type] = {};
+ }
+ acc[current.type][current.id as string] = current;
+ return acc;
+ }, {});
+};
+
+/**
+ * An interface that can be used for the result of a transform of a document
+ * with multiple resources.
+ */
+export interface ResourceItems {
+ meta: {
+ count: number,
+ offset: number,
+ limit: number
+ },
+ items: T[]
+}
+
export interface LocalStorage {
loginRedirect: Ref,
accessToken: Ref,
diff --git a/frontend/packages/kwai-config/vite.config.ts b/frontend/packages/kwai-config/vite.config.ts
index 65b673dc6..46876f6c2 100644
--- a/frontend/packages/kwai-config/vite.config.ts
+++ b/frontend/packages/kwai-config/vite.config.ts
@@ -3,21 +3,24 @@ import dts from 'vite-plugin-dts';
import { defineConfig } from 'vite';
import { resolve } from 'path';
-export default defineConfig({
- plugins: [
- toml(),
- dts({ copyDtsFiles: true }),
- ],
- build: {
- lib: {
- entry: resolve(__dirname, 'src/config.toml'),
- name: '@kwai/config',
- fileName: 'kwai-config',
- },
- rollupOptions: {
- output: {
- exports: 'named',
+export default defineConfig(({ mode }) => {
+ const configFile = mode === 'production' ? 'src/config.production.toml' : 'src/config.toml';
+ return {
+ plugins: [
+ toml(),
+ dts({ copyDtsFiles: true }),
+ ],
+ build: {
+ lib: {
+ entry: resolve(__dirname, configFile),
+ name: '@kwai/config',
+ fileName: 'kwai-config',
+ },
+ rollupOptions: {
+ output: {
+ exports: 'named',
+ },
},
},
- },
+ };
});
diff --git a/frontend/packages/kwai-date/package.json b/frontend/packages/kwai-date/package.json
index 1f1fc7452..457322147 100644
--- a/frontend/packages/kwai-date/package.json
+++ b/frontend/packages/kwai-date/package.json
@@ -6,7 +6,7 @@
"dayjs": "^1.11.10"
},
"devDependencies": {
- "vitest": "^0.34.6"
+ "vitest": "^2.0.5"
},
"exports": {
".": {
diff --git a/frontend/packages/kwai-date/vitest.config.ts b/frontend/packages/kwai-date/vitest.config.ts
index 7a05473e0..10db15723 100644
--- a/frontend/packages/kwai-date/vitest.config.ts
+++ b/frontend/packages/kwai-date/vitest.config.ts
@@ -1,6 +1,4 @@
-import { defineConfig } from "vitest/config"
+import { defineConfig } from 'vitest/config';
export default defineConfig({
- test: {
- }
-})
+});
diff --git a/frontend/packages/kwai-ui/package.json b/frontend/packages/kwai-ui/package.json
index b707191e3..1f60993c6 100644
--- a/frontend/packages/kwai-ui/package.json
+++ b/frontend/packages/kwai-ui/package.json
@@ -4,15 +4,17 @@
"version": "1.0.0",
"dependencies": {
"@kwai/date": "*",
- "@vuepic/vue-datepicker": "8.4.0",
- "primevue": "^3.51.0"
+ "@vuepic/vue-datepicker": "9.0.3",
+ "primevue": "4.2.4"
},
"devDependencies": {
- "@tailwindcss/forms": "^0.5.6",
- "@vitejs/plugin-vue": "^4.5.0",
+ "@tailwindcss/forms": "^0.5.9",
+ "@vitejs/plugin-vue": "^5.2.1",
"autoprefixer": "^10.4.16",
- "postcss": "^8.4.31",
- "tailwindcss": "^3.4.3",
+ "postcss": "^8.4.49",
+ "postcss-import": "^16.1.0",
+ "tailwindcss": "^3.4.15",
+ "tailwindcss-primeui": "^0.3.4",
"vite-plugin-dts": "^3.6.3",
"vue": "3.4.25"
},
diff --git a/frontend/packages/kwai-ui/postcss.config.cjs b/frontend/packages/kwai-ui/postcss.config.cjs
new file mode 100644
index 000000000..1ed1faa14
--- /dev/null
+++ b/frontend/packages/kwai-ui/postcss.config.cjs
@@ -0,0 +1,7 @@
+module.exports = {
+ plugins: [
+ require('postcss-import'),
+ require('tailwindcss'),
+ require('autoprefixer'),
+ ],
+};
diff --git a/frontend/packages/kwai-ui/postcss.config.js b/frontend/packages/kwai-ui/postcss.config.js
deleted file mode 100644
index 9fcb8143f..000000000
--- a/frontend/packages/kwai-ui/postcss.config.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import tailwind from 'tailwindcss'
-import autoprefixer from 'autoprefixer'
-import tailwindConfig from './tailwind.config.js'
-
-export default {
- plugins: [
- tailwind(tailwindConfig), autoprefixer
- ]
-}
diff --git a/frontend/packages/kwai-ui/src/alerts/Alert.vue b/frontend/packages/kwai-ui/src/alerts/Alert.vue
index e41bf47ed..963b98a94 100644
--- a/frontend/packages/kwai-ui/src/alerts/Alert.vue
+++ b/frontend/packages/kwai-ui/src/alerts/Alert.vue
@@ -1,11 +1,23 @@
-
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/frontend/packages/kwai-ui/src/alerts/ErrorAlert.vue b/frontend/packages/kwai-ui/src/alerts/ErrorAlert.vue
index 64e541614..362f510ec 100644
--- a/frontend/packages/kwai-ui/src/alerts/ErrorAlert.vue
+++ b/frontend/packages/kwai-ui/src/alerts/ErrorAlert.vue
@@ -1,15 +1,13 @@
+
+
-
+
-
+
-
-
-
+
-
-
diff --git a/frontend/packages/kwai-ui/src/alerts/InfoAlert.vue b/frontend/packages/kwai-ui/src/alerts/InfoAlert.vue
index 89707302a..7ea0d5b44 100644
--- a/frontend/packages/kwai-ui/src/alerts/InfoAlert.vue
+++ b/frontend/packages/kwai-ui/src/alerts/InfoAlert.vue
@@ -1,15 +1,13 @@
+
+
-
+
-
+
-
-
-
+
-
-
diff --git a/frontend/packages/kwai-ui/src/alerts/LoadingAlert.vue b/frontend/packages/kwai-ui/src/alerts/LoadingAlert.vue
index 67043fb50..d601003d4 100644
--- a/frontend/packages/kwai-ui/src/alerts/LoadingAlert.vue
+++ b/frontend/packages/kwai-ui/src/alerts/LoadingAlert.vue
@@ -1,13 +1,13 @@
+
+
-
+
-
+
-
-
diff --git a/frontend/packages/kwai-ui/src/alerts/WarningAlert.vue b/frontend/packages/kwai-ui/src/alerts/WarningAlert.vue
index 421957095..c1ce94c3f 100644
--- a/frontend/packages/kwai-ui/src/alerts/WarningAlert.vue
+++ b/frontend/packages/kwai-ui/src/alerts/WarningAlert.vue
@@ -1,15 +1,13 @@
-
+
-
+
-
-
-
+
diff --git a/frontend/packages/kwai-ui/src/badges/KwaiBadge.vue b/frontend/packages/kwai-ui/src/badges/KwaiBadge.vue
new file mode 100644
index 000000000..8aa258d63
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/badges/KwaiBadge.vue
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
diff --git a/frontend/packages/kwai-ui/src/badges/KwaiTag.vue b/frontend/packages/kwai-ui/src/badges/KwaiTag.vue
new file mode 100644
index 000000000..aa4709fb4
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/badges/KwaiTag.vue
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
diff --git a/frontend/packages/kwai-ui/src/badges/index.ts b/frontend/packages/kwai-ui/src/badges/index.ts
index 43d7097d4..b98d98d5b 100644
--- a/frontend/packages/kwai-ui/src/badges/index.ts
+++ b/frontend/packages/kwai-ui/src/badges/index.ts
@@ -1 +1,3 @@
+export { default as KwaiBadge } from './KwaiBadge.vue';
export { default as TextBadge } from './TextBadge.vue';
+export { default as KwaiTag } from './KwaiTag.vue';
diff --git a/frontend/packages/kwai-ui/src/card/KwaiCard.vue b/frontend/packages/kwai-ui/src/card/KwaiCard.vue
new file mode 100644
index 000000000..b7dbba409
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/card/KwaiCard.vue
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/packages/kwai-ui/src/card/KwaiPanel.vue b/frontend/packages/kwai-ui/src/card/KwaiPanel.vue
new file mode 100644
index 000000000..51ec9a638
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/card/KwaiPanel.vue
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/packages/kwai-ui/src/card/index.ts b/frontend/packages/kwai-ui/src/card/index.ts
index 3177ca199..cdf8e8acf 100644
--- a/frontend/packages/kwai-ui/src/card/index.ts
+++ b/frontend/packages/kwai-ui/src/card/index.ts
@@ -2,3 +2,5 @@ export { default as CardRouterLinkedTitle } from './CardRouterLinkedTitle.vue';
export { default as CardLinkedTitle } from './CardLinkedTitle.vue';
export { default as CardTitle } from './CardTitle.vue';
export { default as Card } from './Card.vue';
+export { default as KwaiCard } from './KwaiCard.vue';
+export { default as KwaiPanel } from './KwaiPanel.vue';
diff --git a/frontend/packages/kwai-ui/src/css/primevue/accordion.css b/frontend/packages/kwai-ui/src/css/primevue/accordion.css
new file mode 100644
index 000000000..11a13db0f
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/accordion.css
@@ -0,0 +1,58 @@
+.p-accordionpanel {
+ @apply flex flex-col border-b border-surface-200 dark:border-surface-700
+}
+
+.p-accordionheader {
+ @apply cursor-pointer disabled:cursor-auto flex items-center justify-between p-[1.125rem] font-semibold
+ bg-surface-0 dark:bg-surface-900
+ text-surface-500 dark:text-surface-400
+ transition-colors duration-200
+}
+
+.p-accordionpanel:first-child > .p-accordionheader {
+ @apply rounded-ss-md rounded-se-md
+}
+
+.p-accordionpanel:last-child > .p-accordionheader {
+ @apply rounded-ee-md rounded-es-md
+}
+
+.p-accordionpanel:last-child.p-accordionpanel-active > .p-accordionheader {
+ @apply rounded-ee-md rounded-es-md
+}
+
+.p-accordionheader-toggle-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-accordionpanel:not(.p-disabled) .p-accordionheader:focus-visible {
+ @apply outline outline-1 outline-offset-[-1px] outline-primary
+}
+
+.p-accordionpanel:not(.p-accordionpanel-active):not(.p-disabled) > .p-accordionheader:hover {
+ @apply bg-surface-0 dark:bg-surface-900 text-surface-700 dark:text-surface-0
+}
+
+.p-accordionpanel:not(.p-accordionpanel-active):not(.p-disabled) .p-accordionheader:hover .p-accordionheader-toggle-icon {
+ @apply text-surface-700 dark:text-surface-0
+}
+
+.p-accordionpanel:not(.p-disabled).p-accordionpanel-active > .p-accordionheader {
+ @apply bg-surface-0 dark:bg-surface-900 text-surface-700 dark:text-surface-0
+}
+
+.p-accordionpanel:not(.p-disabled).p-accordionpanel-active > .p-accordionheader .p-accordionheader-toggle-icon {
+ @apply text-surface-700 dark:text-surface-0;
+}
+
+.p-accordionpanel:not(.p-disabled).p-accordionpanel-active > .p-accordionheader:hover {
+ @apply bg-surface-0 dark:bg-surface-900 text-surface-700 dark:text-surface-0
+}
+
+.p-accordionpanel:not(.p-disabled).p-accordionpanel-active > .p-accordionheader:hover .p-accordionheader-toggle-icon {
+ @apply text-surface-700 dark:text-surface-0;
+}
+
+.p-accordioncontent-content {
+ @apply bg-surface-0 dark:bg-surface-900 text-surface-700 dark:text-surface-0 pt-0 px-[1.125rem] pb-[1.125rem]
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/autocomplete.css b/frontend/packages/kwai-ui/src/css/primevue/autocomplete.css
new file mode 100644
index 000000000..cb64d9833
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/autocomplete.css
@@ -0,0 +1,143 @@
+@import './inputtext';
+@import './chip';
+
+.p-autocomplete {
+ @apply inline-flex
+}
+
+.p-autocomplete.p-disabled {
+ @apply opacity-100
+}
+
+.p-autocomplete-loader {
+ @apply absolute top-1/2 -mt-2 end-3
+}
+
+.p-autocomplete:has(.p-autocomplete-dropdown) .p-autocomplete-loader {
+ @apply end-[3.25rem]
+}
+
+.p-autocomplete:has(.p-autocomplete-dropdown) .p-autocomplete-input {
+ @apply flex-auto w-[1%]
+}
+
+.p-autocomplete:has(.p-autocomplete-dropdown) .p-autocomplete-input,
+.p-autocomplete:has(.p-autocomplete-dropdown) .p-autocomplete-input-multiple {
+ @apply rounded-e-none
+}
+
+.p-autocomplete-dropdown {
+ @apply cursor-pointer inline-flex items-center justify-center select-none overflow-hidden relative w-10 rounded-e-md
+ bg-surface-100 enabled:hover:bg-surface-200 enabled:active:bg-surface-300
+ text-surface-600 enabled:hover:text-surface-700 enabled:hover:active:text-surface-800
+ dark:bg-surface-800 dark:enabled:hover:bg-surface-700 dark:enabled:active:bg-surface-600
+ dark:text-surface-300 dark:enabled:hover:text-surface-200 dark:enabled:active:text-surface-100
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+ transition-colors duration-200
+}
+
+.p-autocomplete .p-autocomplete-overlay {
+ @apply min-w-full
+}
+
+.p-autocomplete-overlay {
+ @apply absolute top-0 left-0 rounded-md
+ bg-surface-0 dark:bg-surface-900
+ border border-surface-200 dark:border-surface-700
+ text-surface-700 dark:text-surface-0
+ shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-2px_rgba(0,0,0,0.1)]
+}
+
+.p-autocomplete-list-container {
+ @apply overflow-auto
+}
+
+.p-autocomplete-list {
+ @apply m-0 p-1 list-none flex flex-col gap-[2px]
+}
+
+.p-autocomplete-option {
+ @apply cursor-pointer whitespace-nowrap relative overflow-hidden flex items-center px-3 py-2 rounded-sm
+ text-surface-700 dark:text-surface-0 bg-transparent border-none
+ transition-colors duration-200
+}
+
+.p-autocomplete-option:not(.p-autocomplete-option-selected):not(.p-disabled).p-focus {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-700 dark:text-surface-0
+}
+
+.p-autocomplete-option-selected {
+ @apply bg-highlight
+}
+
+.p-autocomplete-option-selected.p-focus {
+ @apply bg-highlight-emphasis
+}
+
+.p-autocomplete-option-group {
+ @apply m-0 px-3 py-2 text-surface-500 dark:text-surface-400 font-semibold bg-transparent
+}
+
+.p-autocomplete-input-multiple {
+ @apply m-0 list-none cursor-text overflow-hidden flex items-center flex-wrap
+ px-3 py-1 gap-1 text-surface-700 dark:text-surface-0 bg-surface-0 dark:bg-surface-950
+ border border-surface-300 dark:border-surface-700 rounded-md w-full
+ shadow-[0_1px_2px_0_rgba(18,18,23,0.05)]
+ transition-colors duration-200 outline-none
+}
+
+.p-autocomplete:not(.p-disabled):hover .p-autocomplete-input-multiple {
+ @apply border-surface-400 dark:border-surface-600
+}
+
+.p-autocomplete:not(.p-disabled).p-focus .p-autocomplete-input-multiple {
+ @apply border-primary
+}
+
+.p-autocomplete.p-invalid .p-autocomplete-input-multiple {
+ @apply border-red-400 dark:border-red-300
+}
+
+.p-variant-filled.p-autocomplete-input-multiple {
+ @apply bg-surface-50 dark:bg-surface-800
+}
+
+.p-autocomplete.p-disabled .p-autocomplete-input-multiple {
+ @apply opacity-100 cursor-default bg-surface-200 text-surface-500 dark:bg-surface-700 dark:text-surface-400
+}
+
+.p-autocomplete-chip.p-chip {
+ @apply py-1 rounded-sm
+}
+
+.p-autocomplete-input-multiple:has(.p-autocomplete-chip) {
+ @apply px-1
+}
+
+.p-autocomplete-chip-item.p-focus .p-autocomplete-chip {
+ @apply bg-surface-200 text-surface-800 dark:bg-surface-700 dark:text-surface-0
+}
+
+.p-autocomplete-input-chip {
+ @apply flex-auto inline-flex py-1
+}
+
+.p-autocomplete-input-chip input {
+ @apply border-none outline-none bg-transparent m-0 p-0 shadow-none rounded-none w-full text-inherit
+}
+
+.p-autocomplete-input-chip input::placeholder {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-autocomplete-empty-message {
+ @apply px-3 py-2
+}
+
+.p-autocomplete-fluid {
+ @apply flex
+}
+
+.p-autocomplete-fluid:has(.p-autocomplete-dropdown) .p-autocomplete-input {
+ @apply w-[1%]
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/avatar.css b/frontend/packages/kwai-ui/src/css/primevue/avatar.css
new file mode 100644
index 000000000..fde16bbb9
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/avatar.css
@@ -0,0 +1,50 @@
+.p-avatar {
+ @apply inline-flex items-center justify-center
+ w-8 h-8 text-base rounded-md
+ bg-surface-200 dark:bg-surface-700
+}
+
+.p-avatar-image {
+ @apply bg-transparent
+}
+
+.p-avatar-circle,
+.p-avatar-circle img {
+ @apply rounded-full
+}
+
+.p-avatar-icon {
+ @apply text-base
+}
+
+.p-avatar img {
+ @apply w-full h-full
+}
+
+.p-avatar-lg {
+ @apply w-12 h-12 text-2xl
+}
+
+.p-avatar-lg .p-avatar-icon {
+ @apply text-2xl
+}
+
+.p-avatar-xl {
+ @apply w-16 h-16 text-[2rem]
+}
+
+.p-avatar-xl .p-avatar-icon {
+ @apply text-[2rem]
+}
+
+.p-avatar-group {
+ @apply flex items-center
+}
+
+.p-avatar-group .p-avatar + .p-avatar {
+ @apply -ms-4
+}
+
+.p-avatar-group .p-avatar {
+ @apply border-2 border-surface-200 dark:border-surface-700
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/badge.css b/frontend/packages/kwai-ui/src/css/primevue/badge.css
new file mode 100644
index 000000000..7488458b4
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/badge.css
@@ -0,0 +1,49 @@
+.p-badge {
+ @apply inline-flex items-center justify-center rounded-md
+ py-0 px-2 text-xs font-bold min-w-6 h-6
+ bg-primary text-primary-contrast
+}
+
+.p-badge-dot {
+ @apply min-w-2 h-2 rounded-full p-0
+}
+
+.p-badge-circle {
+ @apply p-0 rounded-full
+}
+
+.p-badge-secondary {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-600 dark:text-surface-300
+}
+
+.p-badge-success {
+ @apply bg-green-500 dark:bg-green-400 text-white dark:text-green-950
+}
+
+.p-badge-info {
+ @apply bg-sky-500 dark:bg-sky-400 text-white dark:text-sky-950
+}
+
+.p-badge-warn {
+ @apply bg-orange-500 dark:bg-orange-400 text-white dark:text-orange-950
+}
+
+.p-badge-danger {
+ @apply bg-red-500 dark:bg-red-400 text-white dark:text-red-950
+}
+
+.p-badge-contrast {
+ @apply bg-surface-950 dark:bg-white text-white dark:text-surface-950
+}
+
+.p-badge-sm {
+ @apply text-[0.625rem] min-w-5 h-5
+}
+
+.p-badge-lg {
+ @apply text-sm min-w-7 h-7
+}
+
+.p-badge-xl {
+ @apply text-base min-w-8 h-8
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/blockui.css b/frontend/packages/kwai-ui/src/css/primevue/blockui.css
new file mode 100644
index 000000000..bda54dbe1
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/blockui.css
@@ -0,0 +1,15 @@
+.p-blockui {
+ @apply relative
+}
+
+.p-blockui-mask {
+ @apply rounded-md
+}
+
+.p-blockui-mask.p-overlay-mask {
+ @apply absolute
+}
+
+.p-blockui-mask-document.p-overlay-mask {
+ @apply fixed
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/breadcrumb.css b/frontend/packages/kwai-ui/src/css/primevue/breadcrumb.css
new file mode 100644
index 000000000..69beddf21
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/breadcrumb.css
@@ -0,0 +1,41 @@
+.p-breadcrumb {
+ @apply bg-surface-0 dark:bg-surface-900 p-4 overflow-x-auto
+}
+
+.p-breadcrumb-list {
+ @apply m-0 p-0 list-none flex items-center flex-nowrap gap-2
+}
+
+.p-breadcrumb-separator {
+ @apply flex items-center text-surface-400 dark:text-surface-500
+}
+
+.p-breadcrumb-separator-icon:dir(rtl) {
+ @apply rotate-180
+}
+
+.p-breadcrumb::-webkit-scrollbar {
+ @apply hidden
+}
+
+.p-breadcrumb-item-link {
+ @apply no-underline flex items-center gap-2 transition-colors duration-200 rounded-md
+ text-surface-500 dark:text-surface-400
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+}
+
+.p-breadcrumb-item-link:hover .p-breadcrumb-item-label {
+ @apply text-surface-700 dark:text-surface-0
+}
+
+.p-breadcrumb-item-label {
+ @apply transition-colors duration-200
+}
+
+.p-breadcrumb-item-icon {
+ @apply text-surface-400 dark:text-surface-500 transition-colors duration-200
+}
+
+.p-breadcrumb-item-link:hover .p-breadcrumb-item-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/button.css b/frontend/packages/kwai-ui/src/css/primevue/button.css
new file mode 100644
index 000000000..aafbc7692
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/button.css
@@ -0,0 +1,333 @@
+@import './badge';
+
+.p-button {
+ @apply inline-flex cursor-pointer select-none items-center justify-center overflow-hidden relative
+ bg-primary hover:bg-primary-emphasis active:bg-primary-emphasis-alt text-primary-contrast
+ border border-primary hover:border-primary-emphasis active:border-primary-emphasis-alt
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+ px-3 py-2 transition-colors duration-200 gap-2 rounded-md
+ disabled:cursor-default
+}
+
+.p-button-icon-right {
+ @apply order-1
+}
+
+.p-button-icon-right:dir(rtl) {
+ @apply order-[-1]
+}
+
+.p-button:not(.p-button-vertical) .p-button-icon:not(.p-button-icon-right):dir(rtl) {
+ @apply order-1
+}
+
+.p-button-icon-bottom {
+ @apply order-2
+}
+
+.p-button-icon-only {
+ @apply w-10 px-0 gap-0
+}
+
+.p-button-icon-only.p-button-rounded {
+ @apply rounded-full h-10
+}
+
+.p-button-icon-only .p-button-label {
+ @apply invisible w-0
+}
+
+.p-button-sm {
+ @apply text-sm px-[0.625rem] py-[0.375rem]
+}
+
+.p-button-sm .p-button-icon {
+ @apply text-sm
+}
+
+.p-button-lg {
+ @apply text-[1.125rem] px-[0.875rem] py-[0.625rem]
+}
+
+.p-button-lg .p-button-icon {
+ @apply text-[1.125rem]
+}
+
+.p-button-vertical {
+ @apply flex-col
+}
+
+.p-button-label {
+ @apply font-medium
+}
+
+.p-button-fluid {
+ @apply w-full
+}
+
+.p-button-fluid.p-button-icon-only {
+ @apply w-10
+}
+
+.p-button .p-badge {
+ @apply min-w-4 h-4 leading-4
+}
+
+.p-button-raised {
+ @apply shadow-[0_3px_1px_-2px_rgba(0,0,0,0.2),0_2px_2px_0_rgba(0,0,0,0.14),0_1px_5px_0_rgba(0,0,0,0.12)]
+}
+
+.p-button-rounded {
+ @apply rounded-[2rem]
+}
+
+.p-button-secondary {
+ @apply bg-surface-100 hover:bg-surface-200 active:bg-surface-300
+ border-surface-100 hover:border-surface-200 active:border-surface-300
+ text-surface-600 hover:text-surface-700 active:text-surface-800
+ dark:bg-surface-800 dark:hover:bg-surface-700 dark:active:bg-surface-600
+ dark:border-surface-800 dark:hover:border-surface-700 dark:active:border-surface-600
+ dark:text-surface-300 dark:hover:text-surface-200 dark:active:text-surface-100
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2
+ focus-visible:outline-surface-600 dark:focus-visible:outline-surface-300
+}
+
+.p-button-success {
+ @apply bg-green-500 hover:bg-green-600 active:bg-green-700
+ border-green-500 hover:border-green-600 active:border-green-700
+ text-white hover:text-white active:text-white
+ dark:bg-green-400 dark:hover:bg-green-300 dark:active:bg-green-200
+ dark:border-green-400 dark:hover:border-green-300 dark:active:border-green-200
+ dark:text-green-950 dark:hover:text-green-950 dark:active:text-green-950
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2
+ focus-visible:outline-green-500 dark:focus-visible:outline-green-400
+}
+
+.p-button-info {
+ @apply bg-sky-500 hover:bg-sky-600 active:bg-sky-700
+ border-sky-500 hover:border-sky-600 active:border-sky-700
+ text-white hover:text-white active:text-white
+ dark:bg-sky-400 dark:hover:bg-sky-300 dark:active:bg-sky-200
+ dark:border-sky-400 dark:hover:border-sky-300 dark:active:border-sky-200
+ dark:text-sky-950 dark:hover:text-sky-950 dark:active:text-sky-950
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2
+ focus-visible:outline-sky-500 dark:focus-visible:outline-sky-400
+}
+
+.p-button-warn {
+ @apply bg-orange-500 hover:bg-orange-600 active:bg-orange-700
+ border-orange-500 hover:border-orange-600 active:border-orange-700
+ text-white hover:text-white active:text-white
+ dark:bg-orange-400 dark:hover:bg-orange-300 dark:active:bg-orange-200
+ dark:border-orange-400 dark:hover:border-orange-300 dark:active:border-orange-200
+ dark:text-orange-950 dark:hover:text-orange-950 dark:active:text-orange-950
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2
+ focus-visible:outline-orange-500 dark:focus-visible:outline-orange-400
+}
+
+.p-button-help {
+ @apply bg-purple-500 hover:bg-purple-600 active:bg-purple-700
+ border-purple-500 hover:border-purple-600 active:border-purple-700
+ text-white hover:text-white active:text-white
+ dark:bg-purple-400 dark:hover:bg-purple-300 dark:active:bg-purple-200
+ dark:border-purple-400 dark:hover:border-purple-300 dark:active:border-purple-200
+ dark:text-purple-950 dark:hover:text-purple-950 dark:active:text-purple-950
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2
+ focus-visible:outline-purple-500 dark:focus-visible:outline-purple-400
+}
+
+.p-button-help {
+ @apply bg-purple-500 hover:bg-purple-600 active:bg-purple-700
+ border-purple-500 hover:border-purple-600 active:border-purple-700
+ text-white hover:text-white active:text-white
+ dark:bg-purple-400 dark:hover:bg-purple-300 dark:active:bg-purple-200
+ dark:border-purple-400 dark:hover:border-purple-300 dark:active:border-purple-200
+ dark:text-purple-950 dark:hover:text-purple-950 dark:active:text-purple-950
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2
+ focus-visible:outline-purple-500 dark:focus-visible:outline-purple-400
+}
+
+.p-button-danger {
+ @apply bg-red-500 hover:bg-red-600 active:bg-red-700
+ border-red-500 hover:border-red-600 active:border-red-700
+ text-white hover:text-white active:text-white
+ dark:bg-red-400 dark:hover:bg-red-300 dark:active:bg-red-200
+ dark:border-red-400 dark:hover:border-red-300 dark:active:border-red-200
+ dark:text-red-950 dark:hover:text-red-950 dark:active:text-red-950
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2
+ focus-visible:outline-red-500 dark:focus-visible:outline-red-400
+}
+
+.p-button-contrast {
+ @apply bg-surface-950 hover:bg-surface-900 active:bg-surface-800
+ border-surface-950 hover:border-surface-900 active:border-surface-800
+ text-white hover:text-white active:text-white
+ dark:bg-surface-0 dark:hover:bg-surface-100 dark:active:bg-surface-200
+ dark:border-surface-100 dark:hover:border-surface-200 dark:active:border-surface-300
+ dark:text-surface-950 dark:hover:text-surface-950 dark:active:text-surface-950
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2
+ focus-visible:outline-surface-950 dark:focus-visible:outline-surface-0
+}
+
+.p-button-outlined {
+ @apply bg-transparent hover:bg-primary-50 active:bg-primary-100
+ border-primary-200 hover:border-primary-200 active:border-primary-200
+ text-primary hover:text-primary active:text-primary
+ dark:bg-transparent dark:hover:bg-primary/5 dark:active:bg-primary/15
+ dark:border-primary-700 dark:hover:border-primary-700 dark:active:border-primary-700
+ dark:text-primary dark:hover:text-primary dark:active:text-primary
+}
+
+.p-button-outlined.p-button-secondary {
+ @apply bg-transparent hover:bg-surface-50 active:bg-surface-100
+ border-surface-200 hover:border-surface-200 active:border-surface-200
+ text-surface-500 hover:text-surface-500 active:text-surface-500
+ dark:bg-transparent dark:hover:bg-white/5 dark:active:bg-white/15
+ dark:border-surface-700 dark:hover:border-surface-700 dark:active:border-surface-700
+ dark:text-surface-400 dark:hover:text-surface-400 dark:active:text-surface-400
+}
+
+.p-button-outlined.p-button-success {
+ @apply bg-transparent hover:bg-green-50 active:bg-green-100
+ border-green-200 hover:border-green-200 active:border-green-200
+ text-green-500 hover:text-green-500 active:text-green-500
+ dark:bg-transparent dark:hover:bg-green-400/5 dark:active:bg-green-400/15
+ dark:border-green-700 dark:hover:border-green-700 dark:active:border-green-700
+ dark:text-green-400 dark:hover:text-green-400 dark:active:text-green-400
+}
+
+.p-button-outlined.p-button-info {
+ @apply bg-transparent hover:bg-sky-50 active:bg-sky-100
+ border-sky-200 hover:border-sky-200 active:border-sky-200
+ text-sky-500 hover:text-sky-500 active:text-sky-500
+ dark:bg-transparent dark:hover:bg-sky-400/5 dark:active:bg-sky-400/15
+ dark:border-sky-700 dark:hover:border-sky-700 dark:active:border-sky-700
+ dark:text-sky-400 dark:hover:text-sky-400 dark:active:text-sky-400
+}
+
+.p-button-outlined.p-button-warn {
+ @apply bg-transparent hover:bg-orange-50 active:bg-orange-100
+ border-orange-200 hover:border-orange-200 active:border-orange-200
+ text-orange-500 hover:text-orange-500 active:text-orange-500
+ dark:bg-transparent dark:hover:bg-orange-400/5 dark:active:bg-orange-400/15
+ dark:border-orange-700 dark:hover:border-orange-700 dark:active:border-orange-700
+ dark:text-orange-400 dark:hover:text-orange-400 dark:active:text-orange-400
+}
+
+.p-button-outlined.p-button-help {
+ @apply bg-transparent hover:bg-purple-50 active:bg-purple-100
+ border-purple-200 hover:border-purple-200 active:border-purple-200
+ text-purple-500 hover:text-purple-500 active:text-purple-500
+ dark:bg-transparent dark:hover:bg-purple-400/5 dark:active:bg-purple-400/15
+ dark:border-purple-700 dark:hover:border-purple-700 dark:active:border-purple-700
+ dark:text-purple-400 dark:hover:text-purple-400 dark:active:text-purple-400
+}
+
+.p-button-outlined.p-button-danger {
+ @apply bg-transparent hover:bg-red-50 active:bg-red-100
+ border-red-200 hover:border-red-200 active:border-red-200
+ text-red-500 hover:text-red-500 active:text-red-500
+ dark:bg-transparent dark:hover:bg-red-400/5 dark:active:bg-red-400/15
+ dark:border-red-700 dark:hover:border-red-700 dark:active:border-red-700
+ dark:text-red-400 dark:hover:text-red-400 dark:active:text-red-400
+}
+
+.p-button-outlined.p-button-contrast {
+ @apply bg-transparent hover:bg-surface-50 active:bg-surface-100
+ border-surface-700 hover:border-surface-700 active:border-surface-700
+ text-surface-950 hover:text-surface-950 active:text-surface-950
+ dark:bg-transparent dark:hover:bg-surface-800 dark:active:bg-surface-700
+ dark:border-surface-500 dark:hover:border-surface-500 dark:active:border-surface-500
+ dark:text-surface-0 dark:hover:text-surface-0 dark:active:text-surface-0
+}
+
+.p-button-outlined.p-button-plain {
+ @apply bg-transparent hover:bg-surface-50 active:bg-surface-100
+ border-surface-200 hover:border-surface-200 active:border-surface-200
+ text-surface-700 hover:text-surface-700 active:text-surface-700
+ dark:bg-transparent dark:hover:bg-surface-800 dark:active:bg-surface-700
+ dark:border-surface-600 dark:hover:border-surface-600 dark:active:border-surface-600
+ dark:text-surface-0 dark:hover:text-surface-0 dark:active:text-surface-0
+}
+
+.p-button-text {
+ @apply bg-transparent hover:bg-primary-50 active:bg-primary-100
+ border-transparent hover:border-transparent active:border-transparent
+ text-primary hover:text-primary active:text-primary
+ dark:bg-transparent dark:hover:bg-primary/5 dark:active:bg-primary/15
+ dark:border-transparent dark:hover:border-transparent dark:active:border-transparent
+ dark:text-primary dark:hover:text-primary dark:active:text-primary
+}
+
+.p-button-text.p-button-secondary {
+ @apply bg-transparent hover:bg-surface-50 active:bg-surface-100
+ border-transparent hover:border-transparent active:border-transparent
+ text-surface-500 hover:text-surface-500 active:text-surface-500
+ dark:bg-transparent dark:hover:bg-surface-800 dark:active:bg-surface-700
+ dark:border-transparent dark:hover:border-transparent dark:active:border-transparent
+ dark:text-surface-400 dark:hover:text-surface-400 dark:active:text-surface-400
+}
+
+.p-button-text.p-button-success {
+ @apply bg-transparent hover:bg-green-50 active:bg-green-100
+ border-transparent hover:border-transparent active:border-transparent
+ text-green-500 hover:text-green-500 active:text-green-500
+ dark:bg-transparent dark:hover:bg-green-400/5 dark:active:bg-green-400/15
+ dark:border-transparent dark:hover:border-transparent dark:active:border-transparent
+ dark:text-green-400 dark:hover:text-green-400 dark:active:text-green-400
+}
+
+.p-button-text.p-button-info {
+ @apply bg-transparent hover:bg-sky-50 active:bg-sky-100
+ border-transparent hover:border-transparent active:border-transparent
+ text-sky-500 hover:text-sky-500 active:text-sky-500
+ dark:bg-transparent dark:hover:bg-sky-400/5 dark:active:bg-sky-400/15
+ dark:border-transparent dark:hover:border-transparent dark:active:border-transparent
+ dark:text-sky-400 dark:hover:text-sky-400 dark:active:text-sky-400
+}
+
+.p-button-text.p-button-warn {
+ @apply bg-transparent hover:bg-orange-50 active:bg-orange-100
+ border-transparent hover:border-transparent active:border-transparent
+ text-orange-500 hover:text-orange-500 active:text-orange-500
+ dark:bg-transparent dark:hover:bg-orange-400/5 dark:active:bg-orange-400/15
+ dark:border-transparent dark:hover:border-transparent dark:active:border-transparent
+ dark:text-orange-400 dark:hover:text-orange-400 dark:active:text-orange-400
+}
+
+.p-button-text.p-button-help {
+ @apply bg-transparent hover:bg-purple-50 active:bg-purple-100
+ border-transparent hover:border-transparent active:border-transparent
+ text-purple-500 hover:text-purple-500 active:text-purple-500
+ dark:bg-transparent dark:hover:bg-purple-400/5 dark:active:bg-purple-400/15
+ dark:border-transparent dark:hover:border-transparent dark:active:border-transparent
+ dark:text-purple-400 dark:hover:text-purple-400 dark:active:text-purple-400
+}
+
+.p-button-text.p-button-danger {
+ @apply bg-transparent hover:bg-red-50 active:bg-red-100
+ border-transparent hover:border-transparent active:border-transparent
+ text-red-500 hover:text-red-500 active:text-red-500
+ dark:bg-transparent dark:hover:bg-red-400/5 dark:active:bg-red-400/15
+ dark:border-transparent dark:hover:border-transparent dark:active:border-transparent
+ dark:text-red-400 dark:hover:text-red-400 dark:active:text-red-400
+}
+
+.p-button-text.p-button-plain {
+ @apply bg-transparent hover:bg-surface-50 active:bg-surface-100
+ border-transparent hover:border-transparent active:border-transparent
+ text-surface-700 hover:text-surface-700 active:text-surface-700
+ dark:bg-transparent dark:hover:bg-surface-800 dark:active:bg-surface-700
+ dark:border-transparent dark:hover:border-transparent dark:active:border-transparent
+ dark:text-surface-0 dark:hover:text-surface-0 dark:active:text-surface-0
+}
+
+.p-button-link {
+ @apply bg-transparent hover:bg-transparent active:bg-transparent
+ border-transparent hover:border-transparent active:border-transparent
+ text-primary hover:text-primary active:text-primary
+}
+
+.p-button-link:not(:disabled):hover .p-button-label {
+ @apply underline
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/buttongroup.css b/frontend/packages/kwai-ui/src/css/primevue/buttongroup.css
new file mode 100644
index 000000000..b5c888eef
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/buttongroup.css
@@ -0,0 +1,19 @@
+.p-buttongroup .p-button {
+ @apply m-0 focus-visible:relative focus-visible:z-10
+}
+
+.p-buttongroup .p-button:not(:last-child) {
+ @apply border-r-0
+}
+
+.p-buttongroup .p-button:not(:first-of-type):not(:last-of-type) {
+ @apply rounded-none
+}
+
+.p-buttongroup .p-button:first-of-type:not(:only-of-type) {
+ @apply rounded-e-none
+}
+
+.p-buttongroup .p-button:last-of-type:not(:only-of-type) {
+ @apply rounded-s-none
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/card.css b/frontend/packages/kwai-ui/src/css/primevue/card.css
new file mode 100644
index 000000000..45d8a6c51
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/card.css
@@ -0,0 +1,22 @@
+.p-card {
+ @apply flex flex-col rounded-xl
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+ shadow-[0_1px_3px_0_rgba(0,0,0,0.1),0_1px_2px_-1px_rgba(0,0,0,0.1)]
+}
+
+.p-card-caption {
+ @apply flex flex-col gap-2
+}
+
+.p-card-body {
+ @apply p-5 flex flex-col gap-2
+}
+
+.p-card-title {
+ @apply font-medium text-xl
+}
+
+.p-card-subtitle {
+ @apply text-surface-500 dark:text-surface-400
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/carousel.css b/frontend/packages/kwai-ui/src/css/primevue/carousel.css
new file mode 100644
index 000000000..606a8b773
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/carousel.css
@@ -0,0 +1,64 @@
+@import './button';
+
+.p-carousel {
+ @apply flex flex-col
+}
+
+.p-carousel-content-container {
+ @apply flex flex-col overflow-auto
+}
+
+.p-carousel-content {
+ @apply flex flex-row gap-1
+}
+
+.p-carousel-content:dir(rtl) {
+ @apply flex-row-reverse
+}
+
+.p-carousel-viewport {
+ @apply overflow-hidden w-full
+}
+
+.p-carousel-item-list {
+ @apply flex flex-row
+}
+
+.p-carousel-prev-button,
+.p-carousel-next-button {
+ @apply self-center flex-shrink-0
+}
+
+.p-carousel-indicator-list {
+ @apply flex flex-row justify-center flex-wrap p-4 gap-2 m-0 list-none
+}
+
+.p-carousel-indicator-list:dir(rtl) {
+ @apply rtl:flex-row-reverse
+}
+
+.p-carousel-indicator-button {
+ @apply flex items-center justify-center w-8 h-2 border-none rounded-md p-0 m-0 select-none cursor-pointer transition-colors duration-200
+ bg-surface-200 hover:bg-surface-300 dark:bg-surface-700 dark:hover:bg-surface-600
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+}
+
+.p-carousel-indicator-active .p-carousel-indicator-button {
+ @apply bg-primary
+}
+
+.p-carousel-vertical .p-carousel-content {
+ @apply flex-col
+}
+
+.p-carousel-vertical .p-carousel-item-list {
+ @apply flex-col h-full
+}
+
+.p-items-hidden .p-carousel-item {
+ @apply invisible
+}
+
+.p-items-hidden .p-carousel-item.p-carousel-item-active {
+ @apply visible
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/cascadeselect.css b/frontend/packages/kwai-ui/src/css/primevue/cascadeselect.css
new file mode 100644
index 000000000..bcc29a55a
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/cascadeselect.css
@@ -0,0 +1,169 @@
+.p-cascadeselect {
+ @apply inline-flex cursor-pointer relative select-none rounded-md
+ bg-surface-0 dark:bg-surface-950
+ border border-surface-300 dark:border-surface-700
+ shadow-[0_1px_2px_0_rgba(18,18,23,0.05)]
+ transition-colors duration-200
+}
+
+.p-cascadeselect:not(.p-disabled):hover {
+ @apply border-surface-400 dark:border-surface-600
+}
+
+.p-cascadeselect:not(.p-disabled).p-focus {
+ @apply border-primary
+}
+
+.p-cascadeselect.p-variant-filled {
+ @apply bg-surface-50 dark:bg-surface-800
+}
+
+.p-cascadeselect.p-invalid {
+ @apply border-red-400 dark:border-red-300
+}
+
+.p-cascadeselect.p-disabled {
+ @apply bg-surface-200 text-surface-500 dark:bg-surface-700 dark:text-surface-400 opacity-100 cursor-default
+}
+
+.p-cascadeselect-dropdown {
+ @apply flex items-center justify-center shrink-0 bg-transparent
+ text-surface-500 dark:text-surface-400 w-10 rounded-e-md
+}
+
+.p-cascadeselect-label {
+ @apply block whitespace-nowrap overflow-hidden flex-auto w-[1%]
+ py-2 px-3 overflow-ellipsis
+ text-surface-700 dark:text-surface-0 bg-transparent border-none outline-none
+}
+
+.p-cascadeselect-label.p-placeholder {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-cascadeselect-clearable .p-cascadeselect-label {
+ @apply pe-7
+}
+
+.p-cascadeselect.p-disabled .p-cascadeselect-label {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-cascadeselect-label-empty {
+ @apply overflow-hidden opacity-0
+}
+
+.p-cascadeselect-fluid {
+ @apply flex
+}
+
+.p-cascadeselect-fluid .p-cascadeselect-label {
+ @apply w-[1%]
+}
+
+.p-cascadeselect-overlay {
+ @apply absolute top-0 left-0 rounded-md
+ bg-surface-0 dark:bg-surface-900
+ border border-surface-200 dark:border-surface-700
+ text-surface-700 dark:text-surface-0
+ shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-2px_rgba(0,0,0,0.1)]
+}
+
+.p-cascadeselect .p-cascadeselect-overlay {
+ @apply min-w-full
+}
+
+.p-cascadeselect-option-list {
+ @apply hidden min-w-full absolute z-10
+}
+
+.p-cascadeselect-list {
+ @apply min-w-full m-0 list-none p-1 flex flex-col gap-[2px]
+}
+
+.p-cascadeselect-option {
+ @apply cursor-pointer font-normal whitespace-nowrap
+ text-surface-700 dark:text-surface-0 bg-transparent border-none
+ transition-colors duration-200 rounded-sm
+}
+
+.p-cascadeselect-option-active {
+ @apply overflow-visible
+}
+
+.p-cascadeselect-option-active > .p-cascadeselect-option-content {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-cascadeselect-option:not(.p-cascadeselect-option-selected):not(.p-disabled).p-focus > .p-cascadeselect-option-content {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-cascadeselect-option:not(.p-cascadeselect-option-selected):not(.p-disabled).p-focus .p-cascadeselect-group-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-cascadeselect-option-selected .p-cascadeselect-option-content {
+ @apply bg-highlight
+}
+
+.p-cascadeselect-option-selected.p-focus {
+ @apply bg-highlight-emphasis
+}
+
+.p-cascadeselect-option-active > .p-cascadeselect-option-list {
+ @apply block start-full top-0
+}
+
+.p-cascadeselect-option-content {
+ @apply flex items-center justify-between overflow-hidden relative px-3 py-2
+}
+
+.p-cascadeselect-group-icon {
+ @apply text-sm w-[0.875rem] h-[0.875rem] text-surface-400 dark:text-surface-500
+}
+
+.p-cascadeselect-group-icon:dir(rtl) {
+ @apply rotate-180
+}
+
+
+.p-cascadeselect-mobile-active .p-cascadeselect-option-content {
+ @apply rounded-sm
+}
+
+.p-cascadeselect-mobile-active-active .p-cascadeselect-list {
+ @apply flex flex-col top-full start-0 z-10
+}
+
+.p-cascadeselect-mobile-active .p-cascadeselect-list > .p-cascadeselect-option > .p-cascadeselect-option-content .p-cascadeselect-group-icon {
+ @apply ms-auto transition-transform duration-200
+}
+
+.p-cascadeselect-mobile-active .p-cascadeselect-list .p-cascadeselect-group-icon {
+ @apply transition-transform duration-200 rotate-90
+}
+
+.p-cascadeselect-mobile-active .p-cascadeselect-option-active > .p-cascadeselect-option-content .p-cascadeselect-group-icon {
+ @apply -rotate-90
+}
+
+.p-cascadeselect-mobile-active .p-cascadeselect-option-list {
+ @apply static shadow-none border-none ps-4
+}
+
+.p-cascadeselect-sm .p-cascadeselect-label {
+ @apply text-sm px-[0.625rem] py-[0.375rem]
+}
+
+.p-cascadeselect-sm .p-cascadeselect-dropdown .p-icon {
+ @apply text-sm w-[0.875rem] h-[0.875rem]
+}
+
+.p-cascadeselect-lg .p-cascadeselect-label {
+ @apply text-lg px-[0.875rem] py-[0.625rem]
+}
+
+.p-cascadeselect-lg .p-cascadeselect-dropdown .p-icon {
+ @apply text-lg w-[1.125rem] h-[1.125rem]
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/checkbox.css b/frontend/packages/kwai-ui/src/css/primevue/checkbox.css
new file mode 100644
index 000000000..431fbbd6b
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/checkbox.css
@@ -0,0 +1,84 @@
+.p-checkbox {
+ @apply relative inline-flex select-none w-5 h-5 align-bottom
+}
+
+.p-checkbox-input {
+ @apply cursor-pointer disabled:cursor-default appearance-none absolute start-0 top-0 w-full h-full m-0 p-0 opacity-0 z-10
+ border border-transparent rounded-sm
+}
+
+.p-checkbox-box {
+ @apply flex justify-center items-center rounded-sm w-5 h-5
+ border border-surface-300 dark:border-surface-700
+ bg-surface-0 dark:bg-surface-950
+ transition-colors duration-200
+ shadow-[0_1px_2px_0_rgba(18,18,23,0.05)]
+}
+
+.p-checkbox-icon {
+ @apply text-surface-700 dark:text-surface-0
+ text-sm w-[0.875rem] h-[0.875rem]
+ transition-colors duration-200
+}
+
+.p-checkbox:not(.p-disabled):has(.p-checkbox-input:hover) .p-checkbox-box {
+ @apply border-surface-400 dark:border-surface-600
+}
+
+.p-checkbox-checked .p-checkbox-box {
+ @apply border-primary bg-primary
+}
+
+.p-checkbox-checked .p-checkbox-icon {
+ @apply text-primary-contrast
+}
+
+.p-checkbox-checked:not(.p-disabled):has(.p-checkbox-input:hover) .p-checkbox-box {
+ @apply bg-primary-emphasis border-primary-emphasis
+}
+
+.p-checkbox-checked:not(.p-disabled):has(.p-checkbox-input:hover) .p-checkbox-icon {
+ @apply text-primary-contrast
+}
+
+.p-checkbox:not(.p-disabled):has(.p-checkbox-input:focus-visible) .p-checkbox-box {
+ @apply outline outline-1 outline-offset-2 outline-primary
+}
+
+.p-checkbox.p-invalid > .p-checkbox-box {
+ @apply border-red-400 dark:border-red-300
+}
+
+.p-checkbox.p-variant-filled .p-checkbox-box {
+ @apply bg-surface-50 dark:bg-surface-800
+}
+
+.p-checkbox.p-disabled {
+ @apply opacity-100
+}
+
+.p-checkbox.p-disabled .p-checkbox-box {
+ @apply bg-surface-200 dark:bg-surface-400 border-surface-300 dark:border-surface-700
+}
+
+.p-checkbox.p-disabled .p-checkbox-box .p-checkbox-icon {
+ @apply text-surface-700 dark:text-surface-400
+}
+
+.p-checkbox-sm,
+.p-checkbox-sm .p-checkbox-box {
+ @apply w-4 h-4
+}
+
+.p-checkbox-sm .p-checkbox-icon {
+ @apply w-3 h-3
+}
+
+.p-checkbox-lg,
+.p-checkbox-lg .p-checkbox-box {
+ @apply w-6 h-6
+}
+
+.p-checkbox-lg .p-checkbox-icon {
+ @apply w-4 h-4
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/chip.css b/frontend/packages/kwai-ui/src/css/primevue/chip.css
new file mode 100644
index 000000000..7f10d74ed
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/chip.css
@@ -0,0 +1,27 @@
+.p-chip {
+ @apply inline-flex items-center rounded-2xl gap-2 px-3 py-2
+ bg-surface-100 dark:bg-surface-800
+ text-surface-800 dark:text-surface-0
+}
+
+.p-chip-icon {
+ @apply text-surface-800 dark:bg-surface-0 text-base w-4 h-4
+}
+
+.p-chip-image {
+ @apply rounded-full w-8 h-8 -ms-2
+}
+
+.p-chip:has(.p-chip-remove-icon) {
+ @apply pe-2
+}
+
+.p-chip:has(.p-chip-image) {
+ @apply pt-1 pb-1
+}
+
+.p-chip-remove-icon {
+ @apply cursor-pointer text-base w-4 h-4 rounded-full
+ text-surface-800 dark:text-surface-0
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/colorpicker.css b/frontend/packages/kwai-ui/src/css/primevue/colorpicker.css
new file mode 100644
index 000000000..71c433548
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/colorpicker.css
@@ -0,0 +1,47 @@
+.p-colorpicker {
+ @apply inline-block relative;
+}
+
+.p-colorpicker-dragging {
+ @apply cursor-pointer
+}
+
+.p-colorpicker-preview {
+ @apply w-6 h-6 p-0 border-none rounded-md transition-colors duration-200 cursor-pointer disabled:cursor-auto
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+}
+
+.p-colorpicker-panel {
+ @apply bg-surface-800 dark:bg-surface-900
+ border border-surface-900 dark:border-surface-700
+ rounded-md shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-2px_rgba(0,0,0,0.1)]
+ w-[193px] h-[166px] absolute top-0 start-0
+}
+
+.p-colorpicker-panel-inline {
+ @apply static shadow-none
+}
+
+.p-colorpicker-content {
+ @apply relative;
+}
+
+.p-colorpicker-color-selector {
+ @apply w-[150px] h-[150px] top-[8px] start-[8px] absolute
+}
+
+.p-colorpicker-color-background {
+ @apply w-full h-full bg-[linear-gradient(to_top,#000_0%,rgba(0,0,0,0)_100%),linear-gradient(to_right,#fff_0%,rgba(255,255,255,0)_100%)];
+}
+
+.p-colorpicker-color-handle {
+ @apply absolute top-0 start-[150px] rounded-full w-[10px] h-[10px] border border-surface-0 -mt-[5px] me-0 mb-0 -ms-[5px] cursor-pointer opacity-85
+}
+
+.p-colorpicker-hue {
+ @apply w-[17px] h-[150px] top-[8px] start-[167px] absolute opacity-85 bg-[linear-gradient(0deg,red_0,#ff0_17%,#0f0_33%,#0ff_50%,#00f_67%,#f0f_83%,red)];
+}
+
+.p-colorpicker-hue-handle {
+ @apply absolute top-[150px] start-0 w-[21px] -ms-[2px] -mt-[5px] h-[10px] border-2 opacity-85 border-surface-0 cursor-pointer
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/common.css b/frontend/packages/kwai-ui/src/css/primevue/common.css
new file mode 100644
index 000000000..8a388600e
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/common.css
@@ -0,0 +1,81 @@
+.p-connected-overlay-enter-from {
+ @apply opacity-0 scale-y-75
+}
+
+.p-connected-overlay-leave-to {
+ @apply opacity-0
+}
+
+.p-connected-overlay-enter-active {
+ @apply transition-[opacity,transform] duration-150 ease-[cubic-bezier(0,0,0.2,1)]
+}
+
+.p-connected-overlay-leave-active {
+ @apply transition-opacity duration-100 ease-linear
+}
+
+.p-toggleable-content-enter-from,
+.p-toggleable-content-leave-to {
+ @apply max-h-0
+}
+
+.p-toggleable-content-enter-to,
+.p-toggleable-content-leave-from {
+ @apply max-h-[1000px]
+}
+
+.p-toggleable-content-leave-active {
+ @apply overflow-hidden transition-[max-height] duration-[450ms] ease-[cubic-bezier(0,1,0,1)];
+}
+
+.p-toggleable-content-enter-active {
+ @apply overflow-hidden transition-[max-height] duration-1000 ease-in-out
+}
+
+.p-disabled,
+.p-disabled * {
+ @apply cursor-default pointer-events-none select-none
+}
+
+.p-disabled,
+.p-component:disabled {
+ @apply opacity-60
+}
+
+.pi {
+ @apply text-base
+}
+
+.p-icon {
+ @apply w-4 h-4
+}
+
+.p-overlay-mask {
+ @apply bg-black/50 text-surface-200 transition-colors duration-150 fixed top-0 start-0 w-full h-full
+}
+
+.p-overlay-mask-enter {
+ animation: p-overlay-mask-enter-animation 150ms forwards;
+}
+
+.p-overlay-mask-leave {
+ animation: p-overlay-mask-leave-animation 150ms forwards;
+}
+
+@keyframes p-overlay-mask-enter-animation {
+ from {
+ background: transparent;
+ }
+ to {
+ background: rgba(0,0,0,0.5);
+ }
+}
+
+@keyframes p-overlay-mask-leave-animation {
+ from {
+ background: rgba(0,0,0,0.5);
+ }
+ to {
+ background: transparent;
+ }
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/confirmdialog.css b/frontend/packages/kwai-ui/src/css/primevue/confirmdialog.css
new file mode 100644
index 000000000..d28074ddb
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/confirmdialog.css
@@ -0,0 +1,10 @@
+@import './dialog';
+@import './button';
+
+.p-confirmdialog .p-dialog-content {
+ @apply flex items-center gap-4
+}
+
+.p-confirmdialog-icon {
+ @apply text-surface-700 dark:text-surface-0 text-[2rem] h-8 w-8
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/confirmpopup.css b/frontend/packages/kwai-ui/src/css/primevue/confirmpopup.css
new file mode 100644
index 000000000..861a29494
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/confirmpopup.css
@@ -0,0 +1,66 @@
+@import './button';
+
+.p-confirmpopup {
+ @apply absolute mt-[10px] top-0 left-0
+ border border-surface-200 dark:border-surface-700 rounded-md
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+ shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-2px_rgba(0,0,0,0.1)]
+ before:bottom-full before:left-5 before:h-0 before:w-0 before:absolute before:pointer-events-none
+ before:border-[10px] before:-ms-[10px] before:border-transparent before:border-b-surface-200 dark:before:border-b-surface-700
+ after:bottom-full after:left-5 after:h-0 after:w-0 after:absolute after:pointer-events-none
+ after:border-[8px] after:-ms-[8px] after:border-transparent after:border-b-surface-0 dark:after:border-b-surface-900
+}
+
+.p-confirmpopup-content {
+ @apply flex items-center p-3 gap-4
+}
+
+.p-confirmpopup-icon {
+ @apply text-2xl w-6 h-6 text-surface-700 dark:text-surface-0
+}
+
+.p-confirmpopup-footer {
+ @apply flex justify-end gap-2 pt-0 px-3 pb-3
+}
+
+.p-confirmpopup-footer button {
+ @apply w-auto
+}
+
+.p-confirmpopup-footer button:last-child {
+ @apply m-0
+}
+
+.p-confirmpopup-flipped {
+ @apply -mt-[10px] mb-[10px]
+}
+
+.p-confirmpopup-enter-from {
+ @apply opacity-0 scale-y-75
+}
+
+.p-confirmpopup-leave-to {
+ @apply opacity-0
+}
+
+.p-confirmpopup-enter-active {
+ @apply [transition:transform_120ms_cubic-bezier(0,0,0.2,1),opacity_120ms_cubic-bezier(0,0,0.2,1)]
+}
+
+.p-confirmpopup-leave-active {
+ @apply transition-opacity duration-100 ease-linear
+}
+
+.p-confirmpopup-flipped:after,
+.p-confirmpopup-flipped:before {
+ @apply bottom-auto top-full
+}
+
+.p-confirmpopup-flipped:after {
+ @apply border-b-transparent border-t-surface-0 dark:border-t-surface-900
+}
+
+.p-confirmpopup-flipped:before {
+ @apply border-b-transparent border-t-surface-200 dark:border-t-surface-700
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/contextmenu.css b/frontend/packages/kwai-ui/src/css/primevue/contextmenu.css
new file mode 100644
index 000000000..d9af2908b
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/contextmenu.css
@@ -0,0 +1,101 @@
+.p-contextmenu {
+ @apply bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+ border border-surface-200 dark:border-surface-700
+ rounded-md min-w-52 shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-2px_rgba(0,0,0,0.1)]
+}
+
+.p-contextmenu-root-list,
+.p-contextmenu-submenu {
+ @apply m-0 p-1 list-none outline-none flex flex-col gap-[2px]
+}
+
+.p-contextmenu-submenu {
+ @apply absolute min-w-full z-10 rounded-md
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+ border border-surface-200 dark:border-surface-700
+ shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-2px_rgba(0,0,0,0.1)]
+}
+
+.p-contextmenu-item {
+ @apply relative
+}
+
+.p-contextmenu-item-content {
+ @apply transition-colors duration-200 rounded-sm text-surface-700 dark:text-surface-0
+}
+
+.p-contextmenu-item-link {
+ @apply cursor-pointer flex items-center no-underline overflow-hidden relative text-inherit
+ px-3 py-2 gap-2 select-none outline-none
+}
+
+.p-contextmenu-item-icon {
+ @apply text-surface-400 dark:text-surface-500
+}
+
+.p-contextmenu-submenu-icon {
+ @apply text-surface-400 dark:text-surface-500 ms-auto text-sm w-[0.875rem] h-[0.875rem]
+}
+
+.p-contextmenu-item.p-focus > .p-contextmenu-item-content {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-contextmenu-item.p-focus > .p-contextmenu-item-content .p-contextmenu-item-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-contextmenu-item.p-focus > .p-contextmenu-item-content .p-contextmenu-submenu-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-contextmenu-item:not(.p-disabled) > .p-contextmenu-item-content:hover {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-contextmenu-item:not(.p-disabled) > .p-contextmenu-item-content:hover .p-contextmenu-item-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-contextmenu-item:not(.p-disabled) > .p-contextmenu-item-content:hover .p-contextmenu-submenu-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-contextmenu-item-active > .p-contextmenu-item-content {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-contextmenu-item-active > .p-contextmenu-item-content .p-contextmenu-item-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-contextmenu-item-active > .p-contextmenu-item-content .p-contextmenu-submenu-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-contextmenu-separator {
+ @apply border-t border-surface-200 dark:border-surface-700
+}
+
+.p-contextmenu-enter-from,
+.p-contextmenu-leave-active {
+ @apply opacity-0
+}
+
+.p-contextmenu-enter-active {
+ @apply transition-opacity duration-[250ms]
+}
+
+.p-contextmenu-mobile .p-contextmenu-submenu {
+ @apply static shadow-none border-none ps-4 pe-0
+}
+
+.p-contextmenu-mobile .p-contextmenu-submenu-icon {
+ @apply transition-transform duration-200 rotate-90
+}
+
+.p-contextmenu-mobile .p-contextmenu-item-active > .p-contextmenu-item-content .p-contextmenu-submenu-icon {
+ @apply -rotate-90
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/datatable.css b/frontend/packages/kwai-ui/src/css/primevue/datatable.css
new file mode 100644
index 000000000..b77d71d2a
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/datatable.css
@@ -0,0 +1,408 @@
+@import './paginator';
+
+.p-datatable {
+ @apply relative
+}
+
+.p-datatable-table {
+ @apply border-spacing-0 w-full
+}
+
+.p-datatable-scrollable > .p-datatable-table-container {
+ @apply relative
+}
+
+.p-datatable-scrollable-table > .p-datatable-thead {
+ @apply top-0 z-10
+}
+
+.p-datatable-scrollable-table > .p-datatable-frozen-tbody {
+ @apply sticky z-10
+}
+
+.p-datatable-scrollable-table > .p-datatable-tfoot {
+ @apply bottom-0 z-10
+}
+
+.p-datatable-scrollable .p-datatable-frozen-column {
+ @apply sticky bg-surface-0 dark:bg-surface-900
+}
+
+.p-datatable-scrollable th.p-datatable-frozen-column {
+ @apply z-10
+}
+
+.p-datatable-scrollable > .p-datatable-table-container > .p-datatable-table > .p-datatable-thead,
+.p-datatable-scrollable > .p-datatable-table-container > .p-virtualscroller > .p-datatable-table > .p-datatable-thead {
+ @apply bg-surface-0 dark:bg-surface-900
+}
+
+.p-datatable-scrollable > .p-datatable-table-container > .p-datatable-table > .p-datatable-tfoot,
+.p-datatable-scrollable > .p-datatable-table-container > .p-virtualscroller > .p-datatable-table > .p-datatable-tfoot {
+ @apply bg-surface-0 dark:bg-surface-900
+}
+
+.p-datatable-flex-scrollable {
+ @apply flex flex-col h-full
+}
+
+.p-datatable-flex-scrollable > .p-datatable-table-container {
+ @apply flex flex-col flex-1 h-full
+}
+
+.p-datatable-scrollable-table > .p-datatable-tbody > .p-datatable-row-group-header {
+ @apply sticky z-10
+}
+
+.p-datatable-resizable-table > .p-datatable-thead > tr > th,
+.p-datatable-resizable-table > .p-datatable-tfoot > tr > td,
+.p-datatable-resizable-table > .p-datatable-tbody > tr > td {
+ @apply overflow-hidden whitespace-nowrap
+}
+
+.p-datatable-resizable-table > .p-datatable-thead > tr > th.p-datatable-resizable-column:not(.p-datatable-frozen-column) {
+ @apply bg-clip-padding relative
+}
+
+.p-datatable-resizable-table-fit > .p-datatable-thead > tr > th.p-datatable-resizable-column:last-child .p-datatable-column-resizer {
+ @apply hidden
+}
+
+.p-datatable-column-resizer {
+ @apply block absolute top-0 end-0 m-0 w-2 h-full p-0 cursor-col-resize border border-transparent
+}
+
+.p-datatable-column-header-content {
+ @apply flex items-center gap-2
+}
+
+.p-datatable-column-resize-indicator {
+ @apply w-px absolute z-10 hidden bg-primary
+}
+
+.p-datatable-row-reorder-indicator-up,
+.p-datatable-row-reorder-indicator-down {
+ @apply absolute hidden
+}
+
+.p-datatable-reorderable-column,
+.p-datatable-reorderable-row-handle {
+ @apply cursor-move
+}
+
+.p-datatable-mask {
+ @apply absolute flex items-center justify-center z-20
+}
+
+.p-datatable-inline-filter {
+ @apply flex items-center w-full gap-2
+}
+
+.p-datatable-inline-filter .p-datatable-filter-element-container {
+ @apply flex-auto w-[1%]
+}
+
+.p-datatable-filter-overlay {
+ @apply bg-surface-0 dark:bg-surface-900 rounded-md min-w-52
+ border border-surface-200 dark:border-surface-700
+ text-surface-700 dark:text-surface-0
+ shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-2px_rgba(0,0,0,0.1)]
+}
+
+.p-datatable-filter-constraint-list {
+ @apply m-0 list-none flex flex-col p-1 gap-[2px]
+}
+
+.p-datatable-filter-constraint {
+ @apply px-3 py-2 rounded-sm cursor-pointer transition-colors duration-200 text-surface-700 dark:text-surface-0
+}
+
+.p-datatable-filter-constraint-selected {
+ @apply bg-highlight
+}
+
+.p-datatable-filter-constraint:not(.p-datatable-filter-constraint-selected):not(.p-disabled):hover
+{
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-datatable-filter-constraint:focus-visible {
+ @apply outline-none bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-datatable-filter-constraint-selected:focus-visible {
+ @apply bg-highlight-emphasis
+}
+
+.p-datatable-filter-constraint-separator {
+ @apply border-t border-surface-200 dark:border-surface-700
+}
+
+.p-datatable-popover-filter {
+ @apply inline-flex ms-auto
+}
+
+.p-datatable-filter-overlay-popover {
+ @apply flex flex-col gap-2
+ bg-surface-0 dark:bg-surface-900 text-surface-700 dark:text-surface-0
+ border border-surface-200 dark:border-surface-700 rounded-md p-3 min-w-52
+ shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-2px_rgba(0,0,0,0.1)]
+}
+
+.p-datatable-filter-operator-dropdown {
+ @apply w-full
+}
+
+.p-datatable-filter-rule-list,
+.p-datatable-filter-rule {
+ @apply flex flex-col gap-2
+}
+
+.p-datatable-filter-rule {
+ @apply border-b border-surface-200 dark:border-surface-700 last:border-b-0 pb-2 last:pb-0
+}
+
+.p-datatable-filter-add-rule-button {
+ @apply w-full
+}
+
+.p-datatable-filter-remove-rule-button {
+ @apply w-full
+}
+
+.p-datatable-filter-buttonbar {
+ @apply p-0 flex items-center justify-between
+}
+
+.p-datatable-virtualscroller-spacer {
+ @apply flex
+}
+
+.p-datatable .p-virtualscroller .p-virtualscroller-loading {
+ @apply transform-none min-h-0 sticky top-0 start-0
+}
+
+.p-datatable-paginator-top {
+ @apply border-b border-surface-200 dark:border-surface-700
+}
+
+.p-datatable-paginator-bottom {
+ @apply border-t border-surface-200 dark:border-surface-700
+}
+
+.p-datatable-header {
+ @apply py-3 px-4 border-b border-surface-200 dark:border-surface-700
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+}
+
+.p-datatable-footer {
+ @apply py-3 px-4 border-b border-surface-200 dark:border-surface-700
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+}
+
+.p-datatable-header-cell {
+ @apply py-3 px-4 font-normal text-start transition-colors duration-200
+ border-b border-surface-200 dark:border-surface-700
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+}
+
+.p-datatable-column-title {
+ @apply font-semibold
+}
+
+.p-datatable-tbody > tr {
+ @apply bg-surface-0 dark:bg-surface-900 text-surface-700 dark:text-surface-0 transition-colors duration-200
+}
+
+.p-datatable-tbody > tr > td {
+ @apply text-start py-3 px-4 border-b border-surface-200 dark:border-surface-800
+}
+
+.p-datatable-hoverable .p-datatable-tbody > tr:not(.p-datatable-row-selected):hover {
+ @apply bg-surface-100 text-surface-800 dark:bg-surface-800 dark:text-surface-0
+}
+
+.p-datatable-tbody > tr.p-datatable-row-selected {
+ @apply bg-highlight
+}
+
+.p-datatable-tbody > tr:has(+ .p-datatable-row-selected) > td {
+ @apply border-b-primary-100 dark:border-b-primary-900
+}
+
+.p-datatable-tbody > tr.p-datatable-row-selected > td {
+ @apply border-b-primary-100 dark:border-b-primary-900
+}
+
+.p-datatable-tbody > tr:focus-visible,
+.p-datatable-tbody > tr.p-datatable-contextmenu-row-selected {
+ @apply outline outline-1 -outline-offset-1 outline-primary
+}
+
+.p-datatable-tfoot > tr > td {
+ @apply text-start py-3 px-4 border-b border-surface-200 dark:border-surface-800
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+}
+
+.p-datatable-column-footer {
+ @apply font-semibold
+}
+
+.p-datatable-sortable-column {
+ @apply cursor-pointer select-none focus-visible:outline focus-visible:outline-1 focus-visible:-outline-offset-1 focus-visible:outline-primary
+}
+
+.p-datatable-column-title,
+.p-datatable-sort-icon,
+.p-datatable-sort-badge {
+ @apply align-middle
+}
+
+.p-datatable-sort-icon {
+ @apply text-surface-500 dark:text-surface-400 transition-colors duration-200
+}
+
+.p-datatable-sortable-column:not(.p-datatable-column-sorted):hover {
+ @apply bg-surface-100 text-surface-800 dark:bg-surface-800 dark:text-surface-0
+}
+
+.p-datatable-sortable-column:not(.p-datatable-column-sorted):hover .p-datatable-sort-icon {
+ @apply text-surface-600 dark:text-surface-300
+}
+
+.p-datatable-column-sorted {
+ @apply bg-highlight
+}
+
+.p-datatable-column-sorted .p-datatable-sort-icon {
+ @apply bg-highlight
+}
+
+.p-datatable-hoverable .p-datatable-selectable-row {
+ @apply cursor-pointer
+}
+
+.p-datatable-tbody > tr.p-datatable-dragpoint-top > td {
+ @apply shadow-[inset_0_2px_0_0_theme(colors.primary)]
+}
+
+.p-datatable-tbody > tr.p-datatable-dragpoint-bottom > td {
+ @apply shadow-[inset_0_-2px_0_0_theme(colors.primary)]
+}
+
+.p-datatable-loading-icon {
+ @apply text-[2rem] w-8 h-8
+}
+
+.p-datatable-gridlines .p-datatable-header {
+ @apply border-t border-x
+}
+
+.p-datatable-gridlines .p-datatable-footer {
+ @apply border-b border-x
+}
+
+.p-datatable-gridlines .p-datatable-paginator-top {
+ @apply border-t border-x
+}
+
+.p-datatable-gridlines .p-datatable-paginator-bottom {
+ @apply border-b border-x
+}
+
+.p-datatable-gridlines .p-datatable-thead > tr > th {
+ @apply border-t border-x last:border
+}
+
+.p-datatable-gridlines .p-datatable-tbody > tr > td {
+ @apply border-t border-s last:border-r
+}
+
+.p-datatable-gridlines .p-datatable-tbody > tr:last-child > td {
+ @apply border-y border-s last:border
+}
+
+.p-datatable-gridlines .p-datatable-tfoot > tr > td {
+ @apply border-y border-s last:border
+}
+
+.p-datatable.p-datatable-gridlines .p-datatable-thead + .p-datatable-tfoot > tr > td {
+ @apply border-b border-s last:border-r
+}
+
+.p-datatable.p-datatable-gridlines:has(.p-datatable-thead):has(.p-datatable-tbody) .p-datatable-tbody > tr > td {
+ @apply border-b border-s last:border-r
+}
+
+.p-datatable.p-datatable-gridlines:has(.p-datatable-tbody):has(.p-datatable-tfoot) .p-datatable-tbody > tr:last-child > td {
+ @apply border-s last:border-r
+}
+
+.p-datatable.p-datatable-striped .p-datatable-tbody > tr.p-row-odd {
+ @apply bg-surface-50 dark:bg-surface-950
+}
+
+.p-datatable.p-datatable-striped .p-datatable-tbody > tr.p-row-odd.p-datatable-row-selected {
+ @apply bg-highlight
+}
+
+.p-datatable.p-datatable-sm .p-datatable-header {
+ @apply py-1 px-2
+}
+
+.p-datatable.p-datatable-sm .p-datatable-thead > tr > th {
+ @apply py-1 px-2
+}
+
+.p-datatable.p-datatable-sm .p-datatable-tbody > tr > td {
+ @apply py-1 px-2
+}
+
+.p-datatable.p-datatable-sm .p-datatable-tfoot > tr > td {
+ @apply py-1 px-2
+}
+
+.p-datatable.p-datatable-sm .p-datatable-footer {
+ @apply py-1 px-2
+}
+
+.p-datatable.p-datatable-lg .p-datatable-header {
+ @apply py-4 px-5
+}
+
+.p-datatable.p-datatable-lg .p-datatable-thead > tr > th {
+ @apply py-4 px-5
+}
+
+.p-datatable.p-datatable-lg .p-datatable-tbody>tr>td {
+ @apply py-4 px-5
+}
+
+.p-datatable.p-datatable-lg .p-datatable-tfoot>tr>td {
+ @apply py-4 px-5
+}
+
+.p-datatable.p-datatable-lg .p-datatable-footer {
+ @apply py-4 px-5
+}
+
+.p-datatable-row-toggle-button {
+ @apply inline-flex items-center justify-center overflow-hidden relative w-7 h-7 cursor-pointer select-none
+ transition-colors duration-200 rounded-full border-none bg-transparent
+ text-surface-500 enabled:hover:bg-surface-100 enabled:hover:text-surface-700
+ dark:text-surface-400 dark:enabled:hover:bg-surface-800 dark:enabled:hover:text-surface-0
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+
+}
+
+.p-datatable-tbody > tr.p-datatable-row-selected .p-datatable-row-toggle-button:hover {
+ @apply bg-surface-0 dark:bg-surface-900 text-primary
+}
+
+.p-datatable-row-toggle-icon:dir(rtl) {
+ @apply rotate-180
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/dataview.css b/frontend/packages/kwai-ui/src/css/primevue/dataview.css
new file mode 100644
index 000000000..12f5b0750
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/dataview.css
@@ -0,0 +1,29 @@
+@import './paginator';
+
+.p-dataview {
+ @apply border-none
+}
+
+.p-dataview-header {
+ @apply py-3 px-4 border-b border-surface-200 dark:border-surface-700
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+}
+
+.p-dataview-content {
+ @apply bg-surface-0 dark:bg-surface-900 text-surface-700 dark:text-surface-0
+}
+
+.p-dataview-footer {
+ @apply py-3 px-4 border-t border-surface-200 dark:border-surface-700
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+}
+
+.p-dataview-paginator-top {
+ @apply border-b border-surface-200 dark:border-surface-700
+}
+
+.p-dataview-paginator-bottom {
+ @apply border-t border-surface-200 dark:border-surface-700
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/datepicker.css b/frontend/packages/kwai-ui/src/css/primevue/datepicker.css
new file mode 100644
index 000000000..122759842
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/datepicker.css
@@ -0,0 +1,211 @@
+@import './button';
+@import './inputtext';
+
+.p-datepicker {
+ @apply inline-flex max-w-full
+}
+
+.p-datepicker-input {
+ @apply flex-auto w-[1%]
+}
+
+.p-datepicker:has(.p-datepicker-dropdown) .p-datepicker-input {
+ @apply rounded-e-none
+}
+
+.p-datepicker-dropdown {
+ @apply inline-flex items-center justify-center overflow-hidden relative cursor-pointer select-none
+ w-10 rounded-e-md border border-s-0 border-surface-300 dark:border-surface-700
+ bg-surface-100 enabled:hover:bg-surface-200 enabled:active:bg-surface-300
+ text-surface-600 enabled:hover:text-surface-700 enabled:active:text-surface-800
+ dark:bg-surface-800 dark:enabled:hover:bg-surface-700 dark:enabled:active:bg-surface-600
+ dark:text-surface-300 dark:enabled:hover:text-surface-200 dark:enabled:active:text-surface-100
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+ transition-colors duration-200
+}
+
+.p-datepicker:has(.p-datepicker-input-icon-container) {
+ @apply relative
+}
+
+.p-datepicker:has(.p-datepicker-input-icon-container) .p-datepicker-input {
+ @apply pe-10
+}
+
+.p-datepicker-input-icon-container {
+ @apply cursor-pointer absolute top-1/2 end-3 -mt-2 text-surface-400
+}
+
+.p-datepicker-fluid {
+ @apply flex
+}
+
+.p-datepicker-fluid .p-datepicker-input {
+ @apply w-[1%]
+}
+
+.p-datepicker .p-datepicker-panel {
+ @apply min-w-full
+}
+
+.p-datepicker-panel {
+ @apply w-auto p-3 rounded-md
+ border border-surface-200 dark:border-surface-700
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+ shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-2px_rgba(0,0,0,0.1)]
+}
+
+.p-datepicker-panel-inline {
+ @apply inline-block overflow-x-auto shadow-none
+}
+
+.p-datepicker-header {
+ @apply flex items-center justify-between pt-0 px-0 pb-2 font-medium gap-2
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+ border-b border-surface-200 dark:border-surface-700
+}
+
+.p-datepicker-next-button:dir(rtl) {
+ @apply order-[-1]
+}
+.p-datepicker-prev-button:dir(rtl) {
+ @apply order-1
+}
+
+.p-datepicker-title {
+ @apply flex items-center justify-between gap-2 font-medium
+}
+
+.p-datepicker-select-year,
+.p-datepicker-select-month {
+ @apply border-none bg-transparent m-0 cursor-pointer font-medium transition-colors duration-200
+ py-1 px-2 rounded-md text-surface-700 dark:text-surface-0
+ enabled:hover:bg-surface-100 enabled:hover:text-surface-800
+ dark:enabled:hover:bg-surface-800 dark:enabled:hover:text-surface-0
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+}
+
+.p-datepicker-calendar-container {
+ @apply flex
+}
+
+.p-datepicker-calendar-container .p-datepicker-calendar {
+ @apply flex-auto border-s border-surface-200 dark:border-surface-700 gap-3
+ first:ps-0 first:border-s-0 last:pe-0
+}
+
+.p-datepicker-day-view {
+ @apply w-full border-collapse text-base mt-2 mx-0 mb-0
+}
+
+.p-datepicker-weekday-cell {
+ @apply p-1
+}
+
+.p-datepicker-weekday {
+ @apply font-medium text-surface-700 dark:text-surface-0
+}
+
+.p-datepicker-day-cell {
+ @apply p-1
+}
+
+.p-datepicker-day {
+ @apply flex items-center justify-center cursor-pointer my-0 mx-auto overflow-hidden relative w-8 h-8
+ rounded-full p-1 transition-colors duration-200 border border-transparent text-surface-700 dark:text-surface-0
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+}
+
+.p-datepicker-day:not(.p-datepicker-day-selected):not(.p-disabled):hover {
+ @apply bg-surface-100 text-surface-800 dark:bg-surface-800 dark:text-surface-0
+}
+
+.p-datepicker-day-selected {
+ @apply bg-primary text-primary-contrast
+}
+
+.p-datepicker-day-selected-range {
+ @apply bg-highlight
+}
+
+.p-datepicker-today > .p-datepicker-day {
+ @apply bg-surface-200 text-surface-900 dark:bg-surface-700 dark:text-surface-0
+}
+
+.p-datepicker-today > .p-datepicker-day-selected {
+ @apply bg-primary text-primary-contrast
+}
+
+.p-datepicker-today > .p-datepicker-day-selected-range {
+ @apply bg-highlight
+}
+
+.p-datepicker-weeknumber {
+ @apply text-center
+}
+
+.p-datepicker-month-view {
+ @apply mt-2 mb-0 mx-0
+}
+
+.p-datepicker-month {
+ @apply w-1/3 inline-flex items-center justify-center cursor-pointer overflow-hidden relative
+ p-[0.375rem] transition-colors duration-200 rounded-md text-surface-700 dark:text-surface-0
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+}
+
+.p-datepicker-month:not(.p-disabled):not(.p-datepicker-month-selected):hover {
+ @apply bg-surface-100 text-surface-800 dark:bg-surface-800 dark:text-surface-0
+}
+
+.p-datepicker-month-selected {
+ @apply bg-primary text-primary-contrast
+}
+
+.p-datepicker-year-view {
+ @apply mt-2 mb-0 mx-0
+}
+
+.p-datepicker-year {
+ @apply w-1/2 inline-flex items-center justify-center cursor-pointer overflow-hidden relative
+ p-[0.375rem] transition-colors duration-200 rounded-md text-surface-700 dark:text-surface-0
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+}
+
+.p-datepicker-year:not(.p-disabled):not(.p-datepicker-year-selected):hover {
+ @apply bg-surface-100 text-surface-800 dark:bg-surface-800 dark:text-surface-0
+}
+
+.p-datepicker-year-selected {
+ @apply bg-primary text-primary-contrast
+}
+
+.p-datepicker-buttonbar {
+ @apply flex justify-between items-center pt-2 pb-0 px-0 border-t border-surface-200 dark:border-surface-700
+}
+
+.p-datepicker-buttonbar .p-button {
+ @apply w-auto
+}
+
+.p-datepicker-time-picker {
+ @apply flex items-center justify-center border-t border-surface-200 dark:border-surface-700 p-0 gap-2
+}
+
+.p-datepicker-calendar-container + .p-datepicker-time-picker {
+ @apply pt-2 pb-0 px-0
+}
+
+.p-datepicker-time-picker > div {
+ @apply flex items-center flex-col gap-1
+}
+
+.p-datepicker-time-picker span {
+ @apply text-base
+}
+
+.p-datepicker-timeonly .p-datepicker-time-picker {
+ @apply border-t-0
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/dialog.css b/frontend/packages/kwai-ui/src/css/primevue/dialog.css
new file mode 100644
index 000000000..8c9ddf89f
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/dialog.css
@@ -0,0 +1,125 @@
+@import './button';
+
+.p-dialog {
+ @apply max-h-[90%] scale-100 rounded-xl
+ border border-surface-200 dark:border-surface-700
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+ shadow-[0_20px_25px_-5px_rgba(0,0,0,0.1),0_8px_10px_-6px_rgba(0,0,0,0.1)]
+}
+
+.p-dialog-content {
+ @apply overflow-y-auto pt-0 px-5 pb-5
+}
+
+.p-dialog-header {
+ @apply flex items-center justify-between shrink-0 p-5
+}
+
+.p-dialog-title {
+ @apply font-semibold text-xl
+}
+
+.p-dialog-footer {
+ @apply shrink-0 pt-0 px-5 pb-5 flex justify-end gap-2
+}
+
+.p-dialog-header-actions {
+ @apply flex items-center gap-2
+}
+
+.p-dialog-enter-active {
+ @apply transition-all duration-150 ease-[cubic-bezier(0,0,0.2,1)]
+}
+
+.p-dialog-leave-active {
+ @apply transition-all duration-150 ease-[cubic-bezier(0.4,0,0.2,1)]
+}
+
+.p-dialog-enter-from,
+.p-dialog-leave-to {
+ @apply opacity-0 scale-75
+}
+
+.p-dialog-top .p-dialog,
+.p-dialog-bottom .p-dialog,
+.p-dialog-left .p-dialog,
+.p-dialog-right .p-dialog,
+.p-dialog-topleft .p-dialog,
+.p-dialog-topright .p-dialog,
+.p-dialog-bottomleft .p-dialog,
+.p-dialog-bottomright .p-dialog {
+ @apply m-3 [transform:translate3d(0,0,0)]
+}
+
+.p-dialog-top .p-dialog-enter-active,
+.p-dialog-top .p-dialog-leave-active,
+.p-dialog-bottom .p-dialog-enter-active,
+.p-dialog-bottom .p-dialog-leave-active,
+.p-dialog-left .p-dialog-enter-active,
+.p-dialog-left .p-dialog-leave-active,
+.p-dialog-right .p-dialog-enter-active,
+.p-dialog-right .p-dialog-leave-active,
+.p-dialog-topleft .p-dialog-enter-active,
+.p-dialog-topleft .p-dialog-leave-active,
+.p-dialog-topright .p-dialog-enter-active,
+.p-dialog-topright .p-dialog-leave-active,
+.p-dialog-bottomleft .p-dialog-enter-active,
+.p-dialog-bottomleft .p-dialog-leave-active,
+.p-dialog-bottomright .p-dialog-enter-active,
+.p-dialog-bottomright .p-dialog-leave-active {
+ @apply transition-all duration-300 ease-out
+}
+
+.p-dialog-top .p-dialog-enter-from,
+.p-dialog-top .p-dialog-leave-to {
+ @apply [transform:translate3d(0,-100%,0)]
+}
+
+.p-dialog-bottom .p-dialog-enter-from,
+.p-dialog-bottom .p-dialog-leave-to {
+ @apply [transform:translate3d(0,100%,0)]
+}
+
+.p-dialog-left .p-dialog-enter-from,
+.p-dialog-left .p-dialog-leave-to,
+.p-dialog-topleft .p-dialog-enter-from,
+.p-dialog-topleft .p-dialog-leave-to,
+.p-dialog-bottomleft .p-dialog-enter-from,
+.p-dialog-bottomleft .p-dialog-leave-to {
+ @apply [transform:translate3d(-100%,0,0)]
+}
+
+.p-dialog-right .p-dialog-enter-from,
+.p-dialog-right .p-dialog-leave-to,
+.p-dialog-topright .p-dialog-enter-from,
+.p-dialog-topright .p-dialog-leave-to,
+.p-dialog-bottomright .p-dialog-enter-from,
+.p-dialog-bottomright .p-dialog-leave-to {
+ @apply [transform:translate3d(100%,0,0)]
+}
+
+.p-dialog-left:dir(rtl) .p-dialog-enter-from,
+.p-dialog-left:dir(rtl) .p-dialog-leave-to,
+.p-dialog-topleft:dir(rtl) .p-dialog-enter-from,
+.p-dialog-topleft:dir(rtl) .p-dialog-leave-to,
+.p-dialog-bottomleft:dir(rtl) .p-dialog-enter-from,
+.p-dialog-bottomleft:dir(rtl) .p-dialog-leave-to {
+ @apply [transform:translate3d(100%,0,0)]
+}
+.p-dialog-right:dir(rtl) .p-dialog-enter-from,
+.p-dialog-right:dir(rtl) .p-dialog-leave-to,
+.p-dialog-topright:dir(rtl) .p-dialog-enter-from,
+.p-dialog-topright:dir(rtl) .p-dialog-leave-to,
+.p-dialog-bottomright:dir(rtl) .p-dialog-enter-from,
+.p-dialog-bottomright:dir(rtl) .p-dialog-leave-to {
+ @apply [transform:translate3d(-100%,0,0)]
+}
+
+.p-dialog-maximized {
+ @apply !w-screen !h-screen top-0 start-0 max-h-full rounded-none
+}
+
+.p-dialog-maximized .p-dialog-content {
+ @apply flex-grow
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/divider.css b/frontend/packages/kwai-ui/src/css/primevue/divider.css
new file mode 100644
index 000000000..1bb448bb0
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/divider.css
@@ -0,0 +1,52 @@
+.p-divider-horizontal {
+ @apply flex w-full relative items-center my-4 mx-0 py-0 px-4
+ before:absolute before:block before:top-1/2 before:start-0 before:w-full
+ before:border-t before:border-surface-200 dark:before:border-surface-700
+}
+
+.p-divider-horizontal .p-divider-content {
+ @apply py-0 px-2
+}
+
+.p-divider-vertical {
+ @apply min-h-full flex relative justify-center my-0 mx-4 py-2 px-0
+ before:absolute before:block before:top-0 before:start-1/2 before:h-full
+ before:border-s before:border-surface-200 before:dark:border-surface-700
+}
+
+.p-divider.p-divider-vertical .p-divider-content {
+ @apply py-2 px-0
+}
+
+.p-divider-content {
+ @apply z-10 bg-surface-0 dark:bg-surface-900 text-surface-700 dark:text-surface-0
+}
+
+.p-divider-solid.p-divider-horizontal:before {
+ @apply border-solid
+}
+
+.p-divider-solid.p-divider-vertical:before {
+ @apply border-solid
+}
+
+.p-divider-dashed.p-divider-horizontal:before {
+ @apply border-dashed
+}
+
+.p-divider-dashed.p-divider-vertical:before {
+ @apply border-dashed
+}
+
+.p-divider-dotted.p-divider-horizontal:before {
+ @apply border-dotted
+}
+
+.p-divider-dotted.p-divider-vertical:before {
+ @apply border-dotted
+}
+
+.p-divider-left:dir(rtl),
+.p-divider-right:dir(rtl) {
+ @apply flex-row-reverse
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/dock.css b/frontend/packages/kwai-ui/src/css/primevue/dock.css
new file mode 100644
index 000000000..54d5f9cfc
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/dock.css
@@ -0,0 +1,84 @@
+.p-dock {
+ @apply absolute z-10 flex justify-center items-center pointer-events-none
+}
+
+.p-dock-list-container {
+ @apply flex pointer-events-auto bg-white/10 border border-white/10 p-2 rounded-xl
+}
+
+.p-dock-list {
+ @apply m-0 p-0 list-none flex items-center justify-center outline-none
+}
+
+.p-dock-item {
+ @apply transition-all duration-200 ease-[cubic-bezier(0.4,0,0.2,1)] will-change-transform p-2 rounded-md
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+}
+
+.p-dock-item-link {
+ @apply flex flex-col items-center justify-center relative cursor-default w-12 h-12
+}
+
+.p-dock-top {
+ @apply start-0 top-0 w-full
+}
+
+.p-dock-top .p-dock-item {
+ @apply origin-[center_top]
+}
+
+.p-dock-bottom {
+ @apply start-0 bottom-0 w-full
+}
+
+.p-dock-bottom .p-dock-item {
+ @apply origin-[center_bottom]
+}
+
+.p-dock-right {
+ @apply end-0 top-0 h-full
+}
+
+.p-dock-right .p-dock-item {
+ @apply origin-[center_right]
+}
+
+.p-dock-right .p-dock-list {
+ @apply flex-col
+}
+
+.p-dock-left {
+ @apply start-0 top-0 h-full
+}
+
+.p-dock-left .p-dock-item {
+ @apply origin-[center_left]
+}
+
+.p-dock-left .p-dock-list {
+ @apply flex-col
+}
+
+.p-dock-mobile.p-dock-top .p-dock-list-container,
+.p-dock-mobile.p-dock-bottom .p-dock-list-container {
+ @apply overflow-x-auto w-full
+}
+
+.p-dock-mobile.p-dock-top .p-dock-list-container .p-dock-list,
+.p-dock-mobile.p-dock-bottom .p-dock-list-container .p-dock-list {
+ @apply mt-0 mx-auto
+}
+
+.p-dock-mobile.p-dock-left .p-dock-list-container,
+.p-dock-mobile.p-dock-right .p-dock-list-container {
+ @apply overflow-y-auto h-full
+}
+
+.p-dock-mobile.p-dock-left .p-dock-list-container .p-dock-list,
+.p-dock-mobile.p-dock-right .p-dock-list-container .p-dock-list {
+ @apply mt-auto mx-0
+}
+
+.p-dock-mobile .p-dock-list .p-dock-item {
+ @apply transform-none m-0
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/drawer.css b/frontend/packages/kwai-ui/src/css/primevue/drawer.css
new file mode 100644
index 000000000..fe5aa85cd
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/drawer.css
@@ -0,0 +1,94 @@
+@import './button';
+
+.p-drawer {
+ @apply flex flex-col pointer-events-auto relative transition-transform duration-300
+ border border-surface-200 dark:border-surface-700
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+ shadow-[0_20px_25px_-5px_rgba(0,0,0,0.1),0_8px_10px_-6px_rgba(0,0,0,0.1)]
+}
+
+.p-drawer {
+ @apply [transform:translate3d(0,0,0)]
+}
+
+.p-drawer-content {
+ @apply overflow-y-auto flex-grow pt-0 pb-5 px-5
+}
+
+.p-drawer-header {
+ @apply flex items-center justify-between flex-shrink-0 p-5
+}
+
+.p-drawer-footer {
+ @apply px-5
+}
+
+.p-drawer-title {
+ @apply font-semibold text-2xl
+}
+
+.p-drawer-full .p-drawer {
+ @apply transition-none transform-none w-screen h-screen max-h-full top-0 left-0
+}
+
+.p-drawer-left .p-drawer-enter-from,
+.p-drawer-left .p-drawer-leave-to {
+ @apply -translate-x-full
+}
+
+.p-drawer-right .p-drawer-enter-from,
+.p-drawer-right .p-drawer-leave-to {
+ @apply translate-x-full
+}
+
+.p-drawer-top .p-drawer-enter-from,
+.p-drawer-top .p-drawer-leave-to {
+ @apply -translate-y-full
+}
+
+.p-drawer-bottom .p-drawer-enter-from,
+.p-drawer-bottom .p-drawer-leave-to {
+ @apply translate-y-full
+}
+
+.p-drawer-full .p-drawer-enter-from,
+.p-drawer-full .p-drawer-leave-to {
+ @apply opacity-0
+}
+
+.p-drawer-full .p-drawer-enter-active,
+.p-drawer-full .p-drawer-leave-active {
+ @apply transition-opacity animate-duration-400 ease-[cubic-bezier(0.25,0.8,0.25,1)]
+}
+
+.p-drawer-left .p-drawer {
+ @apply w-80 h-full border-r
+}
+
+.p-drawer-right .p-drawer {
+ @apply w-80 h-full border-s
+}
+
+.p-drawer-top .p-drawer {
+ @apply h-40 w-full border-b
+}
+
+.p-drawer-bottom .p-drawer {
+ @apply h-40 w-full border-t
+}
+
+.p-drawer-left .p-drawer-content,
+.p-drawer-right .p-drawer-content,
+.p-drawer-top .p-drawer-content,
+.p-drawer-bottom .p-drawer-content {
+ @apply w-full h-full
+}
+
+.p-drawer-open {
+ @apply flex
+}
+
+.p-overlay-mask:dir(rtl) {
+ @apply flex-row-reverse;
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/fieldset.css b/frontend/packages/kwai-ui/src/css/primevue/fieldset.css
new file mode 100644
index 000000000..28c2bddda
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/fieldset.css
@@ -0,0 +1,45 @@
+.p-fieldset {
+ @apply border border-surface-200 dark:border-surface-700 rounded-md
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+ px-[1.125rem] pt-0 pb-[1.125rem]
+}
+
+.p-fieldset-legend {
+ @apply border border-transparent rounded-md px-3 py-2
+ transition-colors duration-200
+}
+
+.p-fieldset-toggleable > .p-fieldset-legend {
+ @apply p-0
+}
+
+.p-fieldset-toggle-button {
+ @apply select-none overflow-hidden relative
+ flex items-center justify-center gap-2
+ px-3 py-2
+ border-none rounded-md
+ bg-surface-0 dark:bg-surface-900
+ hover:bg-surface-100 dark:hover:bg-surface-800
+ text-surface-700 dark:text-surface-0
+ hover:text-surface-800 dark:hover:text-surface-0
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+ transition-colors duration-200
+}
+
+.p-fieldset-legend-label {
+ @apply font-semibold;
+}
+
+.p-fieldset-toggle-icon {
+ @apply text-surface-500 dark:text-surface-400
+ transition-colors duration-200
+}
+
+.p-fieldset-toggle-button:hover .p-fieldset-toggle-icon {
+ @apply text-surface-600 dark:text-surface-300
+}
+
+.p-fieldset .p-fieldset-content {
+ @apply p-0
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/fileupload.css b/frontend/packages/kwai-ui/src/css/primevue/fileupload.css
new file mode 100644
index 000000000..74ce46d9a
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/fileupload.css
@@ -0,0 +1,57 @@
+@import './button';
+@import './message';
+@import './progressbar';
+
+.p-fileupload input[type="file"] {
+ @apply hidden
+}
+
+.p-fileupload-advanced {
+ @apply border border-surface-200 dark:border-surface-700 rounded-md
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+}
+
+.p-fileupload-header {
+ @apply flex items-center p-[1.125rem] gap-2 text-surface-700 dark:text-surface-0
+}
+
+.p-fileupload-content {
+ @apply border border-transparent relative transition-colors duration-200 pt-0 px-[1.125rem] pb-[1.125rem]
+}
+
+.p-fileupload-content .p-progressbar {
+ @apply w-full absolute top-0 start-0 h-1
+}
+
+.p-fileupload-file-list {
+ @apply flex flex-col gap-2 mt-[1.125rem]
+}
+
+.p-fileupload-file {
+ @apply flex flex-wrap items-center p-4 border-b border-surface-200 dark:border-surface-700 gap-2 last:border-b-0
+}
+
+.p-fileupload-file-info {
+ @apply flex flex-col gap-2
+}
+
+.p-fileupload-file-thumbnail {
+ @apply flex-shrink-0
+}
+
+.p-fileupload-file-actions {
+ @apply ms-auto
+}
+
+.p-fileupload-highlight {
+ @apply border border-dashed border-primary
+}
+
+.p-fileupload-advanced .p-message {
+ @apply mt-0
+}
+
+.p-fileupload-basic {
+ @apply flex flex-wrap items-center justify-center gap-2
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/floatlabel.css b/frontend/packages/kwai-ui/src/css/primevue/floatlabel.css
new file mode 100644
index 000000000..f2544ee7c
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/floatlabel.css
@@ -0,0 +1,73 @@
+.p-floatlabel {
+ @apply block relative
+}
+
+.p-floatlabel label {
+ @apply absolute pointer-events-none top-1/2 -translate-y-1/2 transition-all duration-200 ease-out leading-none font-medium
+ start-3 text-surface-500 dark:text-surface-400
+}
+
+.p-floatlabel:has(.p-textarea) label {
+ @apply top-2 translate-y-0
+}
+
+.p-floatlabel:has(.p-inputicon:first-child) label {
+ @apply start-10
+}
+
+.p-floatlabel:has(.p-invalid) label {
+ @apply text-red-400 dark:text-red-300
+}
+
+.p-floatlabel:has(input:focus) label,
+.p-floatlabel:has(input.p-filled) label,
+.p-floatlabel:has(input:-webkit-autofill) label,
+.p-floatlabel:has(textarea:focus) label,
+.p-floatlabel:has(textarea.p-filled) label,
+.p-floatlabel:has(.p-inputwrapper-focus) label,
+.p-floatlabel:has(.p-inputwrapper-filled) label {
+ @apply -top-5 translate-y-0 text-xs font-normal
+}
+
+.p-floatlabel:has(input.p-filled) label,
+.p-floatlabel:has(textarea.p-filled) label,
+.p-floatlabel:has(.p-inputwrapper-filled) label {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-floatlabel:has(input:focus) label,
+.p-floatlabel:has(input:-webkit-autofill) label,
+.p-floatlabel:has(textarea:focus) label ,
+.p-floatlabel:has(.p-inputwrapper-focus) label {
+ @apply text-primary
+}
+
+.p-floatlabel-in .p-inputtext,
+.p-floatlabel-in .p-textarea,
+.p-floatlabel-in .p-select-label,
+.p-floatlabel-in .p-multiselect-label,
+.p-floatlabel-in .p-autocomplete-input-multiple,
+.p-floatlabel-in .p-cascadeselect-label,
+.p-floatlabel-in .p-treeselect-label {
+ @apply pt-6 pb-2
+}
+
+.p-floatlabel-in:has(input:focus) label,
+.p-floatlabel-in:has(input.p-filled) label,
+.p-floatlabel-in:has(input:-webkit-autofill) label,
+.p-floatlabel-in:has(textarea:focus) label,
+.p-floatlabel-in:has(textarea.p-filled) label,
+.p-floatlabel-in:has(.p-inputwrapper-focus) label,
+.p-floatlabel-in:has(.p-inputwrapper-filled) label {
+ @apply top-2
+}
+
+.p-floatlabel-on:has(input:focus) label,
+.p-floatlabel-on:has(input.p-filled) label,
+.p-floatlabel-on:has(input:-webkit-autofill) label,
+.p-floatlabel-on:has(textarea:focus) label,
+.p-floatlabel-on:has(textarea.p-filled) label,
+.p-floatlabel-on:has(.p-inputwrapper-focus) label,
+.p-floatlabel-on:has(.p-inputwrapper-filled) label {
+ @apply top-0 -translate-y-1/2 rounded-sm bg-surface-0 dark:bg-surface-950 py-0 px-[0.125rem]
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/galleria.css b/frontend/packages/kwai-ui/src/css/primevue/galleria.css
new file mode 100644
index 000000000..e4edff962
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/galleria.css
@@ -0,0 +1,244 @@
+.p-galleria {
+ @apply overflow-hidden border border-surface-200 dark:border-surface-700 rounded-md
+}
+
+.p-galleria-content {
+ @apply flex flex-col
+}
+
+.p-galleria-items-container {
+ @apply flex flex-col relative
+}
+
+.p-galleria-items {
+ @apply relative flex h-full
+}
+
+.p-galleria-nav-button {
+ @apply absolute top-1/2 inline-flex justify-center items-center overflow-hidden select-none border-none cursor-pointer
+ w-12 h-12 transition-colors duration-200 p-0 -mt-12 mx-2 mb-0 rounded-full
+ bg-white/10 text-surface-100 enabled:hover:bg-white/20 enabled:hover:text-surface-0
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+}
+
+.p-galleria-next-icon,
+.p-galleria-prev-icon {
+ @apply text-2xl w-6 h-6
+}
+
+.p-galleria-prev-button {
+ @apply start-0
+}
+
+.p-galleria-next-button {
+ @apply end-0
+}
+
+.p-galleria-prev-button:dir(rtl) {
+ @apply start-auto end-0
+}
+.p-galleria-next-button:dir(rtl) {
+ @apply end-auto start-0
+}
+
+.p-galleria-item {
+ @apply flex justify-center items-center h-full w-full
+}
+
+.p-galleria-hover-navigators .p-galleria-nav-button {
+ @apply pointer-events-none opacity-0 transition-opacity duration-200 ease-in-out
+}
+
+.p-galleria-hover-navigators .p-galleria-items-container:hover .p-galleria-nav-button {
+ @apply pointer-events-auto opacity-100
+}
+
+.p-galleria-hover-navigators .p-galleria-items-container:hover .p-galleria-nav-button.p-disabled {
+ @apply pointer-events-none
+}
+
+.p-galleria-caption {
+ @apply absolute bottom-0 left-0 w-full bg-black/5 text-surface-100 p-4
+}
+
+.p-galleria-thumbnails {
+ @apply flex flex-col overflow-auto flex-shrink-0
+}
+
+.p-galleria-thumbnail-nav-button {
+ @apply self-center flex-grow-0 flex-shrink-0 basis-auto justify-center items-center overflow-hidden relative
+ my-0 mx-2 p-0 border-none select-none cursor-pointer w-8 h-8 rounded-md transition-colors duration-200 bg-transparent
+ text-surface-600 hover:bg-surface-100 hover:text-surface-700
+ dark:text-surface-400 dark:hover:bg-surface-800 dark:hover:text-surface-0
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+}
+
+.p-galleria-thumbnail-nav-button .p-galleria-thumbnail-next-icon,
+.p-galleria-thumbnail-nav-button .p-galleria-thumbnail-prev-icon {
+ @apply text-base w-4 h-4
+}
+
+.p-galleria-thumbnails-content {
+ @apply flex flex-row bg-surface-0 dark:bg-surface-900 py-4 px-1
+}
+
+.p-galleria-thumbnails-viewport {
+ @apply overflow-hidden w-full
+}
+
+.p-galleria:not(.p-galleria-thumbnails-right):not(.p-galleria-thumbnails-left) .p-galleria-thumbnail-prev-button:dir(rtl),
+.p-galleria:not(.p-galleria-thumbnails-right):not(.p-galleria-thumbnails-left) .p-galleria-thumbnail-next-button:dir(rtl) {
+ @apply rotate-180
+}
+
+.p-galleria-thumbnail-items {
+ @apply flex
+}
+
+.p-galleria-thumbnail-item {
+ @apply overflow-auto flex items-center justify-center cursor-pointer opacity-50
+}
+
+.p-galleria-thumbnail {
+ @apply outline-transparent transition-opacity duration-300 hover:opacity-100
+}
+
+.p-galleria-thumbnail-item-current {
+ @apply opacity-100
+}
+
+.p-galleria-thumbnails-left .p-galleria-content,
+.p-galleria-thumbnails-right .p-galleria-content {
+ @apply flex-row
+}
+
+.p-galleria-thumbnails-left .p-galleria-items-container,
+.p-galleria-thumbnails-right .p-galleria-items-container {
+ @apply flex-row
+}
+
+.p-galleria-thumbnails-left .p-galleria-items-container,
+.p-galleria-thumbnails-top .p-galleria-items-container {
+ @apply order-2
+}
+
+.p-galleria-thumbnails-left .p-galleria-thumbnails,
+.p-galleria-thumbnails-top .p-galleria-thumbnails {
+ @apply order-1
+}
+
+.p-galleria-thumbnails-left .p-galleria-thumbnails-content,
+.p-galleria-thumbnails-right .p-galleria-thumbnails-content {
+ @apply flex-col flex-grow
+}
+
+.p-galleria-thumbnails-left .p-galleria-thumbnail-items,
+.p-galleria-thumbnails-right .p-galleria-thumbnail-items {
+ @apply flex-col h-full
+}
+
+.p-galleria-indicator-list {
+ @apply flex items-center justify-center p-4 gap-2 m-0 list-none
+}
+
+.p-galleria-indicator-button {
+ @apply inline-flex items-center w-4 h-4 rounded-full m-0 p-0 border-none select-none cursor-pointer transition-colors duration-200
+ bg-surface-200 hover:bg-surface-300 dark:bg-surface-700 dark:hover:bg-surface-600
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+}
+
+.p-galleria-indicator-active .p-galleria-indicator-button {
+ @apply bg-primary
+}
+
+.p-galleria-indicators-left .p-galleria-items-container,
+.p-galleria-indicators-right .p-galleria-items-container {
+ @apply flex-row items-center
+}
+
+.p-galleria-indicators-left .p-galleria-items,
+.p-galleria-indicators-top .p-galleria-items {
+ @apply order-2
+}
+
+.p-galleria-indicators-left .p-galleria-indicator-list,
+.p-galleria-indicators-top .p-galleria-indicator-list {
+ @apply order-1
+}
+
+.p-galleria-indicators-left .p-galleria-indicator-list,
+.p-galleria-indicators-right .p-galleria-indicator-list {
+ @apply flex-col
+}
+
+.p-galleria-inset-indicators .p-galleria-indicator-list {
+ @apply absolute flex z-10 bg-black/50
+}
+
+.p-galleria-inset-indicators .p-galleria-indicator-button {
+ @apply bg-white/40 hover:bg-white/60
+}
+
+.p-galleria-inset-indicators .p-galleria-indicator-active .p-galleria-indicator-button {
+ @apply bg-white/90
+}
+
+.p-galleria-inset-indicators.p-galleria-indicators-top .p-galleria-indicator-list {
+ @apply top-0 left-0 w-full items-start
+}
+
+.p-galleria-inset-indicators.p-galleria-indicators-right .p-galleria-indicator-list {
+ @apply right-0 top-0 h-full items-end
+}
+
+.p-galleria-inset-indicators.p-galleria-indicators-bottom .p-galleria-indicator-list {
+ @apply bottom-0 left-0 w-full items-end
+}
+
+.p-galleria-inset-indicators.p-galleria-indicators-left .p-galleria-indicator-list {
+ @apply left-0 top-0 h-full items-start
+}
+
+.p-galleria-mask {
+ @apply fixed top-0 left-0 w-full h-full flex items-center justify-center
+}
+
+.p-galleria-close-button {
+ @apply absolute top-0 right-0 flex items-center justify-center overflow-hidden m-2 rounded-full
+ transition-colors duration-200 select-none cursor-pointer w-12 h-12 p-0 border-none
+ bg-white/10 text-surface-50 hover:bg-white/20 hover:text-surface-0
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+}
+
+.p-galleria-close-icon {
+ @apply text-2xl w-6 h-6
+}
+
+.p-galleria-mask .p-galleria-nav-button {
+ @apply fixed top-1/2
+}
+
+.p-galleria-enter-active {
+ @apply transition-all duration-150 ease-[cubic-bezier(0,0,0.2,1)]
+}
+
+.p-galleria-leave-active {
+ @apply transition-all duration-150 ease-[cubic-bezier(0.4,0,0.2,1)]
+}
+
+.p-galleria-enter-from,
+.p-galleria-leave-to {
+ @apply opacity-0 scale-75
+}
+
+.p-galleria-enter-active .p-galleria-nav-button {
+ @apply opacity-0
+}
+
+.p-items-hidden .p-galleria-thumbnail-item {
+ @apply invisible
+}
+
+.p-items-hidden .p-galleria-thumbnail-item.p-galleria-thumbnail-item-active {
+ @apply visible
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/iconfield.css b/frontend/packages/kwai-ui/src/css/primevue/iconfield.css
new file mode 100644
index 000000000..d7aaf1118
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/iconfield.css
@@ -0,0 +1,23 @@
+.p-iconfield {
+ @apply relative
+}
+
+.p-inputicon {
+ @apply absolute top-1/2 -mt-2 text-surface-400 leading-none
+}
+
+.p-iconfield .p-inputicon:first-child {
+ @apply start-3
+}
+
+.p-iconfield .p-inputicon:last-child {
+ @apply end-3
+}
+
+.p-iconfield .p-inputtext:not(:first-child) {
+ @apply ps-10
+}
+
+.p-iconfield .p-inputtext:not(:last-child) {
+ @apply pe-10
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/iftalabel.css b/frontend/packages/kwai-ui/src/css/primevue/iftalabel.css
new file mode 100644
index 000000000..dc323f922
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/iftalabel.css
@@ -0,0 +1,32 @@
+.p-iftalabel {
+ @apply block relative
+}
+
+.p-iftalabel label {
+ @apply absolute pointer-events-none top-2 transition-all ease-out duration-200 leading-none text-xs font-medium start-3 text-surface-500 dark:text-surface-400
+}
+
+.p-iftalabel .p-inputtext,
+.p-iftalabel .p-textarea,
+.p-iftalabel .p-select-label,
+.p-iftalabel .p-multiselect-label,
+.p-iftalabel .p-autocomplete-input-multiple,
+.p-iftalabel .p-cascadeselect-label,
+.p-iftalabel .p-treeselect-label {
+ @apply pt-6 pb-2
+}
+
+.p-iftalabel:has(.p-invalid) label {
+ @apply text-red-400 dark:text-red-300
+}
+
+.p-iftalabel:has(input:focus) label ,
+.p-iftalabel:has(input:-webkit-autofill) label,
+.p-iftalabel:has(textarea:focus) label ,
+.p-iftalabel:has(.p-inputwrapper-focus) label {
+ @apply text-primary
+}
+
+.p-iftalabel .p-inputicon {
+ @apply top-6 translate-y-1/4 mt-0
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/image.css b/frontend/packages/kwai-ui/src/css/primevue/image.css
new file mode 100644
index 000000000..7cb3e4616
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/image.css
@@ -0,0 +1,56 @@
+.p-image-mask {
+ @apply flex items-center justify-center
+}
+
+.p-image-preview {
+ @apply relative inline-flex leading-none
+}
+
+.p-image-preview-mask {
+ @apply absolute start-0 top-0 w-full h-full flex items-center justify-center opacity-0
+ border-none p-0 cursor-pointer bg-transparent text-surface-200 transition-all duration-200
+}
+
+.p-image-preview:hover > .p-image-preview-mask {
+ @apply opacity-100 cursor-pointer bg-black/40 dark:bg-black/60
+}
+
+.p-image-preview-icon {
+ @apply text-2xl w-6 h-6
+}
+
+.p-image-toolbar {
+ @apply absolute top-4 end-4 start-auto bottom-auto flex z-10 p-2 bg-white/10 border border-white/20 rounded-3xl gap-2;
+}
+
+.p-image-action {
+ @apply inline-flex justify-center items-center text-surface-50 bg-transparent w-12 h-12 m-0 p-0
+ border-none cursor-pointer select-none rounded-full transition-colors duration-200
+ hover:text-surface-0 hover:bg-white/10
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+}
+
+.p-image-action .p-icon {
+ @apply text-2xl h-6 w-6
+}
+
+.p-image-action.p-disabled {
+ @apply pointer-events-auto
+}
+
+.p-image-original {
+ @apply transition-transform duration-150 max-w-[100vw] max-h-[100vh]
+}
+
+.p-image-original-enter-active {
+ @apply transition-all duration-150 ease-[cubic-bezier(0,0,0.2,1)]
+}
+
+.p-image-original-leave-active {
+ @apply transition-all duration-150 ease-[cubic-bezier(0.4,0,0.2,1)]
+}
+
+.p-image-original-enter-from,
+.p-image-original-leave-to {
+ @apply opacity-0 scale-75
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/imagecompare.css b/frontend/packages/kwai-ui/src/css/primevue/imagecompare.css
new file mode 100644
index 000000000..64151b4dc
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/imagecompare.css
@@ -0,0 +1,38 @@
+.p-imagecompare {
+ @apply relative overflow-hidden w-full aspect-video
+}
+
+.p-imagecompare img {
+ @apply w-full h-full absolute
+}
+
+.p-imagecompare img + img {
+ @apply [clip-path:polygon(0_0,50%_0,50%_100%,0_100%)]
+}
+
+.p-imagecompare:dir(rtl) img + img {
+ @apply [clip-path:polygon(50%_0,100%_0,100%_100%,50%_100%)]
+}
+
+.p-imagecompare-slider {
+ @apply relative appearance-none w-[calc(100%+1rem)] h-full -ms-2 bg-transparent outline-none transition-all duration-200
+ hover:w-[calc(100%+2rem)] hover:-ms-4
+}
+
+.p-imagecompare-slider::-webkit-slider-thumb {
+ @apply appearance-none h-4 w-4 bg-white/30 rounded-full bg-contain cursor-ew-resize transition-all duration-200
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+}
+
+.p-imagecompare-slider::-moz-range-thumb {
+ @apply appearance-none h-4 w-4 bg-white/30 rounded-full bg-contain cursor-ew-resize transition-all duration-200
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+}
+
+.p-imagecompare-slider:hover::-webkit-slider-thumb {
+ @apply bg-white/40 h-8 w-8
+}
+
+.p-imagecompare-slider:hover::-moz-range-thumb {
+ @apply bg-white/40 h-8 w-8
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/inplace.css b/frontend/packages/kwai-ui/src/css/primevue/inplace.css
new file mode 100644
index 000000000..cefc826d7
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/inplace.css
@@ -0,0 +1,13 @@
+.p-inplace-display {
+ @apply inline cursor-pointer border border-transparent px-3 py-2 rounded-md
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+ transition-colors duration-200
+}
+
+.p-inplace-display:not(.p-disabled):hover {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-inplace-content {
+ @apply block
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/inputgroup.css b/frontend/packages/kwai-ui/src/css/primevue/inputgroup.css
new file mode 100644
index 000000000..99db68584
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/inputgroup.css
@@ -0,0 +1,67 @@
+.p-inputgroup,
+.p-inputgroup .p-floatlabel,
+.p-inputgroup .p-iftalabel {
+ @apply flex items-stretch w-full
+}
+
+.p-inputgroup .p-inputtext,
+.p-inputgroup .p-inputwrapper {
+ @apply flex-auto w-[1%]
+}
+
+.p-inputgroupaddon {
+ @apply flex items-center justify-center p-2 min-w-10
+ border-y border-surface-300 dark:border-surface-700
+ bg-surface-0 dark:bg-surface-950 text-surface-400
+}
+
+.p-inputgroupaddon:first-child,
+.p-inputgroupaddon + .p-inputgroupaddon {
+ @apply border-s
+}
+
+.p-inputgroupaddon:last-child {
+ @apply border-e
+}
+
+.p-inputgroup > .p-component,
+.p-inputgroup > .p-inputwrapper > .p-component,
+.p-inputgroup > .p-floatlabel > .p-component,
+.p-inputgroup > .p-floatlabel > .p-inputwrapper > .p-component,
+.p-inputgroup > .p-iftalabel > .p-component,
+.p-inputgroup > .p-iftalabel > .p-inputwrapper > .p-component {
+ @apply rounded-none m-0
+}
+
+.p-inputgroupaddon:first-child,
+.p-inputgroup > .p-component:first-child,
+.p-inputgroup > .p-inputwrapper:first-child > .p-component,
+.p-inputgroup > .p-floatlabel:first-child > .p-component,
+.p-inputgroup > .p-floatlabel:first-child > .p-inputwrapper > .p-component,
+.p-inputgroup > .p-iftalabel:first-child > .p-component,
+.p-inputgroup > .p-iftalabel:first-child > .p-inputwrapper > .p-component {
+ @apply rounded-s-md
+}
+
+.p-inputgroupaddon:last-child,
+.p-inputgroup > .p-component:last-child,
+.p-inputgroup > .p-inputwrapper:last-child > .p-component,
+.p-inputgroup > .p-floatlabel:last-child > .p-component,
+.p-inputgroup > .p-floatlabel:last-child > .p-inputwrapper > .p-component,
+.p-inputgroup > .p-iftalabel:last-child > .p-component,
+.p-inputgroup > .p-iftalabel:last-child > .p-inputwrapper > .p-component {
+ @apply rounded-e-md
+}
+
+.p-inputgroup .p-component:focus,
+.p-inputgroup .p-component.p-focus,
+.p-inputgroup .p-inputwrapper-focus,
+.p-inputgroup .p-component:focus ~ label,
+.p-inputgroup .p-component.p-focus ~ label,
+.p-inputgroup .p-inputwrapper-focus ~ label {
+ @apply z-10
+}
+
+.p-inputgroup > .p-button:not(.p-button-icon-only) {
+ @apply w-auto
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/inputnumber.css b/frontend/packages/kwai-ui/src/css/primevue/inputnumber.css
new file mode 100644
index 000000000..bdef17232
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/inputnumber.css
@@ -0,0 +1,84 @@
+@import './inputtext';
+
+.p-inputnumber {
+ @apply inline-flex relative
+}
+
+.p-inputnumber-button {
+ @apply flex items-center justify-center flex-grow-0 flex-shrink-0 basis-auto cursor-pointer w-10
+ bg-transparent enabled:hover:bg-surface-100 enabled:active:bg-surface-200
+ border border-surface-300 enabled:hover:border-surface-300 enabled:active:border-surface-300
+ text-surface-400 enabled:hover:text-surface-500 enabled:active:text-surface-600
+ dark:bg-transparent dark:enabled:hover:bg-surface-800 dark:enabled:active:bg-surface-700
+ dark:border-surface-700 dark:enabled:hover:border-surface-700 dark:enabled:active:border-surface-700
+ dark:text-surface-400 dark:enabled:hover:text-surface-300 dark:enabled:active:text-surface-200
+ transition-colors duration-200
+}
+
+.p-inputnumber-stacked .p-inputnumber-button {
+ @apply relative flex-auto border-none
+}
+
+.p-inputnumber-stacked .p-inputnumber-button-group {
+ @apply flex flex-col absolute top-px end-px h-[calc(100%-2px)] z-10
+}
+
+.p-inputnumber-stacked .p-inputnumber-increment-button {
+ @apply p-0 rounded-tr-[5px]
+}
+
+.p-inputnumber-stacked .p-inputnumber-decrement-button {
+ @apply p-0 rounded-br-[5px]
+}
+
+.p-inputnumber-horizontal .p-inputnumber-increment-button {
+ @apply order-3 rounded-e-md border-s-0
+}
+
+.p-inputnumber-horizontal .p-inputnumber-input {
+ @apply order-2 rounded-none
+}
+
+.p-inputnumber-horizontal .p-inputnumber-decrement-button {
+ @apply order-1 rounded-s-md border-r-0
+}
+
+.p-floatlabel:has(.p-inputnumber-horizontal) label {
+ @apply ms-10
+}
+
+.p-inputnumber-vertical {
+ @apply flex-col
+}
+
+.p-inputnumber-vertical .p-inputnumber-button {
+ @apply py-2
+}
+
+.p-inputnumber-vertical .p-inputnumber-increment-button {
+ @apply order-1 rounded-ss-md rounded-se-md w-full border-b-0
+}
+
+.p-inputnumber-vertical .p-inputnumber-input {
+ @apply order-2 rounded-none text-center
+}
+
+.p-inputnumber-vertical .p-inputnumber-decrement-button {
+ @apply order-3 rounded-ee-md rounded-es-md w-full border-t-0
+}
+
+.p-inputnumber-input {
+ @apply flex-auto
+}
+
+.p-inputnumber-fluid {
+ @apply w-full
+}
+
+.p-inputnumber-fluid .p-inputnumber-input {
+ @apply w-[1%]
+}
+
+.p-inputnumber-fluid.p-inputnumber-vertical .p-inputnumber-input {
+ @apply w-full
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/inputotp.css b/frontend/packages/kwai-ui/src/css/primevue/inputotp.css
new file mode 100644
index 000000000..d727efbae
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/inputotp.css
@@ -0,0 +1,9 @@
+@import './inputtext';
+
+.p-inputotp {
+ @apply flex items-center gap-2
+}
+
+.p-inputotp-input {
+ @apply text-center w-10
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/inputtext.css b/frontend/packages/kwai-ui/src/css/primevue/inputtext.css
new file mode 100644
index 000000000..c03d3744c
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/inputtext.css
@@ -0,0 +1,34 @@
+.p-inputtext {
+ @apply appearance-none rounded-md
+ border border-surface-300 dark:border-surface-700
+ enabled:hover:border-surface-400 dark:enabled:hover:border-surface-600
+ enabled:focus:border-primary
+ bg-surface-0 dark:bg-surface-950
+ text-surface-700 dark:text-surface-0
+ disabled:bg-surface-200 disabled:text-surface-500 dark:disabled:bg-surface-700 dark:disabled:text-surface-400 disabled:opacity-100
+ placeholder:text-surface-500 dark:placeholder:text-surface-400
+ px-3 py-2
+ transition-colors duration-200
+ shadow-[0_1px_2px_0_rgba(18,18,23,0.05)]
+ outline-none
+}
+
+.p-inputtext.p-invalid {
+ @apply border-red-400 dark:border-red-300
+}
+
+.p-inputtext.p-variant-filled {
+ @apply bg-surface-50 dark:bg-surface-800
+}
+
+.p-inputtext-sm {
+ @apply text-sm px-[0.625rem] py-[0.375rem]
+}
+
+.p-inputtext-lg {
+ @apply text-lg px-[0.875rem] py-[0.625rem]
+}
+
+.p-inputtext-fluid {
+ @apply w-full
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/knob.css b/frontend/packages/kwai-ui/src/css/primevue/knob.css
new file mode 100644
index 000000000..276761aab
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/knob.css
@@ -0,0 +1,37 @@
+.p-knob-range {
+ @apply fill-none transition-[stroke] duration-100 ease-in
+}
+
+.p-knob-text {
+ @apply text-xl text-center
+}
+
+.p-knob svg {
+ @apply rounded-full
+ transition-colors duration-200
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+}
+
+.p-knob svg path:first-child {
+ @apply stroke-surface-200 dark:stroke-surface-700
+}
+
+.p-knob svg path + path {
+ @apply stroke-primary
+}
+
+.p-knob svg text {
+ @apply fill-surface-500 dark:fill-surface-400
+}
+
+.p-knob-value {
+ animation-name: p-knob-dash-frame;
+ animation-fill-mode: forwards;
+ fill: none;
+}
+
+@keyframes p-knob-dash-frame {
+ 100% {
+ stroke-dashoffset: 0;
+ }
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/listbox.css b/frontend/packages/kwai-ui/src/css/primevue/listbox.css
new file mode 100644
index 000000000..ded48775a
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/listbox.css
@@ -0,0 +1,79 @@
+@import './inputtext';
+@import './iconfield';
+
+.p-listbox {
+ @apply bg-surface-0 dark:bg-surface-950 text-surface-700 dark:text-surface-0
+ border border-surface-300 dark:border-surface-700 rounded-md
+ shadow-[0_1px_2px_0_rgba(18,18,23,0.05)]
+ transition-colors duration-200
+}
+
+.p-listbox.p-focus {
+ @apply border-primary
+}
+
+.p-listbox.p-disabled {
+ @apply bg-surface-200 text-surface-500 dark:bg-surface-700 dark:text-surface-400 opacity-100 cursor-default
+}
+
+.p-listbox.p-disabled .p-listbox-option {
+ @apply text-surface-500 dark:text-surface-400 cursor-default
+}
+
+.p-listbox.p-invalid {
+ @apply border-red-400 dark:border-red-300
+}
+
+.p-listbox-header {
+ @apply pt-2 pb-1 px-4
+}
+
+.p-listbox-filter {
+ @apply w-full
+}
+
+.p-listbox-list-container {
+ @apply overflow-auto
+}
+
+.p-listbox-list {
+ @apply list-none m-0 p-1 outline-none flex flex-col gap-[2px]
+}
+
+.p-listbox-option {
+ @apply flex items-center cursor-pointer relative overflow-hidden px-3 py-2 border-none rounded-sm
+ text-surface-700 dark:text-surface-0
+ transition-colors duration-200
+}
+
+.p-listbox-striped li:nth-child(even of .p-listbox-option) {
+ @apply bg-surface-50 dark:bg-surface-900
+}
+
+.p-listbox .p-listbox-list .p-listbox-option.p-listbox-option-selected {
+ @apply bg-highlight
+}
+
+.p-listbox:not(.p-disabled) .p-listbox-option.p-listbox-option-selected.p-focus {
+ @apply bg-highlight-emphasis
+}
+
+.p-listbox:not(.p-disabled) .p-listbox-option:not(.p-listbox-option-selected):not(.p-disabled).p-focus {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-listbox:not(.p-disabled) .p-listbox-option:not(.p-listbox-option-selected):not(.p-disabled):hover {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-listbox-option-check-icon {
+ @apply relative -ms-[0.375rem] me-[0.375rem] text-surface-700 dark:text-surface-0
+}
+
+.p-listbox-option-group {
+ @apply m-0 px-3 py-2 text-surface-500 dark:text-surface-400 font-semibold
+}
+
+.p-listbox-empty-message {
+ @apply px-3 py-2
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/megamenu.css b/frontend/packages/kwai-ui/src/css/primevue/megamenu.css
new file mode 100644
index 000000000..08a232bce
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/megamenu.css
@@ -0,0 +1,207 @@
+.p-megamenu {
+ @apply relative flex items-center rounded-md gap-2
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+ border border-surface-200 dark:border-surface-700
+}
+
+.p-megamenu-start,
+.p-megamenu-end {
+ @apply flex items-center
+}
+
+.p-megamenu-root-list {
+ @apply m-0 p-0 list-none outline-none flex items-center flex-wrap gap-2
+}
+
+.p-megamenu-root-list > .p-megamenu-item > .p-menumegamenubar-item-content {
+ @apply rounded-md
+}
+
+.p-megamenu-root-list > .p-megamenu-item > .p-megamenu-item-content > .p-megamenu-item-link {
+ @apply px-3 py-2
+}
+
+.p-megamenu-item-content {
+ @apply transition-colors duration-200 rounded-sm text-surface-700 dark:text-surface-0
+}
+
+.p-megamenu-item-link {
+ @apply cursor-pointer flex items-center no-underline overflow-hidden relative text-inherit
+ px-3 py-2 gap-2 select-none outline-none
+}
+
+.p-megamenu-item-icon {
+ @apply text-surface-400 dark:text-surface-500
+}
+
+.p-megamenu-submenu-icon {
+ @apply text-surface-400 dark:text-surface-500 ms-auto text-sm w-[0.875rem] h-[0.875rem]
+}
+
+.p-megamenu-item.p-focus > .p-megamenu-item-content {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-megamenu-item.p-focus > .p-megamenu-item-content .p-megamenu-item-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-megamenu-item.p-focus > .p-megamenu-item-content .p-megamenu-submenu-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-megamenu-item:not(.p-disabled) > .p-megamenu-item-content:hover {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-megamenu-item:not(.p-disabled) > .p-megamenu-item-content:hover .p-megamenu-item-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-megamenu-item:not(.p-disabled) > .p-megamenu-item-content:hover .p-megamenu-submenu-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-megamenu-item-active > .p-megamenu-item-content {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-megamenu-item-active > .p-megamenu-item-content .p-megamenu-item-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-megamenu-item-active > .p-megamenu-item-content .p-megamenu-submenu-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-megamenu-overlay {
+ @apply hidden absolute w-auto z-10 start-0 min-w-full rounded-md
+ bg-surface-0 dark:bg-surface-900
+ border border-surface-200 dark:border-surface-700
+ text-surface-700 dark:text-surface-0
+ shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-2px_rgba(0,0,0,0.1)]
+}
+
+.p-megamenu-root-list > .p-megamenu-item-active > .p-megamenu-overlay {
+ @apply block
+}
+
+.p-megamenu-submenu {
+ @apply m-0 p-1 list-none min-w-52 flex flex-col gap-[2px]
+}
+
+.p-megamenu-submenu-label {
+ @apply px-3 py-2 text-surface-500 dark:text-surface-400 font-semibold bg-transparent
+}
+
+.p-megamenu-separator {
+ @apply border-t border-surface-200 dark:border-surface-700
+}
+
+.p-megamenu-horizontal {
+ @apply items-center px-3 py-2
+}
+
+.p-megamenu-horizontal .p-megamenu-root-list {
+ @apply flex items-center flex-wrap gap-2
+}
+
+.p-megamenu-horizontal .p-megamenu-end {
+ @apply ms-auto self-center
+}
+
+.p-megamenu-vertical {
+ @apply inline-flex min-w-52 flex-col items-stretch p-1
+}
+
+.p-megamenu-vertical .p-megamenu-root-list {
+ @apply items-stretch flex-col gap-[2px]
+}
+
+.p-megamenu-vertical .p-megamenu-root-list > .p-megamenu-item-active > .p-megamenu-overlay {
+ @apply start-full top-0
+}
+
+.p-megamenu-vertical .p-megamenu-root-list > .p-megamenu-item > .p-megamenu-item-content .p-megamenu-submenu-icon {
+ @apply ms-auto
+}
+
+.p-megamenu-grid {
+ @apply flex
+}
+
+.p-megamenu-col-2,
+.p-megamenu-col-3,
+.p-megamenu-col-4,
+.p-megamenu-col-6,
+.p-megamenu-col-12 {
+ @apply flex-grow-0 flex-shrink-0 basis-auto p-2
+}
+
+.p-megamenu-col-2 {
+ @apply w-1/6;
+}
+
+.p-megamenu-col-3 {
+ @apply w-1/4
+}
+
+.p-megamenu-col-4 {
+ @apply w-1/3
+}
+
+.p-megamenu-col-6 {
+ @apply w-1/2
+}
+
+.p-megamenu-col-12 {
+ @apply w-full
+}
+
+.p-megamenu-button {
+ @apply hidden justify-center items-center cursor-pointer w-7 h-7 relative border-none rounded-full
+ text-surface-500 dark:text-surface-400 hover:text-surface-600 dark:hover:text-surface-300
+ bg-transparent hover:bg-surface-100 dark:hover:bg-surface-800
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+ transition-colors duration-200
+}
+
+.p-megamenu-mobile {
+ @apply flex
+}
+
+.p-megamenu-mobile .p-megamenu-button {
+ @apply flex
+}
+
+.p-megamenu-mobile .p-megamenu-root-list {
+ @apply absolute hidden flex-col top-full start-0 z-10 w-full p-1 gap-[2px]
+ bg-surface-0 dark:bg-surface-900
+ border border-surface-200 dark:border-surface-700
+ shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-2px_rgba(0,0,0,0.1)]
+}
+
+.p-megamenu-mobile-active .p-megamenu-root-list {
+ @apply flex
+}
+
+.p-megamenu-mobile .p-megamenu-root-list .p-megamenu-item {
+ @apply w-full static
+}
+
+.p-megamenu-mobile .p-megamenu-overlay {
+ @apply static border-none rounded-none shadow-none
+}
+
+.p-megamenu-mobile .p-megamenu-grid {
+ @apply flex-wrap overflow-auto max-h-[90%]
+}
+
+.p-megamenu-mobile .p-megamenu-root-list > .p-megamenu-item > .p-megamenu-item-content .p-megamenu-submenu-icon {
+ @apply ms-auto transition-transform duration-[200ms]
+}
+
+.p-megamenu-mobile .p-megamenu-root-list > .p-megamenu-item-active > .p-megamenu-item-content .p-megamenu-submenu-icon {
+ @apply -rotate-180
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/menu.css b/frontend/packages/kwai-ui/src/css/primevue/menu.css
new file mode 100644
index 000000000..d5e095aa0
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/menu.css
@@ -0,0 +1,51 @@
+.p-menu {
+ @apply bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+ border border-surface-200 dark:border-surface-700
+ rounded-md min-w-52
+}
+
+.p-menu-list {
+ @apply m-0 p-1 list-none outline-none flex flex-col gap-[2px]
+}
+
+.p-menu-item-content {
+ @apply transition-colors duration-200 rounded-sm text-surface-700 dark:text-surface-0
+}
+
+.p-menu-item-link {
+ @apply cursor-pointer flex items-center no-underline overflow-hidden relative text-inherit
+ px-3 py-2 gap-2 select-none outline-none
+}
+
+.p-menu-item-icon {
+ @apply text-surface-400 dark:text-surface-500
+}
+
+.p-menu-item.p-focus .p-menu-item-content {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-menu-item.p-focus .p-menu-item-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-menu-item:not(.p-disabled) .p-menu-item-content:hover {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-menu-item:not(.p-disabled) .p-menu-item-content:hover .p-menu-item-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-menu-overlay {
+ @apply shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-2px_rgba(0,0,0,0.1)]
+}
+
+.p-menu-submenu-label {
+ @apply bg-transparent px-3 py-2 text-surface-500 dark:text-surface-400 font-semibold
+}
+
+.p-menu-separator {
+ @apply border-t border-surface-200 dark:border-surface-700
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/menubar.css b/frontend/packages/kwai-ui/src/css/primevue/menubar.css
new file mode 100644
index 000000000..c989af621
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/menubar.css
@@ -0,0 +1,169 @@
+.p-menubar {
+ @apply flex items-center rounded-md px-3 py-2 gap-2
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+ border border-surface-200 dark:border-surface-700
+}
+
+.p-menubar-start,
+.p-megamenu-end {
+ @apply flex items-center
+}
+
+.p-menubar-root-list,
+.p-menubar-submenu {
+ @apply flex m-0 p-0 list-none outline-none
+}
+
+.p-menubar-root-list {
+ @apply items-center flex-wrap gap-2
+}
+
+.p-menubar-root-list > .p-menubar-item > .p-menubar-item-content {
+ @apply rounded-md
+}
+
+.p-menubar-root-list > .p-menubar-item > .p-menubar-item-content > .p-menubar-item-link {
+ @apply px-3 py-2
+}
+
+.p-menubar-item-content {
+ @apply transition-colors duration-200 rounded-sm text-surface-700 dark:text-surface-0
+}
+
+.p-menubar-item-link {
+ @apply cursor-pointer flex items-center no-underline overflow-hidden relative text-inherit
+ px-3 py-2 gap-2 select-none outline-none
+}
+
+.p-menubar-item-icon {
+ @apply text-surface-400 dark:text-surface-500
+}
+
+.p-menubar-submenu-icon {
+ @apply text-surface-400 dark:text-surface-500 ms-auto text-sm w-[0.875rem] h-[0.875rem]
+}
+
+.p-menubar-submenu-icon:dir(rtl) {
+ @apply rotate-180
+}
+
+.p-menubar-item.p-focus > .p-menubar-item-content {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-menubar-item.p-focus > .p-menubar-item-content .p-menubar-item-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-menubar-item.p-focus > .p-menubar-item-content .p-menubar-submenu-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-menubar-item:not(.p-disabled) > .p-menubar-item-content:hover {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-menubar-item:not(.p-disabled) > .p-menubar-item-content:hover .p-menubar-item-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-menubar-item:not(.p-disabled) > .p-menubar-item-content:hover .p-menubar-submenu-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-menubar-item-active > .p-menubar-item-content {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-menubar-item-active > .p-menubar-item-content .p-menubar-item-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-menubar-item-active > .p-menubar-item-content .p-menubar-submenu-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-menubar-submenu {
+ @apply hidden absolute min-w-52 z-10
+ bg-surface-0 dark:bg-surface-900
+ border border-surface-200 dark:border-surface-700
+ text-surface-700 dark:text-surface-0
+ flex-col p-1 gap-[2px] rounded-md
+ shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-2px_rgba(0,0,0,0.1)]
+}
+
+.p-menubar-submenu .p-menubar-separator {
+ @apply border-t border-surface-200 dark:border-surface-700
+}
+
+.p-menubar-submenu .p-menubar-item {
+ @apply relative
+}
+
+ .p-menubar-submenu > .p-menubar-item-active > .p-menubar-submenu {
+ @apply block start-full top-0
+}
+
+.p-menubar-end {
+ @apply ms-auto self-center
+}
+
+.p-menubar-button {
+ @apply hidden justify-center items-center cursor-pointer w-7 h-7 relative border-none rounded-full
+ text-surface-500 dark:text-surface-400 hover:text-surface-600 dark:hover:text-surface-300
+ bg-transparent hover:bg-surface-100 dark:hover:bg-surface-800
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+ transition-colors duration-200
+}
+
+.p-menubar-mobile {
+ @apply relative
+}
+
+.p-menubar-mobile .p-menubar-button {
+ @apply flex
+}
+
+.p-menubar-mobile .p-menubar-root-list {
+ @apply absolute hidden w-full flex-col top-full start-0 z-10 p-1 gap-[2px] rounded-md
+ border border-surface-200 dark:border-surface-700
+ bg-surface-0 dark:bg-surface-900
+ shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-2px_rgba(0,0,0,0.1)]
+}
+
+.p-menubar-mobile .p-menubar-root-list > .p-menubar-item > .p-menubar-item-content > .p-menubar-item-link {
+ @apply px-3 py-3
+}
+
+.p-menubar-mobile-active .p-menubar-root-list {
+ @apply flex
+}
+
+.p-menubar-mobile .p-menubar-root-list .p-menubar-item {
+ @apply w-full static
+}
+
+.p-menubar-mobile .p-menubar-root-list .p-menubar-separator {
+ @apply border-t border-surface-200 dark:border-surface-700
+}
+
+.p-menubar-mobile .p-menubar-root-list > .p-menubar-item > .p-menubar-item-content .p-menubar-submenu-icon {
+ @apply ms-auto transition-transform duration-[200ms]
+}
+
+.p-menubar-mobile .p-menubar-root-list > .p-menubar-item-active > .p-menubar-item-content .p-menubar-submenu-icon {
+ @apply -rotate-180
+}
+
+.p-menubar-mobile .p-menubar-submenu .p-menubar-submenu-icon {
+ @apply transition-transform duration-200 rotate-90
+}
+
+.p-menubar-mobile .p-menubar-item-active > .p-menubar-item-content .p-menubar-submenu-icon {
+ @apply -rotate-90
+}
+
+.p-menubar-mobile .p-menubar-submenu {
+ @apply w-full static shadow-none border-none ps-4 pe-0
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/message.css b/frontend/packages/kwai-ui/src/css/primevue/message.css
new file mode 100644
index 000000000..7ba971140
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/message.css
@@ -0,0 +1,212 @@
+.p-message {
+ @apply rounded-md outline outline-1
+}
+
+.p-message-content {
+ @apply flex items-center px-3 py-2 gap-2 h-full
+}
+
+.p-message-icon {
+ @apply flex-shrink-0
+}
+
+.p-message-close-button {
+ @apply flex items-center justify-center flex-shrink-0 ms-auto overflow-hidden relative cursor-pointer select-none
+ w-7 h-7 rounded-full bg-transparent transition-colors duration-200 text-inherit p-0 border-none
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2
+}
+
+.p-message-info {
+ @apply bg-blue-50/95 outline-blue-200 text-blue-600
+ dark:bg-blue-500/15 dark:outline-blue-700/35 dark:text-blue-500
+ shadow-[0px_4px_8px_0px_theme(colors.blue.500/0.04)]
+}
+
+.p-message-info .p-message-close-button {
+ @apply hover:bg-blue-100 focus-visible:outline-blue-600
+ dark:hover:bg-white/5 dark:focus-visible:outline-blue-500
+}
+
+.p-message-info.p-message-outlined {
+ @apply text-blue-500 outline-blue-500 dark:text-blue-600 dark:outline-blue-600
+}
+
+.p-message-info.p-message-simple {
+ @apply text-blue-500 dark:text-blue-600
+}
+
+.p-message-success {
+ @apply bg-green-50/95 outline-green-200 text-green-600
+ dark:bg-green-500/15 dark:outline-green-700/35 dark:text-green-500
+ shadow-[0px_4px_8px_0px_theme(colors.green.500/0.04)]
+}
+
+.p-message-success .p-message-close-button {
+ @apply hover:bg-green-100 focus-visible:outline-green-600
+ dark:hover:bg-white/5 dark:focus-visible:outline-green-500
+}
+
+.p-message-success.p-message-outlined {
+ @apply text-green-500 outline-green-500 dark:text-green-600 dark:outline-green-600
+}
+
+.p-message-success.p-message-simple {
+ @apply text-green-500 dark:text-green-600
+}
+
+.p-message-warn {
+ @apply bg-yellow-50/95 outline-yellow-200 text-yellow-600
+ dark:bg-yellow-500/15 dark:outline-yellow-700/35 dark:text-yellow-500
+ shadow-[0px_4px_8px_0px_theme(colors.yellow.500/0.04)]
+}
+
+.p-message-warn .p-message-close-button {
+ @apply hover:bg-yellow-100 focus-visible:outline-yellow-600
+ dark:hover:bg-white/5 dark:focus-visible:outline-yellow-500
+}
+
+.p-message-warn.p-message-outlined {
+ @apply text-yellow-500 outline-yellow-500 dark:text-yellow-600 dark:outline-yellow-600
+}
+
+.p-message-warn.p-message-simple {
+ @apply text-yellow-500 dark:text-yellow-600
+}
+
+.p-message-error {
+ @apply bg-red-50/95 outline-red-200 text-red-600
+ dark:bg-red-500/15 dark:outline-red-700/35 dark:text-red-500
+ shadow-[0px_4px_8px_0px_theme(colors.red.500/0.04)]
+}
+
+.p-message-error .p-message-close-button {
+ @apply hover:bg-red-100 focus-visible:outline-red-600
+ dark:hover:bg-white/5 dark:focus-visible:outline-red-500
+}
+
+.p-message-error.p-message-outlined {
+ @apply text-red-500 outline-red-500 dark:text-red-600 dark:outline-red-600
+}
+
+.p-message-error.p-message-simple {
+ @apply text-red-500 dark:text-red-600
+}
+
+.p-message-secondary {
+ @apply bg-surface-100 outline-surface-200 text-surface-600
+ dark:bg-surface-800 dark:outline-surface-700 dark:text-surface-300
+ shadow-[0px_4px_8px_0px_rgba(0,0,0,0.04)]
+}
+
+.p-message-secondary .p-message-close-button {
+ @apply hover:bg-surface-200 focus-visible:outline-surface-600
+ dark:hover:bg-surface-700 dark:focus-visible:outline-surface-300
+}
+
+.p-message-secondary.p-message-outlined {
+ @apply text-surface-500 outline-surface-500 dark:text-surface-600 dark:outline-surface-600
+}
+
+.p-message-secondary.p-message-simple {
+ @apply text-surface-500 dark:text-surface-600
+}
+
+.p-message-contrast {
+ @apply bg-surface-900 outline-surface-950 text-surface-50
+ dark:bg-surface-0 dark:outline-surface-100 dark:text-surface-950
+ shadow-[0px_4px_8px_0px_rgba(0,0,0,0.04)]
+}
+
+.p-message-contrast .p-message-close-button {
+ @apply hover:bg-surface-800 focus-visible:outline-surface-50
+ dark:hover:bg-surface-100 dark:focus-visible:outline-surface-950
+}
+
+.p-message-contrast.p-message-outlined {
+ @apply text-surface-950 outline-surface-950 dark:text-surface-0 dark:outline-surface-0
+}
+
+.p-message-contrast.p-message-simple {
+ @apply text-surface-950 dark:text-surface-0
+}
+
+.p-message-text {
+ @apply text-base font-medium
+}
+
+.p-message-icon {
+ @apply text-lg w-[1.125rem] h-[1.125rem]
+}
+
+.p-message-enter-from {
+ @apply opacity-0
+}
+
+.p-message-enter-active {
+ @apply transition-opacity duration-300
+}
+
+.p-message.p-message-leave-from {
+ @apply max-h-[1000px]
+}
+
+.p-message.p-message-leave-to {
+ @apply max-h-0 opacity-0 m-0
+}
+
+.p-message-leave-active {
+ @apply overflow-hidden [transition:max-height_0.45s_cubic-bezier(0,1,0,1),opacity_0.3s,margin0.3s]
+}
+
+.p-message-leave-active .p-message-close-button {
+ @apply opacity-0
+}
+
+.p-message-sm .p-message-content {
+ @apply px-2.5 py-[0.375rem]
+}
+
+.p-message-sm .p-message-text {
+ @apply text-sm
+}
+
+.p-message-sm .p-message-icon {
+ @apply w-4 h-4 text-sm
+}
+
+.p-message-sm .p-message-close-icon {
+ @apply w-3.5 h-3.5 text-sm
+}
+
+.p-message-lg .p-message-content {
+ @apply px-3.5 py-2.5
+}
+
+.p-message-lg .p-message-text {
+ @apply text-xl
+}
+
+.p-message-lg .p-message-icon {
+ @apply w-5 h-5 text-xl
+}
+
+.p-message-lg .p-message-close-icon {
+ @apply w-[1.125rem] h-[1.125rem] text-xl
+}
+
+.p-message-outlined {
+ @apply bg-transparent outline outline-1
+}
+
+.p-message-simple {
+ @apply bg-transparent outline-none shadow-none
+}
+
+.p-message-simple .p-message-content {
+ @apply p-0
+}
+
+.p-message-outlined .p-message-close-button:hover,
+.p-message-simple .p-message-close-button:hover {
+ @apply bg-transparent
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/metergroup.css b/frontend/packages/kwai-ui/src/css/primevue/metergroup.css
new file mode 100644
index 000000000..74227a115
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/metergroup.css
@@ -0,0 +1,67 @@
+.p-metergroup {
+ @apply flex gap-4
+}
+
+.p-metergroup-meters {
+ @apply flex bg-surface-200 dark:bg-surface-700 rounded-md
+}
+
+.p-metergroup-label-list {
+ @apply flex flex-wrap m-0 p-0 list-none
+}
+
+.p-metergroup-label {
+ @apply inline-flex items-center gap-2
+}
+
+.p-metergroup-label-marker {
+ @apply inline-flex w-2 h-2 rounded-full
+}
+
+.p-metergroup-label-icon {
+ @apply text-base w-4 h-4
+}
+
+.p-metergroup-horizontal {
+ @apply flex-col
+}
+
+.p-metergroup-label-list-horizontal {
+ @apply gap-4
+}
+
+.p-metergroup-horizontal .p-metergroup-meters {
+ @apply h-2
+}
+
+.p-metergroup-horizontal .p-metergroup-meter:first-of-type {
+ @apply rounded-s-md
+}
+
+.p-metergroup-horizontal .p-metergroup-meter:last-of-type {
+ @apply rounded-e-md
+}
+
+.p-metergroup-vertical {
+ @apply flex-row
+}
+
+.p-metergroup-label-list-vertical {
+ @apply flex-col gap-2
+}
+
+.p-metergroup-vertical .p-metergroup-meters {
+ @apply flex-col w-2 h-full
+}
+
+.p-metergroup-vertical .p-metergroup-label-list {
+ @apply items-start
+}
+
+.p-metergroup-vertical .p-metergroup-meter:first-of-type {
+ @apply rounded-ss-md rounded-se-md
+}
+
+.p-metergroup-vertical .p-metergroup-meter:last-of-type {
+ @apply rounded-ee-md rounded-es-md
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/multiselect.css b/frontend/packages/kwai-ui/src/css/primevue/multiselect.css
new file mode 100644
index 000000000..a6d7e59c8
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/multiselect.css
@@ -0,0 +1,139 @@
+@import './checkbox';
+@import './chip';
+@import './inputtext';
+@import './iconfield';
+
+.p-multiselect {
+ @apply inline-flex cursor-pointer relative select-none rounded-md
+ bg-surface-0 dark:bg-surface-950
+ border border-surface-300 dark:border-surface-700
+ shadow-[0_1px_2px_0_rgba(18,18,23,0.05)]
+ transition-colors duration-200
+}
+
+.p-multiselect:not(.p-disabled):hover {
+ @apply border-surface-400 dark:border-surface-600
+}
+
+.p-multiselect:not(.p-disabled).p-focus {
+ @apply border-primary
+}
+
+.p-multiselect.p-variant-filled {
+ @apply bg-surface-50 dark:bg-surface-800
+}
+
+.p-multiselect.p-invalid {
+ @apply border-red-400 dark:border-red-300
+}
+
+.p-multiselect.p-disabled {
+ @apply bg-surface-200 text-surface-500 dark:bg-surface-700 dark:text-surface-400 opacity-100 cursor-default
+}
+
+.p-multiselect-dropdown {
+ @apply flex items-center justify-center shrink-0 bg-transparent
+ text-surface-500 dark:text-surface-400 w-10 rounded-e-md
+}
+
+.p-multiselect-label-container {
+ @apply overflow-hidden flex-auto
+}
+
+.p-multiselect-label {
+ @apply flex items-center gap-1 whitespace-nowrap overflow-hidden text-ellipsis px-3 py-2 text-surface-700 dark:text-surface-0
+}
+
+.p-multiselect-label.p-placeholder {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-multiselect.p-disabled .p-multiselect-label {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-multiselect-label-empty {
+ @apply overflow-hidden opacity-0
+}
+
+.p-multiselect .p-multiselect-overlay {
+ @apply min-w-full
+}
+
+.p-multiselect-overlay {
+ @apply absolute top-0 left-0 rounded-md
+ bg-surface-0 dark:bg-surface-900
+ border border-surface-200 dark:border-surface-700
+ text-surface-700 dark:text-surface-0
+ shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-2px_rgba(0,0,0,0.1)]
+}
+
+.p-multiselect-header {
+ @apply flex items-center pt-2 pb-1 px-4
+}
+
+.p-multiselect-header .p-checkbox {
+ @apply me-2
+}
+
+.p-multiselect-filter-container {
+ @apply flex-auto
+}
+
+.p-multiselect-filter {
+ @apply w-full
+}
+
+.p-multiselect-list-container {
+ @apply overflow-auto
+}
+
+.p-multiselect-list {
+ @apply m-0 p-1 list-none gap-[2px] flex flex-col
+}
+
+.p-multiselect-option {
+ @apply cursor-pointer font-normal whitespace-nowrap relative overflow-hidden flex items-center gap-2 px-3 py-2
+ rounded-sm text-surface-700 dark:text-surface-0 bg-transparent border-none
+ transition-colors duration-200
+}
+
+.p-multiselect-option:not(.p-disabled).p-focus {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-600 dark:text-surface-0
+}
+
+.p-multiselect-option-group {
+ @apply m-0 px-3 py-2 bg-transparent text-surface-500 dark:text-surface-400 font-semibold
+}
+
+.p-multiselect-empty-message {
+ @apply px-3 py-2
+}
+
+.p-multiselect-label .p-chip {
+ @apply py-1 rounded-sm
+}
+
+.p-multiselect-label:has(.p-chip) {
+ @apply py-1 px-[0.375rem]
+}
+
+.p-multiselect-fluid {
+ @apply flex
+}
+
+.p-multiselect-sm .p-multiselect-label {
+ @apply text-sm px-[0.625rem] py-[0.375rem]
+}
+
+.p-multiselect-sm .p-multiselect-dropdown .p-icon {
+ @apply text-sm w-[0.875rem] h-[0.875rem]
+}
+
+.p-multiselect-lg .p-multiselect-label {
+ @apply text-lg px-[0.875rem] py-[0.625rem]
+}
+
+.p-multiselect-lg .p-multiselect-dropdown .p-icon {
+ @apply text-lg w-[1.125rem] h-[1.125rem]
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/orderlist.css b/frontend/packages/kwai-ui/src/css/primevue/orderlist.css
new file mode 100644
index 000000000..99619f931
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/orderlist.css
@@ -0,0 +1,10 @@
+@import './button';
+@import './listbox';
+
+.p-orderlist {
+ @apply flex gap-[1.125rem]
+}
+
+.p-orderlist-controls {
+ @apply flex flex-col justify-center gap-2
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/organizationchart.css b/frontend/packages/kwai-ui/src/css/primevue/organizationchart.css
new file mode 100644
index 000000000..69bbb496a
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/organizationchart.css
@@ -0,0 +1,71 @@
+.p-organizationchart-table {
+ @apply border-spacing-0 border-separate my-0 mx-auto
+}
+
+.p-organizationchart-table > tbody > tr > td {
+ @apply text-center align-top py-0 px-3
+}
+
+.p-organizationchart-node {
+ @apply inline-block relative py-3 px-4 rounded-md
+ border border-surface-200 dark:border-surface-700
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+ transition-colors duration-200
+}
+
+.p-organizationchart-node:has(.p-organizationchart-node-toggle-button) {
+ @apply pt-3 px-4 pb-5
+}
+
+.p-organizationchart-node.p-organizationchart-node-selectable:not(.p-organizationchart-node-selected):hover {
+ @apply bg-surface-100 text-surface-800 dark:bg-surface-800 dark:text-surface-0
+}
+
+.p-organizationchart-node-selected {
+ @apply bg-highlight
+}
+
+.p-organizationchart-node-toggle-button {
+ @apply absolute -bottom-3 -ms-3 z-20 start-1/2 select-none cursor-pointer w-6 h-6 no-underline rounded-full
+ inline-flex items-center justify-center transition-colors duration-200
+ border border-surface-200 dark:border-surface-700
+ bg-surface-0 text-surface-500 hover:bg-surface-100 hover:text-surface-700
+ dark:bg-surface-900 dark:text-surface-400 dark:hover:bg-surface-800 dark:hover:text-surface-0
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+}
+.p-organizationchart-node-toggle-button-icon {
+ @apply relative top-px
+}
+
+.p-organizationchart-connector-down {
+ @apply my-0 mx-auto h-6 w-px bg-surface-200 dark:bg-surface-700
+}
+
+.p-organizationchart-connector-right {
+ @apply rounded-none
+}
+
+.p-organizationchart-connector-left {
+ @apply rounded-none border-e border-surface-200 dark:border-surface-700
+}
+
+.p-organizationchart-connector-top {
+ @apply border-t border-surface-200 dark:border-surface-700
+}
+
+.p-organizationchart-node-selectable {
+ @apply cursor-pointer
+}
+
+.p-organizationchart-connectors :nth-child(1 of .p-organizationchart-connector-left) {
+ @apply border-e-0
+}
+
+.p-organizationchart-connectors :nth-last-child(1 of .p-organizationchart-connector-left) {
+ @apply rounded-se-md
+}
+
+.p-organizationchart-connectors :nth-child(1 of .p-organizationchart-connector-right) {
+ @apply border-s border-surface-200 dark:border-surface-700 rounded-ss-md
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/overlaybadge.css b/frontend/packages/kwai-ui/src/css/primevue/overlaybadge.css
new file mode 100644
index 000000000..c0193ea23
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/overlaybadge.css
@@ -0,0 +1,13 @@
+@import './badge';
+
+.p-overlaybadge {
+ @apply relative
+}
+
+.p-overlaybadge .p-badge {
+ @apply absolute top-0 end-0 translate-x-[50%] translate-y-[-50%] origin-[100%_0] m-0 outline outline-2 outline-surface-0 dark:outline-surface-900
+}
+
+.p-overlaybadge .p-badge:dir(rtl) {
+ @apply -translate-x-1/2 -translate-y-1/2
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/paginator.css b/frontend/packages/kwai-ui/src/css/primevue/paginator.css
new file mode 100644
index 000000000..25d694302
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/paginator.css
@@ -0,0 +1,58 @@
+.p-paginator {
+ @apply flex items-center justify-center flex-wrap py-2 px-4 rounded-md gap-1
+ bg-surface-0 dark:bg-surface-900 text-surface-700 dark:text-surface-0
+}
+
+.p-paginator-content {
+ @apply flex items-center justify-center flex-wrap gap-1
+}
+
+.p-paginator-content-start {
+ @apply ms-auto
+}
+
+.p-paginator-content-end {
+ @apply me-auto
+}
+
+.p-paginator-page,
+.p-paginator-next,
+.p-paginator-last,
+.p-paginator-first,
+.p-paginator-prev {
+ @apply cursor-pointer inline-flex items-center justify-center leading-none overflow-hidden relative
+ bg-transparent border-none min-w-10 h-10 transition-colors duration-200 rounded-full p-0 m-0
+ text-surface-500 dark:text-surface-400
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+}
+
+.p-paginator-page:not(.p-disabled):not(.p-paginator-page-selected):hover,
+.p-paginator-first:not(.p-disabled):hover,
+.p-paginator-prev:not(.p-disabled):hover,
+.p-paginator-next:not(.p-disabled):hover,
+.p-paginator-last:not(.p-disabled):hover {
+ @apply bg-surface-100 text-surface-600 dark:bg-surface-800 dark:text-surface-300
+}
+
+.p-paginator-page.p-paginator-page-selected {
+ @apply bg-highlight
+}
+
+.p-paginator-current {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-paginator-pages {
+ @apply flex items-center gap-1
+}
+
+.p-paginator-jtp-input .p-inputtext {
+ @apply max-w-10
+}
+
+.p-paginator-first:dir(rtl),
+.p-paginator-prev:dir(rtl),
+.p-paginator-next:dir(rtl),
+.p-paginator-last:dir(rtl) {
+ @apply rotate-180
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/panel.css b/frontend/packages/kwai-ui/src/css/primevue/panel.css
new file mode 100644
index 000000000..6a9aa44a6
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/panel.css
@@ -0,0 +1,27 @@
+@import './button';
+
+.p-panel {
+ @apply border border-surface-200 dark:border-surface-700 rounded-md
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+}
+
+.p-panel-header {
+ @apply flex justify-between items-center p-[1.125rem]
+}
+
+.p-panel-toggleable .p-panel-header {
+ @apply py-[0.375rem] px-[1.125rem]
+}
+
+.p-panel-title {
+ @apply leading-none font-semibold
+}
+
+.p-panel-content {
+ @apply pt-0 pb-[1.125rem] px-[1.125rem]
+}
+
+.p-panel-footer {
+ @apply pt-0 pb-[1.125rem] px-[1.125rem]
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/panelmenu.css b/frontend/packages/kwai-ui/src/css/primevue/panelmenu.css
new file mode 100644
index 000000000..77f28503b
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/panelmenu.css
@@ -0,0 +1,94 @@
+.p-panelmenu {
+ @apply flex flex-col gap-2
+}
+
+.p-panelmenu-panel {
+ @apply bg-surface-0 dark:bg-surface-900 rounded-md p-1
+ border border-surface-200 dark:border-surface-700
+ text-surface-700 dark:text-surface-0
+}
+
+.p-panelmenu-header {
+ @apply outline-none
+}
+
+.p-panelmenu-header-content {
+ @apply rounded-md transition-colors duration-200 text-surface-700 dark:text-surface-0
+}
+
+.p-panelmenu-header-link {
+ @apply flex items-center gap-2 px-3 py-2 select-none cursor-pointer relative no-underline text-inherit
+}
+
+.p-panelmenu-header-icon,
+.p-panelmenu-item-icon {
+ @apply text-surface-400 dark:text-surface-500
+}
+
+.p-panelmenu-submenu-icon {
+ @apply text-surface-400 dark:text-surface-500
+}
+
+.p-panelmenu-header:not(.p-disabled):focus-visible .p-panelmenu-header-content {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-panelmenu-header:not(.p-disabled):focus-visible .p-panelmenu-header-content .p-panelmenu-header-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-panelmenu-header:not(.p-disabled):focus-visible .p-panelmenu-header-content .p-panelmenu-submenu-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-panelmenu-header:not(.p-panelmenu-header-active) .p-panelmenu-submenu-icon:dir(rtl) {
+ @apply rotate-180;
+}
+
+.p-panelmenu-header:not(.p-disabled) .p-panelmenu-header-content:hover {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-panelmenu-header:not(.p-disabled) .p-panelmenu-header-content:hover .p-panelmenu-header-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-panelmenu-header:not(.p-disabled) .p-panelmenu-header-content:hover .p-panelmenu-submenu-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-panelmenu-submenu {
+ @apply m-0 py-0 ps-4 outline-none list-none
+}
+
+.p-panelmenu-item-link {
+ @apply flex items-center gap-2 px-3 py-2 select-none cursor-pointer no-underline text-inherit relative overflow-hidden
+}
+
+.p-panelmenu-item-content {
+ @apply rounded-md transition-colors duration-200 text-surface-700 dark:text-surface-0
+}
+
+.p-panelmenu-item.p-focus > .p-panelmenu-item-content {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-panelmenu-item.p-focus > .p-panelmenu-item-content .p-panelmenu-item-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-panelmenu-item.p-focus > .p-panelmenu-item-content .p-panelmenu-submenu-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-panelmenu-item:not(.p-disabled) > .p-panelmenu-item-content:hover {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-panelmenu-item:not(.p-disabled) > .p-panelmenu-item-content:hover .p-panelmenu-item-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-panelmenu-item:not(.p-disabled) > .p-panelmenu-item-content:hover .p-panelmenu-submenu-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/password.css b/frontend/packages/kwai-ui/src/css/primevue/password.css
new file mode 100644
index 000000000..e350fcbab
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/password.css
@@ -0,0 +1,61 @@
+@import './inputtext';
+
+.p-password {
+ @apply inline-flex relative
+}
+
+.p-password .p-password-overlay {
+ @apply min-w-full
+}
+
+.p-password-meter {
+ @apply h-3 bg-surface-200 dark:bg-surface-700 rounded-md
+}
+
+.p-password-meter-label {
+ @apply h-full w-0 transition-[width] duration-1000 ease-in-out rounded-md
+}
+
+.p-password-meter-weak {
+ @apply bg-red-500 dark:bg-red-400
+}
+
+.p-password-meter-medium {
+ @apply bg-amber-500 dark:bg-amber-400
+}
+
+.p-password-meter-strong {
+ @apply bg-green-500 dark:bg-green-400
+}
+
+.p-password-fluid {
+ @apply flex
+}
+
+.p-password-fluid .p-password-input {
+ @apply w-full
+}
+
+.p-password-input::-ms-reveal,
+.p-password-input::-ms-clear {
+ @apply hidden
+}
+
+.p-password-overlay {
+ @apply p-3 rounded-md bg-surface-0 dark:bg-surface-900
+ border border-surface-200 dark:border-surface-700
+ text-surface-700 dark:text-surface-0
+ shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-2px_rgba(0,0,0,0.1)]
+}
+
+.p-password-content {
+ @apply flex flex-col gap-2
+}
+
+.p-password-toggle-mask-icon {
+ @apply end-3 text-surface-500 dark:text-surface-400 absolute top-1/2 -mt-2 w-4 h-4
+}
+
+.p-password:has(.p-password-toggle-mask-icon) .p-password-input {
+ @apply pe-10
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/picklist.css b/frontend/packages/kwai-ui/src/css/primevue/picklist.css
new file mode 100644
index 000000000..0dec3454d
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/picklist.css
@@ -0,0 +1,18 @@
+@import './button';
+@import './listbox';
+
+.p-picklist {
+ @apply flex gap-[1.125rem]
+}
+
+.p-picklist-controls {
+ @apply flex flex-col justify-center gap-2
+}
+
+.p-picklist-list-container {
+ @apply flex-grow flex-shrink basis-1/2
+}
+
+.p-picklist .p-listbox {
+ @apply h-full
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/popover.css b/frontend/packages/kwai-ui/src/css/primevue/popover.css
new file mode 100644
index 000000000..964d2d9df
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/popover.css
@@ -0,0 +1,46 @@
+.p-popover {
+ @apply mt-[10px] bg-surface-0 dark:bg-surface-900 text-surface-700 dark:text-surface-0
+ border border-surface-200 dark:border-surface-700
+ rounded-md shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-2px_rgba(0,0,0,0.1)]
+ before:bottom-full before:left-5 before:h-0 before:w-0 before:absolute before:pointer-events-none
+ before:border-[10px] before:-ms-[10px] before:border-transparent before:border-b-surface-200 dark:before:border-b-surface-700
+ after:bottom-full after:left-5 after:h-0 after:w-0 after:absolute after:pointer-events-none
+ after:border-[8px] after:-ms-[8px] after:border-transparent after:border-b-surface-0 dark:after:border-b-surface-900
+}
+
+.p-popover-content {
+ @apply p-3
+}
+
+.p-popover-flipped {
+ @apply -mt-[10px] mb-[10px]
+}
+
+.p-popover-enter-from {
+ @apply opacity-0 scale-y-75
+}
+
+.p-popover-leave-to {
+ @apply opacity-0
+}
+
+.p-popover-enter-active {
+ @apply [transition:transform_120ms_cubic-bezier(0,0,0.2,1),opacity_120ms_cubic-bezier(0,0,0.2,1)]
+}
+
+.p-popover-leave-active {
+ @apply transition-opacity duration-100 ease-linear
+}
+
+.p-popover-flipped:after,
+.p-popover-flipped:before {
+ @apply bottom-auto top-full
+}
+
+.p-popover.p-popover-flipped:after {
+ @apply border-b-transparent border-t-surface-0 dark:border-t-surface-900
+}
+
+.p-popover.p-popover-flipped:before {
+ @apply border-b-transparent border-t-surface-200 dark:border-t-surface-700
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/progressbar.css b/frontend/packages/kwai-ui/src/css/primevue/progressbar.css
new file mode 100644
index 000000000..3788b236f
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/progressbar.css
@@ -0,0 +1,67 @@
+.p-progressbar {
+ @apply relative overflow-hidden h-5 bg-surface-200 dark:bg-surface-700 rounded-md
+}
+
+.p-progressbar-value {
+ @apply m-0 bg-primary
+}
+
+.p-progressbar-label {
+ @apply text-primary-contrast text-xs font-semibold
+}
+
+.p-progressbar-determinate .p-progressbar-value {
+ @apply h-full w-0 absolute flex items-center justify-center overflow-hidden transition-[width] duration-1000 ease-in-out
+}
+
+.p-progressbar-determinate .p-progressbar-label {
+ @apply inline-flex
+}
+
+.p-progressbar-indeterminate .p-progressbar-value::before {
+ @apply content-[''] absolute bg-inherit top-0 start-0 bottom-0 will-change-[inset-inline-start,inset-inline-end];
+}
+
+.p-progressbar-indeterminate .p-progressbar-value::before {
+ animation: p-progressbar-indeterminate-anim 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite;
+}
+
+.p-progressbar-indeterminate .p-progressbar-value::after {
+ @apply content-[''] absolute bg-inherit top-0 start-0 bottom-0 will-change-[inset-inline-start,inset-inline-end];
+
+}
+
+.p-progressbar-indeterminate .p-progressbar-value::after {
+ animation: p-progressbar-indeterminate-anim-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1) infinite;
+ animation-delay: 1.15s;
+}
+
+@keyframes p-progressbar-indeterminate-anim {
+ 0% {
+ inset-inline-start: -35%;
+ inset-inline-end: 100%;
+ }
+ 60% {
+ inset-inline-start: 100%;
+ inset-inline-end: -90%;
+ }
+ 100% {
+ inset-inline-start: 100%;
+ inset-inline-end: -90%;
+ }
+}
+
+@keyframes p-progressbar-indeterminate-anim-short {
+ 0% {
+ inset-inline-start: -200%;
+ inset-inline-end: 100%;
+ }
+ 60% {
+ inset-inline-start: 107%;
+ inset-inline-end: -8%;
+ }
+ 100% {
+ inset-inline-start: 107%;
+ inset-inline-end: -8%;
+ }
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/progressspinner.css b/frontend/packages/kwai-ui/src/css/primevue/progressspinner.css
new file mode 100644
index 000000000..335abd177
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/progressspinner.css
@@ -0,0 +1,58 @@
+.p-progressspinner {
+ @apply relative my-0 mx-auto w-[100px] h-[100px] inline-block
+ before:block before:pt-[100%]
+}
+
+.p-progressspinner-spin {
+ @apply h-full origin-center w-full absolute top-0 bottom-0 start-0 end-0 m-auto;
+}
+
+.p-progressspinner-spin {
+ animation: p-progressspinner-rotate 2s linear infinite;
+}
+
+.p-progressspinner-circle {
+ stroke-dasharray: 89, 200;
+ stroke-dashoffset: 0;
+ stroke: theme(colors.red.500);
+ stroke-linecap: round;
+ animation: p-progressspinner-dash 1.5s ease-in-out infinite, p-progressspinner-color 6s ease-in-out infinite;
+}
+
+@keyframes p-progressspinner-rotate {
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+
+@keyframes p-progressspinner-dash {
+ 0% {
+ stroke-dasharray: 1, 200;
+ stroke-dashoffset: 0;
+ }
+ 50% {
+ stroke-dasharray: 89, 200;
+ stroke-dashoffset: -35px;
+ }
+ 100% {
+ stroke-dasharray: 89, 200;
+ stroke-dashoffset: -124px;
+ }
+}
+
+@keyframes p-progressspinner-color {
+ 100%,
+ 0% {
+ stroke: theme(colors.red.500);
+ }
+ 40% {
+ stroke: theme(colors.blue.500);
+ }
+ 66% {
+ stroke: theme(colors.green.500);
+ }
+ 80%,
+ 90% {
+ stroke: theme(colors.yellow.500);
+ }
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/radiobutton.css b/frontend/packages/kwai-ui/src/css/primevue/radiobutton.css
new file mode 100644
index 000000000..bd88f93da
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/radiobutton.css
@@ -0,0 +1,93 @@
+.p-radiobutton {
+ @apply relative inline-flex select-none w-5 h-5
+}
+
+.p-radiobutton-input {
+ @apply cursor-pointer disabled:cursor-default appearance-none absolute start-0 top-0 w-full h-full m-0 p-0 opacity-0 z-10
+ border border-transparent rounded-full
+}
+
+.p-radiobutton-box {
+ @apply flex justify-center items-center rounded-full
+ border border-surface-300 dark:border-surface-700
+ bg-surface-0 dark:bg-surface-950
+ w-5 h-5
+ transition-colors duration-200
+ shadow-[0_1px_2px_0_rgba(18,18,23,0.05)]
+}
+
+.p-radiobutton-icon {
+ @apply bg-transparent text-xs w-3 h-3 rounded-full
+ transition-all duration-200 backface-hidden
+}
+
+.p-radiobutton-icon {
+ @apply scale-[0.1]
+}
+
+.p-radiobutton:not(.p-disabled):has(.p-radiobutton-input:hover) .p-radiobutton-box {
+ @apply border-surface-400 dark:border-surface-600
+}
+
+.p-radiobutton-checked .p-radiobutton-box {
+ @apply border-primary bg-primary
+}
+
+.p-radiobutton-checked .p-radiobutton-box .p-radiobutton-icon {
+ @apply bg-primary-contrast visible
+}
+
+.p-radiobutton-checked .p-radiobutton-box .p-radiobutton-icon {
+ @apply scale-100
+}
+
+.p-radiobutton-checked:not(.p-disabled):has(.p-radiobutton-input:hover) .p-radiobutton-box {
+ @apply border-primary-emphasis bg-primary-emphasis
+}
+
+.p-radiobutton:not(.p-disabled):has(.p-radiobutton-input:hover).p-radiobutton-checked .p-radiobutton-box .p-radiobutton-icon {
+ @apply bg-primary-contrast
+}
+
+.p-radiobutton:not(.p-disabled):has(.p-radiobutton-input:focus-visible) .p-radiobutton-box {
+ @apply outline outline-1 outline-offset-2 outline-primary
+}
+
+.p-radiobutton.p-invalid > .p-radiobutton-box {
+ @apply border-red-400 dark:border-red-300
+}
+
+.p-radiobutton.p-variant-filled .p-radiobutton-box {
+ @apply bg-surface-50 dark:bg-surface-800
+}
+
+.p-radiobutton.p-disabled {
+ @apply opacity-100
+}
+
+.p-radiobutton.p-disabled .p-radiobutton-box {
+ @apply bg-surface-200 dark:bg-surface-400
+ border-surface-300 dark:border-surface-700
+}
+
+.p-radiobutton-checked.p-disabled .p-radiobutton-box .p-radiobutton-icon {
+ @apply bg-surface-700 dark:bg-surface-400
+}
+
+.p-radiobutton-sm,
+.p-radiobutton-sm .p-radiobutton-box {
+ @apply w-4 h-4
+}
+
+.p-radiobutton-sm .p-radiobutton-icon {
+ @apply w-2 h-2
+}
+
+.p-radiobutton-lg,
+.p-radiobutton-lg .p-radiobutton-box {
+ @apply w-6 h-6
+}
+
+.p-radiobutton-lg .p-radiobutton-icon {
+ @apply w-4 h-4
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/rating.css b/frontend/packages/kwai-ui/src/css/primevue/rating.css
new file mode 100644
index 000000000..61cc30843
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/rating.css
@@ -0,0 +1,23 @@
+.p-rating {
+ @apply relative flex items-center gap-1
+}
+
+.p-rating-option {
+ @apply inline-flex items-center cursor-pointer rounded-full
+}
+
+.p-rating-option.p-focus-visible {
+ @apply outline outline-1 outline-offset-2 outline-primary
+}
+
+.p-rating-icon {
+ @apply text-surface-500 dark:text-surface-400 text-base w-4 h-4 transition-colors duration-200
+}
+
+.p-rating:not(.p-disabled):not(.p-readonly) .p-rating-option:hover .p-rating-icon {
+ @apply text-primary
+}
+
+.p-rating-option-active .p-rating-icon {
+ @apply text-primary
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/ripple.css b/frontend/packages/kwai-ui/src/css/primevue/ripple.css
new file mode 100644
index 000000000..a40d975c6
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/ripple.css
@@ -0,0 +1,7 @@
+.p-ink {
+ @apply block absolute bg-black/10 dark:bg-white/30 scale-0 rounded-[100%] pointer-events-none
+}
+
+.p-ink-active {
+ @apply transition-[opacity,transform] duration-500 scale-[2.5] opacity-0 ease-linear
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/scrollpanel.css b/frontend/packages/kwai-ui/src/css/primevue/scrollpanel.css
new file mode 100644
index 000000000..8bf7fd55c
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/scrollpanel.css
@@ -0,0 +1,41 @@
+.p-scrollpanel-content-container {
+ @apply overflow-hidden w-full h-full relative z-10 float-left
+}
+
+.p-scrollpanel-content {
+ @apply relative overflow-auto
+ h-[calc(100%+18px)] w-[calc(100%+18px)]
+ pt-0 ps-0 pr-[18px] pb-[18px] [scrollbar-width:none]
+}
+
+.p-scrollpanel-content::-webkit-scrollbar {
+ @apply hidden
+}
+
+.p-scrollpanel-bar {
+ @apply relative rounded-sm z-20 cursor-pointer opacity-0
+ bg-surface-100 dark:bg-surface-800
+ transition-opacity duration-200 border-none
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+}
+
+.p-scrollpanel-bar-y {
+ @apply w-[9px] top-0
+}
+
+.p-scrollpanel-bar-x {
+ @apply h-[9px] bottom-0
+}
+
+.p-scrollpanel-hidden {
+ @apply invisible
+}
+
+.p-scrollpanel:hover .p-scrollpanel-bar,
+.p-scrollpanel:active .p-scrollpanel-bar {
+ @apply opacity-100
+}
+
+.p-scrollpanel-grabbed {
+ @apply select-none
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/scrolltop.css b/frontend/packages/kwai-ui/src/css/primevue/scrolltop.css
new file mode 100644
index 000000000..40e5381f4
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/scrolltop.css
@@ -0,0 +1,25 @@
+@import './button';
+
+.p-scrolltop.p-button {
+ @apply fixed bottom-5 end-5
+}
+
+.p-scrolltop-sticky.p-button {
+ @apply sticky flex ms-auto
+}
+
+.p-scrolltop-enter-from {
+ @apply opacity-0
+}
+
+.p-scrolltop-enter-active {
+ @apply transition-opacity duration-150
+}
+
+.p-scrolltop.p-scrolltop-leave-to {
+ @apply opacity-0
+}
+
+.p-scrolltop-leave-active {
+ @apply transition-opacity duration-150
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/select.css b/frontend/packages/kwai-ui/src/css/primevue/select.css
new file mode 100644
index 000000000..85b108e83
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/select.css
@@ -0,0 +1,144 @@
+@import './button';
+@import './inputtext';
+@import './iconfield';
+
+.p-select {
+ @apply inline-flex cursor-pointer relative select-none rounded-md
+ bg-surface-0 dark:bg-surface-950
+ border border-surface-300 dark:border-surface-700
+ shadow-[0_1px_2px_0_rgba(18,18,23,0.05)]
+ transition-colors duration-200
+}
+
+.p-select:not(.p-disabled):hover {
+ @apply border-surface-400 dark:border-surface-600
+}
+
+.p-select:not(.p-disabled).p-focus {
+ @apply border-primary
+}
+
+.p-select.p-variant-filled {
+ @apply bg-surface-50 dark:bg-surface-800
+}
+
+.p-select.p-invalid {
+ @apply border-red-400 dark:border-red-300
+}
+
+.p-select.p-disabled {
+ @apply bg-surface-200 text-surface-500 dark:bg-surface-700 dark:text-surface-400 opacity-100 cursor-default
+}
+
+.p-select-clear-icon {
+ @apply absolute top-1/2 -mt-2 text-surface-500 dark:text-surface-400 end-10
+}
+
+.p-select-dropdown {
+ @apply flex items-center justify-center shrink-0 bg-transparent
+ text-surface-500 dark:text-surface-400 w-10 rounded-e-md
+}
+
+.p-select-label {
+ @apply block whitespace-nowrap overflow-hidden flex-auto w-[1%]
+ py-2 px-3 overflow-ellipsis
+ text-surface-700 dark:text-surface-0 bg-transparent border-none outline-none
+}
+
+.p-select-label.p-placeholder {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-select:has(.p-select-clear-icon) .p-select-label {
+ @apply pe-7
+}
+
+.p-select.p-disabled .p-select-label {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-select-label-empty {
+ @apply overflow-hidden opacity-0
+}
+
+input.p-select-label {
+ @apply cursor-default
+}
+
+.p-select .p-select-overlay {
+ @apply min-w-full
+}
+
+.p-select-overlay {
+ @apply absolute top-0 left-0 rounded-md
+ bg-surface-0 dark:bg-surface-900
+ border border-surface-200 dark:border-surface-700
+ text-surface-700 dark:text-surface-0
+ shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-2px_rgba(0,0,0,0.1)]
+}
+
+.p-select-header {
+ @apply pt-2 pb-1 px-4
+}
+
+.p-select-filter {
+ @apply w-full
+}
+
+.p-select-list-container {
+ @apply overflow-auto
+}
+
+.p-select-option-group {
+ @apply m-0 px-3 py-2 bg-transparent text-surface-500 dark:text-surface-400 font-semibold
+}
+
+.p-select-list {
+ @apply m-0 p-1 list-none gap-[2px] flex flex-col
+}
+
+.p-select-option {
+ @apply cursor-pointer font-normal whitespace-nowrap relative overflow-hidden flex items-center
+ px-3 py-2 border-none text-surface-700 dark:text-surface-0 bg-transparent rounded-sm
+ transition-colors duration-200
+}
+
+.p-select-option:not(.p-select-option-selected):not(.p-disabled).p-focus {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-select-option.p-select-option-selected {
+ @apply bg-highlight
+}
+
+.p-select-option.p-select-option-selected.p-focus {
+ @apply bg-highlight-emphasis
+}
+
+.p-select-option-check-icon {
+ @apply relative -ms-[0.375rem] me-[0.375rem] text-surface-700 dark:text-surface-0
+}
+
+.p-select-empty-message {
+ @apply px-3 py-2
+}
+
+.p-select-fluid {
+ @apply flex
+}
+
+.p-select-sm .p-select-label {
+ @apply text-sm px-[0.625rem] py-[0.375rem]
+}
+
+.p-select-sm .p-select-dropdown .p-icon {
+ @apply text-sm w-[0.875rem] h-[0.875rem]
+}
+
+.p-select-lg .p-select-label {
+ @apply text-lg px-[0.875rem] py-[0.625rem]
+}
+
+.p-select-lg .p-select-dropdown .p-icon {
+ @apply text-lg w-[1.125rem] h-[1.125rem]
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/selectbutton.css b/frontend/packages/kwai-ui/src/css/primevue/selectbutton.css
new file mode 100644
index 000000000..5350fdeef
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/selectbutton.css
@@ -0,0 +1,25 @@
+@import './togglebutton';
+
+.p-selectbutton {
+ @apply inline-flex select-none rounded-md
+}
+
+.p-selectbutton .p-togglebutton {
+ @apply rounded-none border-y border-r border-s-0
+}
+
+.p-selectbutton .p-togglebutton:focus-visible {
+ @apply relative z-10
+}
+
+.p-selectbutton .p-togglebutton:first-child {
+ @apply border-s rounded-s-md
+}
+
+.p-selectbutton .p-togglebutton:last-child {
+ @apply rounded-e-md
+}
+
+.p-selectbutton.p-invalid {
+ @apply outline outline-offset-0 outline-red-400 dark:outline-red-300
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/skeleton.css b/frontend/packages/kwai-ui/src/css/primevue/skeleton.css
new file mode 100644
index 000000000..e2393cd21
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/skeleton.css
@@ -0,0 +1,11 @@
+.p-skeleton {
+ @apply overflow-hidden bg-surface-200 dark:bg-surface-700 animate-pulse rounded-md
+}
+
+.p-skeleton-circle {
+ @apply rounded-full
+}
+
+.p-skeleton-animation-none::after {
+ @apply animate-none
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/slider.css b/frontend/packages/kwai-ui/src/css/primevue/slider.css
new file mode 100644
index 000000000..ae3b9718b
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/slider.css
@@ -0,0 +1,42 @@
+.p-slider {
+ @apply relative bg-surface-200 dark:bg-surface-700 rounded-sm
+}
+
+.p-slider-handle {
+ @apply cursor-grab touch-none flex items-center justify-center h-[20px] w-[20px]
+ bg-surface-200 dark:bg-surface-700 rounded-full
+ transition-colors duration-200
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+ before:w-[16px] before:h-[16px] before:block before:rounded-full
+ before:bg-surface-0 dark:before:bg-surface-950
+ before:shadow-[0px_0.5px_0px_0px_rgba(0,0,0,0.08),0px_1px_1px_0px_rgba(0,0,0,0.14)]
+ before:transition-colors before:duration-200
+}
+
+.p-slider-range {
+ @apply block bg-primary rounded-sm
+}
+
+.p-slider.p-slider-horizontal {
+ @apply h-[3px]
+}
+
+.p-slider-horizontal .p-slider-range {
+ @apply top-0 start-0 h-full
+}
+
+.p-slider-horizontal .p-slider-handle {
+ @apply top-1/2 -mt-[10px] -ms-[10px]
+}
+
+.p-slider-vertical {
+ @apply min-h-[100px] w-[3px]
+}
+
+.p-slider-vertical .p-slider-handle {
+ @apply start-1/2 -mb-[10px] -ms-[10px]
+}
+
+.p-slider-vertical .p-slider-range {
+ @apply bottom-0 start-0 w-full
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/speeddial.css b/frontend/packages/kwai-ui/src/css/primevue/speeddial.css
new file mode 100644
index 000000000..a9f3c4692
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/speeddial.css
@@ -0,0 +1,48 @@
+@import './button';
+
+.p-speeddial {
+ @apply static flex gap-2
+}
+
+.p-speeddial-button {
+ @apply z-10
+}
+
+.p-speeddial-button.p-speeddial-rotate {
+ @apply [transition:transform_250ms_cubic-bezier(0.4,0,0.2,1)_0ms,background_200ms,color_200ms,border-color_200ms] will-change-transform
+}
+
+.p-speeddial-list {
+ @apply m-0 p-0 list-none flex items-center justify-center pointer-events-none outline-none z-20 gap-2
+ transition-[top] ease-linear duration-200
+}
+
+.p-speeddial-item {
+ @apply scale-0 opacity-0 [transition:transform_200ms_cubic-bezier(0.4,0,0.2,1)_0ms,opacity_0.8s] will-change-transform
+}
+
+.p-speeddial-circle .p-speeddial-item,
+.p-speeddial-semi-circle .p-speeddial-item,
+.p-speeddial-quarter-circle .p-speeddial-item {
+ @apply absolute
+}
+
+.p-speeddial-mask {
+ @apply absolute start-0 top-0 w-full h-full opacity-0 bg-white/40 dark:bg-white/60 rounded-md transition-opacity duration-150
+}
+
+.p-speeddial-mask-visible {
+ @apply pointer-events-none opacity-100 transition-opacity duration-150
+}
+
+.p-speeddial-open .p-speeddial-list {
+ @apply pointer-events-auto
+}
+
+.p-speeddial-open .p-speeddial-item {
+ @apply scale-100 opacity-100
+}
+
+.p-speeddial-open .p-speeddial-rotate {
+ @apply rotate-45
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/splitbutton.css b/frontend/packages/kwai-ui/src/css/primevue/splitbutton.css
new file mode 100644
index 000000000..cf0cd0a49
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/splitbutton.css
@@ -0,0 +1,34 @@
+@import './button';
+@import './tieredmenu';
+
+.p-splitbutton {
+ @apply inline-flex relative rounded-md
+}
+
+.p-splitbutton-button {
+ @apply rounded-e-none border-r-0 enabled:hover:border-r-0 enabled:active:border-r-0 focus-visible:z-10
+}
+
+.p-splitbutton-dropdown {
+ @apply rounded-s-none focus-visible:z-10
+}
+
+.p-splitbutton .p-menu {
+ @apply min-w-full
+}
+
+.p-splitbutton-fluid {
+ @apply w-full
+}
+
+.p-splitbutton-rounded .p-splitbutton-dropdown {
+ @apply rounded-e-[2rem]
+}
+
+.p-splitbutton-rounded .p-splitbutton-button {
+ @apply rounded-s-[2rem]
+}
+
+.p-splitbutton-raised {
+ @apply shadow-[0_3px_1px_-2px_rgba(0,0,0,0.2),0_2px_2px_0_rgba(0,0,0,0.14),0_1px_5px_0_rgba(0,0,0,0.12)]
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/splitter.css b/frontend/packages/kwai-ui/src/css/primevue/splitter.css
new file mode 100644
index 000000000..f6915f564
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/splitter.css
@@ -0,0 +1,56 @@
+.p-splitter {
+ @apply flex flex-wrap
+ border border-surface-200 dark:border-surface-700 rounded-md
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+}
+
+.p-splitter-vertical {
+ @apply flex-col
+}
+
+.p-splitter-gutter {
+ @apply flex-grow-0 flex-shrink-0 flex items-center justify-center z-10 bg-surface-200 dark:bg-surface-700
+}
+
+.p-splitter-gutter-handle {
+ @apply rounded-md bg-transparent
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+ transition-colors duration-200
+}
+
+.p-splitter-horizontal.p-splitter-resizing {
+ @apply cursor-col-resize select-none
+}
+
+.p-splitter-vertical.p-splitter-resizing {
+ @apply cursor-row-resize select-none
+}
+
+.p-splitter-horizontal > .p-splitter-gutter > .p-splitter-gutter-handle {
+ @apply h-[24px] w-full
+}
+
+.p-splitter-vertical > .p-splitter-gutter > .p-splitter-gutter-handle {
+ @apply w-[24px] h-full
+}
+
+.p-splitter-horizontal > .p-splitter-gutter {
+ @apply cursor-col-resize
+}
+
+.p-splitter-vertical > .p-splitter-gutter {
+ @apply cursor-row-resize
+}
+
+.p-splitterpanel {
+ @apply flex-grow overflow-hidden
+}
+
+.p-splitterpanel-nested {
+ @apply flex
+}
+
+.p-splitterpanel .p-splitter {
+ @apply flex-grow border-none
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/stepper.css b/frontend/packages/kwai-ui/src/css/primevue/stepper.css
new file mode 100644
index 000000000..43f44e75e
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/stepper.css
@@ -0,0 +1,102 @@
+.p-steplist {
+ @apply relative flex justify-between items-center m-0 p-0 list-none overflow-x-auto
+}
+
+.p-step {
+ @apply relative flex flex-auto items-center gap-4 p-2 last-of-type:flex-initial
+}
+
+.p-step-header {
+ @apply border-none inline-flex items-center no-underline cursor-pointer
+ transition-colors duration-200 rounded-md bg-transparent p-0 gap-2
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+}
+
+.p-step.p-disabled .p-step-header {
+ @apply cursor-default
+}
+
+
+.p-stepper.p-stepper-readonly .p-step {
+ @apply cursor-auto
+}
+
+.p-step-title {
+ @apply block whitespace-nowrap overflow-hidden text-ellipsis max-w-full
+ text-surface-500 dark:text-surface-400 font-medium transition-colors duration-200
+}
+
+.p-step-number {
+ @apply flex items-center justify-center text-surface-500 dark:text-surface-400
+ bg-surface-0 dark:bg-surface-900 border-2 border-surface-200 dark:border-surface-700
+ min-w-8 h-8 leading-8 text-lg font-medium rounded-full z-10 relative
+ after:absolute after:w-full after:h-full after:rounded-full after:shadow-[0px_0.5px_0px_0px_rgba(0,0,0,0.06),0px_1px_1px_0px_rgba(0,0,0,0.12)]
+}
+
+.p-step-active .p-step-header {
+ @apply cursor-default
+}
+
+.p-step-active .p-step-number {
+ @apply bg-surface-0 dark:bg-surface-900 text-primary border-surface-200 dark:border-surface-700
+}
+
+.p-step-active .p-step-title {
+ @apply text-primary
+}
+
+.p-step:not(.p-disabled):focus-visible {
+ @apply outline outline-1 outline-offset-2 outline-primary
+}
+
+.p-step:has(~ .p-step-active) .p-stepper-separator {
+ @apply bg-primary
+}
+
+.p-stepper-separator {
+ @apply flex-1 bg-surface-200 dark:bg-surface-700 w-full h-[2px] transition-colors duration-200
+}
+
+.p-steppanels {
+ @apply pt-[0.875rem] pb-[1.125rem] px-2
+}
+
+.p-steppanel {
+ @apply bg-surface-0 dark:bg-surface-900 text-surface-700 dark:text-surface-0
+}
+
+.p-stepper:has(.p-stepitem) {
+ @apply flex flex-col
+}
+
+.p-stepitem {
+ @apply flex flex-col flex-initial
+}
+
+.p-stepitem.p-stepitem-active {
+ @apply flex-auto
+}
+
+.p-stepitem .p-step {
+ @apply flex-initial
+}
+
+.p-stepitem .p-steppanel-content {
+ @apply w-full ps-4
+}
+
+.p-stepitem .p-steppanel {
+ @apply flex flex-auto
+}
+
+.p-stepitem .p-stepper-separator {
+ @apply flex-grow-0 flex-shrink-0 basis-auto w-[2px] h-auto ms-[1.625rem] relative start-[-2.5px]
+}
+
+.p-stepitem:has(~ .p-stepitem-active) .p-stepper-separator {
+ @apply bg-primary
+}
+
+.p-stepitem:last-of-type .p-steppanel {
+ @apply ps-8
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/tabs.css b/frontend/packages/kwai-ui/src/css/primevue/tabs.css
new file mode 100644
index 000000000..0ac004ba9
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/tabs.css
@@ -0,0 +1,84 @@
+.p-tabs {
+ @apply flex flex-col
+}
+
+.p-tablist {
+ @apply flex relative
+}
+
+.p-tabs-scrollable > .p-tablist {
+ @apply overflow-hidden
+}
+
+.p-tablist-viewport {
+ @apply overflow-x-auto overflow-y-hidden overscroll-y-contain overscroll-x-auto
+}
+
+.p-tablist-viewport::-webkit-scrollbar {
+ @apply hidden
+}
+
+.p-tablist-tab-list {
+ @apply relative flex bg-surface-0 dark:bg-surface-900 border-b border-surface-200 dark:border-surface-700
+}
+
+.p-tablist-content {
+ @apply flex-grow
+}
+
+.p-tablist-nav-button {
+ @apply !absolute flex-shrink-0 top-0 z-20 h-full flex items-center justify-center cursor-pointer
+ bg-surface-0 dark:bg-surface-900 text-surface-500 dark:text-surface-400 hover:text-surface-700 dark:hover:text-surface-0 w-10
+ shadow-[0px_0px_10px_50px_rgba(255,255,255,0.6)] dark:shadow-[0px_0px_10px_50px] dark:shadow-surface-900/50
+ focus-visible:z-10 focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-[-1px] focus-visible:outline-primary
+ transition-colors duration-200
+}
+
+.p-tablist-prev-button {
+ @apply start-0
+}
+
+.p-tablist-next-button {
+ @apply end-0
+}
+
+.p-tablist-prev-button:dir(rtl),
+.p-tablist-next-button:dir(rtl) {
+ @apply rotate-180
+}
+
+.p-tab {
+ @apply flex-shrink-0 cursor-pointer select-none relative whitespace-nowrap py-4 px-[1.125rem]
+ border-b border-surface-200 dark:border-surface-700 font-semibold
+ text-surface-500 dark:text-surface-400
+ transition-colors duration-200 -mb-px
+}
+
+.p-tab.p-disabled {
+ @apply cursor-default
+}
+
+.p-tab:not(.p-disabled):focus-visible {
+ @apply z-10 outline outline-1 outline-offset-[-1px] outline-primary
+}
+
+.p-tab:not(.p-tab-active):not(.p-disabled):hover {
+ @apply text-surface-700 dark:text-surface-0
+}
+
+.p-tab-active {
+ @apply border-primary text-primary
+}
+
+.p-tabpanels {
+ @apply bg-surface-0 dark:bg-surface-900 text-surface-700 dark:text-surface-0
+ pt-[0.875rem] pb-[1.125rem] px-[1.125rem] outline-none
+}
+
+.p-tablist-active-bar {
+ @apply z-10 block absolute -bottom-px h-px bg-primary transition-[left] duration-200 ease-[cubic-bezier(0.35,0,0.25,1)]
+}
+
+.p-tablist-viewport {
+ @apply [scrollbar-behavior:smooth] [scrollbar-width:none]
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/tag.css b/frontend/packages/kwai-ui/src/css/primevue/tag.css
new file mode 100644
index 000000000..8ef41faa2
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/tag.css
@@ -0,0 +1,38 @@
+.p-tag {
+ @apply inline-flex items-center justify-center
+ bg-primary-100 dark:bg-primary-500/15
+ text-primary-700 dark:text-primary-300
+ text-sm font-bold py-1 px-2 rounded-md gap-1
+}
+
+.p-tag-icon {
+ @apply text-xs w-3 h-3
+}
+
+.p-tag-rounded {
+ @apply rounded-2xl
+}
+
+.p-tag-success {
+ @apply bg-green-100 dark:bg-green-500/15 text-green-700 dark:text-green-300
+}
+
+.p-tag-info {
+ @apply bg-sky-100 dark:bg-sky-500/15 text-sky-700 dark:text-sky-300
+}
+
+.p-tag-warn {
+ @apply bg-orange-100 dark:bg-orange-500/15 text-orange-700 dark:text-orange-300
+}
+
+.p-tag-danger {
+ @apply bg-red-100 dark:bg-red-500/15 text-red-700 dark:text-red-300
+}
+
+.p-tag-secondary {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-600 dark:text-surface-300
+}
+
+.p-tag-contrast {
+ @apply bg-surface-950 dark:bg-surface-0 text-surface-0 dark:text-surface-950
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/tailwind.css b/frontend/packages/kwai-ui/src/css/primevue/tailwind.css
new file mode 100644
index 000000000..7aec51300
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/tailwind.css
@@ -0,0 +1,104 @@
+@import './common';
+
+/* Form */
+@import './autocomplete';
+@import './cascadeselect';
+@import './checkbox';
+@import './colorpicker';
+@import './datepicker';
+@import './iconfield';
+@import './iftalabel';
+@import './inputgroup';
+@import './inputnumber';
+@import './inputotp';
+@import './inputtext';
+@import './floatlabel';
+@import './knob';
+@import './listbox';
+@import './multiselect';
+@import './password';
+@import './radiobutton';
+@import './rating';
+@import './select';
+@import './selectbutton';
+@import './slider';
+@import './textarea';
+@import './togglebutton';
+@import './toggleswitch';
+@import './treeselect';
+
+/* Button */
+@import './button';
+@import './buttongroup';
+@import './speeddial';
+@import './splitbutton';
+
+/* Data */
+@import './datatable';
+@import './dataview';
+@import './paginator';
+@import './picklist';
+@import './orderlist';
+@import './organizationchart';
+@import './timeline';
+@import './tree';
+@import './treetable';
+
+/* Overlay */
+@import './confirmdialog';
+@import './confirmpopup';
+@import './dialog';
+@import './drawer';
+@import './popover';
+@import './tooltip';
+
+/* Menu */
+@import './breadcrumb';
+@import './contextmenu';
+@import './dock';
+@import './menu';
+@import './menubar';
+@import './megamenu';
+@import './panelmenu';
+@import './tieredmenu';
+
+/* Panel */
+@import './accordion';
+@import './card';
+@import './divider';
+@import './fieldset';
+@import './panel';
+@import './scrollpanel';
+@import './splitter';
+@import './stepper';
+@import './tabs';
+@import './toolbar';
+
+/* File */
+@import './fileupload';
+
+/* Message */
+@import './message';
+@import './toast';
+
+/* Media */
+@import './carousel';
+@import './galleria';
+@import './image';
+@import './imagecompare';
+
+/* Misc */
+@import './avatar';
+@import './badge';
+@import './blockui';
+@import './chip';
+@import './inplace';
+@import './metergroup';
+@import './overlaybadge';
+@import './progressbar';
+@import './progressspinner';
+@import './ripple';
+@import './scrolltop';
+@import './skeleton';
+@import './tag';
+@import './terminal';
diff --git a/frontend/packages/kwai-ui/src/css/primevue/terminal.css b/frontend/packages/kwai-ui/src/css/primevue/terminal.css
new file mode 100644
index 000000000..71d107d69
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/terminal.css
@@ -0,0 +1,22 @@
+.p-terminal {
+ @apply h-72 overflow-auto px-3 py-2 rounded-md
+ border border-surface-300 dark:border-surface-700
+ bg-surface-0 dark:bg-surface-950
+ text-surface-700 dark:text-surface-0
+}
+
+.p-terminal-prompt {
+ @apply flex items-center
+}
+
+.p-terminal-prompt-value {
+ @apply flex-auto border-none bg-transparent text-inherit p-0 outline-none text-base
+}
+
+.p-terminal-prompt-label {
+ @apply me-1
+}
+
+.p-terminal-input::-ms-clear {
+ @apply hidden
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/textarea.css b/frontend/packages/kwai-ui/src/css/primevue/textarea.css
new file mode 100644
index 000000000..c5bb8fac5
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/textarea.css
@@ -0,0 +1,38 @@
+.p-textarea {
+ @apply appearance-none rounded-md
+ border border-surface-300 dark:border-surface-700
+ enabled:hover:border-surface-400 dark:enabled:hover:border-surface-600
+ enabled:focus:border-primary
+ bg-surface-0 dark:bg-surface-950
+ text-surface-700 dark:text-surface-0
+ disabled:bg-surface-200 disabled:text-surface-500 disabled:opacity-100 dark:disabled:bg-surface-700 dark:disabled:text-surface-400
+ placeholder:text-surface-500 dark:placeholder:text-surface-400
+ px-3 py-2
+ transition-colors duration-200
+ shadow-[0_1px_2px_0_rgba(18,18,23,0.05)]
+ outline-none
+}
+
+.p-textarea.p-invalid {
+ @apply border-red-400 dark:border-red-300
+}
+
+.p-textarea.p-variant-filled {
+ @apply bg-surface-50 dark:bg-surface-800
+}
+
+.p-textarea-fluid {
+ @apply w-full
+}
+
+.p-textarea-resizable {
+ @apply overflow-hidden resize-none
+}
+
+.p-textarea-sm {
+ @apply text-sm px-[0.625rem] py-[0.375rem]
+}
+
+.p-textarea-lg {
+ @apply text-lg px-[0.875rem] py-[0.625rem]
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/tieredmenu.css b/frontend/packages/kwai-ui/src/css/primevue/tieredmenu.css
new file mode 100644
index 000000000..900dea161
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/tieredmenu.css
@@ -0,0 +1,105 @@
+.p-tieredmenu {
+ @apply bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+ border border-surface-200 dark:border-surface-700
+ rounded-md min-w-52
+}
+
+.p-tieredmenu-root-list,
+.p-tieredmenu-submenu {
+ @apply m-0 p-1 list-none outline-none flex flex-col gap-[2px]
+}
+
+.p-tieredmenu-submenu {
+ @apply absolute min-w-full z-10 rounded-md
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+ border border-surface-200 dark:border-surface-700
+ shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-2px_rgba(0,0,0,0.1)]
+}
+
+.p-tieredmenu-item {
+ @apply relative
+}
+
+.p-tieredmenu-item-content {
+ @apply transition-colors duration-200 rounded-sm text-surface-700 dark:text-surface-0
+}
+
+.p-tieredmenu-item-link {
+ @apply cursor-pointer flex items-center no-underline overflow-hidden relative text-inherit
+ px-3 py-2 gap-2 select-none outline-none
+}
+
+.p-tieredmenu-item-icon {
+ @apply text-surface-400 dark:text-surface-500
+}
+
+.p-tieredmenu-submenu-icon {
+ @apply text-surface-400 dark:text-surface-500 ms-auto text-sm w-[0.875rem] h-[0.875rem]
+}
+
+.p-tieredmenu-item.p-focus > .p-tieredmenu-item-content {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-tieredmenu-item.p-focus > .p-tieredmenu-item-content .p-tieredmenu-item-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-tieredmenu-item.p-focus > .p-tieredmenu-item-content .p-tieredmenu-submenu-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-tieredmenu-item:not(.p-disabled) > .p-tieredmenu-item-content:hover {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-tieredmenu-item:not(.p-disabled) > .p-tieredmenu-item-content:hover .p-tieredmenu-item-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-tieredmenu-item:not(.p-disabled) > .p-tieredmenu-item-content:hover .p-tieredmenu-submenu-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-tieredmenu-item-active > .p-tieredmenu-item-content {
+ @apply bg-surface-100 dark:bg-surface-800 text-surface-800 dark:text-surface-0
+}
+
+.p-tieredmenu-item-active > .p-tieredmenu-item-content .p-tieredmenu-item-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-tieredmenu-item-active > .p-tieredmenu-item-content .p-tieredmenu-submenu-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-tieredmenu-separator {
+ @apply border-t border-surface-200 dark:border-surface-700
+}
+
+.p-tieredmenu-overlay {
+ @apply shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-2px_rgba(0,0,0,0.1)]
+}
+
+.p-tieredmenu-enter-from,
+.p-tieredmenu-leave-active {
+ @apply opacity-0
+}
+
+.p-tieredmenu-enter-active {
+ @apply transition-opacity duration-[250ms]
+}
+
+.p-tieredmenu-mobile .p-tieredmenu-submenu {
+ @apply static shadow-none border-none ps-4 pe-0
+}
+
+.p-tieredmenu-mobile .p-tieredmenu-submenu-icon {
+ @apply transition-transform duration-200 rotate-90
+}
+
+.p-tieredmenu-mobile .p-tieredmenu-item-active > .p-tieredmenu-item-content .p-tieredmenu-submenu-icon {
+ @apply -rotate-90
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/timeline.css b/frontend/packages/kwai-ui/src/css/primevue/timeline.css
new file mode 100644
index 000000000..4d00cd472
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/timeline.css
@@ -0,0 +1,113 @@
+.p-timeline {
+ @apply flex flex-col flex-grow
+}
+
+.p-timeline-left .p-timeline-event-opposite {
+ @apply text-end
+}
+
+.p-timeline-left .p-timeline-event-content {
+ @apply text-start
+}
+
+.p-timeline-right .p-timeline-event {
+ @apply flex-row-reverse
+}
+
+.p-timeline-right .p-timeline-event-opposite {
+ @apply text-start
+}
+
+.p-timeline-right .p-timeline-event-content {
+ @apply text-end
+}
+
+.p-timeline-vertical.p-timeline-alternate .p-timeline-event:nth-child(even) {
+ @apply flex-row-reverse
+}
+
+.p-timeline-vertical.p-timeline-alternate .p-timeline-event:nth-child(odd) .p-timeline-event-opposite {
+ @apply text-end
+}
+
+.p-timeline-vertical.p-timeline-alternate .p-timeline-event:nth-child(odd) .p-timeline-event-content {
+ @apply text-start
+}
+
+.p-timeline-vertical.p-timeline-alternate .p-timeline-event:nth-child(even) .p-timeline-event-opposite {
+ @apply text-start
+}
+
+.p-timeline-vertical.p-timeline-alternate .p-timeline-event:nth-child(even) .p-timeline-event-content {
+ @apply text-end
+}
+
+.p-timeline-vertical .p-timeline-event-opposite,
+.p-timeline-vertical .p-timeline-event-content {
+ @apply py-0 px-4 leading-none
+}
+
+.p-timeline-vertical .p-timeline-event-connector {
+ @apply w-[2px]
+}
+
+.p-timeline-event {
+ @apply flex relative min-h-20 last:min-h-0
+}
+
+.p-timeline-event-opposite {
+ @apply flex-1
+}
+
+.p-timeline-event-content {
+ @apply flex-1
+}
+
+.p-timeline-event-separator {
+ @apply flex-none flex flex-col items-center
+}
+
+.p-timeline-event-marker {
+ @apply inline-flex items-center justify-center relative self-baseline
+ border-2 rounded-full border-surface-200 dark:border-surface-700 w-[1.125rem] h-[1.125rem]
+ bg-surface-0 dark:bg-surface-900
+ before:rounded-full before:w-[0.375rem] before:h-[0.375rem] before:bg-primary
+ after:absolute after:w-full after:h-full after:rounded-full after:shadow-[0px_0.5px_0px_0px_rgba(0,0,0,0.06),0px_1px_1px_0px_rgba(0,0,0,0.12)]
+}
+
+.p-timeline-event-connector {
+ @apply flex-grow bg-surface-200 dark:bg-surface-700
+}
+
+.p-timeline-horizontal {
+ @apply flex-row
+}
+
+.p-timeline-horizontal .p-timeline-event {
+ @apply flex-col flex-1
+}
+
+.p-timeline-horizontal .p-timeline-event:last-child {
+ @apply flex-none
+}
+
+.p-timeline-horizontal .p-timeline-event-separator {
+ @apply flex-row
+}
+
+.p-timeline-horizontal .p-timeline-event-connector {
+ @apply w-full h-[2px]
+}
+
+.p-timeline-horizontal .p-timeline-event-opposite,
+.p-timeline-horizontal .p-timeline-event-content {
+ @apply py-4 px-0
+}
+
+.p-timeline-horizontal.p-timeline-alternate .p-timeline-event:nth-child(even) {
+ @apply flex-col-reverse
+}
+
+.p-timeline-bottom .p-timeline-event {
+ @apply flex-col-reverse
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/toast.css b/frontend/packages/kwai-ui/src/css/primevue/toast.css
new file mode 100644
index 000000000..c2b013f86
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/toast.css
@@ -0,0 +1,172 @@
+.p-toast {
+ @apply w-96 rounded-md whitespace-pre-line break-words
+}
+
+.p-toast-message {
+ @apply mb-4
+}
+
+.p-toast-message-icon {
+ @apply flex-shrink-0 text-lg w-[1.125rem] h-[1.125rem]
+}
+
+.p-toast-message-content {
+ @apply flex items-start p-3 gap-2
+}
+
+.p-toast-message-text {
+ @apply flex-auto flex flex-col gap-2
+}
+
+.p-toast-summary {
+ @apply font-medium text-base
+}
+
+.p-toast-detail {
+ @apply font-medium text-sm
+}
+
+.p-toast-close-button {
+ @apply flex items-center justify-center overflow-hidden relative cursor-pointer bg-transparent select-none
+ transition-colors duration-200 text-inherit w-7 h-7 rounded-full -mt-[25%] -end-1/4 p-0 border-none
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2
+}
+
+.p-toast-close-button:dir(rtl) {
+ @apply ms-auto end-auto
+}
+
+.p-toast-message-info,
+.p-toast-message-success,
+.p-toast-message-warn,
+.p-toast-message-error,
+.p-toast-message-secondary,
+.p-toast-message-contrast {
+ @apply border backdrop-blur-sm dark:backdrop-blur-md rounded-md
+}
+
+.p-toast-close-icon {
+ @apply text-base w-4 h-4
+}
+
+.p-toast-message-info {
+ @apply bg-blue-50/95 border-blue-200 text-blue-600
+ dark:bg-blue-500/15 dark:border-blue-700/35 dark:text-blue-500
+ shadow-[0px_4px_8px_0px_theme(colors.blue.500/0.04)]
+}
+
+.p-toast-message-info .p-toast-detail {
+ @apply text-surface-700 dark:text-surface-0
+}
+
+.p-toast-message-info .p-toast-close-button {
+ @apply hover:bg-blue-100 focus-visible:outline-blue-600
+ dark:hover:bg-white/5 dark:focus-visible:outline-blue-500
+}
+
+.p-toast-message-success {
+ @apply bg-green-50/95 border-green-200 text-green-600
+ dark:bg-green-500/15 dark:border-green-700/35 dark:text-green-500
+ shadow-[0px_4px_8px_0px_theme(colors.green.500/0.04)]
+}
+
+.p-toast-message-success .p-toast-detail {
+ @apply text-surface-700 dark:text-surface-0
+}
+
+.p-toast-message-success .p-toast-close-button {
+ @apply hover:bg-green-100 focus-visible:outline-green-600
+ dark:hover:bg-white/5 dark:focus-visible:outline-green-500
+}
+
+.p-toast-message-warn {
+ @apply bg-yellow-50/95 border-yellow-200 text-yellow-600
+ dark:bg-yellow-500/15 dark:border-yellow-700/35 dark:text-yellow-500
+ shadow-[0px_4px_8px_0px_theme(colors.yellow.500/0.04)]
+}
+
+.p-toast-message-warn .p-toast-detail {
+ @apply text-surface-700 dark:text-surface-0
+}
+
+.p-toast-message-warn .p-toast-close-button {
+ @apply hover:bg-yellow-100 focus-visible:outline-yellow-600
+ dark:hover:bg-white/5 dark:focus-visible:outline-yellow-500
+}
+
+.p-toast-message-error {
+ @apply bg-red-50/95 border-red-200 text-red-600
+ dark:bg-red-500/15 dark:border-red-700/35 dark:text-red-500
+ shadow-[0px_4px_8px_0px_theme(colors.blue.500/0.04)]
+}
+
+.p-toast-message-error .p-toast-detail {
+ @apply text-surface-700 dark:text-surface-0
+}
+
+.p-toast-message-error .p-toast-close-button {
+ @apply hover:bg-red-100 focus-visible:outline-red-600
+ dark:hover:bg-white/5 dark:focus-visible:outline-red-500
+}
+
+.p-toast-message-secondary {
+ @apply bg-surface-100 border-surface-200 text-surface-600
+ dark:bg-surface-800 dark:border-surface-700 dark:text-surface-300
+ shadow-[0px_4px_8px_0px_rgba(0,0,0,0.04)]
+}
+
+.p-toast-message-secondary .p-toast-detail {
+ @apply text-surface-700 dark:text-surface-0
+}
+
+.p-toast-message-secondary .p-toast-close-button {
+ @apply hover:bg-surface-200 focus-visible:outline-surface-600
+ dark:hover:bg-surface-700 dark:focus-visible:outline-surface-300
+}
+
+.p-toast-message-contrast {
+ @apply bg-surface-900 border-surface-950 text-surface-50
+ dark:bg-surface-0 dark:border-surface-100 dark:text-surface-950
+ shadow-[0px_4px_8px_0px_rgba(0,0,0,0.04)]
+}
+
+.p-toast-message-contrast .p-toast-detail {
+ @apply text-surface-0 dark:text-surface-950
+}
+
+.p-toast-message-contrast .p-toast-close-button {
+ @apply hover:bg-surface-800 focus-visible:outline-surface-50
+ dark:hover:bg-surface-100 dark:focus-visible:outline-surface-950
+}
+
+.p-toast-top-center {
+ @apply -translate-x-1/2;
+}
+
+.p-toast-bottom-center {
+ @apply -translate-x-1/2;
+}
+
+.p-toast-center {
+ @apply min-w-[20vw] -translate-x-1/2 -translate-y-1/2
+}
+
+.p-toast-message-enter-from {
+ @apply opacity-0 translate-y-1/2
+}
+
+.p-toast-message-leave-from {
+ @apply max-h-[1000px]
+}
+
+.p-toast .p-toast-message.p-toast-message-leave-to {
+ @apply max-h-0 opacity-0 mb-0 overflow-hidden
+}
+
+.p-toast-message-enter-active {
+ @apply [transition:transform_0.3s,opacity_0.3s]
+}
+
+.p-toast-message-leave-active {
+ @apply [transition:max-height_0.45s_cubic-bezier(0,1,0,1),opacity_0.3s,margin-bottom_0.3s]
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/togglebutton.css b/frontend/packages/kwai-ui/src/css/primevue/togglebutton.css
new file mode 100644
index 000000000..0961add9b
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/togglebutton.css
@@ -0,0 +1,63 @@
+.p-togglebutton {
+ @apply inline-flex items-center justify-center overflow-hidden relative cursor-pointer select-none
+ border border-surface-100 dark:border-surface-950 rounded-md
+ bg-surface-100 dark:bg-surface-950
+ text-surface-500 dark:text-surface-400 text-base font-medium
+ px-4 py-2
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+ disabled:opacity-100 disabled:cursor-default
+ disabled:bg-surface-200 disabled:border-surface-200 disabled:text-surface-500
+ disabled:dark:bg-surface-700 disabled:dark:border-surface-700 disabled:dark:text-surface-400
+ transition-colors duration-300
+ before:bg-transparent before:absolute before:start-1 before:top-1 before:rounded-md before:w-[calc(100%-0.5rem)] before:h-[calc(100%-0.5rem)]
+ before:transition-colors before:duration-200
+}
+
+.p-togglebutton-content {
+ @apply relative inline-flex items-center justify-center gap-2
+}
+
+.p-togglebutton-label,
+.p-togglebutton-icon {
+ @apply relative transition-none
+}
+
+.p-togglebutton.p-togglebutton-checked::before {
+ @apply bg-surface-0 dark:bg-surface-800 shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02),0px_1px_2px_0px_rgba(0,0,0,0.04)]
+}
+
+.p-togglebutton:not(:disabled):not(.p-togglebutton-checked):hover {
+ @apply bg-surface-100 dark:bg-surface-950 text-surface-700 dark:text-surface-300
+}
+
+.p-togglebutton.p-togglebutton-checked {
+ @apply bg-surface-100 dark:bg-surface-950 border-surface-100 dark:border-surface-950 text-surface-900 dark:text-surface-0
+}
+
+.p-togglebutton.p-invalid {
+ @apply border-red-400 dark:border-red-300
+}
+
+.p-togglebutton-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-togglebutton:not(:disabled):not(.p-togglebutton-checked):hover .p-togglebutton-icon {
+ @apply text-surface-700 dark:text-surface-300
+}
+
+.p-togglebutton.p-togglebutton-checked .p-togglebutton-icon {
+ @apply text-surface-900 dark:text-surface-0
+}
+
+.p-togglebutton:disabled .p-togglebutton-icon {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-togglebutton-sm {
+ @apply text-sm px-[0.75rem] py-[0.375rem]
+}
+
+.p-togglebutton-lg {
+ @apply text-lg px-[1.25rem] py-[0.625rem]
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/toggleswitch.css b/frontend/packages/kwai-ui/src/css/primevue/toggleswitch.css
new file mode 100644
index 000000000..ea4a9dc05
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/toggleswitch.css
@@ -0,0 +1,66 @@
+.p-toggleswitch {
+ @apply inline-block w-10 h-6
+}
+
+.p-toggleswitch-input {
+ @apply cursor-pointer disabled:cursor-default appearance-none absolute top-0 start-0 w-full h-full m-0 p-0 opacity-0 z-10 rounded-[30px]
+}
+
+.p-toggleswitch-slider {
+ @apply inline-block w-full h-full rounded-[30px] shadow-[0_1px_2px_0_rgba(18,18,23,0.05)]
+ bg-surface-300 dark:bg-surface-700
+ border border-transparent
+ transition-colors duration-200
+}
+
+.p-toggleswitch-handle {
+ @apply absolute top-1/2 flex justify-center items-center
+ bg-surface-0 dark:bg-surface-400
+ text-surface-500 dark:text-surface-900
+ w-4 h-4 start-1 -mt-2 rounded-full
+ transition-[background,color,left] duration-200
+}
+
+.p-toggleswitch.p-toggleswitch-checked .p-toggleswitch-slider {
+ @apply bg-primary
+}
+
+.p-toggleswitch.p-toggleswitch-checked .p-toggleswitch-handle {
+ @apply bg-surface-0 dark:bg-surface-900 text-primary start-5
+}
+
+.p-toggleswitch:not(.p-disabled):has(.p-toggleswitch-input:hover) .p-toggleswitch-slider {
+ @apply bg-surface-400 dark:bg-surface-600
+}
+
+.p-toggleswitch:not(.p-disabled):has(.p-toggleswitch-input:hover) .p-toggleswitch-handle {
+ @apply bg-surface-0 dark:bg-surface-300 text-surface-700 dark:text-surface-800
+}
+
+.p-toggleswitch:not(.p-disabled):has(.p-toggleswitch-input:hover).p-toggleswitch-checked .p-toggleswitch-slider {
+ @apply bg-primary-emphasis
+}
+
+.p-toggleswitch:not(.p-disabled):has(.p-toggleswitch-input:hover).p-toggleswitch-checked .p-toggleswitch-handle {
+ @apply bg-surface-0 dark:bg-surface-900 text-primary-emphasis
+}
+
+.p-toggleswitch:not(.p-disabled):has(.p-toggleswitch-input:focus-visible) .p-toggleswitch-slider {
+ @apply outline outline-1 outline-offset-2 outline-primary
+}
+
+.p-toggleswitch.p-invalid > .p-toggleswitch-slider {
+ @apply border-red-400 dark:border-red-300
+}
+
+.p-toggleswitch.p-disabled {
+ @apply opacity-100
+}
+
+.p-toggleswitch.p-disabled .p-toggleswitch-slider {
+ @apply bg-surface-200 dark:bg-surface-600
+}
+
+.p-toggleswitch.p-disabled .p-toggleswitch-handle {
+ @apply bg-surface-700 dark:bg-surface-900
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/toolbar.css b/frontend/packages/kwai-ui/src/css/primevue/toolbar.css
new file mode 100644
index 000000000..8c46bd166
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/toolbar.css
@@ -0,0 +1,12 @@
+.p-toolbar {
+ @apply flex items-center justify-between flex-wrap p-3 gap-2
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+ border border-surface-200 dark:border-surface-700 rounded-md
+}
+
+.p-toolbar-start,
+.p-toolbar-center,
+.p-toolbar-end {
+ @apply flex items-center
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/tooltip.css b/frontend/packages/kwai-ui/src/css/primevue/tooltip.css
new file mode 100644
index 000000000..a7aac7224
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/tooltip.css
@@ -0,0 +1,38 @@
+.p-tooltip {
+ @apply absolute hidden max-w-48
+}
+
+.p-tooltip-right,
+.p-tooltip-left {
+ @apply py-0 px-1
+}
+
+.p-tooltip-top,
+.p-tooltip-bottom {
+ @apply py-1 px-0
+}
+
+.p-tooltip-text {
+ @apply whitespace-pre-line break-words bg-surface-700 text-surface-0 py-2 px-3
+ rounded-md shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-2px_rgba(0,0,0,0.1)]
+}
+
+.p-tooltip-arrow {
+ @apply absolute w-0 h-0 border-solid border-transparent
+}
+
+.p-tooltip-right .p-tooltip-arrow {
+ @apply -mt-1 border-[.25rem] border-s-0 border-e-surface-700 rtl:rotate-180
+}
+
+.p-tooltip-left .p-tooltip-arrow {
+ @apply -mt-1 border-[.25rem] border-e-0 border-s-surface-700 rtl:rotate-180
+}
+
+.p-tooltip-top .p-tooltip-arrow {
+ @apply -ms-1 border-[.25rem] border-b-0 border-t-surface-700
+}
+
+.p-tooltip-bottom .p-tooltip-arrow {
+ @apply -ms-1 border-[.25rem] border-t-0 border-b-surface-700
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/tree.css b/frontend/packages/kwai-ui/src/css/primevue/tree.css
new file mode 100644
index 000000000..933f1e196
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/tree.css
@@ -0,0 +1,103 @@
+.p-tree {
+ @apply bg-surface-0 dark:bg-surface-900 text-surface-700 dark:text-surface-0 p-4
+}
+
+.p-tree-root-children,
+.p-tree-node-children {
+ @apply flex flex-col list-none m-0 gap-[2px]
+}
+
+.p-tree-root-children {
+ @apply pt-[2px] pb-0 px-0
+}
+
+.p-tree-node-children {
+ @apply pt-[2px] pe-0 pb-0 ps-4
+}
+
+.p-tree-node {
+ @apply p-0 outline-none
+}
+
+.p-tree-node-content {
+ @apply rounded-md px-2 py-1 flex items-center text-surface-700 dark:text-surface-0 gap-1 transition-colors duration-200
+}
+
+.p-tree-node:focus-visible > .p-tree-node-content {
+ @apply outline outline-1 outline-offset-2 outline-primary
+}
+
+.p-tree-node-content.p-tree-node-selectable:not(.p-tree-node-selected):hover {
+ @apply bg-surface-100 text-surface-700 dark:bg-surface-800 dark:text-surface-0
+}
+
+.p-tree-node-content.p-tree-node-selectable:not(.p-tree-node-selected):hover .p-tree-node-icon {
+ @apply text-surface-600 dark:text-surface-300
+}
+
+.p-tree-node-content.p-tree-node-selected {
+ @apply bg-highlight
+}
+
+.p-tree-node-content.p-tree-node-selected .p-tree-node-toggle-button {
+ @apply text-inherit
+}
+
+.p-tree-node-toggle-button {
+ @apply cursor-pointer select-none inline-flex justify-center rounded-full items-center overflow-hidden relative flex-shrink-0
+ w-7 h-7 p-0 transition-colors duration-200 border-none
+ bg-transparent enabled:hover:bg-surface-100 dark:enabled:hover:bg-surface-800
+ text-surface-500 dark:text-surface-400 enabled:hover:text-surface-600 dark:enabled:hover:text-surface-300
+}
+
+.p-tree-node-content.p-tree-node-selected .p-tree-node-toggle-button:hover {
+ @apply bg-surface-0 dark:bg-surface-900 text-primary
+}
+
+.p-tree-root {
+ @apply overflow-auto
+}
+
+.p-tree-node-selectable {
+ @apply cursor-pointer select-none
+}
+
+.p-tree-node-leaf > .p-tree-node-content .p-tree-node-toggle-button {
+ @apply invisible
+}
+
+.p-tree-node-icon {
+ @apply text-surface-500 dark:text-surface-400 transition-colors duration-200
+}
+
+.p-tree-node-content.p-tree-node-selected .p-tree-node-icon {
+ @apply text-primary
+}
+
+.p-tree-filter {
+ @apply mb-2
+}
+
+.p-tree-filter-input {
+ @apply w-full
+}
+
+.p-tree-loading {
+ @apply relative h-full
+}
+
+.p-tree-loading-icon {
+ @apply text-[2rem] h-8 w-8
+}
+
+.p-tree .p-tree-mask {
+ @apply absolute z-10 flex items-center justify-center
+}
+
+.p-tree-flex-scrollable {
+ @apply flex flex-1 h-full flex-col
+}
+
+.p-tree-flex-scrollable .p-tree-root {
+ @apply flex-1
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/treeselect.css b/frontend/packages/kwai-ui/src/css/primevue/treeselect.css
new file mode 100644
index 000000000..1fd487668
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/treeselect.css
@@ -0,0 +1,112 @@
+@import './chip';
+@import './tree';
+
+.p-treeselect {
+ @apply inline-flex cursor-pointer relative select-none rounded-md
+ bg-surface-0 dark:bg-surface-950
+ border border-surface-300 dark:border-surface-700
+ shadow-[0_1px_2px_0_rgba(18,18,23,0.05)]
+ transition-colors duration-200
+}
+
+.p-treeselect:not(.p-disabled):hover {
+ @apply border-surface-400 dark:border-surface-600
+}
+
+.p-treeselect:not(.p-disabled).p-focus {
+ @apply border-primary
+}
+
+.p-treeselect.p-variant-filled {
+ @apply bg-surface-50 dark:bg-surface-800
+}
+
+.p-treeselect.p-invalid {
+ @apply border-red-400 dark:border-red-300
+}
+
+.p-treeselect.p-disabled {
+ @apply bg-surface-200 text-surface-500 dark:bg-surface-700 dark:text-surface-400 opacity-100 cursor-default
+}
+
+.p-treeselect-dropdown {
+ @apply flex items-center justify-center shrink-0 bg-transparent
+ text-surface-500 dark:text-surface-400 w-10 rounded-e-md
+}
+
+.p-treeselect-label-container {
+ @apply overflow-hidden flex-auto
+}
+
+.p-treeselect-label {
+ @apply flex items-center gap-1 whitespace-nowrap text-ellipsis px-3 py-2 text-surface-700 dark:text-surface-0
+}
+
+.p-treeselect-label.p-placeholder {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-treeselect.p-disabled .p-treeselect-label {
+ @apply text-surface-500 dark:text-surface-400
+}
+
+.p-treeselect-label-empty {
+ @apply overflow-hidden invisible
+}
+
+.p-treeselect .p-treeselect-overlay {
+ @apply min-w-full
+}
+
+.p-treeselect-overlay {
+ @apply absolute top-0 left-0 rounded-md
+ bg-surface-0 dark:bg-surface-900
+ border border-surface-200 dark:border-surface-700
+ text-surface-700 dark:text-surface-0
+ shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1),0_2px_4px_-2px_rgba(0,0,0,0.1)]
+}
+
+
+.p-treeselect-tree-container {
+ @apply overflow-auto
+}
+
+.p-treeselect-empty-message {
+ @apply px-3 py-2
+}
+
+.p-treeselect-fluid {
+ @apply flex
+}
+
+.p-treeselect-overlay .p-tree {
+ @apply p-1
+}
+
+.p-treeselect-overlay .p-tree-loading {
+ @apply min-h-12
+}
+
+.p-treeselect-label .p-chip {
+ @apply pt-1 pb-1 rounded-sm
+}
+
+.p-treeselect-label:has(.p-chip) {
+ @apply py-1 px-1
+}
+
+.p-treeselect-sm .p-treeselect-label {
+ @apply text-sm px-[0.625rem] py-[0.375rem]
+}
+
+.p-treeselect-sm .p-treeselect-dropdown .p-icon {
+ @apply text-sm w-[0.875rem] h-[0.875rem]
+}
+
+.p-treeselect-lg .p-treeselect-label {
+ @apply text-lg px-[0.875rem] py-[0.625rem]
+}
+
+.p-treeselect-lg .p-treeselect-dropdown .p-icon {
+ @apply text-lg w-[1.125rem] h-[1.125rem]
+}
diff --git a/frontend/packages/kwai-ui/src/css/primevue/treetable.css b/frontend/packages/kwai-ui/src/css/primevue/treetable.css
new file mode 100644
index 000000000..a9c014240
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/css/primevue/treetable.css
@@ -0,0 +1,300 @@
+@import './paginator';
+
+.p-treetable {
+ @apply relative
+}
+
+.p-treetable-table {
+ @apply border-spacing-0 w-full
+}
+
+.p-treetable-scrollable > .p-treetable-table-container {
+ @apply relative
+}
+
+.p-treetable-scrollable-table > .p-treetable-thead {
+ @apply top-0 z-10
+}
+
+.p-treetable-scrollable-table > .p-treetable-frozen-tbody {
+ @apply sticky z-10
+}
+
+.p-treetable-scrollable-table>.p-treetable-tfoot {
+ @apply bottom-0 z-10
+}
+
+.p-treetable-scrollable .p-treetable-frozen-column {
+ @apply sticky bg-surface-0 dark:bg-surface-900
+}
+
+.p-treetable-scrollable th.p-treetable-frozen-column {
+ @apply z-10
+}
+
+.p-treetable-scrollable > .p-treetable-table-container > .p-treetable-table > .p-treetable-thead {
+ @apply bg-surface-0 dark:bg-surface-900
+}
+
+.p-treetable-scrollable > .p-treetable-table-container > .p-treetable-table > .p-treetable-tfoot {
+ @apply bg-surface-0 dark:bg-surface-900
+}
+
+.p-treetable-flex-scrollable {
+ @apply flex flex-col h-full
+}
+
+.p-treetable-flex-scrollable > .p-treetable-table-container {
+ @apply flex flex-col flex-1 h-full
+}
+
+.p-treetable-scrollable-table > .p-treetable-tbody > .p-treetable-row-group-header {
+ @apply sticky z-10
+}
+
+.p-treetable-resizable-table > .p-treetable-thead > tr > th,
+.p-treetable-resizable-table > .p-treetable-tfoot > tr > td,
+.p-treetable-resizable-table > .p-treetable-tbody > tr > td {
+ @apply overflow-hidden whitespace-nowrap
+}
+
+.p-treetable-resizable-table > .p-treetable-thead > tr > th.p-treetable-resizable-column:not(.p-treetable-frozen-column) {
+ @apply bg-clip-padding relative
+}
+
+.p-treetable-resizable-table-fit > .p-treetable-thead > tr > th.p-treetable-resizable-column:last-child .p-treetable-column-resizer {
+ @apply hidden
+}
+
+.p-treetable-column-resizer {
+ @apply block absolute top-0 end-0 m-0 w-2 h-full p-0 cursor-col-resize border border-transparent
+}
+
+.p-treetable-column-header-content {
+ @apply flex items-center gap-2
+}
+
+.p-treetable-column-resize-indicator {
+ @apply w-px absolute z-10 hidden bg-primary
+}
+
+.p-treetable-mask {
+ @apply absolute flex items-center justify-center z-20
+}
+
+.p-treetable-paginator-top {
+ @apply border-b border-surface-200 dark:border-surface-700
+}
+
+.p-treetable-paginator-bottom {
+ @apply border-t border-surface-200 dark:border-surface-700
+}
+
+.p-treetable-header {
+ @apply py-3 px-4 border-b border-surface-200 dark:border-surface-700
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+}
+
+.p-treetable-footer {
+ @apply py-3 px-4 border-b border-surface-200 dark:border-surface-700
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+}
+
+.p-treetable-header-cell {
+ @apply py-3 px-4 font-normal text-start transition-colors duration-200
+ border-b border-surface-200 dark:border-surface-700
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+}
+
+.p-treetable-column-title {
+ @apply font-semibold
+}
+
+.p-treetable-tbody > tr {
+ @apply bg-surface-0 dark:bg-surface-900 text-surface-700 dark:text-surface-0 transition-colors duration-200
+}
+
+.p-treetable-tbody > tr > td {
+ @apply text-start py-3 px-4 border-b border-surface-200 dark:border-surface-800
+}
+
+.p-treetable-hoverable .p-treetable-tbody > tr:not(.p-treetable-row-selected):hover {
+ @apply bg-surface-100 text-surface-800 dark:bg-surface-800 dark:text-surface-0
+}
+
+.p-treetable-tbody > tr.p-treetable-row-selected {
+ @apply bg-highlight
+}
+
+.p-treetable-tbody > tr:has(+ .p-treetable-row-selected) > td {
+ @apply border-b-primary-100 dark:border-b-primary-900
+}
+
+.p-treetable-tbody > tr.p-treetable-row-selected > td {
+ @apply border-b-primary-100 dark:border-b-primary-900
+}
+
+.p-treetable-tbody > tr:focus-visible,
+.p-treetable-tbody > tr.p-treetable-contextmenu-row-selected {
+ @apply outline outline-1 -outline-offset-1 outline-primary
+}
+
+.p-treetable-tfoot > tr > td {
+ @apply text-start py-3 px-4 border-b border-surface-200 dark:border-surface-800
+ bg-surface-0 dark:bg-surface-900
+ text-surface-700 dark:text-surface-0
+}
+
+.p-treetable-column-footer {
+ @apply font-semibold
+}
+
+.p-treetable-sortable-column {
+ @apply cursor-pointer select-none focus-visible:outline focus-visible:outline-1 focus-visible:-outline-offset-1 focus-visible:outline-primary
+}
+
+.p-treetable-column-title,
+.p-treetable-sort-icon,
+.p-treetable-sort-badge {
+ @apply align-middle
+}
+
+.p-treetable-sort-icon {
+ @apply text-surface-500 dark:text-surface-400 transition-colors duration-200
+}
+
+.p-treetable-sortable-column:not(.p-treetable-column-sorted):hover {
+ @apply bg-surface-100 text-surface-800 dark:bg-surface-800 dark:text-surface-0
+}
+
+.p-treetable-sortable-column:not(.p-treetable-column-sorted):hover .p-treetable-sort-icon {
+ @apply text-surface-600 dark:text-surface-300
+}
+
+.p-treetable-column-sorted {
+ @apply bg-highlight
+}
+
+.p-treetable-column-sorted .p-treetable-sort-icon {
+ @apply bg-highlight
+}
+
+.p-treetable-hoverable .p-treetable-selectable-row {
+ @apply cursor-pointer
+}
+
+.p-treetable-loading-icon {
+ @apply text-[2rem] w-8 h-8
+}
+
+.p-treetable-gridlines .p-treetable-header {
+ @apply border-t border-x
+}
+
+.p-treetable-gridlines .p-treetable-footer {
+ @apply border-b border-x
+}
+
+.p-treetable-gridlines .p-treetable-paginator-top {
+ @apply border-t border-x
+}
+
+.p-treetable-gridlines .p-treetable-paginator-bottom {
+ @apply border-b border-x
+}
+
+.p-treetable-gridlines .p-treetable-thead > tr > th {
+ @apply border-t border-x last:border
+}
+
+.p-treetable-gridlines .p-treetable-tbody > tr > td {
+ @apply border-t border-s last:border-r
+}
+
+.p-treetable-gridlines .p-treetable-tbody > tr:last-child > td {
+ @apply border-y border-s last:border
+}
+
+.p-treetable-gridlines .p-treetable-tfoot > tr > td {
+ @apply border-y border-s last:border
+}
+
+.p-treetable.p-treetable-gridlines .p-treetable-thead + .p-treetable-tfoot > tr > td {
+ @apply border-b border-s last:border-r
+}
+
+.p-treetable.p-treetable-gridlines:has(.p-treetable-thead):has(.p-treetable-tbody) .p-treetable-tbody > tr > td {
+ @apply border-b border-s last:border-r
+}
+
+.p-treetable.p-treetable-gridlines:has(.p-treetable-tbody):has(.p-treetable-tfoot) .p-treetable-tbody > tr:last-child > td {
+ @apply border-x
+}
+
+.p-treetable.p-treetable-sm .p-treetable-header {
+ @apply py-1 px-2
+}
+
+.p-treetable.p-treetable-sm .p-treetable-thead > tr > th {
+ @apply py-1 px-2
+}
+
+.p-treetable.p-treetable-sm .p-treetable-tbody > tr > td {
+ @apply py-1 px-2
+}
+
+.p-treetable.p-treetable-sm .p-treetable-tfoot > tr > td {
+ @apply py-1 px-2
+}
+
+.p-treetable.p-treetable-sm .p-treetable-footer {
+ @apply py-1 px-2
+}
+
+.p-treetable.p-treetable-lg .p-treetable-header {
+ @apply py-4 px-5
+}
+
+.p-treetable.p-treetable-lg .p-treetable-thead > tr > th {
+ @apply py-4 px-5
+}
+
+.p-treetable.p-treetable-lg .p-treetable-tbody>tr>td {
+ @apply py-4 px-5
+}
+
+.p-treetable.p-treetable-lg .p-treetable-tfoot>tr>td {
+ @apply py-4 px-5
+}
+
+.p-treetable.p-treetable-lg .p-treetable-footer {
+ @apply py-4 px-5
+}
+
+.p-treetable-body-cell-content {
+ @apply flex items-center gap-2
+}
+
+.p-treetable-tbody > tr.p-treetable-row-selected .p-treetable-node-toggle-button {
+ @apply text-inherit
+}
+
+.p-treetable-node-toggle-button {
+ @apply inline-flex items-center justify-center overflow-hidden relative select-none
+ transition-colors duration-200 w-7 h-7 rounded-full border-none bg-transparent cursor-pointer
+ enabled:hover:bg-surface-100 dark:enabled:hover:bg-surface-900
+ text-surface-500 dark:text-surface-400 enabled:hover:text-surface-700 dark:enabled:hover:text-surface-0
+ focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-primary
+
+}
+
+.p-treetable-tbody > tr.p-treetable-row-selected .p-treetable-node-toggle-button:hover {
+ @apply bg-surface-0 dark:bg-surface-900 text-primary
+}
+
+.p-treetable-node-toggle-icon:dir(rtl) {
+ @apply rotate-180
+}
diff --git a/frontend/packages/kwai-ui/src/form/Button.vue b/frontend/packages/kwai-ui/src/form/Button.vue
deleted file mode 100644
index 41450a016..000000000
--- a/frontend/packages/kwai-ui/src/form/Button.vue
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
-
-
-
diff --git a/frontend/packages/kwai-ui/src/form/KwaiButton.vue b/frontend/packages/kwai-ui/src/form/KwaiButton.vue
index fab4f1fb5..4057257be 100644
--- a/frontend/packages/kwai-ui/src/form/KwaiButton.vue
+++ b/frontend/packages/kwai-ui/src/form/KwaiButton.vue
@@ -2,46 +2,45 @@
-
-
-
diff --git a/frontend/packages/kwai-ui/src/form/KwaiButtonGroup.vue b/frontend/packages/kwai-ui/src/form/KwaiButtonGroup.vue
index e9a19e4a7..4a1496721 100644
--- a/frontend/packages/kwai-ui/src/form/KwaiButtonGroup.vue
+++ b/frontend/packages/kwai-ui/src/form/KwaiButtonGroup.vue
@@ -1,6 +1,10 @@
@@ -8,3 +12,17 @@ import ButtonGroup from 'primevue/buttongroup';
+
+
diff --git a/frontend/packages/kwai-ui/src/form/KwaiCheckbox.vue b/frontend/packages/kwai-ui/src/form/KwaiCheckbox.vue
index 1dd0c869e..6037df9f2 100644
--- a/frontend/packages/kwai-ui/src/form/KwaiCheckbox.vue
+++ b/frontend/packages/kwai-ui/src/form/KwaiCheckbox.vue
@@ -1,25 +1,34 @@
-
-
-
+
+
diff --git a/frontend/packages/kwai-ui/src/form/KwaiCheckboxField.vue b/frontend/packages/kwai-ui/src/form/KwaiCheckboxField.vue
new file mode 100644
index 000000000..a7dcae4ad
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/form/KwaiCheckboxField.vue
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ errorMessage }}
+
+
+
diff --git a/frontend/packages/kwai-ui/src/form/DatePicker.vue b/frontend/packages/kwai-ui/src/form/KwaiDatePicker.vue
similarity index 61%
rename from frontend/packages/kwai-ui/src/form/DatePicker.vue
rename to frontend/packages/kwai-ui/src/form/KwaiDatePicker.vue
index 2a3d6d8bc..77fc21e67 100644
--- a/frontend/packages/kwai-ui/src/form/DatePicker.vue
+++ b/frontend/packages/kwai-ui/src/form/KwaiDatePicker.vue
@@ -2,34 +2,31 @@
import { toRef, useSlots } from 'vue';
import { useField } from 'vee-validate';
import RequiredIcon from '../icons/RequiredIcon.vue';
-import VueDatePicker from '@vuepic/vue-datepicker';
-import '@vuepic/vue-datepicker/dist/main.css';
-import { createFromDate } from '@kwai/date';
+import DatePicker from 'primevue/datepicker';
-const props = defineProps<{
+interface Props {
name: string,
- id?: string,
+ id?: string | null,
placeholder?: string
format?: string
time?: boolean
required?: boolean
-}>();
+}
+
+const props = withDefaults(
+ defineProps(),
+ {
+ id: null,
+ placeholder: '',
+ format: 'dd-mm-yy',
+ time: false,
+ required: false,
+ }
+);
const slots = useSlots();
const nameRef = toRef(props, 'name');
const { value, errorMessage } = useField(nameRef);
-
-const format = (date: Date | null) : string => {
- if (date) {
- const formatString = props.format ?? (props.time ? 'L LTS' : 'L');
- try {
- return createFromDate(date).format(formatString);
- } catch (e) {
- console.log(e);
- }
- }
- return '';
-};
@@ -45,13 +42,13 @@ const format = (date: Date | null) : string => {
class="ml-1 w-2 h-2 -mt-4 fill-black"
/>
-
(), {
id: undefined,
placeholder: '',
+ format: 'dd-mm-yy',
partial: true,
required: false,
time: false,
@@ -26,17 +27,6 @@ const slots = useSlots();
const nameRef = toRef(props, 'name');
const { value, errorMessage } = useField(nameRef);
-
-const format = (dates: Date[]) : string => {
- const format = props.time ? 'L LTS' : 'L';
- let formattedRange = createFromDate(dates[0]).format(format);
- if (dates.length === 2) {
- if (dates[1]) {
- formattedRange += ' - ' + createFromDate(dates[1]).format(format);
- }
- }
- return formattedRange;
-};
@@ -52,16 +42,15 @@ const format = (dates: Date[]) : string => {
class="ml-1 w-2 h-2 -mt-4 fill-black"
/>
-
+import { toRef, useSlots } from 'vue';
+import { useField } from 'vee-validate';
+import RequiredIcon from '../icons/RequiredIcon.vue';
+import InputText from 'primevue/inputtext';
+import Password from 'primevue/password';
+
+const props = defineProps<{
+ name: string,
+ type?: string,
+ id?: string,
+ placeholder?: string
+ required?: boolean
+}>();
+const slots = useSlots();
+
+const nameRef = toRef(props, 'name');
+const { value, errorMessage } = useField(nameRef);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ errorMessage }}
+
+
+
+
diff --git a/frontend/packages/kwai-ui/src/form/KwaiSlider.vue b/frontend/packages/kwai-ui/src/form/KwaiSlider.vue
new file mode 100644
index 000000000..8c2b94a7a
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/form/KwaiSlider.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ errorMessage }}
+
+
+
diff --git a/frontend/packages/kwai-ui/src/form/KwaiTextarea.vue b/frontend/packages/kwai-ui/src/form/KwaiTextarea.vue
new file mode 100644
index 000000000..01ae1142b
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/form/KwaiTextarea.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ errorMessage }}
+
+
+
diff --git a/frontend/packages/kwai-ui/src/form/TimePicker.vue b/frontend/packages/kwai-ui/src/form/KwaiTimePicker.vue
similarity index 61%
rename from frontend/packages/kwai-ui/src/form/TimePicker.vue
rename to frontend/packages/kwai-ui/src/form/KwaiTimePicker.vue
index 1936baf7f..e86762953 100644
--- a/frontend/packages/kwai-ui/src/form/TimePicker.vue
+++ b/frontend/packages/kwai-ui/src/form/KwaiTimePicker.vue
@@ -1,24 +1,19 @@
@@ -34,14 +29,12 @@ const format = computed(() => props.format ?? 'HH:mm');
class="ml-1 w-2 h-2 -mt-4 fill-black"
/>
-
-import { toRef, useSlots } from 'vue';
-import { useField } from 'vee-validate';
-
-const props = defineProps<{
- name: string,
- id?: string,
- min?: number,
- max?: number,
- type?: string,
- required?: boolean
-}>();
-const slots = useSlots();
-
-const nameRef = toRef(props, 'name');
-const { value, errorMessage } = useField(nameRef);
-if (value.value == null) {
- value.value = 0;
-}
-
-
-
-
-
-
-
-
-
-
-
-
- {{ errorMessage }}
-
-
-
-
-
diff --git a/frontend/packages/kwai-ui/src/form/index.ts b/frontend/packages/kwai-ui/src/form/index.ts
index a0cfb2b23..3d7558e39 100644
--- a/frontend/packages/kwai-ui/src/form/index.ts
+++ b/frontend/packages/kwai-ui/src/form/index.ts
@@ -2,18 +2,20 @@ export { default as FormSectionHeader } from './FormSectionHeader.vue';
export { default as FormSectionFields } from './FormSectionFields.vue';
export { default as FormSection } from './FormSection.vue';
export { default as ButtonGroup } from './ButtonGroup.vue';
-export { default as Button } from './Button.vue';
-export { default as RangeSlider } from './RangeSlider.vue';
+export { default as KwaiSlider } from './KwaiSlider.vue';
export type { Option } from './SelectOption.vue';
export { default as SelectOption } from './SelectOption.vue';
export { default as TextareaField } from './TextareaField.vue';
export { default as InputField } from './InputField.vue';
-export { default as DateRangePicker } from './DateRangePicker.vue';
-export { default as DatePicker } from './DatePicker.vue';
+export { default as KwaiDateRangePicker } from './KwaiDateRangePicker.vue';
+export { default as KwaiDatePicker } from './KwaiDatePicker.vue';
export type { TimeModel } from '@vuepic/vue-datepicker';
-export { default as TimePicker } from './TimePicker.vue';
+export { default as KwaiTimePicker } from './KwaiTimePicker.vue';
export { default as CheckBox } from './CheckBox.vue';
export { default as KwaiButton } from './KwaiButton.vue';
export { default as KwaiButtonGroup } from './KwaiButtonGroup.vue';
export { default as KwaiCheckbox } from './KwaiCheckbox.vue';
+export { default as KwaiCheckboxField } from './KwaiCheckboxField.vue';
+export { default as KwaiInputField } from './KwaiInputField.vue';
export { default as KwaiFileUpload } from './KwaiFileUpload.vue';
+export { default as KwaiTextarea } from './KwaiTextarea.vue';
diff --git a/frontend/packages/kwai-ui/src/index.css b/frontend/packages/kwai-ui/src/index.css
index b5c61c956..6f5543ccc 100644
--- a/frontend/packages/kwai-ui/src/index.css
+++ b/frontend/packages/kwai-ui/src/index.css
@@ -1,3 +1,5 @@
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
+/* Use @import */
+@import "tailwindcss/base";
+@import "tailwindcss/components";
+@import "./css/primevue/tailwind.css";
+@import "tailwindcss/utilities";
diff --git a/frontend/packages/kwai-ui/src/index.ts b/frontend/packages/kwai-ui/src/index.ts
index 74f964011..50e4256d3 100644
--- a/frontend/packages/kwai-ui/src/index.ts
+++ b/frontend/packages/kwai-ui/src/index.ts
@@ -1,7 +1,7 @@
-import './index.css';
import { App } from 'vue';
-import Kwai from './presets/kwai';
import PrimeVue from 'primevue/config';
+import './index.css';
+
export type { MenuItem } from './types';
export * from './alerts';
export * from './badges';
@@ -13,8 +13,9 @@ export type * from './form';
export * from './layout';
export * from './nav';
export * from './section';
+export * from './table';
export * from './validations';
export const init = (app: App) => {
- app.use(PrimeVue, { unstyled: true, pt: Kwai });
+ app.use(PrimeVue, { theme: 'none' });
};
diff --git a/frontend/packages/kwai-ui/src/nav/KwaiMenubar.vue b/frontend/packages/kwai-ui/src/nav/KwaiMenubar.vue
new file mode 100644
index 000000000..1e91ebf56
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/nav/KwaiMenubar.vue
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+ {{ item.label }}
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
diff --git a/frontend/packages/kwai-ui/src/nav/LinkTag.vue b/frontend/packages/kwai-ui/src/nav/LinkTag.vue
index 44e01b645..deb146c50 100644
--- a/frontend/packages/kwai-ui/src/nav/LinkTag.vue
+++ b/frontend/packages/kwai-ui/src/nav/LinkTag.vue
@@ -18,6 +18,7 @@ const click = computed(() => props.method ? 'click' : null);
:is="tag"
:to="route"
:href="url"
+ class="cursor-pointer"
@[click]="method"
>
diff --git a/frontend/packages/kwai-ui/src/nav/ToolbarMenu.vue b/frontend/packages/kwai-ui/src/nav/ToolbarMenu.vue
deleted file mode 100644
index c5212a35f..000000000
--- a/frontend/packages/kwai-ui/src/nav/ToolbarMenu.vue
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
-
-
-
-
-
diff --git a/frontend/packages/kwai-ui/src/nav/ToolbarMenuItem.vue b/frontend/packages/kwai-ui/src/nav/ToolbarMenuItem.vue
deleted file mode 100644
index 6418c5526..000000000
--- a/frontend/packages/kwai-ui/src/nav/ToolbarMenuItem.vue
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
- {{ menuItem.title }}
-
-
-
-
-
diff --git a/frontend/packages/kwai-ui/src/nav/index.ts b/frontend/packages/kwai-ui/src/nav/index.ts
index d7740bfbe..a745c4997 100644
--- a/frontend/packages/kwai-ui/src/nav/index.ts
+++ b/frontend/packages/kwai-ui/src/nav/index.ts
@@ -1,9 +1,8 @@
export { useSidebar } from './useSidebar';
export { default as Sidebar } from './Sidebar.vue';
-export { default as ToolbarMenuItem } from './ToolbarMenuItem.vue';
-export { default as ToolbarMenu } from './ToolbarMenu.vue';
export { useMenu } from './useMenu';
export { default as ToolbarLogo } from './ToolbarLogo.vue';
export { default as LinkTag } from './LinkTag.vue';
export { default as OffsetPagination } from './OffsetPagination.vue';
export { usePagination } from './usePagination';
+export { default as KwaiMenubar } from './KwaiMenubar.vue';
diff --git a/frontend/packages/kwai-ui/src/nav/useMenu.ts b/frontend/packages/kwai-ui/src/nav/useMenu.ts
index fb3c156c0..8a3a28eab 100644
--- a/frontend/packages/kwai-ui/src/nav/useMenu.ts
+++ b/frontend/packages/kwai-ui/src/nav/useMenu.ts
@@ -1,6 +1,6 @@
import { useRouter } from 'vue-router';
import { computed } from 'vue';
-import { MenuItem } from '../../dist';
+import { MenuItem } from '../types';
/**
* A composable that returns a MenuItem array based on the routes.
@@ -11,14 +11,32 @@ export const useMenu = () => {
return computed((): MenuItem[] => {
const result: MenuItem[] = [];
+ const routeOrder: Record = {};
+ let rank = 0;
+ for (const route of router.options.routes[0].children || []) {
+ if (!route.name) continue;
+ routeOrder[route.name as string] = rank++;
+ }
+ const routes = [];
for (const route of router.getRoutes()) {
if (route.meta.title) {
- result.push({
- title: route.meta.title as string,
- route,
- });
+ routes.push(route);
}
}
+ routes.sort((a, b) => {
+ const menuA = routeOrder[a.name as string];
+ const menuB = routeOrder[b.name as string];
+ if (menuA < menuB) return -1;
+ if (menuA > menuB) return 1;
+ return 0;
+ });
+ for (const route of routes) {
+ result.push({
+ title: route.meta.title as string,
+ route,
+ disabled: false,
+ });
+ }
return result;
});
};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/accordion/index.js b/frontend/packages/kwai-ui/src/presets/kwai/accordion/index.js
deleted file mode 100644
index 24fcb5063..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/accordion/index.js
+++ /dev/null
@@ -1,78 +0,0 @@
-export default {
- accordiontab: {
- root: {
- class: 'mb-1'
- },
- header: ({ props }) => ({
- class: [
- // State
- { 'select-none pointer-events-none cursor-default opacity-60': props?.disabled }
- ]
- }),
- headerAction: ({ context }) => ({
- class: [
- //Font
- 'font-bold',
- 'leading-none',
-
- // Alignments
- 'flex items-center',
- 'relative',
-
- // Sizing
- 'p-5',
-
- // Shape
- 'rounded-t-md',
- { 'rounded-br-md rounded-bl-md': !context.active, 'rounded-br-0 rounded-bl-0': context.active },
-
- // Color
- 'border border-surface-200 dark:border-surface-700',
- 'bg-surface-50 dark:bg-surface-800',
- 'text-surface-600 dark:text-surface-0/80',
- { 'text-surface-900': context.active },
-
- // Transition
- 'transition duration-200 ease-in-out',
- 'transition-shadow duration-200',
-
- // States
- 'hover:bg-surface-100 dark:hover:bg-surface-700/40',
- 'hover:text-surface-900',
- 'focus:outline-none focus:outline-offset-0 focus-visible:ring focus-visible:ring-primary-400/50 ring-inset dark:focus-visible:ring-primary-300/50', // Focus
-
- // Misc
- 'cursor-pointer no-underline select-none'
- ]
- }),
- headerIcon: {
- class: 'inline-block mr-2'
- },
- headerTitle: {
- class: 'leading-none'
- },
- content: {
- class: [
- // Spacing
- 'p-5',
-
- //Shape
- 'rounded-tl-none rounded-tr-none rounded-br-lg rounded-bl-lg',
- 'border-t-0',
-
- // Color
- 'bg-surface-0 dark:bg-surface-800',
- 'border border-surface-200 dark:border-surface-700',
- 'text-surface-700 dark:text-surface-0/80'
- ]
- },
- transition: {
- enterFromClass: 'max-h-0',
- enterActiveClass: 'overflow-hidden transition-[max-height] duration-1000 ease-[cubic-bezier(0.42,0,0.58,1)]',
- enterToClass: 'max-h-[1000px]',
- leaveFromClass: 'max-h-[1000px]',
- leaveActiveClass: 'overflow-hidden transition-[max-height] duration-[450ms] ease-[cubic-bezier(0,1,0,1)]',
- leaveToClass: 'max-h-0'
- }
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/autocomplete/index.js b/frontend/packages/kwai-ui/src/presets/kwai/autocomplete/index.js
deleted file mode 100644
index d45e7f240..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/autocomplete/index.js
+++ /dev/null
@@ -1,259 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- 'relative',
-
- // Flex
- 'inline-flex',
-
- // Size
- { 'w-full': props.multiple },
-
- // Color
- 'text-surface-900 dark:text-surface-0',
-
- //States
- {
- 'opacity-60 select-none pointer-events-none cursor-default': props.disabled
- }
- ]
- }),
- container: ({ props, state }) => ({
- class: [
- // Font
- 'font-sans text-base leading-none',
-
- // Flex
- 'flex items-center flex-wrap',
- 'gap-2',
-
- // Spacing
- 'm-0 list-none',
- 'px-3 py-1.5',
-
- // Size
- 'w-full',
- 'min-h-[2.877rem]',
-
- // Shape
- 'appearance-none rounded-md',
-
- // Color
- 'text-surface-700 dark:text-white/80',
- 'placeholder:text-surface-400 dark:placeholder:text-surface-500',
- 'bg-surface-0 dark:bg-surface-900',
- 'border',
- { 'border-surface-300 dark:border-surface-600': !props.invalid },
-
- // Invalid State
- { 'border-red-500 dark:border-red-400': props.invalid },
-
- // States
- { 'hover:border-primary-500 dark:hover:border-primary-400': !props.invalid },
- 'focus:outline-none focus:outline-offset-0',
- { 'ring ring-primary-400/50 dark:ring-primary-300/50': state.focused },
- { 'ring ring-primary-400/50 dark:ring-primary-300/50': state.hovered },
- // Transition
- 'transition duration-200 ease-in-out',
-
- // Misc
- 'cursor-text overflow-hidden'
- ]
- }),
- inputtoken: {
- class: ['py-1.5 px-0', 'inline-flex flex-auto']
- },
- input: ({ props }) => ({
- class: [
- // Font
- 'font-sans text-base leading-none',
-
- // Shape
- 'appearance-none rounded-md',
- { 'rounded-tr-none rounded-br-none': props.dropdown },
- { 'outline-none shadow-none rounded-none': props.multiple },
-
- // Size
- { 'w-full': props.multiple },
-
- // Spacing
- 'm-0',
- { 'p-3': !props.multiple, 'p-0': props.multiple },
-
- // Colors
- 'text-surface-700 dark:text-white/80',
- 'border',
- {
- 'bg-surface-0 dark:bg-surface-900': !props.multiple,
- ' border-surface-300 dark:border-surface-700': !props.multiple && !props.invalid,
- 'border-0 bg-transparent': props.multiple
- },
-
- // Invalid State
- { 'border-red-500 dark:border-red-400': props.invalid },
-
- // States
- { 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50': !props.multiple },
-
- // Transition
- 'transition-colors duration-200'
- ]
- }),
- token: {
- class: [
- // Flex
- 'inline-flex items-center',
-
- // Spacings
- 'py-1.5 px-3',
-
- // Shape
- 'rounded-[1.14rem]',
-
- // Colors
- 'bg-surface-200 dark:bg-surface-700',
- 'text-surface-700 dark:text-white/70',
-
- // Misc
- 'cursor-default'
- ]
- },
- label: {
- class: 'leading-5'
- },
- removeTokenIcon: {
- class: [
- // Shape
- 'rounded-md leading-6',
-
- // Spacing
- 'ml-2',
-
- // Size
- 'w-4 h-4',
-
- // Transition
- 'transition duration-200 ease-in-out',
-
- // Misc
- 'cursor-pointer'
- ]
- },
- dropdownbutton: {
- root: {
- class: [
- 'relative',
-
- // Alignments
- 'items-center inline-flex text-center align-bottom',
-
- // Shape
- 'rounded-r-md',
-
- // Size
- 'px-4 py-3 leading-none',
-
- // Colors
- 'text-white dark:text-surface-900',
- 'bg-primary-500 dark:bg-primary-400',
- 'border border-primary-500 dark:border-primary-400',
-
- // States
- 'focus:outline-none focus:outline-offset-0 focus:ring',
- 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50'
- ]
- }
- },
- loadingicon: {
- class: ['text-surface-500 dark:text-surface-0/70', 'absolute top-[50%] right-[0.5rem] -mt-2 animate-spin']
- },
- panel: {
- class: [
- // Colors
- 'bg-surface-0 dark:bg-surface-800',
- 'text-surface-700 dark:text-white/80',
-
- // Shape
- 'border-0',
- 'rounded-md',
- 'shadow-md',
-
- // Size
- 'max-h-[200px] overflow-auto'
- ]
- },
- list: {
- class: 'py-3 px-0 list-none m-0'
- },
- item: ({ context }) => ({
- class: [
- 'relative',
-
- // Font
- 'font-normal text-base leading-none',
-
- // Spacing
- 'm-0 px-5 py-3',
-
- // Shape
- 'border-0 rounded-none',
-
- // Colors
- {
- 'text-surface-700 dark:text-white/80': !context.focused && !context.selected,
- 'bg-surface-200 dark:bg-surface-600/60': context.focused && !context.selected,
- 'text-surface-700 dark:text-white/80': context.focused && !context.selected,
-
- 'text-primary-700 dark:text-white/80': context.focused && context.selected,
- 'bg-primary-100 dark:bg-primary-400': context.focused && context.selected,
- 'text-primary-700 dark:text-white/80': !context.focused && context.selected,
- 'bg-primary-50 dark:bg-primary-300': !context.focused && context.selected
- },
-
- //States
- { 'hover:bg-surface-100 dark:hover:bg-surface-600/80': !context.focused && !context.selected },
- { 'hover:text-surface-700 hover:bg-surface-100 dark:hover:text-white dark:hover:bg-surface-600/80': context.focused && !context.selected },
-
- // Transition
- 'transition-shadow duration-200',
-
- // Misc
- 'cursor-pointer overflow-hidden whitespace-nowrap'
- ]
- }),
- itemgroup: {
- class: [
- 'font-bold',
-
- // Spacing
- 'm-0 p-3',
-
- // Colors
- 'bg-surface-0 dark:bg-surface-700',
- 'text-surface-800 dark:text-white/80',
-
- // Misc
- 'cursor-auto'
- ]
- },
- emptymessage: {
- class: [
- // Font
- 'leading-none',
-
- // Spacing
- 'py-3 px-5',
-
- // Color
- 'text-surface-800 dark:text-white/80',
- 'bg-transparent'
- ]
- },
- transition: {
- enterFromClass: 'opacity-0 scale-y-[0.8]',
- enterActiveClass: 'transition-[transform,opacity] duration-[120ms] ease-[cubic-bezier(0,0,0.2,1)]',
- leaveActiveClass: 'transition-opacity duration-100 ease-linear',
- leaveToClass: 'opacity-0'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/avatar/index.js b/frontend/packages/kwai-ui/src/presets/kwai/avatar/index.js
deleted file mode 100644
index 9c77beb98..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/avatar/index.js
+++ /dev/null
@@ -1,43 +0,0 @@
-export default {
- root: ({ props, parent }) => ({
- class: [
- // Font
- {
- 'text-xl': props.size == 'large',
- 'text-2xl': props.size == 'xlarge'
- },
-
- // Alignments
- 'inline-flex items-center justify-center',
- 'relative',
-
- // Sizes
- {
- 'h-8 w-8': props.size == null || props.size == 'normal',
- 'w-12 h-12': props.size == 'large',
- 'w-16 h-16': props.size == 'xlarge'
- },
- { '-ml-4': parent.instance.$style?.name == 'avatargroup' },
-
- // Shapes
- {
- 'rounded-lg': props.shape == 'square',
- 'rounded-full': props.shape == 'circle'
- },
- { 'border-2': parent.instance.$style?.name == 'avatargroup' },
-
- // Colors
- 'bg-surface-300 dark:bg-surface-700',
- { 'border-white dark:border-surface-800': parent.instance.$style?.name == 'avatargroup' }
- ]
- }),
- image: ({ props }) => ({
- class: [
- 'h-full w-full',
- {
- 'rounded-lg': props.shape == 'square',
- 'rounded-full': props.shape == 'circle'
- }
- ]
- })
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/badge/index.js b/frontend/packages/kwai-ui/src/presets/kwai/badge/index.js
deleted file mode 100644
index 513562c8a..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/badge/index.js
+++ /dev/null
@@ -1,43 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- // Font
- 'font-bold',
-
- {
- 'text-xs leading-[1.5rem]': props.size == null,
- 'text-lg leading-[2.25rem]': props.size == 'large',
- 'text-2xl leading-[3rem]': props.size == 'xlarge'
- },
-
- // Alignment
- 'text-center inline-block',
-
- // Size
- 'p-0 px-1',
- {
- 'min-w-[1.5rem] h-[1.5rem]': props.size == null,
- 'min-w-[2.25rem] h-[2.25rem]': props.size == 'large',
- 'min-w-[3rem] h-[3rem]': props.size == 'xlarge'
- },
-
- // Shape
- {
- 'rounded-full': props.value.length == 1,
- 'rounded-[0.71rem]': props.value.length !== 1
- },
-
- // Color
- 'text-white dark:text-surface-900',
- {
- 'bg-primary-500 dark:bg-primary-400': props.severity == null || props.severity == 'primary',
- 'bg-surface-500 dark:bg-surface-400': props.severity == 'secondary',
- 'bg-green-500 dark:bg-green-400': props.severity == 'success',
- 'bg-blue-500 dark:bg-blue-400': props.severity == 'info',
- 'bg-orange-500 dark:bg-orange-400': props.severity == 'warning',
- 'bg-purple-500 dark:bg-purple-400': props.severity == 'help',
- 'bg-red-500 dark:bg-red-400': props.severity == 'danger'
- }
- ]
- })
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/badgedirective/index.js b/frontend/packages/kwai-ui/src/presets/kwai/badgedirective/index.js
deleted file mode 100644
index 4c25273d4..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/badgedirective/index.js
+++ /dev/null
@@ -1,43 +0,0 @@
-export default {
- root: ({ context }) => ({
- class: [
- // Font
- 'font-bold font-sans',
- 'text-xs leading-5',
-
- // Alignment
- 'flex items-center justify-center',
- 'text-center',
-
- // Position
- 'absolute top-0 right-0 transform translate-x-1/2 -translate-y-1/2 origin-top-right',
-
- // Size
- 'm-0',
- {
- 'p-0': context.nogutter || context.dot,
- 'px-2': !context.nogutter && !context.dot,
- 'min-w-[0.5rem] w-2 h-2': context.dot,
- 'min-w-[1.5rem] h-6': !context.dot
- },
-
- // Shape
- {
- 'rounded-full': context.nogutter || context.dot,
- 'rounded-[10px]': !context.nogutter && !context.dot
- },
-
- // Color
- 'text-white dark:text-surface-900',
- {
- 'bg-primary-500 dark:bg-primary-400': !context.info && !context.success && !context.warning && !context.danger && !context.help && !context.secondary,
- 'bg-surface-500 dark:bg-surface-400': context.secondary,
- 'bg-green-500 dark:bg-green-400': context.success,
- 'bg-blue-500 dark:bg-blue-400': context.info,
- 'bg-orange-500 dark:bg-orange-400': context.warning,
- 'bg-purple-500 dark:bg-purple-400': context.help,
- 'bg-red-500 dark:bg-red-400': context.danger
- }
- ]
- })
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/blockui/index.js b/frontend/packages/kwai-ui/src/presets/kwai/blockui/index.js
deleted file mode 100644
index 0c81a0c93..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/blockui/index.js
+++ /dev/null
@@ -1,8 +0,0 @@
-export default {
- root: {
- class: 'relative'
- },
- mask: {
- class: 'bg-black/40'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/breadcrumb/index.js b/frontend/packages/kwai-ui/src/presets/kwai/breadcrumb/index.js
deleted file mode 100644
index 81b23fd0d..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/breadcrumb/index.js
+++ /dev/null
@@ -1,64 +0,0 @@
-export default {
- root: {
- class: [
- // Shape
- 'rounded-md',
-
- // Spacing
- 'p-4',
-
- // Color
- 'bg-surface-0 dark:bg-surface-700',
- 'border border-surface-200 dark:border-surface-700',
-
- // Misc
- 'overflow-x-auto'
- ]
- },
- menu: {
- class: [
- // Flex & Alignment
- 'flex items-center flex-nowrap',
-
- // Spacing
- 'm-0 p-0 list-none leading-none'
- ]
- },
- action: {
- class: [
- // Flex & Alignment
- 'flex items-center',
-
- // Shape
- 'rounded-md',
-
- // Color
- 'text-surface-600 dark:text-white/70',
-
- // States
- 'focus-visible:outline-none focus-visible:outline-offset-0',
- 'focus-visible:ring focus-visible:ring-primary-400/50 dark:focus-visible:ring-primary-300/50',
-
- // Transitions
- 'transition-shadow duration-200',
-
- // Misc
- 'text-decoration-none'
- ]
- },
- icon: {
- class: 'text-surface-600 dark:text-white/70'
- },
- separator: {
- class: [
- // Flex & Alignment
- 'flex items-center',
-
- // Spacing
- ' mx-2',
-
- // Color
- 'text-surface-600 dark:text-white/70'
- ]
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/button/index.js b/frontend/packages/kwai-ui/src/presets/kwai/button/index.js
deleted file mode 100644
index 9fbb0d90b..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/button/index.js
+++ /dev/null
@@ -1,220 +0,0 @@
-export default {
- root: ({ props, context, parent }) => ({
- class: [
- 'relative',
-
- // Alignments
- 'items-center inline-flex text-center align-bottom justify-center',
-
- // Sizes & Spacing
- 'leading-[normal]',
- {
- 'px-4 py-3': props.size === null,
- 'text-sm py-2 px-3': props.size === 'small',
- 'text-xl py-3 px-4': props.size === 'large',
- },
- {
- 'w-12 p-0 py-3': props.label == null && props.icon !== null,
- },
-
- // Shapes
- { 'shadow-lg': props.raised },
- { 'rounded-md': !props.rounded, 'rounded-full': props.rounded },
- { 'rounded-none first:rounded-l-md last:rounded-r-md': parent.instance.$name === 'ButtonGroup' },
-
- // Link Button
- { 'text-primary-600 bg-transparent border-transparent': props.link },
-
- // Plain Button
- { 'text-white bg-gray-500 border border-gray-500': props.plain && !props.outlined && !props.text },
- // Plain Text Button
- { 'text-surface-500': props.plain && props.text },
- // Plain Outlined Button
- { 'text-surface-500 border border-gray-500': props.plain && props.outlined },
-
- // Text Button
- { 'bg-transparent border-transparent': props.text && !props.plain },
-
- // Outlined Button
- { 'bg-transparent border': props.outlined && !props.plain },
-
- // --- Severity Buttons ---
-
- // Primary Button
- {
- 'text-white dark:text-surface-900': !props.link && props.severity === null && !props.text && !props.outlined && !props.plain,
- 'bg-primary-500 dark:bg-primary-400': !props.link && props.severity === null && !props.text && !props.outlined && !props.plain,
- 'border border-primary-500 dark:border-primary-400': !props.link && props.severity === null && !props.text && !props.outlined && !props.plain,
- },
- // Primary Text Button
- { 'text-primary-500 dark:text-primary-400': props.text && props.severity === null && !props.plain },
- // Primary Outlined Button
- { 'text-primary-500 border border-primary-500 hover:bg-primary-300/20': props.outlined && props.severity === null && !props.plain },
-
- // Secondary Button
- {
- 'text-white dark:text-surface-900': props.severity === 'secondary' && !props.text && !props.outlined && !props.plain,
- 'bg-surface-500 dark:bg-surface-400': props.severity === 'secondary' && !props.text && !props.outlined && !props.plain,
- 'border border-surface-500 dark:border-surface-400': props.severity === 'secondary' && !props.text && !props.outlined && !props.plain,
- },
- // Secondary Text Button
- { 'text-surface-500 dark:text-surface-300': props.text && props.severity === 'secondary' && !props.plain },
- // Secondary Outlined Button
- { 'text-surface-500 dark:text-surface-300 border border-surface-500 hover:bg-surface-300/20': props.outlined && props.severity === 'secondary' && !props.plain },
-
- // Success Button
- {
- 'text-white dark:text-green-900': props.severity === 'success' && !props.text && !props.outlined && !props.plain,
- 'bg-green-500 dark:bg-green-400': props.severity === 'success' && !props.text && !props.outlined && !props.plain,
- 'border border-green-500 dark:border-green-400': props.severity === 'success' && !props.text && !props.outlined && !props.plain,
- },
- // Success Text Button
- { 'text-green-500 dark:text-green-400': props.text && props.severity === 'success' && !props.plain },
- // Success Outlined Button
- { 'text-green-500 border border-green-500 hover:bg-green-300/20': props.outlined && props.severity === 'success' && !props.plain },
-
- // Info Button
- {
- 'text-white dark:text-surface-900': props.severity === 'info' && !props.text && !props.outlined && !props.plain,
- 'bg-blue-500 dark:bg-blue-400': props.severity === 'info' && !props.text && !props.outlined && !props.plain,
- 'border border-blue-500 dark:border-blue-400': props.severity === 'info' && !props.text && !props.outlined && !props.plain,
- },
- // Info Text Button
- { 'text-blue-500 dark:text-blue-400': props.text && props.severity === 'info' && !props.plain },
- // Info Outlined Button
- { 'text-blue-500 border border-blue-500 hover:bg-blue-300/20 ': props.outlined && props.severity === 'info' && !props.plain },
-
- // Warning Button
- {
- 'text-white dark:text-surface-900': props.severity === 'warning' && !props.text && !props.outlined && !props.plain,
- 'bg-orange-500 dark:bg-orange-400': props.severity === 'warning' && !props.text && !props.outlined && !props.plain,
- 'border border-orange-500 dark:border-orange-400': props.severity === 'warning' && !props.text && !props.outlined && !props.plain,
- },
- // Warning Text Button
- { 'text-orange-500 dark:text-orange-400': props.text && props.severity === 'warning' && !props.plain },
- // Warning Outlined Button
- { 'text-orange-500 border border-orange-500 hover:bg-orange-300/20': props.outlined && props.severity === 'warning' && !props.plain },
-
- // Help Button
- {
- 'text-white dark:text-surface-900': props.severity === 'help' && !props.text && !props.outlined && !props.plain,
- 'bg-purple-500 dark:bg-purple-400': props.severity === 'help' && !props.text && !props.outlined && !props.plain,
- 'border border-purple-500 dark:border-purple-400': props.severity === 'help' && !props.text && !props.outlined && !props.plain,
- },
- // Help Text Button
- { 'text-purple-500 dark:text-purple-400': props.text && props.severity === 'help' && !props.plain },
- // Help Outlined Button
- { 'text-purple-500 border border-purple-500 hover:bg-purple-300/20': props.outlined && props.severity === 'help' && !props.plain },
-
- // Danger Button
- {
- 'text-white dark:text-surface-900': props.severity === 'danger' && !props.text && !props.outlined && !props.plain,
- 'bg-red-500 dark:bg-red-400': props.severity === 'danger' && !props.text && !props.outlined && !props.plain,
- 'border border-red-500 dark:border-red-400': props.severity === 'danger' && !props.text && !props.outlined && !props.plain,
- },
- // Danger Text Button
- { 'text-red-500 dark:text-red-400': props.text && props.severity === 'danger' && !props.plain },
- // Danger Outlined Button
- { 'text-red-500 border border-red-500 hover:bg-red-300/20': props.outlined && props.severity === 'danger' && !props.plain },
-
- // --- Severity Button States ---
- 'focus:outline-none focus:outline-offset-0 focus:ring',
-
- // Link
- { 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50': props.link },
-
- // Plain
- { 'hover:bg-gray-600 hover:border-gray-600': props.plain && !props.outlined && !props.text },
- // Text & Outlined Button
- { 'hover:bg-surface-300/20': props.plain && (props.text || props.outlined) },
-
- // Primary
- { 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300': !props.link && props.severity === null && !props.text && !props.outlined && !props.plain },
- { 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50': props.severity === null },
- // Text & Outlined Button
- { 'hover:bg-primary-300/20': (props.text || props.outlined) && props.severity === null && !props.plain },
-
- // Secondary
- { 'hover:bg-surface-600 dark:hover:bg-surface-300 hover:border-surface-600 dark:hover:border-surface-300': props.severity === 'secondary' && !props.text && !props.outlined && !props.plain },
- { 'focus:ring-surface-400/50 dark:focus:ring-surface-300/50': props.severity === 'secondary' },
- // Text & Outlined Button
- { 'hover:bg-surface-300/20': (props.text || props.outlined) && props.severity === 'secondary' && !props.plain },
-
- // Success
- { 'hover:bg-green-600 dark:hover:bg-green-300 hover:border-green-600 dark:hover:border-green-300': props.severity === 'success' && !props.text && !props.outlined && !props.plain },
- { 'focus:ring-green-400/50 dark:focus:ring-green-300/50': props.severity === 'success' },
- // Text & Outlined Button
- { 'hover:bg-green-300/20': (props.text || props.outlined) && props.severity === 'success' && !props.plain },
-
- // Info
- { 'hover:bg-blue-600 dark:hover:bg-blue-300 hover:border-blue-600 dark:hover:border-blue-300': props.severity === 'info' && !props.text && !props.outlined && !props.plain },
- { 'focus:ring-blue-400/50 dark:focus:ring-blue-300/50': props.severity === 'info' },
- // Text & Outlined Button
- { 'hover:bg-blue-300/20': (props.text || props.outlined) && props.severity === 'info' && !props.plain },
-
- // Warning
- { 'hover:bg-orange-600 dark:hover:bg-orange-300 hover:border-orange-600 dark:hover:border-orange-300': props.severity === 'warning' && !props.text && !props.outlined && !props.plain },
- { 'focus:ring-orange-400/50 dark:focus:ring-orange-300/50': props.severity === 'warning' },
- // Text & Outlined Button
- { 'hover:bg-orange-300/20': (props.text || props.outlined) && props.severity === 'warning' && !props.plain },
-
- // Help
- { 'hover:bg-purple-600 dark:hover:bg-purple-300 hover:border-purple-600 dark:hover:border-purple-300': props.severity === 'help' && !props.text && !props.outlined && !props.plain },
- { 'focus:ring-purple-400/50 dark:focus:ring-purple-300/50': props.severity === 'help' },
- // Text & Outlined Button
- { 'hover:bg-purple-300/20': (props.text || props.outlined) && props.severity === 'help' && !props.plain },
-
- // Danger
- { 'hover:bg-red-600 dark:hover:bg-red-300 hover:border-red-600 dark:hover:border-red-300': props.severity === 'danger' && !props.text && !props.outlined && !props.plain },
- { 'focus:ring-red-400/50 dark:focus:ring-red-300/50': props.severity === 'danger' },
- // Text & Outlined Button
- { 'hover:bg-red-300/20': (props.text || props.outlined) && props.severity === 'danger' && !props.plain },
-
- // Disabled
- { 'opacity-60 pointer-events-none cursor-default': context.disabled },
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // Misc
- 'cursor-pointer overflow-hidden select-none',
- ],
- }),
- label: ({ props }) => ({
- class: [
- 'duration-200',
- 'font-bold',
- {
- 'hover:underline': props.link,
- },
- { 'flex-1': props.label !== null, 'invisible w-0': props.label == null },
- ],
- }),
- icon: ({ props }) => ({
- class: [
- 'mx-0',
- {
- 'mr-2': props.iconPos == 'left' && props.label != null,
- 'ml-2 order-1': props.iconPos == 'right' && props.label != null,
- 'mb-2': props.iconPos == 'top' && props.label != null,
- 'mt-2': props.iconPos == 'bottom' && props.label != null,
- },
- ],
- }),
- loadingicon: ({ props }) => ({
- class: [
- 'h-4 w-4',
- 'mx-0',
- {
- 'mr-2': props.iconPos == 'left' && props.label != null,
- 'ml-2 order-1': props.iconPos == 'right' && props.label != null,
- 'mb-2': props.iconPos == 'top' && props.label != null,
- 'mt-2': props.iconPos == 'bottom' && props.label != null,
- },
- 'animate-spin',
- ],
- }),
- badge: ({ props }) => ({
- class: [{ 'ml-2 w-4 h-4 leading-none flex items-center justify-center': props.badge }],
- }),
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/calendar/index.js b/frontend/packages/kwai-ui/src/presets/kwai/calendar/index.js
deleted file mode 100644
index 8834ea094..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/calendar/index.js
+++ /dev/null
@@ -1,643 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- // Display and Position
- 'inline-flex',
- 'max-w-full',
- 'relative',
-
- // Misc
- { 'opacity-60 select-none pointer-events-none cursor-default': props.disabled }
- ]
- }),
- input: ({ props }) => ({
- class: [
- // Display
- 'flex flex-auto',
-
- // Font
- 'font-sans leading-none',
-
- // Colors
- 'text-surface-600 dark:text-surface-200',
- 'placeholder:text-surface-400 dark:placeholder:text-surface-500',
- 'bg-surface-0 dark:bg-surface-900',
- 'border',
- { 'border-surface-300 dark:border-surface-600': !props.invalid },
-
- // Invalid State
- { 'border-red-500 dark:border-red-400': props.invalid },
-
- // Spacing
- 'm-0 p-3',
-
- // Shape
- 'appearance-none',
- { 'rounded-md': !props.showIcon || props.iconDisplay == 'input' },
- { 'rounded-l-md flex-1 pr-9': props.showIcon && props.iconDisplay !== 'input' },
- { 'rounded-md flex-1 pr-9': props.showIcon && props.iconDisplay === 'input' },
-
- // Transitions
- 'transition-colors',
- 'duration-200',
-
- // States
- { 'hover:border-primary-500 dark:hover:border-primary-400': !props.invalid },
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-500/50 dark:focus:ring-primary-400/50'
- ]
- }),
- inputicon: {
- class: ['absolute top-[50%] -mt-2', 'text-surface-600 dark:text-surface-200', 'right-[.75rem]']
- },
- dropdownbutton: {
- root: {
- class: [
- 'relative',
-
- // Alignments
- 'items-center inline-flex text-center align-bottom',
-
- // Shape
- 'rounded-r-md',
-
- // Size
- 'px-4 py-3 leading-none',
-
- // Colors
- 'text-white dark:text-surface-900',
- 'bg-primary-500 dark:bg-primary-400',
- 'border border-primary-500 dark:border-primary-400',
-
- // States
- 'focus:outline-none focus:outline-offset-0 focus:ring',
- 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50'
- ]
- }
- },
- panel: ({ props }) => ({
- class: [
- // Display & Position
- {
- absolute: !props.inline,
- 'inline-block': props.inline
- },
-
- // Size
- { 'w-auto p-2 ': !props.inline },
- { 'min-w-[80vw] w-auto p-2 ': props.touchUI },
- { 'p-2 min-w-full': props.inline },
-
- // Shape
- 'border rounded-lg',
- {
- 'shadow-md': !props.inline
- },
-
- // Colors
- 'bg-surface-0 dark:bg-surface-800',
- 'border-surface-200 dark:border-surface-700',
-
- //misc
- { 'overflow-x-auto': props.inline }
- ]
- }),
- datepickerMask: {
- class: ['fixed top-0 left-0 w-full h-full', 'flex items-center justify-center', 'bg-black bg-opacity-90']
- },
- header: {
- class: [
- //Font
- 'font-semibold',
-
- // Flexbox and Alignment
- 'flex items-center justify-between',
-
- // Spacing
- 'p-2',
- 'm-0',
-
- // Shape
- 'border-b',
- 'rounded-t-md',
-
- // Colors
- 'text-surface-700 dark:text-white/80',
- 'bg-surface-0 dark:bg-surface-800',
- 'border-surface-200 dark:border-surface-700'
- ]
- },
- previousbutton: {
- class: [
- 'relative',
-
- // Flexbox and Alignment
- 'inline-flex items-center justify-center',
-
- // Size
- 'w-8 h-8',
- 'p-0 m-0',
-
- // Shape
- 'rounded-full',
-
- // Colors
- 'text-surface-600 dark:text-white/70',
- 'border-0',
- 'bg-transparent',
-
- // Transitions
- 'transition-colors duration-200 ease-in-out',
-
- // States
- 'hover:text-surface-700 dark:hover:text-white/80',
- 'hover:bg-surface-100 dark:hover:bg-surface-800/80',
-
- // Misc
- 'cursor-pointer overflow-hidden'
- ]
- },
- title: {
- class: [
- // Text
- 'leading-8',
- 'mx-auto my-0'
- ]
- },
- monthTitle: {
- class: [
- // Font
- 'text-base leading-5',
- 'font-semibold',
-
- // Colors
- 'text-surface-700 dark:text-white/80',
-
- // Transitions
- 'transition duration-200',
-
- // Spacing
- 'p-2',
- 'm-0 mr-2',
-
- // States
- 'hover:text-primary-500 dark:hover:text-primary-400',
-
- // Misc
- 'cursor-pointer'
- ]
- },
- yearTitle: {
- class: [
- // Font
- 'text-base leading-5',
- 'font-semibold',
-
- // Colors
- 'text-surface-700 dark:text-white/80',
-
- // Transitions
- 'transition duration-200',
-
- // Spacing
- 'p-2',
- 'm-0',
-
- // States
- 'hover:text-primary-500 dark:hover:text-primary-400',
-
- // Misc
- 'cursor-pointer'
- ]
- },
- nextbutton: {
- class: [
- 'relative',
-
- // Flexbox and Alignment
- 'inline-flex items-center justify-center',
-
- // Size
- 'w-8 h-8',
- 'p-0 m-0',
-
- // Shape
- 'rounded-full',
-
- // Colors
- 'text-surface-600 dark:text-white/70',
- 'border-0',
- 'bg-transparent',
-
- // Transitions
- 'transition-colors duration-200 ease-in-out',
-
- // States
- 'hover:text-surface-700 dark:hover:text-white/80',
- 'hover:bg-surface-100 dark:hover:bg-surface-800/80',
-
- // Misc
- 'cursor-pointer overflow-hidden'
- ]
- },
- table: {
- class: [
- // Font
- 'text-base leading-none',
- // Size & Shape
- 'border-collapse',
- 'w-full',
-
- // Spacing
- 'm-0 my-2'
- ]
- },
- tableheadercell: {
- class: [
- // Spacing
- 'p-0 md:p-2'
- ]
- },
- weekheader: {
- class: ['leading-5', 'text-surface-600 dark:text-white/70', 'opacity-60 cursor-default']
- },
- weeknumber: {
- class: ['text-surface-600 dark:text-white/70', 'opacity-60 cursor-default']
- },
- weekday: {
- class: [
- // Colors
- 'text-surface-500 dark:text-white/60'
- ]
- },
- day: {
- class: [
- // Spacing
- 'p-0 md:p-2'
- ]
- },
- weeklabelcontainer: ({ context }) => ({
- class: [
- // Flexbox and Alignment
- 'flex items-center justify-center',
- 'mx-auto',
-
- // Shape & Size
- 'w-10 h-10',
- 'rounded-full',
- 'border-transparent border',
-
- // Colors
- {
- 'text-surface-600 dark:text-white/70 bg-transparent': !context.selected && !context.disabled,
- 'text-primary-700 bg-primary-100': context.selected && !context.disabled
- },
-
- // States
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
- {
- 'hover:bg-surface-100 dark:hover:bg-surface-800/80': !context.selected && !context.disabled,
- 'hover:bg-primary-200': context.selected && !context.disabled
- },
- {
- 'opacity-60 cursor-default': context.disabled,
- 'cursor-pointer': !context.disabled
- }
- ]
- }),
- daylabel: ({ context }) => ({
- class: [
- // Flexbox and Alignment
- 'flex items-center justify-center',
- 'mx-auto',
-
- // Shape & Size
- 'w-10 h-10',
- 'rounded-full',
- 'border-transparent border',
-
- // Colors
- {
- 'text-primary-500 dark:text-primary-400': context.date.today,
- 'text-surface-600 dark:text-white/70 bg-transparent': !context.selected && !context.disabled && !context.date.today,
- 'text-primary-700 bg-primary-100 dark:text-surface-0 dark:bg-primary-300/40': context.selected && !context.disabled
- },
-
- // States
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
- {
- 'hover:bg-surface-100 dark:hover:bg-surface-600/80': !context.selected && !context.disabled,
- 'hover:bg-primary-200 dark:hover:bg-primary-200/40': context.selected && !context.disabled
- },
- {
- 'opacity-60 cursor-default': context.disabled,
- 'cursor-pointer': !context.disabled
- }
- ]
- }),
- monthpicker: {
- class: [
- // Spacing
- 'my-2'
- ]
- },
- month: ({ context }) => ({
- class: [
- // Flexbox and Alignment
- 'inline-flex items-center justify-center',
-
- // Size
- 'w-1/3',
- 'p-2',
-
- // Shape
- 'rounded-md',
-
- // Colors
- {
- 'text-surface-600 dark:text-white/70 bg-transparent': !context.selected && !context.disabled,
- 'text-primary-700 bg-primary-100 dark:text-surface-0 dark:bg-primary-300/40': context.selected && !context.disabled
- },
-
- // States
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
- {
- 'hover:bg-surface-100 dark:hover:bg-surface-600/80': !context.selected && !context.disabled,
- 'hover:bg-primary-200 dark:hover:bg-primary-200/40': context.selected && !context.disabled
- },
-
- // Misc
- 'cursor-pointer'
- ]
- }),
- yearpicker: {
- class: [
- // Spacing
- 'my-2'
- ]
- },
- year: ({ context }) => ({
- class: [
- // Flexbox and Alignment
- 'inline-flex items-center justify-center',
-
- // Size
- 'w-1/3',
- 'p-2',
-
- // Shape
- 'rounded-md',
-
- // Colors
- {
- 'text-surface-600 dark:text-white/70 bg-transparent': !context.selected && !context.disabled,
- 'text-primary-700 bg-primary-100 dark:text-surface-0 dark:bg-primary-300/40': context.selected && !context.disabled
- },
-
- // States
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
- {
- 'hover:bg-surface-100 dark:hover:bg-surface-600/80': !context.selected && !context.disabled,
- 'hover:bg-primary-200 dark:hover:bg-primary-200/40': context.selected && !context.disabled
- },
-
- // Misc
- 'cursor-pointer'
- ]
- }),
- timepicker: {
- class: [
- // Flexbox
- 'flex',
- 'justify-center items-center',
-
- // Borders
- 'border-t-1',
- 'border-solid border-surface-200',
-
- // Spacing
- 'p-2'
- ]
- },
- separatorcontainer: {
- class: [
- // Flexbox and Alignment
- 'flex',
- 'items-center',
- 'flex-col',
-
- // Spacing
- 'px-2'
- ]
- },
- separator: {
- class: [
- // Text
- 'text-xl'
- ]
- },
- hourpicker: {
- class: [
- // Flexbox and Alignment
- 'flex',
- 'items-center',
- 'flex-col',
-
- // Spacing
- 'px-2'
- ]
- },
- minutepicker: {
- class: [
- // Flexbox and Alignment
- 'flex',
- 'items-center',
- 'flex-col',
-
- // Spacing
- 'px-2'
- ]
- },
- secondPicker: {
- class: [
- // Flexbox and Alignment
- 'flex',
- 'items-center',
- 'flex-col',
-
- // Spacing
- 'px-2'
- ]
- },
- ampmpicker: {
- class: [
- // Flexbox and Alignment
- 'flex',
- 'items-center',
- 'flex-col',
-
- // Spacing
- 'px-2'
- ]
- },
- incrementbutton: {
- class: [
- 'relative',
-
- // Flexbox and Alignment
- 'inline-flex items-center justify-center',
-
- // Size
- 'w-8 h-8',
- 'p-0 m-0',
-
- // Shape
- 'rounded-full',
-
- // Colors
- 'text-surface-600 dark:text-white/70',
- 'border-0',
- 'bg-transparent',
-
- // Transitions
- 'transition-colors duration-200 ease-in-out',
-
- // States
- 'hover:text-surface-700 dark:hover:text-white/80',
- 'hover:bg-surface-100 dark:hover:bg-surface-800/80',
-
- // Misc
- 'cursor-pointer overflow-hidden'
- ]
- },
- decrementbutton: {
- class: [
- 'relative',
-
- // Flexbox and Alignment
- 'inline-flex items-center justify-center',
-
- // Size
- 'w-8 h-8',
- 'p-0 m-0',
-
- // Shape
- 'rounded-full',
-
- // Colors
- 'text-surface-600 dark:text-white/70',
- 'border-0',
- 'bg-transparent',
-
- // Transitions
- 'transition-colors duration-200 ease-in-out',
-
- // States
- 'hover:text-surface-700 dark:hover:text-white/80',
- 'hover:bg-surface-100 dark:hover:bg-surface-800/80',
-
- // Misc
- 'cursor-pointer overflow-hidden'
- ]
- },
- groupcontainer: {
- class: [
- // Flexbox
- 'flex'
- ]
- },
- group: {
- class: [
- // Flexbox and Sizing
- 'flex-1',
-
- // Borders
- 'border-l',
- 'border-surface-200',
-
- // Spacing
- 'pr-0.5',
- 'pl-0.5',
- 'pt-0',
- 'pb-0',
-
- // Pseudo-Classes
- 'first:pl-0',
- 'first:border-l-0'
- ]
- },
- buttonbar: {
- class: [
- // Flexbox
- 'flex justify-between items-center',
-
- // Spacing
- 'py-3 px-0',
-
- // Shape
- 'border-t border-surface-200 dark:border-surface-700'
- ]
- },
- todaybutton: {
- root: {
- class: [
- // Flexbox and Alignment
- 'inline-flex items-center justify-center',
-
- // Spacing
- 'px-4 py-3 leading-none',
-
- // Shape
- 'rounded-md',
-
- // Colors
- 'bg-transparent border-transparent',
- 'text-primary-500 dark:text-primary-400',
-
- // Transitions
- 'transition-colors duration-200 ease-in-out',
-
- // States
- 'focus:outline-none focus:outline-offset-0 focus:ring',
- 'hover:bg-primary-300/20',
-
- // Misc
- 'cursor-pointer'
- ]
- }
- },
- clearbutton: {
- root: {
- class: [
- // Flexbox and Alignment
- 'inline-flex items-center justify-center',
-
- // Spacing
- 'px-4 py-3 leading-none',
-
- // Shape
- 'rounded-md',
-
- // Colors
- 'bg-transparent border-transparent',
- 'text-primary-500 dark:text-primary-400',
-
- // Transitions
- 'transition-colors duration-200 ease-in-out',
-
- // States
- 'focus:outline-none focus:outline-offset-0 focus:ring',
- 'hover:bg-primary-300/20',
-
- // Misc
- 'cursor-pointer'
- ]
- }
- },
- transition: {
- enterFromClass: 'opacity-0 scale-y-[0.8]',
- enterActiveClass: 'transition-[transform,opacity] duration-[120ms] ease-[cubic-bezier(0,0,0.2,1)]',
- leaveActiveClass: 'transition-opacity duration-100 ease-linear',
- leaveToClass: 'opacity-0'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/card/index.js b/frontend/packages/kwai-ui/src/presets/kwai/card/index.js
deleted file mode 100644
index d4832f650..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/card/index.js
+++ /dev/null
@@ -1,37 +0,0 @@
-export default {
- root: {
- class: [
- //Shape
- 'rounded-md',
- 'shadow-md',
-
- //Color
- 'bg-surface-0 dark:bg-surface-900',
- 'text-surface-700 dark:text-surface-0'
- ]
- },
- body: {
- class: 'p-5'
- },
- title: {
- class: 'text-2xl font-bold mb-2'
- },
- subtitle: {
- class: [
- //Font
- 'font-normal',
-
- //Spacing
- 'mb-2',
-
- //Color
- 'text-surface-600 dark:text-surface-0/60'
- ]
- },
- content: {
- class: 'py-5' // Vertical padding.
- },
- footer: {
- class: 'pt-5' // Top padding.
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/carousel/index.js b/frontend/packages/kwai-ui/src/presets/kwai/carousel/index.js
deleted file mode 100644
index e03862830..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/carousel/index.js
+++ /dev/null
@@ -1,149 +0,0 @@
-export default {
- root: {
- class: [
- // Flexbox
- 'flex flex-col'
- ]
- },
- content: {
- class: [
- // Flexbox & Overflow
- 'flex flex-col overflow-auto'
- ]
- },
- container: ({ props }) => ({
- class: [
- // Flexbox
- 'flex',
-
- // Orientation
- {
- 'flex-row': props.orientation !== 'vertical',
- 'flex-col': props.orientation == 'vertical'
- }
- ]
- }),
- previousbutton: {
- class: [
- // Flexbox & Alignment
- 'flex justify-center items-center self-center',
-
- // Sizing & Overflow
- 'overflow-hidden w-8 h-8',
-
- // Spacing
- 'mx-2',
-
- // Shape
- 'rounded-full',
-
- // Border & Background
- 'border-0 bg-transparent',
-
- // Color
- 'text-surface-600',
-
- // Transitions
- 'transition duration-200 ease-in-out'
- ]
- },
- nextbutton: {
- class: [
- // Flexbox & Alignment
- 'flex justify-center items-center self-center',
-
- // Sizing & Overflow
- 'overflow-hidden w-8 h-8',
-
- // Spacing
- 'mx-2',
-
- // Shape
- 'rounded-full',
-
- // Border & Background
- 'border-0 bg-transparent',
-
- // Color
- 'text-surface-600',
-
- // Transitions
- 'transition duration-200 ease-in-out'
- ]
- },
- itemscontent: {
- class: [
- // Overflow & Width
- 'overflow-hidden w-full'
- ]
- },
- itemscontainer: ({ props }) => ({
- class: [
- // Flexbox
- 'flex',
-
- // Orientation & Sizing
- {
- 'flex-row': props.orientation !== 'vertical',
- 'flex-col h-full': props.orientation == 'vertical'
- }
- ]
- }),
- item: ({ props }) => ({
- class: [
- // Flexbox
- 'flex shrink-0 grow ',
-
- // Size
- {
- 'w-full sm:w-[50%] md:w-[33.333333333333336%]': props.orientation !== 'vertical',
-
- 'w-full h-full': props.orientation == 'vertical'
- }
- ]
- }),
- itemcloned: ({ props }) => ({
- class: [
- // Flexbox
- 'flex shrink-0 grow',
- 'unvisible',
-
- // Size
- {
- 'w-full sm:w-[50%] md:w-[33.333333333333336%]': props.orientation !== 'vertical',
-
- 'w-full h-full': props.orientation == 'vertical'
- }
- ]
- }),
- indicators: {
- class: [
- // Flexbox & Alignment
- 'flex flex-row justify-center flex-wrap'
- ]
- },
- indicator: {
- class: [
- // Spacing
- 'mr-2 mb-2'
- ]
- },
- indicatorbutton: ({ context }) => ({
- class: [
- // Sizing & Shape
- 'w-8 h-2 rounded-0',
-
- // Transitions
- 'transition duration-200',
-
- // Focus Styles
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
-
- // Color & Background
- {
- 'bg-surface-200 hover:bg-surface-300 dark:bg-surface-700 dark:hover:bg-surface-600': !context.highlighted,
- 'bg-primary-500 hover:bg-primary-600': context.highlighted
- }
- ]
- })
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/cascadeselect/index.js b/frontend/packages/kwai-ui/src/presets/kwai/cascadeselect/index.js
deleted file mode 100644
index e51adb2b8..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/cascadeselect/index.js
+++ /dev/null
@@ -1,209 +0,0 @@
-export default {
- root: ({ props, state }) => ({
- class: [
- // Display and Position
- 'inline-flex',
- 'relative',
-
- // Shape
- 'rounded-md',
-
- // Color and Background
- 'bg-surface-0 dark:bg-surface-900',
- 'border',
- { 'border-surface-300 dark:border-surface-600': !props.invalid },
-
- // Invalid State
- { 'border-red-500 dark:border-red-400': props.invalid },
-
- // Transitions
- 'transition-all',
- 'duration-200',
-
- // States
- { 'hover:border-primary-500 dark:hover:border-primary-300': !props.invalid },
- { 'outline-none outline-offset-0 ring ring-primary-400/50 dark:ring-primary-300/50': state.focused },
-
- // Misc
- 'cursor-pointer',
- 'select-none',
- { 'opacity-60': props.disabled, 'pointer-events-none': props.disabled, 'cursor-default': props.disabled }
- ]
- }),
- label: ({ props }) => ({
- class: [
- //Font
- 'font-sans',
- 'leading-none',
-
- // Flex & Alignment
- ' flex flex-auto',
-
- // Sizing and Spacing
- 'w-[1%]',
- 'p-3',
-
- //Shape
- 'rounded-none',
-
- // Color and Background
- 'bg-transparent',
- 'border-0',
- { 'text-surface-800 dark:text-white/80': props.modelValue, 'text-surface-400 dark:text-surface-500': !props.modelValue },
- 'placeholder:text-surface-400 dark:placeholder:text-surface-500',
-
- // Transitions
- 'transition',
- 'duration-200',
-
- // States
- 'focus:outline-none focus:shadow-none',
-
- // Misc
- 'relative',
- 'cursor-pointer',
- 'overflow-hidden overflow-ellipsis',
- 'whitespace-nowrap',
- 'appearance-none'
- ]
- }),
- dropdownbutton: {
- class: [
- // Flexbox
- 'flex items-center justify-center',
- 'shrink-0',
-
- // Color and Background
- 'bg-transparent',
- 'text-surface-500',
-
- // Size
- 'w-12',
-
- // Shape
- 'rounded-tr-md',
- 'rounded-br-md'
- ]
- },
- panel: {
- class: [
- // Position
- 'absolute top-0 left-0',
-
- // Shape
- 'border-0 dark:border',
- 'rounded-md',
- 'shadow-md',
-
- // Color
- 'bg-surface-0 dark:bg-surface-700',
- 'text-surface-800 dark:text-white/80',
- 'dark:border-surface-700'
- ]
- },
- wrapper: {
- class: [
- // Sizing
- 'max-h-[200px]',
-
- // Misc
- 'overflow-auto'
- ]
- },
- list: {
- class: 'py-3 list-none m-0'
- },
- item: ({ context }) => ({
- class: [
- // Font
- 'font-normal',
- 'leading-none',
-
- // Shape
- 'border-0',
- 'rounded-none',
-
- // Spacing
- 'm-0',
-
- // Colors
- {
- 'text-surface-500 dark:text-white/70': !context.focused && !context.active,
- 'text-surface-500 dark:text-white/70 bg-surface-200 dark:bg-surface-600/90': context.focused && !context.active,
- 'text-primary-700 dark:text-surface-0/80 bg-primary-50 dark:bg-primary-400/30': context.focused && context.active,
- 'text-primary-700 dark:text-surface-0/80 bg-primary-50 dark:bg-primary-400/30': !context.focused && context.active
- },
-
- // Hover States
- {
- 'hover:bg-surface-100 dark:hover:bg-surface-600/80': !context.active,
- 'hover:bg-primary-500/50 dark:hover:bg-primary-300/30 text-primary-700 dark:text-surface-0/80': context.active
- },
-
- // Transitions
- 'transition-shadow',
- 'duration-200',
-
- // Misc
- 'cursor-pointer',
- 'overflow-hidden',
- 'whitespace-nowrap'
- ]
- }),
- content: {
- class: [
- 'relative',
-
- // Flexbox
- 'flex',
- 'items-center',
-
- // Spacing
- 'py-3',
- 'px-5',
-
- // Misc
- 'no-underline',
- 'overflow-hidden',
- 'cursor-pointer',
- 'select-none'
- ]
- },
- groupicon: {
- class: [
- // Alignment
- 'ml-auto'
- ]
- },
- sublist: {
- class: [
- // Size
- 'w-full',
-
- // Spacing
- 'py-1',
- 'm-0',
- 'list-none',
-
- // Shape
- 'shadow-none sm:shadow-md',
- 'border-0',
-
- // Position
- 'static sm:absolute',
- 'z-10',
-
- // Color
- 'bg-surface-0 dark:bg-surface-700'
- ]
- },
- separator: {
- class: 'border-t border-surface-200 dark:border-surface-600 my-1'
- },
- transition: {
- enterFromClass: 'opacity-0 scale-y-[0.8]',
- enterActiveClass: 'transition-[transform,opacity] duration-[120ms] ease-[cubic-bezier(0,0,0.2,1)]',
- leaveActiveClass: 'transition-opacity duration-100 ease-linear',
- leaveToClass: 'opacity-0'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/checkbox/index.js b/frontend/packages/kwai-ui/src/presets/kwai/checkbox/index.js
deleted file mode 100644
index 58f52949e..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/checkbox/index.js
+++ /dev/null
@@ -1,101 +0,0 @@
-export default {
- root: {
- class: [
- 'relative',
-
- // Alignment
- 'inline-flex',
- 'align-bottom',
-
- // Size
- 'w-6',
- 'h-6',
-
- // Misc
- 'cursor-pointer',
- 'select-none'
- ]
- },
- box: ({ props, context }) => ({
- class: [
- // Alignment
- 'flex',
- 'items-center',
- 'justify-center',
-
- // Size
- 'w-6',
- 'h-6',
-
- // Shape
- 'rounded-md',
- 'border-2',
-
- // Colors
- {
- 'border-surface-200 bg-surface-0 dark:border-surface-700 dark:bg-surface-900': !context.checked && !props.invalid,
- 'border-primary-500 bg-primary-500 dark:border-primary-400 dark:bg-primary-400': context.checked
- },
-
- // Invalid State
- { 'border-red-500 dark:border-red-400': props.invalid },
-
- // States
- {
- 'peer-hover:border-primary-500 dark:peer-hover:border-primary-400': !props.disabled && !context.checked && !props.invalid,
- 'peer-hover:bg-primary-600 dark:peer-hover:bg-primary-300 peer-hover:border-primary-700 dark:peer-hover:border-primary-300': !props.disabled && context.checked,
- 'peer-focus-visible:border-primary-500 dark:peer-focus-visible:border-primary-400 peer-focus-visible:ring-2 peer-focus-visible:ring-primary-400/20 dark:peer-focus-visible:ring-primary-300/20': !props.disabled,
- 'cursor-default opacity-60': props.disabled
- },
-
- // Transitions
- 'transition-colors',
- 'duration-200'
- ]
- }),
- input: {
- class: [
- 'peer',
-
- // Size
- 'w-full ',
- 'h-full',
-
- // Position
- 'absolute',
- 'top-0 left-0',
- 'z-10',
-
- // Spacing
- 'p-0',
- 'm-0',
-
- // Shape
- 'opacity-0',
- 'rounded-md',
- 'outline-none',
- 'border-2 border-surface-200 dark:border-surface-700',
-
- // Misc
- 'appearance-none',
- 'cursor-pointer'
- ]
- },
- icon: {
- class: [
- // Font
- 'text-base leading-none',
-
- // Size
- 'w-4',
- 'h-4',
-
- // Colors
- 'text-white dark:text-surface-900',
-
- // Transitions
- 'transition-all',
- 'duration-200'
- ]
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/chip/index.js b/frontend/packages/kwai-ui/src/presets/kwai/chip/index.js
deleted file mode 100644
index c6ff8795a..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/chip/index.js
+++ /dev/null
@@ -1,45 +0,0 @@
-export default {
- root: {
- class: [
- // Flexbox
- 'inline-flex items-center',
-
- // Spacing
- 'px-3',
-
- // Shape
- 'rounded-[1.14rem]',
-
- // Colors
- 'text-surface-700 dark:text-white/70',
- 'bg-surface-200 dark:bg-surface-700'
- ]
- },
- label: {
- class: 'leading-6 my-1.5 mx-0'
- },
- icon: {
- class: 'leading-6 mr-2'
- },
- image: {
- class: ['w-9 h-9 -ml-3 mr-2', 'rounded-full']
- },
- removeIcon: {
- class: [
- // Shape
- 'rounded-md leading-6',
-
- // Spacing
- 'ml-2',
-
- // Size
- 'w-4 h-4',
-
- // Transition
- 'transition duration-200 ease-in-out',
-
- // Misc
- 'cursor-pointer'
- ]
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/chips/index.js b/frontend/packages/kwai-ui/src/presets/kwai/chips/index.js
deleted file mode 100644
index 4042944b7..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/chips/index.js
+++ /dev/null
@@ -1,114 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- 'flex',
- {
- 'opacity-60 select-none pointer-events-none cursor-default': props.disabled
- }
- ]
- }),
- container: ({ state, props }) => ({
- class: [
- // Font
- 'font-sans text-base leading-none',
-
- // Flex
- 'flex items-center flex-wrap gap-2',
-
- // Spacing
- 'm-0 py-1.5 px-3',
-
- // Size
- 'w-full',
- 'min-h-[2.877rem]',
-
- // Shape
- 'list-none',
- 'rounded-md',
-
- // Color
- 'text-surface-700 dark:text-white/80',
- 'bg-surface-0 dark:bg-surface-900',
- 'border',
- { 'border-surface-300 dark:border-surface-600': !props.invalid },
-
- // Invalid State
- { 'border-red-500 dark:border-red-400': props.invalid },
-
- // States
- { 'hover:border-primary-500 dark:hover:border-primary-400': !props.invalid },
- 'focus:outline-none focus:outline-offset-0',
- { 'ring ring-primary-400/50 dark:ring-primary-300/50': state.focused },
- { 'ring ring-primary-400/50 dark:ring-primary-300/50': state.hovered },
-
- // Transition
- 'transition-colors duration-200',
-
- // Misc
- 'cursor-text overflow-hidden',
- 'appearance-none'
- ]
- }),
-
- inputtoken: {
- class: ['py-1.5 px-0', 'inline-flex flex-auto']
- },
- input: {
- class: [
- // Font
- 'font-sans text-base leading-[1.2]',
-
- // Size
- 'w-full',
-
- // Spacing
- 'p-0 m-0',
-
- // Shape
- 'appearance-none rounded-none',
- 'border-0 outline-none',
- 'shadow-none',
-
- // Color
- 'text-surface-700 dark:text-white/80',
- 'bg-transparent'
- ]
- },
- token: {
- class: [
- // Flexbox
- 'inline-flex items-center',
-
- // Spacing
- 'py-1.5 px-3',
-
- // Shape
- 'rounded-[1.14rem]',
-
- // Colors
- 'text-surface-700 dark:text-white/70',
- 'bg-surface-200 dark:bg-surface-700'
- ]
- },
- label: {
- class: 'leading-5'
- },
- removeTokenIcon: {
- class: [
- // Shape
- 'rounded-md leading-6',
-
- // Spacing
- 'ml-2',
-
- // Size
- 'w-4 h-4',
-
- // Transition
- 'transition duration-200 ease-in-out',
-
- // Misc
- 'cursor-pointer'
- ]
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/colorpicker/index.js b/frontend/packages/kwai-ui/src/presets/kwai/colorpicker/index.js
deleted file mode 100644
index 4b22e21c3..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/colorpicker/index.js
+++ /dev/null
@@ -1,123 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- // Display
- 'inline-block',
-
- // Misc
- { 'opacity-60 select-none pointer-events-none cursor-default': props.disabled }
- ]
- }),
- input: {
- class: [
- // Font
- 'font-sans text-base ',
-
- // Spacing
- 'm-0',
- 'p-3',
-
- // Size & Shape
- 'rounded-lg w-8 h-8',
-
- // Colors
- 'bg-surface-0 dark:bg-surface-900',
- 'border border-surface-300 dark:border-surface-700',
-
- // States
- 'hover:border-primary-500 dark:hover:border-primary-400',
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
-
- // Transition
- 'transition-colors duration-200',
-
- // Misc
- 'cursor-pointer'
- ]
- },
- panel: ({ props }) => ({
- class: [
- // Position & Size
- {
- 'relative h-[166px] w-[193px]': props.inline,
- 'absolute h-[166px] w-[193px]': !props.inline
- },
-
- // Shape
- 'shadow-md border',
-
- // Colors
- 'bg-surface-800 border-surface-900 dark:border-surface-600'
- ]
- }),
- selector: {
- class: [
- // Position
- 'absolute top-[8px] left-[8px]',
-
- // Size
- 'h-[150px] w-[150px]'
- ]
- },
- color: {
- class: [
- // Size
- 'h-[150px] w-[150px]'
- ],
- style: 'background: linear-gradient(to top, #000 0%, rgb(0 0 0 / 0) 100%), linear-gradient(to right, #fff 0%, rgb(255 255 255 / 0) 100%)'
- },
- colorhandle: {
- class: [
- 'absolute',
-
- // Shape
- 'rounded-full border border-solid',
-
- // Size
- 'h-[10px] w-[10px]',
-
- // Spacing
- '-ml-[5px] -mt-[5px]',
-
- // Colors
- 'border-white',
-
- // Misc
- 'cursor-pointer opacity-85'
- ]
- },
- hue: {
- class: [
- // Position
- 'absolute top-[8px] left-[167px]',
-
- // Size
- 'h-[150px] w-[17px]',
-
- // Opacity
- 'opacity-85'
- ],
- style: 'background: linear-gradient(0deg, red 0, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, red)'
- },
- huehandle: {
- class: [
- // Position
- 'absolute left-0 -ml-[2px] -mt-[5px]',
-
- // Size
- 'h-[10px] w-[21px]',
-
- // Shape
- 'border-solid border-2',
-
- // Misc
- 'cursor-pointer opacity-85'
- ]
- },
- transition: {
- enterFromClass: 'opacity-0 scale-y-[0.8]',
- enterActiveClass: 'transition-[transform,opacity] duration-[120ms] ease-[cubic-bezier(0,0,0.2,1)]',
- leaveActiveClass: 'transition-opacity duration-100 ease-linear',
- leaveToClass: 'opacity-0'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/confirmpopup/index.js b/frontend/packages/kwai-ui/src/presets/kwai/confirmpopup/index.js
deleted file mode 100644
index cef7ad32c..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/confirmpopup/index.js
+++ /dev/null
@@ -1,106 +0,0 @@
-export default {
- root: {
- class: [
- // Shape
- 'rounded-lg',
- 'shadow-lg',
- 'border-0',
-
- // Positioning
- 'z-40 transform origin-center',
- 'mt-3 absolute left-0 top-0',
-
- // Color
- 'dark:border',
- 'dark:border-surface-700',
- 'bg-surface-0 dark:bg-surface-800',
- 'text-surface-700 dark:text-surface-0/80',
-
- // Before: Arrow
- 'before:absolute before:w-0 before:-top-3 before:h-0 before:border-transparent before:border-solid before:ml-6 before:border-x-[0.75rem] before:border-b-[0.75rem] before:border-t-0 before:border-b-surface-0 dark:before:border-b-surface-800'
- ]
- },
- content: {
- class: 'p-5 items-center flex'
- },
- icon: {
- class: 'text-2xl mr-4'
- },
- footer: {
- class: [
- // Flexbox and Alignment
- 'flex items-center justify-end',
- 'shrink-0',
- 'text-right',
- 'gap-2',
-
- // Spacing
- 'px-6',
- 'pb-6',
-
- // Shape
- 'border-t-0',
- 'rounded-b-lg',
-
- // Colors
- 'bg-surface-0 dark:bg-surface-800',
- 'text-surface-700 dark:text-surface-0/80'
- ]
- },
- rejectbutton: {
- root: {
- class: [
- 'relative',
-
- // Alignments
- 'items-center inline-flex text-center align-bottom justify-center',
-
- // Sizes & Spacing
- 'px-4 py-3 leading-none',
-
- // Shape
- 'rounded-md',
-
- // Color
- 'text-primary-500 dark:text-primary-400',
-
- // States
- 'hover:bg-primary-300/20',
- 'focus:outline-none focus:outline-offset-0 focus:ring',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50'
- ]
- }
- },
- acceptbutton: {
- root: {
- class: [
- 'relative',
-
- // Alignments
- 'items-center inline-flex text-center align-bottom justify-center',
-
- // Sizes & Spacing
- 'px-4 py-3 leading-none',
-
- // Shape
- 'rounded-md',
-
- // Color
- 'text-white dark:text-surface-900',
- 'bg-primary-500 dark:bg-primary-400',
- 'border border-primary-500 dark:border-primary-400',
-
- // States
- 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300',
- 'focus:outline-none focus:outline-offset-0 focus:ring',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50'
- ]
- }
- },
- transition: {
- enterFromClass: 'opacity-0 scale-y-[0.8]',
- enterActiveClass: 'transition-[transform,opacity] duration-[120ms] ease-[cubic-bezier(0,0,0.2,1)]',
- leaveActiveClass: 'transition-opacity duration-100 ease-linear',
- leaveToClass: 'opacity-0'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/contextmenu/index.js b/frontend/packages/kwai-ui/src/presets/kwai/contextmenu/index.js
deleted file mode 100644
index 2e7ae2746..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/contextmenu/index.js
+++ /dev/null
@@ -1,125 +0,0 @@
-export default {
- root: {
- class: [
- // Sizing and Shape
- 'min-w-[12rem]',
- 'rounded-md',
- 'shadow-md',
-
- // Spacing
- 'py-2',
-
- // Colors
- 'bg-surface-0 dark:bg-surface-700',
- 'text-surface-700 dark:text-white/80',
- 'dark:border dark:border-surface-700'
- ]
- },
- menu: {
- class: [
- // Spacings and Shape
- 'list-none',
- 'm-0',
- 'p-0',
- 'outline-none'
- ]
- },
- menuitem: {
- class: 'relative'
- },
- content: ({ context }) => ({
- class: [
- //Shape
- 'rounded-none',
- // Colors
- 'text-surface-700 dark:text-white/80',
- {
- 'text-surface-500 dark:text-white/70': !context.focused && !context.active,
- 'text-surface-500 dark:text-white/70 bg-surface-200 dark:bg-surface-600/90': context.focused && !context.active,
- 'text-primary-700 dark:text-surface-0/80 bg-primary-50 dark:bg-primary-400/30': context.focused && context.active,
- 'text-primary-700 dark:text-surface-0/80 bg-primary-50 dark:bg-primary-400/30': !context.focused && context.active
- },
-
- // Transitions
- 'transition-shadow',
- 'duration-200',
-
- // States
- {
- 'hover:bg-surface-100 dark:hover:bg-surface-600/80': !context.active,
- 'hover:bg-primary-400/30 dark:hover:bg-primary-300/30 text-primary-700 dark:text-surface-0/80': context.active
- },
-
- // Disabled
- { 'opacity-60 pointer-events-none cursor-default': context.disabled }
- ]
- }),
- action: {
- class: [
- 'relative',
- // Flexbox
-
- 'flex',
- 'items-center',
-
- // Spacing
- 'py-3',
- 'px-5',
-
- // Color
- 'text-surface-700 dark:text-white/80',
-
- // Misc
- 'no-underline',
- 'overflow-hidden',
- 'cursor-pointer',
- 'select-none'
- ]
- },
- icon: {
- class: [
- // Spacing
- 'mr-2',
-
- // Color
- 'text-surface-600 dark:text-white/70'
- ]
- },
- label: {
- class: ['leading-none']
- },
- submenu: ({ props }) => ({
- class: [
- // Size
- 'w-full sm:w-48',
-
- // Spacing
- 'py-1',
- 'm-0',
- 'list-none',
-
- // Shape
- 'shadow-md',
- 'rounded-md',
- 'dark:border dark:border-surface-700',
-
- // Position
- 'static sm:absolute',
- 'z-10',
- { 'sm:absolute sm:left-full sm:top-0': props.level > 1 },
-
- // Color
- 'bg-surface-0 dark:bg-surface-700'
- ]
- }),
- submenuicon: {
- class: ['ml-auto']
- },
- separator: {
- class: 'border-t border-surface-200 dark:border-surface-600 my-1'
- },
- transition: {
- enterFromClass: 'opacity-0',
- enterActiveClass: 'transition-opacity duration-250'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/datatable/index.js b/frontend/packages/kwai-ui/src/presets/kwai/datatable/index.js
deleted file mode 100644
index 2c2860f03..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/datatable/index.js
+++ /dev/null
@@ -1,1170 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- 'relative',
-
- // Flex & Alignment
- { 'flex flex-col': props.scrollable && props.scrollHeight === 'flex' },
-
- // Size
- { 'h-full': props.scrollable && props.scrollHeight === 'flex' }
- ]
- }),
- loadingoverlay: {
- class: [
- // Position
- 'absolute',
- 'top-0 left-0',
- 'z-20',
-
- // Flex & Alignment
- 'flex items-center justify-center',
-
- // Size
- 'w-full h-full',
-
- // Color
- 'bg-surface-100/40 dark:bg-surface-800/40',
-
- // Transition
- 'transition duration-200'
- ]
- },
- loadingicon: {
- class: 'w-8 h-8 animate-spin'
- },
- wrapper: ({ props }) => ({
- class: [
- { relative: props.scrollable, 'flex flex-col grow': props.scrollable && props.scrollHeight === 'flex' },
-
- // Size
- { 'h-full': props.scrollable && props.scrollHeight === 'flex' }
- ]
- }),
- header: ({ props }) => ({
- class: [
- 'font-bold',
-
- // Shape
- props.showGridlines ? 'border-x border-t border-b-0' : 'border-y border-x-0',
-
- // Spacing
- 'p-4',
-
- // Color
- 'bg-surface-50 dark:bg-surface-800',
- 'border-surface-200 dark:border-surface-700',
- 'text-surface-700 dark:text-white/80'
- ]
- }),
- table: {
- class: 'w-full border-spacing-0 border-separate'
- },
- thead: ({ context }) => ({
- class: [
- {
- 'bg-surface-50 top-0 z-40 sticky': context.scrollable
- }
- ]
- }),
- tbody: ({ instance, context }) => ({
- class: [
- {
- 'sticky z-20': instance.frozenRow && context.scrollable
- }
- ]
- }),
- tfoot: ({ context }) => ({
- class: [
- {
- 'bg-surface-50 bottom-0 z-0': context.scrollable
- }
- ]
- }),
- footer: {
- class: [
- 'font-bold',
-
- // Shape
- 'border-t-0 border-b border-x-0',
-
- // Spacing
- 'p-4',
-
- // Color
- 'bg-surface-50 dark:bg-surface-800',
- 'border-surface-200 dark:border-surface-700',
- 'text-surface-700 dark:text-white/80'
- ]
- },
- column: {
- headercell: ({ context, props }) => ({
- class: [
- 'font-bold',
-
- // Position
- { 'sticky z-20 border-b': props.frozen || props.frozen === '' },
-
- { relative: context.resizable },
-
- // Alignment
- 'text-left',
-
- // Shape
- { 'first:border-l border-y border-r': context?.showGridlines },
- 'border-0 border-b border-solid',
-
- // Spacing
- context?.size === 'small' ? 'p-2' : context?.size === 'large' ? 'p-5' : 'p-4',
-
- // Color
- (props.sortable === '' || props.sortable) && context.sorted ? 'bg-primary-50 text-primary-700' : 'bg-surface-50 text-surface-700',
- (props.sortable === '' || props.sortable) && context.sorted ? 'dark:text-white dark:bg-primary-400/30' : 'dark:text-white/80 dark:bg-surface-800',
- 'border-surface-200 dark:border-surface-700 ',
-
- // States
- { 'hover:bg-surface-100 dark:hover:bg-surface-400/30': (props.sortable === '' || props.sortable) && !context?.sorted },
- 'focus-visible:outline-none focus-visible:outline-offset-0 focus-visible:ring focus-visible:ring-inset focus-visible:ring-primary-400/50 dark:focus-visible:ring-primary-300/50',
-
- // Transition
- { 'transition duration-200': props.sortable === '' || props.sortable },
-
- // Misc
- { 'cursor-pointer': props.sortable === '' || props.sortable },
- {
- 'overflow-hidden space-nowrap border-y bg-clip-padding': context.resizable // Resizable
- }
- ]
- }),
- headercontent: {
- class: 'flex items-center'
- },
- sort: ({ context }) => ({
- class: [context.sorted ? 'text-primary-500' : 'text-surface-700', context.sorted ? 'dark:text-primary-400' : 'dark:text-white/80']
- }),
- bodycell: ({ props, context, state, parent }) => ({
- class: [
- //Position
- { 'sticky box-border border-b': parent.instance.frozenRow },
- { 'sticky box-border border-b': props.frozen || props.frozen === '' },
-
- // Alignment
- 'text-left',
-
- // Shape
- 'border-0 border-b border-solid',
- { 'first:border-l border-r border-b': context?.showGridlines },
- { 'bg-surface-0 dark:bg-surface-800': parent.instance.frozenRow || props.frozen || props.frozen === '' },
-
- // Spacing
- { 'p-2': context?.size === 'small' && !state['d_editing'] },
- { 'p-5': context?.size === 'large' && !state['d_editing'] },
- { 'p-4': context?.size !== 'large' && context?.size !== 'small' && !state['d_editing'] },
- { 'py-[0.6rem] px-2': state['d_editing'] },
-
- // Color
- 'border-surface-200 dark:border-surface-700'
- ]
- }),
- footercell: ({ context }) => ({
- class: [
- // Font
- 'font-bold',
-
- // Alignment
- 'text-left',
-
- // Shape
- 'border-0 border-b border-solid',
- { 'border-x border-y': context?.showGridlines },
-
- // Spacing
- context?.size === 'small' ? 'p-2' : context?.size === 'large' ? 'p-5' : 'p-4',
-
- // Color
- 'border-surface-200 dark:border-surface-700',
- 'text-surface-700 dark:text-white/80',
- 'bg-surface-50 dark:bg-surface-800'
- ]
- }),
- sorticon: ({ context }) => ({
- class: ['ml-2', context.sorted ? 'text-primary-700 dark:text-white/80' : 'text-surface-700 dark:text-white/70']
- }),
- sortbadge: {
- class: [
- // Flex & Alignment
- 'flex items-center justify-center align-middle',
-
- // Shape
- 'rounded-full',
-
- // Size
- 'w-[1.143rem] leading-[1.143rem]',
-
- // Spacing
- 'ml-2',
-
- // Color
- 'text-primary-700 dark:text-white',
- 'bg-primary-50 dark:bg-primary-400/30'
- ]
- },
- columnfilter: {
- class: 'inline-flex items-center ml-auto'
- },
- filteroverlay: {
- class: [
- // Position
- 'absolute top-0 left-0',
-
- // Shape
- 'border-0 dark:border',
- 'rounded-md',
- 'shadow-md',
-
- // Size
- 'min-w-[12.5rem]',
-
- // Color
- 'bg-surface-0 dark:bg-surface-800',
- 'text-surface-800 dark:text-white/80',
- 'dark:border-surface-700'
- ]
- },
- filtermatchmodedropdown: {
- root: ({ state }) => ({
- class: [
- // Display and Position
- 'flex',
- 'relative',
-
- // Spacing
- 'my-2',
-
- // Shape
- 'w-full',
- 'rounded-md',
-
- // Color and Background
- 'bg-surface-0 dark:bg-surface-900',
- 'border border-surface-300 dark:border-surface-700',
- 'text-surface-800 dark:text-white/80',
- 'placeholder:text-surface-400 dark:placeholder:text-surface-500',
-
- // Transitions
- 'transition-all',
- 'duration-200',
-
- // States
- 'hover:border-primary-500 dark:hover:border-primary-300',
- { 'outline-none outline-offset-0 ring ring-primary-400/50 dark:ring-primary-300/50': state.focused },
-
- // Misc
- 'cursor-pointer',
- 'select-none'
- ]
- })
- },
- filterrowitems: {
- class: 'm-0 p-0 py-3 list-none'
- },
- filterrowitem: ({ context }) => ({
- class: [
- // Font
- 'font-normal',
- 'leading-none',
-
- // Position
- 'relative',
-
- // Shape
- 'border-0',
- 'rounded-none',
-
- // Spacing
- 'm-0',
- 'py-3 px-5',
-
- // Color
- { 'text-surface-700 dark:text-white/80': !context?.highlighted },
- { 'bg-surface-0 dark:bg-surface-800 text-surface-700 dark:text-white/80': !context?.highlighted },
- { 'bg-primary-100 dark:bg-primary-400/40 text-primary-700 dark:text-white/80': context?.highlighted },
- { 'bg-primary-50 dark:bg-primary-400/40 text-primary-700 dark:text-white/80': context?.highlighted },
-
- //States
- { 'hover:bg-surface-100 dark:hover:bg-surface-600/80': !context?.highlighted },
- { 'hover:text-surface-700 hover:bg-surface-100 dark:hover:text-white dark:hover:bg-surface-600/80': !context?.highlighted },
- 'focus-visible:outline-none focus-visible:outline-offset-0 focus-visible:ring focus-visible:ring-inset focus-visible:ring-primary-400/50 dark:focus-visible:ring-primary-300/50',
-
- // Transitions
- 'transition-shadow',
- 'duration-200',
-
- // Misc
- 'cursor-pointer',
- 'overflow-hidden',
- 'whitespace-nowrap'
- ]
- }),
- filteroperator: {
- class: [
- // Spacing
- 'px-5 py-3',
-
- // Shape
- 'border-b border-solid',
- 'rounded-t-md',
-
- // Color
- 'text-surface-700 dark:text-white/80',
- 'border-surface-200 dark:border-surface-800',
- 'bg-surface-0 dark:bg-surface-700'
- ]
- },
- filteroperatordropdown: {
- root: ({ state }) => ({
- class: [
- // Display and Position
- 'inline-flex',
- 'relative',
-
- // Shape
- 'w-full',
- 'rounded-md',
-
- // Color and Background
- 'bg-surface-0 dark:bg-surface-900',
- 'border border-surface-300 dark:border-surface-700',
-
- // Transitions
- 'transition-all',
- 'duration-200',
-
- // States
- 'hover:border-primary-500 dark:hover:border-primary-300',
- { 'outline-none outline-offset-0 ring ring-primary-400/50 dark:ring-primary-300/50': state.focused },
-
- // Misc
- 'cursor-pointer',
- 'select-none'
- ]
- }),
- input: ({ props }) => ({
- class: [
- //Font
- 'font-sans',
- 'leading-none',
-
- // Display
- 'block',
- 'flex-auto',
-
- // Color and Background
- 'bg-transparent',
- 'border-0',
- { 'text-surface-800 dark:text-white/80': props.modelValue, 'text-surface-400 dark:text-surface-500': !props.modelValue },
- 'placeholder:text-surface-400 dark:placeholder:text-surface-500',
-
- // Sizing and Spacing
- 'w-[1%]',
- 'p-3',
-
- //Shape
- 'rounded-none',
-
- // Transitions
- 'transition',
- 'duration-200',
-
- // States
- 'focus:outline-none focus:shadow-none',
-
- // Misc
- 'relative',
- 'cursor-pointer',
- 'overflow-hidden overflow-ellipsis',
- 'whitespace-nowrap',
- 'appearance-none'
- ]
- }),
- trigger: {
- class: [
- // Flexbox
- 'flex items-center justify-center',
- 'shrink-0',
-
- // Color and Background
- 'bg-transparent',
- 'text-surface-500',
-
- // Size
- 'w-12',
-
- // Shape
- 'rounded-tr-md',
- 'rounded-br-md'
- ]
- },
- panel: {
- class: [
- // Position
- 'absolute top-0 left-0',
-
- // Shape
- 'border-0 dark:border',
- 'rounded-md',
- 'shadow-md',
-
- // Color
- 'bg-surface-0 dark:bg-surface-800',
- 'text-surface-800 dark:text-white/80',
- 'dark:border-surface-700'
- ]
- },
- item: ({ context }) => ({
- class: [
- // Font
- 'font-normal',
- 'leading-none',
-
- // Position
- 'relative',
-
- // Shape
- 'border-0',
- 'rounded-none',
-
- // Spacing
- 'm-0',
- 'py-3 px-5',
-
- // Color
- { 'text-surface-700 dark:text-white/80': !context.focused && !context.selected },
- { 'bg-surface-50 dark:bg-surface-600/60 text-surface-700 dark:text-white/80': context.focused && !context.selected },
- { 'bg-primary-100 dark:bg-primary-400/40 text-primary-700 dark:text-white/80': context.focused && context.selected },
- { 'bg-primary-50 dark:bg-primary-400/40 text-primary-700 dark:text-white/80': !context.focused && context.selected },
-
- //States
- { 'hover:bg-surface-100 dark:hover:bg-surface-600/80': !context.focused && !context.selected },
- { 'hover:text-surface-700 hover:bg-surface-100 dark:hover:text-white dark:hover:bg-surface-600/80': context.focused && !context.selected },
-
- // Transitions
- 'transition-shadow',
- 'duration-200',
-
- // Misc
- 'cursor-pointer',
- 'overflow-hidden',
- 'whitespace-nowrap'
- ]
- })
- },
- filterconstraint: {
- class: [
- // Spacing
- 'py-3 px-5',
-
- // Shape
- 'border-b border-solid',
-
- // Color
- 'border-surface-200 dark:border-surface-700'
- ]
- },
- filteraddrule: {
- class: 'py-3 px-5'
- },
- filteraddrulebutton: {
- root: {
- class: [
- 'relative',
-
- // Alignments
- 'items-center inline-flex text-center align-bottom justify-center',
-
- // Sizes & Spacing
- 'text-sm py-2 px-3 w-full',
-
- // Shape
- 'rounded-md',
-
- 'bg-transparent border-transparent',
- 'text-primary-500 dark:text-primary-400',
- 'hover:bg-primary-300/20',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // Misc
- 'cursor-pointer overflow-hidden select-none'
- ]
- },
- label: {
- class: 'flex-auto grow-0'
- },
- icon: {
- class: 'mr-2'
- }
- },
- filterremovebutton: {
- root: {
- class: [
- 'relative',
-
- // Alignments
- 'items-center inline-flex text-center align-bottom justify-center',
-
- // Sizes & Spacing
- 'text-sm py-2 px-3 w-full mt-2',
-
- // Shape
- 'rounded-md',
-
- 'bg-transparent border-transparent',
- 'text-red-500 dark:text-red-400',
- 'hover:bg-red-300/20',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // Misc
- 'cursor-pointer overflow-hidden select-none'
- ]
- },
- label: {
- class: 'flex-auto grow-0'
- },
- icon: {
- class: 'mr-2'
- }
- },
- filterbuttonbar: {
- class: [
- // Flex & Alignment
- 'flex items-center justify-between',
-
- // Space
- 'py-3 px-5'
- ]
- },
- filterclearbutton: {
- root: {
- class: [
- 'relative',
-
- // Alignments
- 'items-center inline-flex text-center align-bottom justify-center',
-
- // Sizes & Spacing
- 'text-sm py-2 px-3',
-
- // Shape
- 'rounded-md',
-
- 'text-primary-500 border border-primary-500',
- 'hover:bg-primary-300/20',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // Misc
- 'cursor-pointer overflow-hidden select-none'
- ]
- }
- },
- filterapplybutton: {
- root: {
- class: [
- 'relative',
-
- // Alignments
- 'items-center inline-flex text-center align-bottom justify-center',
-
- // Sizes & Spacing
- 'text-sm py-2 px-3',
-
- // Shape
- 'rounded-md',
-
- 'text-white dark:text-surface-900',
- 'bg-primary-500 dark:bg-primary-400',
- 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // Misc
- 'cursor-pointer overflow-hidden select-none'
- ]
- }
- },
- filtermenubutton: ({ context }) => ({
- class: [
- 'relative',
- // Flex & Alignment
- 'inline-flex items-center justify-center',
-
- // Size
- 'w-8 h-8',
-
- // Spacing
- 'ml-2',
-
- // Shape
- 'rounded-full',
-
- // Color
- { 'bg-primary-50 text-primary-700': context.active },
- 'dark:text-white/70 dark:hover:text-white/80 dark:bg-surface-800',
-
- // States
- 'hover:text-surface-700 hover:bg-surface-300/20',
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
-
- // Transition
- 'transition duration-200',
-
- // Misc
- 'cursor-pointer no-underline overflow-hidden'
- ]
- }),
- headerfilterclearbutton: ({ context }) => ({
- class: [
- 'relative',
-
- // Flex & Alignment
- 'inline-flex items-center justify-center',
- 'text-left',
-
- // Shape
- 'border-none',
-
- // Spacing
- 'm-0 p-0 ml-2',
-
- // Color
- 'bg-transparent',
-
- // Misc
- 'cursor-pointer no-underline overflow-hidden select-none',
- {
- invisible: !context.hidden
- }
- ]
- }),
- rowtoggler: {
- class: [
- 'relative',
-
- // Flex & Alignment
- 'inline-flex items-center justify-center',
- 'text-left',
-
- // Spacing
- 'm-0 p-0',
-
- // Size
- 'w-8 h-8',
-
- // Shape
- 'border-0 rounded-full',
-
- // Color
- 'text-surface-500 dark:text-white/70',
- 'bg-transparent',
- 'focus-visible:outline-none focus-visible:outline-offset-0',
- 'focus-visible:ring focus-visible:ring-primary-400/50 dark:focus-visible:ring-primary-300/50',
-
- // Transition
- 'transition duration-200',
-
- // Misc
- 'overflow-hidden',
- 'cursor-pointer select-none'
- ]
- },
- columnresizer: {
- class: [
- 'block',
-
- // Position
- 'absolute top-0 right-0',
-
- // Sizing
- 'w-2 h-full',
-
- // Spacing
- 'm-0 p-0',
-
- // Color
- 'border border-transparent',
-
- // Misc
- 'cursor-col-resize'
- ]
- },
- rowreordericon: {
- class: 'cursor-move'
- },
- roweditorinitbutton: {
- class: [
- 'relative',
-
- // Flex & Alignment
- 'inline-flex items-center justify-center',
- 'text-left',
-
- // Size
- 'w-8 h-8',
-
- // Shape
- 'border-0 rounded-full',
-
- // Color
- 'text-surface-700 dark:text-white/70',
- 'border-transparent',
-
- // States
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
- 'hover:text-surface-700 hover:bg-surface-300/20',
-
- // Transition
- 'transition duration-200',
-
- // Misc
- 'overflow-hidden',
- 'cursor-pointer select-none'
- ]
- },
- roweditorsavebutton: {
- class: [
- 'relative',
-
- // Flex & Alignment
- 'inline-flex items-center justify-center',
- 'text-left',
-
- // Size
- 'w-8 h-8',
-
- // Shape
- 'border-0 rounded-full',
-
- // Color
- 'text-surface-700 dark:text-white/70',
- 'border-transparent',
-
- // States
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
- 'hover:text-surface-700 hover:bg-surface-300/20',
-
- // Transition
- 'transition duration-200',
-
- // Misc
- 'overflow-hidden',
- 'cursor-pointer select-none'
- ]
- },
- roweditorcancelbutton: {
- class: [
- 'relative',
-
- // Flex & Alignment
- 'inline-flex items-center justify-center',
- 'text-left',
-
- // Size
- 'w-8 h-8',
-
- // Shape
- 'border-0 rounded-full',
-
- // Color
- 'text-surface-700 dark:text-white/70',
- 'border-transparent',
-
- // States
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
- 'hover:text-surface-700 hover:bg-surface-300/20',
-
- // Transition
- 'transition duration-200',
-
- // Misc
- 'overflow-hidden',
- 'cursor-pointer select-none'
- ]
- },
- rowRadiobutton: {
- root: {
- class: [
- 'relative',
-
- // Flexbox & Alignment
- 'inline-flex',
- 'align-bottom',
-
- // Size
- 'w-[1.571rem] h-[1.571rem]',
-
- // Misc
- 'cursor-pointer',
- 'select-none'
- ]
- },
- box: ({ props }) => ({
- class: [
- // Flexbox
- 'flex justify-center items-center',
-
- // Size
- 'w-[1.571rem] h-[1.571rem]',
-
- // Shape
- 'border-2',
- 'rounded-full',
-
- // Transition
- 'transition duration-200 ease-in-out',
-
- // Colors
- {
- 'text-surface-700 dark:text-white/80': !props.modelValue,
- 'bg-surface-0 dark:bg-surface-900': !props.modelValue,
- 'border-surface-300 dark:border-surface-700': !props.modelValue,
- 'border-primary-500 dark:border-primary-400': props.modelValue,
- 'bg-primary-500 dark:bg-primary-400': props.modelValue
- },
-
- // States
- {
- 'peer-hover:border-primary-500 dark:peer-hover:border-primary-400': !props.disabled,
- 'peer-hover:border-primary-600 dark:peer-hover:border-primary-300 peer-hover:bg-primary-600 dark:peer-hover:bg-primary-300': !props.disabled && props.modelValue,
- 'peer-focus-visible:border-primary-500 dark:peer-focus-visible:border-primary-400 peer-focus-visible:ring-2 peer-focus-visible:ring-primary-400/20 dark:peer-focus-visible:ring-primary-300/20': !props.disabled,
- 'opacity-60 cursor-default': props.disabled
- }
- ]
- }),
- input: {
- class: [
- 'peer',
-
- // Size
- 'w-full ',
- 'h-full',
-
- // Position
- 'absolute',
- 'top-0 left-0',
- 'z-10',
-
- // Spacing
- 'p-0',
- 'm-0',
-
- // Shape
- 'opacity-0',
- 'rounded-md',
- 'outline-none',
- 'border-2 border-surface-200 dark:border-surface-700',
-
- // Misc
- 'appearance-none',
- 'cursor-pointer'
- ]
- },
- icon: ({ props }) => ({
- class: [
- 'block',
-
- // Shape
- 'rounded-full',
-
- // Size
- 'w-[0.857rem] h-[0.857rem]',
-
- // Colors
- 'bg-surface-0 dark:bg-surface-900',
-
- // Conditions
- {
- 'backface-hidden scale-10 invisible': !props.modelValue,
- 'transform visible scale-[1.1]': props.modelValue
- },
-
- // Transition
- 'transition duration-200'
- ]
- })
- },
- headercheckbox: {
- root: {
- class: [
- 'relative',
-
- // Alignment
- 'inline-flex',
- 'align-bottom',
-
- // Size
- 'w-6',
- 'h-6',
-
- // Misc
- 'cursor-pointer',
- 'select-none'
- ]
- },
- box: ({ props, context }) => ({
- class: [
- // Alignment
- 'flex',
- 'items-center',
- 'justify-center',
-
- // Size
- 'w-6',
- 'h-6',
-
- // Shape
- 'rounded-md',
- 'border-2',
-
- // Colors
- {
- 'border-surface-200 bg-surface-0 dark:border-surface-700 dark:bg-surface-900': !context.checked,
- 'border-primary-500 bg-primary-500 dark:border-primary-400 dark:bg-primary-400': context.checked
- },
-
- // States
- {
- 'peer-hover:border-primary-500 dark:peer-hover:border-primary-400': !props.disabled && !context.checked,
- 'peer-hover:bg-primary-600 dark:peer-hover:bg-primary-300 peer-hover:border-primary-700 dark:peer-hover:border-primary-300': !props.disabled && context.checked,
- 'peer-focus-visible:border-primary-500 dark:peer-focus-visible:border-primary-400 peer-focus-visible:ring-2 peer-focus-visible:ring-primary-400/20 dark:peer-focus-visible:ring-primary-300/20': !props.disabled,
- 'cursor-default opacity-60': props.disabled
- },
-
- // Transitions
- 'transition-colors',
- 'duration-200'
- ]
- }),
- input: {
- class: [
- 'peer',
-
- // Size
- 'w-full ',
- 'h-full',
-
- // Position
- 'absolute',
- 'top-0 left-0',
- 'z-10',
-
- // Spacing
- 'p-0',
- 'm-0',
-
- // Shape
- 'opacity-0',
- 'rounded-md',
- 'outline-none',
- 'border-2 border-surface-200 dark:border-surface-700',
-
- // Misc
- 'appearance-none',
- 'cursor-pointer'
- ]
- },
- icon: {
- class: [
- // Font
- 'text-base leading-none',
-
- // Size
- 'w-4',
- 'h-4',
-
- // Colors
- 'text-white dark:text-surface-900',
-
- // Transitions
- 'transition-all',
- 'duration-200'
- ]
- }
- },
- rowCheckbox: {
- root: {
- class: [
- 'relative',
-
- // Alignment
- 'inline-flex',
- 'align-bottom',
-
- // Size
- 'w-6',
- 'h-6',
-
- // Misc
- 'cursor-pointer',
- 'select-none'
- ]
- },
- box: ({ props, context }) => ({
- class: [
- // Alignment
- 'flex',
- 'items-center',
- 'justify-center',
-
- // Size
- 'w-6',
- 'h-6',
-
- // Shape
- 'rounded-md',
- 'border-2',
-
- // Colors
- {
- 'border-surface-200 bg-surface-0 dark:border-surface-700 dark:bg-surface-900': !context.checked,
- 'border-primary-500 bg-primary-500 dark:border-primary-400 dark:bg-primary-400': context.checked
- },
-
- // States
- {
- 'peer-hover:border-primary-500 dark:peer-hover:border-primary-400': !props.disabled && !context.checked,
- 'peer-hover:bg-primary-600 dark:peer-hover:bg-primary-300 peer-hover:border-primary-700 dark:peer-hover:border-primary-300': !props.disabled && context.checked,
- 'peer-focus-visible:border-primary-500 dark:peer-focus-visible:border-primary-400 peer-focus-visible:ring-2 peer-focus-visible:ring-primary-400/20 dark:peer-focus-visible:ring-primary-300/20': !props.disabled,
- 'cursor-default opacity-60': props.disabled
- },
-
- // Transitions
- 'transition-colors',
- 'duration-200'
- ]
- }),
- input: {
- class: [
- 'peer',
-
- // Size
- 'w-full ',
- 'h-full',
-
- // Position
- 'absolute',
- 'top-0 left-0',
- 'z-10',
-
- // Spacing
- 'p-0',
- 'm-0',
-
- // Shape
- 'opacity-0',
- 'rounded-md',
- 'outline-none',
- 'border-2 border-surface-200 dark:border-surface-700',
-
- // Misc
- 'appearance-none',
- 'cursor-pointer'
- ]
- },
- icon: {
- class: [
- // Font
- 'text-base leading-none',
-
- // Size
- 'w-4',
- 'h-4',
-
- // Colors
- 'text-white dark:text-surface-900',
-
- // Transitions
- 'transition-all',
- 'duration-200'
- ]
- }
- },
- transition: {
- enterFromClass: 'opacity-0 scale-y-[0.8]',
- enterActiveClass: 'transition-[transform,opacity] duration-[120ms] ease-[cubic-bezier(0,0,0.2,1)]',
- leaveActiveClass: 'transition-opacity duration-100 ease-linear',
- leaveToClass: 'opacity-0'
- }
- },
- bodyrow: ({ context, props }) => ({
- class: [
- // Color
- 'dark:text-white/80',
- { 'bg-primary-50 text-primary-700 dark:bg-primary-400/30': context.selected },
- { 'bg-surface-0 text-surface-600 dark:bg-surface-800': !context.selected },
- { 'font-bold bg-surface-0 dark:bg-surface-800': props.frozenRow },
- { 'odd:bg-surface-0 odd:text-surface-600 dark:odd:bg-surface-800 even:bg-surface-50 even:text-surface-600 dark:even:bg-surface-900/50': context.stripedRows },
-
- // State
- { 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 ring-inset dark:focus:ring-primary-300/50': context.selectable },
- { 'hover:bg-surface-300/20 hover:text-surface-600': props.selectionMode && !context.selected },
-
- // Transition
- { 'transition duration-200': (props.selectionMode && !context.selected) || props.rowHover },
-
- // Misc
- { 'cursor-pointer': props.selectionMode }
- ]
- }),
- rowexpansion: {
- class: 'bg-surface-0 dark:bg-surface-800 text-surface-600 dark:text-white/80'
- },
- rowgroupheader: {
- class: ['sticky z-20', 'bg-surface-0 text-surface-600 dark:text-white/70', 'dark:bg-surface-800']
- },
- rowgroupfooter: {
- class: ['sticky z-20', 'bg-surface-0 text-surface-600 dark:text-white/70', 'dark:bg-surface-800']
- },
- rowgrouptoggler: {
- class: [
- 'relative',
-
- // Flex & Alignment
- 'inline-flex items-center justify-center',
- 'text-left',
-
- // Spacing
- 'm-0 p-0',
-
- // Size
- 'w-8 h-8',
-
- // Shape
- 'border-0 rounded-full',
-
- // Color
- 'text-surface-500 dark:text-white/70',
- 'bg-transparent',
- 'focus-visible:outline-none focus-visible:outline-offset-0',
- 'focus-visible:ring focus-visible:ring-primary-400/50 dark:focus-visible:ring-primary-300/50',
-
- // Transition
- 'transition duration-200',
-
- // Misc
- 'overflow-hidden',
- 'cursor-pointer select-none'
- ]
- },
- rowgrouptogglericon: {
- class: 'inline-block w-4 h-4'
- },
- resizehelper: {
- class: 'absolute hidden w-[2px] z-20 bg-primary-500 dark:bg-primary-400'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/dataview/index.js b/frontend/packages/kwai-ui/src/presets/kwai/dataview/index.js
deleted file mode 100644
index 2eed11b05..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/dataview/index.js
+++ /dev/null
@@ -1,40 +0,0 @@
-export default {
- content: {
- class: [
- // Spacing
- 'p-0',
-
- // Shape
- 'border-0',
-
- // Color
- 'text-surface-700 dark:text-white/80',
- 'bg-surface-0 dark:bg-surface-800'
- ]
- },
- grid: {
- class: [
- // flex
- 'flex flex-wrap',
-
- // Spacing
- 'ml-0 mr-0 mt-0',
-
- // Color
- 'bg-surface-0 dark:bg-surface-800'
- ]
- },
- header: {
- class: [
- 'font-bold',
-
- // Spacing
- 'p-4',
-
- // Color
- 'text-surface-800 dark:text-white/80',
- 'bg-surface-50 dark:bg-surface-800',
- 'border-surface-200 dark:border-surface-700 border-y'
- ]
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/deferred/index.js b/frontend/packages/kwai-ui/src/presets/kwai/deferred/index.js
deleted file mode 100644
index 2064371ae..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/deferred/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-export default {
- root: {}
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/dialog/index.js b/frontend/packages/kwai-ui/src/presets/kwai/dialog/index.js
deleted file mode 100644
index adb8f1e6e..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/dialog/index.js
+++ /dev/null
@@ -1,235 +0,0 @@
-export default {
- root: ({ state }) => ({
- class: [
- // Shape
- 'rounded-lg',
- 'shadow-lg',
- 'border-0',
-
- // Size
- 'max-h-[90vh]',
- 'w-[50vw]',
- 'm-0',
-
- // Color
- 'dark:border',
- 'dark:border-surface-700',
-
- // Transitions
- 'transform',
- 'scale-100',
-
- // Maximized State
- {
- 'transition-none': state.maximized,
- 'transform-none': state.maximized,
- '!w-screen': state.maximized,
- '!h-screen': state.maximized,
- '!max-h-full': state.maximized,
- '!top-0': state.maximized,
- '!left-0': state.maximized
- }
- ]
- }),
- header: {
- class: [
- // Flexbox and Alignment
- 'flex items-center justify-between',
- 'shrink-0',
-
- // Spacing
- 'p-6',
-
- // Shape
- 'border-t-0',
- 'rounded-tl-lg',
- 'rounded-tr-lg',
-
- // Colors
- 'bg-surface-0 dark:bg-surface-800',
- 'text-surface-700 dark:text-surface-0/80'
- ]
- },
- title: {
- class: ['font-bold text-lg']
- },
- icons: {
- class: ['flex items-center']
- },
- closeButton: {
- class: [
- 'relative',
-
- // Flexbox and Alignment
- 'flex items-center justify-center',
-
- // Size and Spacing
- 'mr-2',
- 'last:mr-0',
- 'w-8 h-8',
-
- // Shape
- 'border-0',
- 'rounded-full',
-
- // Colors
- 'text-surface-500',
- 'bg-transparent',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // States
- 'hover:text-surface-700 dark:hover:text-white/80',
- 'hover:bg-surface-100 dark:hover:bg-surface-800/80',
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-inset',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
-
- // Misc
- 'overflow-hidden'
- ]
- },
- maximizablebutton: {
- class: [
- 'relative',
-
- // Flexbox and Alignment
- 'flex items-center justify-center',
-
- // Size and Spacing
- 'mr-2',
- 'last:mr-0',
- 'w-8 h-8',
-
- // Shape
- 'border-0',
- 'rounded-full',
-
- // Colors
- 'text-surface-500',
- 'bg-transparent',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // States
- 'hover:text-surface-700 dark:hover:text-white/80',
- 'hover:bg-surface-100 dark:hover:bg-surface-800/80',
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-inset',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
-
- // Misc
- 'overflow-hidden'
- ]
- },
- closeButtonIcon: {
- class: [
- // Display
- 'inline-block',
-
- // Size
- 'w-4',
- 'h-4'
- ]
- },
- maximizableicon: {
- class: [
- // Display
- 'inline-block',
-
- // Size
- 'w-4',
- 'h-4'
- ]
- },
- content: ({ state, instance }) => ({
- class: [
- // Spacing
- 'px-6',
- 'pb-8',
- 'pt-0',
-
- // Shape
- {
- grow: state.maximized,
- 'rounded-bl-lg': !instance.$slots.footer,
- 'rounded-br-lg': !instance.$slots.footer
- },
-
- // Colors
- 'bg-surface-0 dark:bg-surface-800',
- 'text-surface-700 dark:text-surface-0/80',
-
- // Misc
- 'overflow-y-auto'
- ]
- }),
- footer: {
- class: [
- // Flexbox and Alignment
- 'flex items-center justify-end',
- 'shrink-0',
- 'text-right',
- 'gap-2',
-
- // Spacing
- 'px-6',
- 'pb-6',
-
- // Shape
- 'border-t-0',
- 'rounded-b-lg',
-
- // Colors
- 'bg-surface-0 dark:bg-surface-800',
- 'text-surface-700 dark:text-surface-0/80'
- ]
- },
- mask: ({ props }) => ({
- class: [
- // Transitions
- 'transition-all',
- 'duration-300',
- { 'p-5': !props.position == 'full' },
-
- // Background and Effects
- { 'has-[.mask-active]:bg-transparent bg-black/40': props.modal, 'has-[.mask-active]:backdrop-blur-none backdrop-blur-sm': props.modal }
- ]
- }),
- transition: ({ props }) => {
- return props.position === 'top'
- ? {
- enterFromClass: 'opacity-0 scale-75 translate-x-0 -translate-y-full translate-z-0 mask-active',
- enterActiveClass: 'transition-all duration-200 ease-out',
- leaveActiveClass: 'transition-all duration-200 ease-out',
- leaveToClass: 'opacity-0 scale-75 translate-x-0 -translate-y-full translate-z-0 mask-active'
- }
- : props.position === 'bottom'
- ? {
- enterFromClass: 'opacity-0 scale-75 translate-y-full mask-active',
- enterActiveClass: 'transition-all duration-200 ease-out',
- leaveActiveClass: 'transition-all duration-200 ease-out',
- leaveToClass: 'opacity-0 scale-75 translate-x-0 translate-y-full translate-z-0 mask-active'
- }
- : props.position === 'left' || props.position === 'topleft' || props.position === 'bottomleft'
- ? {
- enterFromClass: 'opacity-0 scale-75 -translate-x-full translate-y-0 translate-z-0 mask-active',
- enterActiveClass: 'transition-all duration-200 ease-out',
- leaveActiveClass: 'transition-all duration-200 ease-out',
- leaveToClass: 'opacity-0 scale-75 -translate-x-full translate-y-0 translate-z-0 mask-active'
- }
- : props.position === 'right' || props.position === 'topright' || props.position === 'bottomright'
- ? {
- enterFromClass: 'opacity-0 scale-75 translate-x-full translate-y-0 translate-z-0 mask-active',
- enterActiveClass: 'transition-all duration-200 ease-out',
- leaveActiveClass: 'transition-all duration-200 ease-out',
- leaveToClass: 'opacity-0 scale-75 translate-x-full translate-y-0 translate-z-0 mask-active'
- }
- : {
- enterFromClass: 'opacity-0 scale-75 mask-active',
- enterActiveClass: 'transition-all duration-200 ease-out',
- leaveActiveClass: 'transition-all duration-200 ease-out',
- leaveToClass: 'opacity-0 scale-75 mask-active'
- };
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/divider/index.js b/frontend/packages/kwai-ui/src/presets/kwai/divider/index.js
deleted file mode 100644
index b4406974e..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/divider/index.js
+++ /dev/null
@@ -1,67 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- // Flex and Position
- 'flex relative',
- { 'justify-center': props.layout == 'vertical' },
- { 'items-center': props.layout == 'vertical' },
- {
- 'justify-start': props?.align == 'left' && props.layout == 'horizontal',
- 'justify-center': props?.align == 'center' && props.layout == 'horizontal',
- 'justify-end': props?.align == 'right' && props.layout == 'horizontal',
- 'items-center': props?.align == 'top' && props.layout == 'vertical',
- 'items-start': props?.align == 'center' && props.layout == 'vertical',
- 'items-end': props?.align == 'bottom' && props.layout == 'vertical'
- },
-
- // Spacing
- {
- 'my-5 mx-0 py-0 px-5': props.layout == 'horizontal',
- 'mx-4 md:mx-5 py-5': props.layout == 'vertical'
- },
-
- // Size
- {
- 'w-full': props.layout == 'horizontal',
- 'min-h-full': props.layout == 'vertical'
- },
-
- // Before: Line
- 'before:block',
-
- // Position
- {
- 'before:absolute before:left-0 before:top-1/2': props.layout == 'horizontal',
- 'before:absolute before:left-1/2 before:top-0 before:transform before:-translate-x-1/2': props.layout == 'vertical'
- },
-
- // Size
- {
- 'before:w-full': props.layout == 'horizontal',
- 'before:min-h-full': props.layout == 'vertical'
- },
-
- // Shape
- {
- 'before:border-solid': props.type == 'solid',
- 'before:border-dotted': props.type == 'dotted',
- 'before:border-dashed': props.type == 'dashed'
- },
-
- // Color
- {
- 'before:border-t before:border-surface-200 before:dark:border-surface-600': props.layout == 'horizontal',
- 'before:border-l before:border-surface-200 before:dark:border-surface-600': props.layout == 'vertical'
- }
- ]
- }),
- content: {
- class: [
- // Space and Position
- 'px-1 z-10',
-
- // Color
- 'bg-surface-0 dark:bg-surface-800'
- ]
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/dock/index.js b/frontend/packages/kwai-ui/src/presets/kwai/dock/index.js
deleted file mode 100644
index 5a33adedf..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/dock/index.js
+++ /dev/null
@@ -1,93 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- // Positioning
- 'absolute z-1',
- {
- 'left-0 bottom-0 w-full': props.position == 'bottom',
- 'left-0 top-0 w-full': props.position == 'top',
- 'left-0 top-0 h-full': props.position == 'left',
- 'right-0 top-0 h-full': props.position == 'right'
- },
-
- // Flexbox & Alignment
- 'flex justify-center items-center',
-
- // Interactivity
- 'pointer-events-none'
- ]
- }),
- container: {
- class: [
- // Flexbox
- 'flex',
-
- // Shape & Border
- 'rounded-md',
-
- // Color
- 'bg-surface-0/10 dark:bg-surface-900/20 border border-surface-0/20',
- 'backdrop-blur-sm',
-
- // Spacing
- 'p-2',
-
- // Misc
- 'pointer-events-auto'
- ]
- },
- menu: ({ props }) => ({
- class: [
- // Flexbox & Alignment
- 'flex items-center justify-center',
- {
- 'flex-col': props.position == 'left' || props.position == 'right'
- },
-
- // List Style
- 'm-0 p-0 list-none',
-
- // Shape
- 'outline-none'
- ]
- }),
- menuitem: ({ props, context, instance }) => ({
- class: [
- // Spacing & Shape
- 'p-2 rounded-md',
-
- // Conditional Scaling
- {
- 'hover:scale-150': instance.currentIndex === context.index,
- 'scale-125': instance.currentIndex - 1 === context.index || instance.currentIndex + 1 === context.index,
- 'scale-110': instance.currentIndex - 2 === context.index || instance.currentIndex + 2 === context.index
- },
-
- // Positioning & Hover States
- {
- 'origin-bottom hover:mx-6': props.position == 'bottom',
- 'origin-top hover:mx-6': props.position == 'top',
- 'origin-left hover:my-6': props.position == 'left',
- 'origin-right hover:my-6': props.position == 'right'
- },
-
- // Transitions & Transform
- 'transition-all duration-200 ease-cubic-bezier-will-change-transform transform'
- ]
- }),
- action: {
- class: [
- // Flexbox & Alignment
- 'flex flex-col items-center justify-center',
-
- // Position
- 'relative',
-
- // Size
- 'w-16 h-16',
-
- // Misc
- 'cursor-default overflow-hidden'
- ]
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/dropdown/index.js b/frontend/packages/kwai-ui/src/presets/kwai/dropdown/index.js
deleted file mode 100644
index 10a834f37..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/dropdown/index.js
+++ /dev/null
@@ -1,265 +0,0 @@
-export default {
- root: ({ props, state }) => ({
- class: [
- // Display and Position
- 'inline-flex',
- 'relative',
-
- // Shape
- 'rounded-md',
-
- // Color and Background
- 'bg-surface-0 dark:bg-surface-900',
- 'border',
- { 'border-surface-300 dark:border-surface-600': !props.invalid },
-
- // Invalid State
- { 'border-red-500 dark:border-red-400': props.invalid },
-
- // Transitions
- 'transition-all',
- 'duration-200',
-
- // States
- { 'hover:border-primary-500 dark:hover:border-primary-300': !props.invalid },
- { 'outline-none outline-offset-0 ring ring-primary-400/50 dark:ring-primary-300/50': state.focused },
-
- // Misc
- 'cursor-pointer',
- 'select-none',
- { 'opacity-60': props.disabled, 'pointer-events-none': props.disabled, 'cursor-default': props.disabled }
- ]
- }),
- input: ({ props }) => ({
- class: [
- //Font
- 'font-sans',
- 'leading-none',
-
- // Display
- 'block',
- 'flex-auto',
-
- // Color and Background
- 'bg-transparent',
- 'border-0',
- { 'text-surface-800 dark:text-white/80': props.modelValue != undefined, 'text-surface-400 dark:text-surface-500': props.modelValue == undefined },
- 'placeholder:text-surface-400 dark:placeholder:text-surface-500',
-
- // Sizing and Spacing
- 'w-[1%]',
- 'p-3',
- { 'pr-7': props.showClear },
-
- //Shape
- 'rounded-none',
-
- // Transitions
- 'transition',
- 'duration-200',
-
- // States
- 'focus:outline-none focus:shadow-none',
-
- // Misc
- 'relative',
- 'cursor-pointer',
- 'overflow-hidden overflow-ellipsis',
- 'whitespace-nowrap',
- 'appearance-none'
- ]
- }),
- trigger: {
- class: [
- // Flexbox
- 'flex items-center justify-center',
- 'shrink-0',
-
- // Color and Background
- 'bg-transparent',
- 'text-surface-500',
-
- // Size
- 'w-12',
-
- // Shape
- 'rounded-tr-md',
- 'rounded-br-md'
- ]
- },
- panel: {
- class: [
- // Position
- 'absolute top-0 left-0',
-
- // Shape
- 'border-0 dark:border',
- 'rounded-md',
- 'shadow-md',
-
- // Color
- 'bg-surface-0 dark:bg-surface-800',
- 'text-surface-800 dark:text-white/80',
- 'dark:border-surface-700'
- ]
- },
- wrapper: {
- class: [
- // Sizing
- 'max-h-[200px]',
-
- // Misc
- 'overflow-auto'
- ]
- },
- list: {
- class: 'py-3 list-none m-0'
- },
- item: ({ context }) => ({
- class: [
- // Font
- 'font-normal',
- 'leading-none',
-
- // Position
- 'relative',
-
- // Shape
- 'border-0',
- 'rounded-none',
-
- // Spacing
- 'm-0',
- 'py-3 px-5',
-
- // Color
- { 'text-surface-700 dark:text-white/80': !context.focused && !context.selected && !context.disabled },
- { 'text-surface-600 dark:text-white/70': !context.focused && !context.selected && context.disabled },
- { 'bg-surface-200 dark:bg-surface-600/60 text-surface-700 dark:text-white/80': context.focused && !context.selected },
- { 'bg-primary-100 dark:bg-primary-400/40 text-primary-700 dark:text-white/80': context.focused && context.selected },
- { 'bg-primary-50 dark:bg-primary-400/40 text-primary-700 dark:text-white/80': !context.focused && context.selected },
-
- //States
- { 'hover:bg-surface-100 dark:hover:bg-surface-600/80': !context.focused && !context.selected },
- { 'hover:text-surface-700 hover:bg-surface-100 dark:hover:text-white dark:hover:bg-surface-600/80': context.focused && !context.selected },
- 'focus-visible:outline-none focus-visible:outline-offset-0 focus-visible:ring focus-visible:ring-inset focus-visible:ring-primary-400/50 dark:focus-visible:ring-primary-300/50',
-
- // Transitions
- 'transition-shadow',
- 'duration-200',
-
- // Misc
- { 'pointer-events-none cursor-default': context.disabled },
- { 'cursor-pointer': !context.disabled },
- 'overflow-hidden',
- 'whitespace-nowrap'
- ]
- }),
- itemgroup: {
- class: [
- //Font
- 'font-bold',
-
- // Spacing
- 'm-0',
- 'py-3 px-5',
-
- // Color
- 'text-surface-800 dark:text-white/80',
- 'bg-surface-0 dark:bg-surface-600/80',
-
- // Misc
- 'cursor-auto'
- ]
- },
- emptymessage: {
- class: [
- // Font
- 'leading-none',
-
- // Spacing
- 'py-3 px-5',
-
- // Color
- 'text-surface-800 dark:text-white/80',
- 'bg-transparent'
- ]
- },
- header: {
- class: [
- // Spacing
- 'py-3 px-5',
- 'm-0',
-
- //Shape
- 'border-b',
- 'rounded-tl-md',
- 'rounded-tr-md',
-
- // Color
- 'text-surface-700 dark:text-white/80',
- 'bg-surface-100 dark:bg-surface-800',
- 'border-surface-300 dark:border-surface-700'
- ]
- },
- filtercontainer: {
- class: 'relative'
- },
- filterinput: {
- class: [
- // Font
- 'font-sans',
- 'leading-none',
-
- // Sizing
- 'pr-7 py-3 px-3',
- '-mr-7',
- 'w-full',
-
- //Color
- 'text-surface-700 dark:text-white/80',
- 'bg-surface-0 dark:bg-surface-900',
- 'border-surface-200 dark:border-surface-700',
-
- // Shape
- 'border',
- 'rounded-lg',
- 'appearance-none',
-
- // Transitions
- 'transition',
- 'duration-200',
-
- // States
- 'hover:border-primary-500 dark:hover:border-primary-300',
- 'focus:ring focus:outline-none focus:outline-offset-0',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
-
- // Misc
- 'appearance-none'
- ]
- },
- filtericon: {
- class: ['absolute', 'top-1/2 right-3', '-mt-2']
- },
- clearicon: {
- class: [
- // Color
- 'text-surface-500',
-
- // Position
- 'absolute',
- 'top-1/2',
- 'right-12',
-
- // Spacing
- '-mt-2'
- ]
- },
- transition: {
- enterFromClass: 'opacity-0 scale-y-[0.8]',
- enterActiveClass: 'transition-[transform,opacity] duration-[120ms] ease-[cubic-bezier(0,0,0.2,1)]',
- leaveActiveClass: 'transition-opacity duration-100 ease-linear',
- leaveToClass: 'opacity-0'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/fieldset/index.js b/frontend/packages/kwai-ui/src/presets/kwai/fieldset/index.js
deleted file mode 100644
index 3b70c8043..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/fieldset/index.js
+++ /dev/null
@@ -1,84 +0,0 @@
-export default {
- root: {
- class: [
- 'block',
-
- // Spacing
- 'px-4 pt-2 py-3',
- 'inline-size-min',
-
- // Shape
- 'rounded-md',
- // Color
- 'border border-surface-200 dark:border-surface-700',
- 'bg-surface-0 dark:bg-surface-900',
- 'text-surface-700 dark:text-surface-0/80'
- ]
- },
- legend: ({ props }) => ({
- class: [
- // Font
- 'font-bold',
- 'leading-none',
-
- //Spacing
- { 'p-0': props.toggleable, 'p-5': !props.toggleable },
-
- // Shape
- 'rounded-md',
-
- // Color
- 'text-surface-700 dark:text-surface-0/80',
- 'border border-surface-200 dark:border-surface-700',
- 'bg-surface-50 dark:bg-surface-900',
-
- // Transition
- 'transition-none',
-
- // States
- { 'hover:bg-surface-100 hover:border-surface-200 hover:text-surface-900 dark:hover:text-surface-0/80 dark:hover:bg-surface-800/80': props.toggleable }
- ]
- }),
- toggler: ({ props }) => ({
- class: [
- // Alignments
- 'flex items-center justify-center',
- 'relative',
-
- //Spacing
- { 'p-5': props.toggleable },
-
- // Shape
- { 'rounded-md': props.toggleable },
-
- // Color
- { 'text-surface-700 dark:text-surface-200 hover:text-surface-900': props.toggleable },
-
- // States
- { 'hover:text-surface-900 dark:hover:text-surface-100': props.toggleable },
- { 'focus-visible:outline-none focus-visible:outline-offset-0 focus-visible:ring focus-visible:ring-inset focus-visible:ring-primary-400/50 dark:focus-visible:ring-primary-300/50': props.toggleable },
-
- // Misc
- {
- 'transition-none cursor-pointer overflow-hidden select-none': props.toggleable
- }
- ]
- }),
- togglerIcon: {
- class: 'mr-2 inline-block'
- },
- legendTitle: {
- class: 'flex items-center justify-center leading-none'
- },
- content: {
- class: 'p-5'
- },
- transition: {
- enterFromClass: 'max-h-0',
- enterActiveClass: 'overflow-hidden transition-[max-height] duration-1000 ease-[cubic-bezier(0.42,0,0.58,1)]',
- enterToClass: 'max-h-[1000px]',
- leaveFromClass: 'max-h-[1000px]',
- leaveActiveClass: 'overflow-hidden transition-[max-height] duration-[450ms] ease-[cubic-bezier(0,1,0,1)]',
- leaveToClass: 'max-h-0'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/fileupload/index.js b/frontend/packages/kwai-ui/src/presets/kwai/fileupload/index.js
deleted file mode 100644
index 1e17c7064..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/fileupload/index.js
+++ /dev/null
@@ -1,173 +0,0 @@
-export default {
- input: {
- class: 'hidden'
- },
- buttonbar: {
- class: [
- // Flexbox
- 'flex',
- 'flex-wrap',
-
- // Colors
- 'bg-surface-50',
- 'dark:bg-surface-800',
- 'text-surface-700',
- 'dark:text-white/80',
-
- // Spacing
- 'p-5',
- 'gap-2',
-
- // Borders
- 'border',
- 'border-solid',
- 'border-surface-200',
- 'dark:border-surface-700',
- 'border-b-0',
-
- // Shape
- 'rounded-tr-lg',
- 'rounded-tl-lg'
- ]
- },
- chooseButton: {
- class: [
- 'relative',
-
- // Alignments
- 'items-center inline-flex text-center align-bottom justify-center',
-
- // Spacing
- 'px-4 py-3',
-
- // Shape
- 'rounded-md',
-
- // Font
- 'leading-[normal]',
- 'font-bold',
-
- // Colors
- 'text-white dark:text-surface-900',
- 'bg-primary-500 dark:bg-primary-400',
- 'border-primary-500 dark:border-primary-400',
-
- // States
- 'hover:bg-primary-600 dark:hover:bg-primary-300',
-
- // Misc
- 'overflow-hidden',
- 'cursor-pointer'
- ]
- },
- chooseIcon: {
- class: ['mr-2', 'inline-block']
- },
- chooseButtonLabel: {
- class: ['flex-1', 'font-bold']
- },
- uploadbutton: {
- icon: {
- class: 'mr-2'
- }
- },
- cancelbutton: {
- icon: {
- class: 'mr-2'
- }
- },
- content: {
- class: [
- // Position
- 'relative',
-
- // Colors
- 'bg-surface-0',
- 'dark:bg-surface-900',
- 'text-surface-700',
- 'dark:text-white/80',
-
- // Spacing
- 'p-8',
-
- // Borders
- 'border',
- 'border-surface-200',
- 'dark:border-surface-700',
-
- // Shape
- 'rounded-b-lg'
- ]
- },
- file: {
- class: [
- // Flexbox
- 'flex',
- 'items-center',
- 'flex-wrap',
-
- // Spacing
- 'p-4',
- 'mb-2',
- 'last:mb-0',
-
- // Borders
- 'border',
- 'border-surface-200',
- 'dark:border-surface-700',
- 'gap-2',
-
- // Shape
- 'rounded'
- ]
- },
- thumbnail: {
- class: 'shrink-0'
- },
- fileName: {
- class: 'mb-2 break-all'
- },
- fileSize: {
- class: 'mr-2'
- },
- uploadicon: {
- class: 'mr-2'
- },
- progressbar: {
- root: {
- class: [
- // Position and Overflow
- 'overflow-hidden',
- 'absolute top-0 left-0',
-
- // Shape and Size
- 'border-0',
- 'h-2',
- 'rounded-md',
- 'w-full',
-
- // Colors
- 'bg-surface-100 dark:bg-surface-700'
- ]
- },
- value: {
- class: [
- // Flexbox & Overflow & Position
- 'absolute flex items-center justify-center overflow-hidden',
-
- // Colors
- 'bg-primary-500 dark:bg-primary-400',
-
- // Spacing & Sizing
- 'm-0',
- 'h-full w-0',
-
- // Shape
- 'border-0',
-
- // Transitions
- 'transition-width duration-1000 ease-in-out'
- ]
- }
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/floatlabel/index.js b/frontend/packages/kwai-ui/src/presets/kwai/floatlabel/index.js
deleted file mode 100644
index 557808fee..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/floatlabel/index.js
+++ /dev/null
@@ -1,26 +0,0 @@
-export default {
- root: {
- class: [
- 'block relative',
-
- // Base Label Appearance
- '[&>*:last-child]:text-surface-900/60 dark:[&>*:last-child]:text-white/60',
- '[&>*:last-child]:absolute',
- '[&>*:last-child]:top-1/2',
- '[&>*:last-child]:-translate-y-1/2',
- '[&>*:last-child]:left-3',
- '[&>*:last-child]:pointer-events-none',
- '[&>*:last-child]:transition-all',
- '[&>*:last-child]:duration-200',
- '[&>*:last-child]:ease',
-
- // Focus Label Appearance
- '[&>*:last-child]:has-[:focus]:-top-3',
- '[&>*:last-child]:has-[:focus]:text-sm',
-
- // Filled Input Label Appearance
- '[&>*:last-child]:has-[.filled]:-top-3',
- '[&>*:last-child]:has-[.filled]:text-sm'
- ]
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/galleria/index.js b/frontend/packages/kwai-ui/src/presets/kwai/galleria/index.js
deleted file mode 100644
index 96e026ac8..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/galleria/index.js
+++ /dev/null
@@ -1,306 +0,0 @@
-export default {
- content: ({ parent, props }) => ({
- class: [
- 'flex',
- {
- 'flex-col': props.fullScreen
- },
- {
- 'flex-col': parent.props.thumbnailsPosition === 'top' || parent.props.thumbnailsPosition === 'bottom',
- 'flex-row': parent.props.thumbnailsPosition === 'right' || parent.props.thumbnailsPosition === 'left'
- }
- ]
- }),
- itemwrapper: ({ parent, props }) => ({
- class: [
- 'group',
- 'flex relative',
- {
- 'grow shrink w-0 justify-center': props.fullScreen
- },
- {
- 'flex-col': parent.props.indicatorsPosition === 'bottom' || parent.props.indicatorsPosition === 'top',
- 'flex-row items-center': parent.props.indicatorsPosition === 'left' || parent.props.indicatorsPosition === 'right'
- },
- {
- 'order-2': parent.props.thumbnailsPosition === 'top' || parent.props.thumbnailsPosition === 'left',
- 'flex-row': parent.props.thumbnailsPosition === 'right'
- }
- ]
- }),
-
- itemcontainer: ({ parent }) => ({
- class: [
- 'flex h-full relative',
- {
- 'order-1': parent.props.indicatorsPosition === 'bottom' || parent.props.indicatorsPosition === 'right',
- 'order-2': parent.props.indicatorsPosition === 'top' || parent.props.indicatorsPosition === 'left'
- }
- ]
- }),
- item: {
- class: [
- // Flex
- 'flex justify-center items-center h-full w-full',
-
- // Sizing
- 'h-full w-full'
- ]
- },
- thumbnailwrapper: ({ parent }) => ({
- class: [
- // Flex
- 'flex flex-col shrink-0',
-
- {
- 'order-1': parent.props.thumbnailsPosition === 'top' || parent.props.thumbnailsPosition === 'left'
- },
-
- // Misc
- 'overflow-auto'
- ]
- }),
- thumbnailcontainer: ({ parent }) => ({
- class: [
- // Flex
- 'flex',
-
- // Spacing
- 'p-4',
-
- // Colors
- 'bg-black/90',
-
- {
- 'flex-row': parent.props.thumbnailsPosition === 'top' || parent.props.thumbnailsPosition === 'bottom',
- 'flex-col grow': parent.props.thumbnailsPosition === 'right' || parent.props.thumbnailsPosition === 'left'
- }
- ]
- }),
- previousthumbnailbutton: {
- class: [
- // Positioning
- 'self-center relative',
-
- // Display & Flexbox
- 'flex shrink-0 justify-center items-center overflow-hidden',
-
- // Spacing
- 'm-2',
-
- // Appearance
- 'bg-transparent text-white w-8 h-8 rounded-full transition duration-200 ease-in-out',
-
- // Hover Effects
- 'hover:bg-surface-0/10 hover:text-white',
-
- // Focus Effects
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50'
- ]
- },
- thumbnailitemscontainer: {
- class: 'overflow-hidden w-full'
- },
- thumbnailitems: ({ parent }) => ({
- class: [
- 'flex',
- {
- 'flex-col h-full': parent.props.thumbnailsPosition === 'right' || parent.props.thumbnailsPosition === 'left'
- }
- ]
- }),
- thumbnailitem: ({ parent }) => ({
- class: [
- // Flexbox
- 'flex items-center justify-center',
- 'grow shrink-0',
-
- // Sizing
- {
- 'w-full md:w-[25%] lg:w-[20%]': parent.props.thumbnailsPosition === 'top' || parent.props.thumbnailsPosition === 'bottom'
- },
-
- // Misc
- 'overflow-auto',
- 'cursor-pointer',
- 'opacity-50',
-
- // States
- 'hover:opacity-100',
- 'hover:transition-opacity',
- 'hover:duration-300'
- ]
- }),
- nextthumbnailbutton: {
- class: [
- // Positioning
- 'self-center relative',
-
- // Display & Flexbox
- 'flex shrink-0 justify-center items-center overflow-hidden',
-
- // Spacing
- 'm-2',
-
- // Appearance
- 'bg-transparent text-white w-8 h-8 rounded-full transition duration-200 ease-in-out',
-
- // Hover Effects
- 'hover:bg-surface-0/10 hover:text-white',
-
- // Focus Effects
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50'
- ]
- },
- indicators: ({ parent }) => ({
- class: [
- // flex
- 'flex items-center justify-center',
-
- // Spacing
- 'p-4',
-
- // Indicators Position
- {
- 'order-2': parent.props.indicatorsPosition == 'bottom',
- 'order-1': parent.props.indicatorsPosition == 'top',
- 'order-1 flex-col': parent.props.indicatorsPosition == 'left',
- 'flex-col order-2': parent.props.indicatorsPosition == 'right'
- },
- {
- 'absolute z-10 bg-black/50': parent.props.showIndicatorsOnItem
- },
-
- {
- 'bottom-0 left-0 w-full items-start': parent.props.indicatorsPosition == 'bottom' && parent.props.showIndicatorsOnItem,
- 'top-0 left-0 w-full items-start': parent.props.indicatorsPosition == 'top' && parent.props.showIndicatorsOnItem,
- 'left-0 top-0 h-full items-start': parent.props.indicatorsPosition == 'left' && parent.props.showIndicatorsOnItem,
- 'right-0 top-0 h-full items-start': parent.props.indicatorsPosition == 'right' && parent.props.showIndicatorsOnItem
- }
- ]
- }),
- indicator: ({ parent }) => ({
- class: [
- {
- 'mr-2': parent.props.indicatorsPosition == 'bottom' || parent.props.indicatorsPosition == 'top',
- 'mb-2': parent.props.indicatorsPosition == 'left' || parent.props.indicatorsPosition == 'right'
- }
- ]
- }),
- indicatorbutton: ({ context }) => ({
- class: [
- // Size
- 'w-4 h-4',
-
- // Appearance
- 'rounded-full transition duration-200',
-
- // Focus Effects
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
-
- // Conditional Appearance: Not Highlighted
- { 'bg-surface-200 hover:bg-surface-300 dark:bg-surface-700 dark:hover:bg-surface-600': !context.highlighted },
-
- // Conditional Appearance: Highlighted
- { 'bg-primary-500 hover:bg-primary-600': context.highlighted }
- ]
- }),
- mask: {
- class: ['fixed top-0 left-0 w-full h-full', 'flex items-center justify-center', 'bg-black/90']
- },
- closebutton: {
- class: [
- // Positioning
- '!absolute top-0 right-0',
-
- // Display & Flexbox
- 'flex justify-center items-center overflow-hidden',
-
- // Spacing
- 'm-2',
-
- // Appearance
- 'text-white bg-transparent w-12 h-12 rounded-full transition duration-200 ease-in-out',
-
- // Hover Effect
- 'hover:text-white hover:bg-surface-0/10',
-
- // Focus Effects
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50'
- ]
- },
- closeicon: {
- class: 'w-6 h-6'
- },
- previousitembutton: ({ parent }) => ({
- class: [
- // Display & Flexbox
- 'inline-flex justify-center items-center overflow-hidden',
-
- // Appearance
- 'bg-transparent text-white w-16 h-16 transition duration-200 ease-in-out rounded-md',
- {
- 'opacity-0 group-hover:opacity-100': parent.props.showItemNavigatorsOnHover
- },
-
- // Spacing
- 'mx-2',
-
- // Positioning
- 'top-1/2 mt-[-0.5rem] left-0',
- {
- '!absolute': parent.props.showItemNavigators,
- '!fixed': !parent.props.showItemNavigators
- },
-
- // Hover Effect
- 'hover:bg-surface-0/10 hover:text-white',
-
- // Focus Effects
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50'
- ]
- }),
- nextitembutton: ({ parent }) => ({
- class: [
- // Display & Flexbox
- 'inline-flex justify-center items-center overflow-hidden',
-
- // Appearance
- 'bg-transparent text-white w-16 h-16 transition duration-200 ease-in-out rounded-md',
- {
- 'opacity-0 group-hover:opacity-100': parent.props.showItemNavigatorsOnHover
- },
-
- // Spacing
- 'mx-2',
-
- // Positioning
- 'top-1/2 mt-[-0.5rem] right-0',
- {
- '!absolute': parent.props.showItemNavigators,
- '!fixed': !parent.props.showItemNavigators
- },
-
- // Hover Effect
- 'hover:bg-surface-0/10 hover:text-white',
-
- // Focus Effects
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50'
- ]
- }),
- caption: {
- class: [
- // Positioning
- 'absolute bottom-0 left-0 w-full',
-
- // Appearance
- 'bg-black/50 text-white p-4'
- ]
- },
- transition: {
- enterFromClass: 'opacity-0 scale-75',
- enterActiveClass: 'transition-all duration-150 ease-in-out',
- leaveActiveClass: 'transition-all duration-150 ease-in',
- leaveToClass: 'opacity-0 scale-75'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/global.js b/frontend/packages/kwai-ui/src/presets/kwai/global.js
deleted file mode 100644
index 42552db83..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/global.js
+++ /dev/null
@@ -1,90 +0,0 @@
-export default {
- css: `
- *[data-pd-ripple="true"]{
- overflow: hidden;
- position: relative;
- }
- span[data-p-ink-active="true"]{
- animation: ripple 0.4s linear;
- }
- @keyframes ripple {
- 100% {
- opacity: 0;
- transform: scale(2.5);
- }
- }
-
- .progress-spinner-circle {
- stroke-dasharray: 89, 200;
- stroke-dashoffset: 0;
- animation: p-progress-spinner-dash 1.5s ease-in-out infinite, p-progress-spinner-color 6s ease-in-out infinite;
- stroke-linecap: round;
- }
-
- @keyframes p-progress-spinner-dash{
- 0% {
- stroke-dasharray: 1, 200;
- stroke-dashoffset: 0;
- }
-
- 50% {
- stroke-dasharray: 89, 200;
- stroke-dashoffset: -35px;
- }
- 100% {
- stroke-dasharray: 89, 200;
- stroke-dashoffset: -124px;
- }
- }
- @keyframes p-progress-spinner-color {
- 100%, 0% {
- stroke: #ff5757;
- }
- 40% {
- stroke: #696cff;
- }
- 66% {
- stroke: #1ea97c;
- }
- 80%, 90% {
- stroke: #cc8925;
- }
- }
-
- .progressbar-value-animate::after {
- will-change: left, right;
- animation: p-progressbar-indeterminate-anim-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1) infinite;
- }
- .progressbar-value-animate::before {
- will-change: left, right;
- animation: p-progressbar-indeterminate-anim 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite;
- }
- @keyframes p-progressbar-indeterminate-anim {
- 0% {
- left: -35%;
- right: 100%;
- }
- 60% {
- left: 100%;
- right: -90%;
- }
- 100% {
- left: 100%;
- right: -90%;
- }
- }
-
- .p-fadein {
- animation: p-fadein 250ms linear;
- }
-
- @keyframes p-fadein {
- 0% {
- opacity: 0;
- }
- 100% {
- opacity: 1;
- }
- }
-`
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/iconfield/index.js b/frontend/packages/kwai-ui/src/presets/kwai/iconfield/index.js
deleted file mode 100644
index 108735b0b..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/iconfield/index.js
+++ /dev/null
@@ -1,22 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- 'relative',
- '[&>input]:w-full',
-
- '[&>*:first-child]:absolute',
- '[&>*:first-child]:top-1/2',
- '[&>*:first-child]:-mt-2',
- '[&>*:first-child]:leading-none',
- '[&>*:first-child]:text-surface-900/60 dark:[&>*:first-child]:text-white/60',
- {
- '[&>*:first-child]:right-3': props.iconPosition === 'right',
- '[&>*:first-child]:left-3': props.iconPosition === 'left'
- },
- {
- '[&>*:last-child]:pr-10': props.iconPosition === 'right',
- '[&>*:last-child]:pl-10': props.iconPosition === 'left'
- }
- ]
- })
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/image/index.js b/frontend/packages/kwai-ui/src/presets/kwai/image/index.js
deleted file mode 100644
index e6d6f9fed..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/image/index.js
+++ /dev/null
@@ -1,206 +0,0 @@
-export default {
- root: {
- class: 'relative inline-block'
- },
- button: {
- class: [
- // Flexbox & Alignment
- 'flex items-center justify-center',
-
- // Positioning
- 'absolute',
-
- // Shape
- 'inset-0 opacity-0 transition-opacity duration-300',
-
- // Color
- 'bg-transparent text-surface-100',
-
- // States
- 'hover:opacity-100 hover:cursor-pointer hover:bg-black/50 hover:bg-opacity-50'
- ]
- },
- mask: {
- class: [
- // Flexbox & Alignment
- 'flex items-center justify-center',
-
- // Positioning
- 'fixed top-0 left-0',
-
- // Sizing
- 'w-full h-full',
-
- // Color
- 'bg-black/90'
- ]
- },
- toolbar: {
- class: [
- // Flexbox
- 'flex',
-
- // Positioning
- 'absolute top-0 right-0',
-
- // Spacing
- 'p-4'
- ]
- },
- rotaterightbutton: {
- class: [
- 'z-20',
-
- // Flexbox & Alignment
- 'flex justify-center items-center',
-
- // Size
- 'w-12 h-12',
-
- // Spacing
- 'mr-2',
-
- // Shape
- 'rounded-full',
-
- // Color
- 'text-white bg-transparent',
-
- // States
- 'hover:text-white hover:bg-surface-0/10',
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
-
- // Transition
- 'transition duration-200 ease-in-out'
- ]
- },
- rotaterighticon: {
- class: 'w-6 h-6'
- },
- rotateleftbutton: {
- class: [
- 'z-20',
-
- // Flexbox & Alignment
- 'flex justify-center items-center',
-
- // Size
- 'w-12 h-12',
-
- // Spacing
- 'mr-2',
-
- // Shape
- 'rounded-full',
-
- // Color
- 'text-white bg-transparent',
-
- // States
- 'hover:text-white hover:bg-surface-0/10',
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
-
- // Transition
- 'transition duration-200 ease-in-out'
- ]
- },
- rotatelefticon: {
- class: 'w-6 h-6'
- },
- zoomoutbutton: {
- class: [
- 'z-20',
-
- // Flexbox & Alignment
- 'flex justify-center items-center',
-
- // Size
- 'w-12 h-12',
-
- // Spacing
- 'mr-2',
-
- // Shape
- 'rounded-full',
-
- // Color
- 'text-white bg-transparent',
-
- // States
- 'hover:text-white hover:bg-surface-0/10',
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
-
- // Transition
- 'transition duration-200 ease-in-out'
- ]
- },
- zoomouticon: {
- class: 'w-6 h-6'
- },
- zoominbutton: {
- class: [
- 'z-20',
-
- // Flexbox & Alignment
- 'flex justify-center items-center',
-
- // Size
- 'w-12 h-12',
-
- // Spacing
- 'mr-2',
-
- // Shape
- 'rounded-full',
-
- // Color
- 'text-white bg-transparent',
-
- // States
- 'hover:text-white hover:bg-surface-0/10',
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
-
- // Transition
- 'transition duration-200 ease-in-out'
- ]
- },
- zoominicon: {
- class: 'w-6 h-6'
- },
- closebutton: {
- class: [
- 'z-20',
-
- // Flexbox & Alignment
- 'flex justify-center items-center',
-
- // Size
- 'w-12 h-12',
-
- // Spacing
- 'mr-2',
-
- // Shape
- 'rounded-full',
-
- // Color
- 'text-white bg-transparent',
-
- // States
- 'hover:text-white hover:bg-surface-0/10',
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
-
- // Transition
- 'transition duration-200 ease-in-out'
- ]
- },
- closeicon: {
- class: 'w-6 h-6'
- },
- transition: {
- enterFromClass: 'opacity-0 scale-75',
- enterActiveClass: 'transition-all duration-150 ease-in-out',
- leaveActiveClass: 'transition-all duration-150 ease-in',
- leaveToClass: 'opacity-0 scale-75'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/index.d.ts b/frontend/packages/kwai-ui/src/presets/kwai/index.d.ts
deleted file mode 100644
index c60f67d6e..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/index.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import type { PrimeVuePTOptions } from 'primevue/config';
-import type { PassThrough } from 'primevue/ts-helpers';
-
-declare module 'index.js' {
- export = PassThrough;
-}
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/index.js b/frontend/packages/kwai-ui/src/presets/kwai/index.js
deleted file mode 100644
index d0984c4a8..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/index.js
+++ /dev/null
@@ -1,181 +0,0 @@
-import global from './global.js';
-import autocomplete from './autocomplete';
-import calendar from './calendar';
-import cascadeselect from './cascadeselect';
-import checkbox from './checkbox';
-import chips from './chips';
-import colorpicker from './colorpicker';
-import dropdown from './dropdown';
-import floatlabel from './floatlabel';
-import iconfield from './iconfield';
-import inputgroup from './inputgroup';
-import inputotp from './inputotp';
-import inputgroupaddon from './inputgroupaddon';
-import inputmask from './inputmask';
-import inputnumber from './inputnumber';
-import inputswitch from './inputswitch';
-import inputtext from './inputtext';
-import knob from './knob';
-import listbox from './listbox';
-import multiselect from './multiselect';
-import password from './password';
-import radiobutton from './radiobutton';
-import rating from './rating';
-import selectbutton from './selectbutton';
-import slider from './slider';
-import textarea from './textarea';
-import togglebutton from './togglebutton';
-import treeselect from './treeselect';
-import tristatecheckbox from './tristatecheckbox';
-import button from './button';
-import speeddial from './speeddial';
-import splitbutton from './splitbutton';
-import accordion from './accordion';
-import card from './card';
-import deferred from './deferred';
-import divider from './divider';
-import fieldset from './fieldset';
-import panel from './panel';
-import scrollpanel from './scrollpanel';
-import splitter from './splitter';
-import stepper from './stepper';
-import tabview from './tabview';
-import toolbar from './toolbar';
-import datatable from './datatable';
-import dataview from './dataview';
-import orderlist from './orderlist';
-import organizationchart from './organizationchart';
-import paginator from './paginator';
-import picklist from './picklist';
-import tree from './tree';
-import treetable from './treetable';
-import timeline from './timeline';
-import breadcrumb from './breadcrumb';
-import contextmenu from './contextmenu';
-import dock from './dock';
-import menu from './menu';
-import menubar from './menubar';
-import megamenu from './megamenu';
-import panelmenu from './panelmenu';
-import steps from './steps';
-import tabmenu from './tabmenu';
-import tieredmenu from './tieredmenu';
-import confirmpopup from './confirmpopup';
-import dialog from './dialog';
-import overlaypanel from './overlaypanel';
-import sidebar from './sidebar';
-import tooltip from './tooltip';
-import fileupload from './fileupload';
-import message from './message';
-import inlinemessage from './inlinemessage';
-import toast from './toast';
-import carousel from './carousel';
-import galleria from './galleria';
-import image from './image';
-import avatar from './avatar';
-import badge from './badge';
-import badgedirective from './badgedirective';
-import blockui from './blockui';
-import chip from './chip';
-import inplace from './inplace';
-import metergroup from './metergroup';
-import scrolltop from './scrolltop';
-import skeleton from './skeleton';
-import progressbar from './progressbar';
-import progressspinner from './progressspinner';
-import ripple from './ripple';
-import tag from './tag';
-import terminal from './terminal';
-
-export default {
- global,
- directives: {
- tooltip,
- badgedirective,
- ripple
- },
- autocomplete,
- calendar,
- cascadeselect,
- checkbox,
- chips,
- colorpicker,
- dropdown,
- floatlabel,
- iconfield,
- inputgroup,
- inputotp,
- inputgroupaddon,
- inputmask,
- inputnumber,
- inputswitch,
- inputtext,
- knob,
- listbox,
- multiselect,
- password,
- radiobutton,
- rating,
- selectbutton,
- slider,
- textarea,
- togglebutton,
- treeselect,
- tristatecheckbox,
- button,
- speeddial,
- splitbutton,
- accordion,
- card,
- deferred,
- divider,
- fieldset,
- panel,
- scrollpanel,
- splitter,
- stepper,
- tabview,
- toolbar,
- datatable,
- dataview,
- orderlist,
- organizationchart,
- paginator,
- picklist,
- tree,
- treetable,
- timeline,
- breadcrumb,
- contextmenu,
- dock,
- menu,
- menubar,
- megamenu,
- panelmenu,
- steps,
- tabmenu,
- tieredmenu,
- confirmpopup,
- dialog,
- overlaypanel,
- sidebar,
- fileupload,
- message,
- inlinemessage,
- toast,
- carousel,
- galleria,
- image,
- avatar,
- badge,
- blockui,
- chip,
- inplace,
- metergroup,
- scrolltop,
- skeleton,
- progressbar,
- progressspinner,
- tag,
- terminal
-}
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/inlinemessage/index.js b/frontend/packages/kwai-ui/src/presets/kwai/inlinemessage/index.js
deleted file mode 100644
index 5e0faf7d4..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/inlinemessage/index.js
+++ /dev/null
@@ -1,36 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- 'inline-flex items-center justify-center align-top gap-2',
- 'p-3 m-0 rounded-md dark:border',
- {
- 'bg-blue-100/70 dark:bg-blue-500/20': props.severity == 'info',
- 'bg-green-100/70 dark:bg-green-500/20': props.severity == 'success',
- 'bg-orange-100/70 dark:bg-orange-500/20': props.severity == 'warn',
- 'bg-red-100/70 dark:bg-red-500/20': props.severity == 'error'
- },
- {
- 'dark:border-blue-400': props.severity == 'info',
- 'dark:border-green-400': props.severity == 'success',
- 'dark:border-orange-400': props.severity == 'warn',
- 'dark:border-red-400': props.severity == 'error'
- },
- {
- 'text-blue-700 dark:text-blue-300': props.severity == 'info',
- 'text-green-700 dark:text-green-300': props.severity == 'success',
- 'text-orange-700 dark:text-orange-300': props.severity == 'warn',
- 'text-red-700 dark:text-red-300': props.severity == 'error'
- }
- ]
- }),
- icon: {
- class: 'text-base'
- },
- text: {
- class: [
- // Font and Text
- 'text-base leading-none',
- 'font-medium'
- ]
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/inplace/index.js b/frontend/packages/kwai-ui/src/presets/kwai/inplace/index.js
deleted file mode 100644
index ef7bf3757..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/inplace/index.js
+++ /dev/null
@@ -1,27 +0,0 @@
-export default {
- display: {
- class: [
- // Display
- 'inline',
-
- // Spacing
- 'p-3',
-
- // Shape
- 'rounded-md',
-
- // Colors
- 'text-surface-700 dark:text-white/80',
-
- // States
- 'hover:bg-surface-100 hover:text-surface-700 dark:hover:bg-surface-700/80 dark:hover:text-white/80',
-
- // Transitions
- 'transition',
- 'duration-200',
-
- // Misc
- 'cursor-pointer'
- ]
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/inputgroup/index.js b/frontend/packages/kwai-ui/src/presets/kwai/inputgroup/index.js
deleted file mode 100644
index cce711149..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/inputgroup/index.js
+++ /dev/null
@@ -1,5 +0,0 @@
-export default {
- root: {
- class: ['flex items-stretch', 'w-full']
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/inputgroupaddon/index.js b/frontend/packages/kwai-ui/src/presets/kwai/inputgroupaddon/index.js
deleted file mode 100644
index 5ed52fbc8..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/inputgroupaddon/index.js
+++ /dev/null
@@ -1,28 +0,0 @@
-export default {
- root: {
- class: [
- // Flex
- 'flex items-center justify-center',
-
- // Shape
- 'first:rounded-l-md',
- 'last:rounded-r-md',
- 'border-y',
-
- 'last:border-r',
- 'border-l',
- 'border-r-0',
-
- // Space
- 'p-3',
-
- // Size
- 'min-w-[3rem]',
-
- // Color
- 'bg-surface-50 dark:bg-surface-800',
- 'text-surface-600 dark:text-surface-400',
- 'border-surface-300 dark:border-surface-600'
- ]
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/inputmask/index.js b/frontend/packages/kwai-ui/src/presets/kwai/inputmask/index.js
deleted file mode 100644
index b2b1da705..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/inputmask/index.js
+++ /dev/null
@@ -1,34 +0,0 @@
-export default {
- root: ({ context, props }) => ({
- class: [
- // Font
- 'font-sans leading-none',
-
- // Spacing
- 'm-0 p-3',
-
- // Colors
- 'text-surface-600 dark:text-surface-200',
- 'placeholder:text-surface-400 dark:placeholder:text-surface-500',
- 'bg-surface-0 dark:bg-surface-900',
-
- 'border',
- { 'border-surface-300 dark:border-surface-600': !props.invalid },
-
- // Invalid State
- { 'border-red-500 dark:border-red-400': props.invalid },
-
- // States
- {
- 'hover:border-primary-500 dark:hover:border-primary-400': !context.disabled && !props.invalid,
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-500/50 dark:focus:ring-primary-400/50': !context.disabled,
- 'opacity-60 select-none pointer-events-none cursor-default': context.disabled
- },
-
- // Misc
- 'rounded-md',
- 'appearance-none',
- 'transition-colors duration-200'
- ]
- })
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/inputnumber/index.js b/frontend/packages/kwai-ui/src/presets/kwai/inputnumber/index.js
deleted file mode 100644
index bf5f406de..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/inputnumber/index.js
+++ /dev/null
@@ -1,164 +0,0 @@
-export default {
- root: ({ props, parent }) => ({
- class: [
- // Flex
- 'inline-flex',
- { 'flex-col': props.showButtons && props.buttonLayout == 'vertical' },
- { 'flex-1 w-[1%]': parent.instance.$name == 'InputGroup' },
-
- // Shape
- { 'first:rounded-l-md rounded-none last:rounded-r-md': parent.instance.$name == 'InputGroup' && !props.showButtons },
- { 'border-0 border-y border-l last:border-r border-surface-300 dark:border-surface-600': parent.instance.$name == 'InputGroup' && !props.showButtons },
- { 'first:ml-0 -ml-px': parent.instance.$name == 'InputGroup' && !props.showButtons },
-
- //Sizing
- { '!w-16': props.showButtons && props.buttonLayout == 'vertical' }
- ]
- }),
- input: {
- root: ({ parent, context }) => ({
- class: [
- // Display
- 'flex flex-auto',
-
- // Font
- 'font-sans leading-none',
-
- //Text
- { 'text-center': parent.props.showButtons && parent.props.buttonLayout == 'vertical' },
-
- // Spacing
- 'p-3',
- 'm-0',
-
- // Shape
- 'rounded-lg',
- { 'rounded-tr-none rounded-br-none': parent.props.showButtons },
- { 'rounded-tl-none rounded-bl-none': parent.props.showButtons && parent.props.buttonLayout == 'horizontal' },
- { 'rounded-none': parent.props.showButtons && parent.props.buttonLayout == 'vertical' },
-
- { '!rounded-none': parent.instance.$parentInstance?.$name == 'InputGroup' && !parent.props.showButtons },
- { 'border-0': parent.instance.$parentInstance?.$name == 'InputGroup' && !parent.props.showButtons },
-
- // Colors
- 'text-surface-600 dark:text-surface-200',
- 'placeholder:text-surface-400 dark:placeholder:text-surface-500',
- 'bg-surface-0 dark:bg-surface-900',
- 'border',
- { 'border-surface-300 dark:border-surface-600': !parent.props.invalid },
-
- // Invalid State
- { 'border-red-500 dark:border-red-400': parent.props.invalid },
-
- // States
- { 'hover:border-primary-500 dark:hover:border-primary-400': !parent.props.invalid },
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-500/50 dark:focus:ring-primary-400/50 focus:z-10',
- { 'opacity-60 select-none pointer-events-none cursor-default': context.disabled },
-
- // Filled State *for FloatLabel
- { filled: parent.instance?.$name == 'FloatLabel' && context.filled },
-
- //Position
- { 'order-2': parent.props.buttonLayout == 'horizontal' || parent.props.buttonLayout == 'vertical' }
- ]
- })
- },
- buttongroup: ({ props }) => ({
- class: [
- // Flex
- 'flex',
- 'flex-col'
- ]
- }),
-
- incrementbutton: {
- root: ({ parent }) => ({
- class: [
- // Display
- 'flex flex-auto',
-
- // Alignment
- 'items-center',
- 'justify-center',
- 'text-center align-bottom',
-
- //Position
- 'relative',
- { 'order-3': parent.props.showButtons && parent.props.buttonLayout == 'horizontal' },
- { 'order-1': parent.props.showButtons && parent.props.buttonLayout == 'vertical' },
-
- //Color
- 'text-white dark:text-surface-900',
- 'bg-primary-500 dark:bg-primary-400',
- 'border border-primary-500 dark:border-primary-400',
-
- // Sizing
- 'w-[3rem]',
- { 'px-4 py-3': parent.props.showButtons && parent.props.buttonLayout !== 'stacked' },
- { 'p-0': parent.props.showButtons && parent.props.buttonLayout == 'stacked' },
- { 'w-full': parent.props.showButtons && parent.props.buttonLayout == 'vertical' },
-
- // Shape
- 'rounded-md',
- { 'rounded-tl-none rounded-br-none rounded-bl-none': parent.props.showButtons && parent.props.buttonLayout == 'stacked' },
- { 'rounded-bl-none rounded-tl-none': parent.props.showButtons && parent.props.buttonLayout == 'horizontal' },
- { 'rounded-bl-none rounded-br-none': parent.props.showButtons && parent.props.buttonLayout == 'vertical' },
-
- //States
- 'focus:outline-none focus:outline-offset-0 focus:ring',
- 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300',
-
- //Misc
- 'cursor-pointer overflow-hidden select-none'
- ]
- }),
- label: {
- class: 'h-0 w-0'
- }
- },
- decrementbutton: {
- root: ({ parent }) => ({
- class: [
- // Display
- 'flex flex-auto',
-
- // Alignment
- 'items-center',
- 'justify-center',
- 'text-center align-bottom',
-
- //Position
- 'relative',
- { 'order-1': parent.props.showButtons && parent.props.buttonLayout == 'horizontal' },
- { 'order-3': parent.props.showButtons && parent.props.buttonLayout == 'vertical' },
-
- //Color
- 'text-white dark:text-surface-900',
- 'bg-primary-500 dark:bg-primary-400',
- 'border border-primary-500 dark:border-primary-400',
-
- // Sizing
- 'w-[3rem]',
- { 'px-4 py-3': parent.props.showButtons && parent.props.buttonLayout !== 'stacked' },
- { 'p-0': parent.props.showButtons && parent.props.buttonLayout == 'stacked' },
- { 'w-full': parent.props.showButtons && parent.props.buttonLayout == 'vertical' },
-
- // Shape
- 'rounded-md',
- { 'rounded-tr-none rounded-tl-none rounded-bl-none': parent.props.showButtons && parent.props.buttonLayout == 'stacked' },
- { 'rounded-tr-none rounded-br-none ': parent.props.showButtons && parent.props.buttonLayout == 'horizontal' },
- { 'rounded-tr-none rounded-tl-none ': parent.props.showButtons && parent.props.buttonLayout == 'vertical' },
-
- //States
- 'focus:outline-none focus:outline-offset-0 focus:ring',
- 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300',
-
- //Misc
- 'cursor-pointer overflow-hidden select-none'
- ]
- }),
- label: {
- class: 'h-0 w-0'
- }
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/inputotp/index.js b/frontend/packages/kwai-ui/src/presets/kwai/inputotp/index.js
deleted file mode 100644
index 338587269..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/inputotp/index.js
+++ /dev/null
@@ -1,60 +0,0 @@
-export default {
- root: {
- class: [
- // Alignment
- 'flex items-center',
- 'gap-2'
- ]
- },
- input: {
- root: ({ props, context, parent }) => ({
- class: [
- // Font
- 'font-sans leading-none',
-
- // Flex & Alignment
- { 'flex-1 w-[1%]': parent.instance.$name == 'InputGroup' },
- 'text-center',
-
- // Spacing
- 'm-0',
- {
- 'p-3': props.size == null
- },
-
- // Size
- 'w-10',
-
- // Shape
- { 'rounded-md': parent.instance.$name !== 'InputGroup' },
- { 'first:rounded-l-md rounded-none last:rounded-r-md': parent.instance.$name == 'InputGroup' },
- { 'border-0 border-y border-l last:border-r': parent.instance.$name == 'InputGroup' },
- { 'first:ml-0 ml-[-1px]': parent.instance.$name == 'InputGroup' && !props.showButtons },
-
- // Colors
- 'text-surface-600 dark:text-surface-200',
- 'placeholder:text-surface-400 dark:placeholder:text-surface-500',
- 'bg-surface-0 dark:bg-surface-900',
- 'border',
- { 'border-surface-300 dark:border-surface-600': !props.invalid },
-
- // Invalid State
- { 'border-red-500 dark:border-red-400': props.invalid },
-
- // States
- {
- 'hover:border-primary-500 dark:hover:border-primary-400': !context.disabled && !props.invalid,
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-500/50 dark:focus:ring-primary-400/50 focus:z-10': !context.disabled,
- 'opacity-60 select-none pointer-events-none cursor-default': context.disabled
- },
-
- // Filled State *for FloatLabel
- { filled: parent.instance?.$name == 'FloatLabel' && context.filled },
-
- // Misc
- 'appearance-none',
- 'transition-colors duration-200'
- ]
- })
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/inputswitch/index.js b/frontend/packages/kwai-ui/src/presets/kwai/inputswitch/index.js
deleted file mode 100644
index 029a81019..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/inputswitch/index.js
+++ /dev/null
@@ -1,80 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- 'inline-block relative',
- 'w-12 h-7',
- 'rounded-2xl',
- {
- 'opacity-60 select-none pointer-events-none cursor-default': props.disabled
- }
- ]
- }),
- slider: ({ props }) => ({
- class: [
- // Position
- 'absolute top-0 left-0 right-0 bottom-0',
- { 'before:transform before:translate-x-5': props.modelValue == props.trueValue },
-
- // Shape
- 'rounded-2xl',
-
- // Before:
- 'before:absolute before:top-1/2 before:left-1',
- 'before:-mt-2.5',
- 'before:h-5 before:w-5',
- 'before:rounded-full',
- 'before:duration-200',
- 'before:bg-surface-0 before:dark:bg-surface-900',
-
- // Colors
- 'border',
- {
- 'bg-surface-200 dark:bg-surface-700': !(props.modelValue == props.trueValue),
- 'bg-primary-500 dark:bg-primary-400': props.modelValue == props.trueValue
- },
-
- { 'border-transparent': !props.invalid },
-
- // Invalid State
- { 'border-red-500 dark:border-red-400': props.invalid },
-
- // States
- { 'peer-hover:bg-surface-300 dark:peer-hover:bg-surface-600 ': !(props.modelValue == props.trueValue) && !props.disabled },
- { 'peer-hover:bg-primary-600 dark:peer-hover:bg-surface-300 ': props.modelValue == props.trueValue && !props.disabled },
- 'peer-focus-visible:ring peer-focus-visible:ring-primary-400/50 dark:peer-focus-visible:ring-primary-300/50',
-
- // Transition
- 'transition-colors duration-200',
-
- // Misc
- 'cursor-pointer'
- ]
- }),
- input: {
- class: [
- 'peer',
-
- // Size
- 'w-full ',
- 'h-full',
-
- // Position
- 'absolute',
- 'top-0 left-0',
- 'z-10',
-
- // Spacing
- 'p-0',
- 'm-0',
-
- // Shape
- 'opacity-0',
- 'rounded-[2.5rem]',
- 'outline-none',
-
- // Misc
- 'appearance-none',
- 'cursor-pointer'
- ]
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/inputtext/index.js b/frontend/packages/kwai-ui/src/presets/kwai/inputtext/index.js
deleted file mode 100644
index de9b0dce9..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/inputtext/index.js
+++ /dev/null
@@ -1,49 +0,0 @@
-export default {
- root: ({ props, context, parent }) => ({
- class: [
- // Font
- 'font-sans leading-none',
-
- // Flex
- { 'flex-1 w-[1%]': parent.instance.$name == 'InputGroup' },
-
- // Spacing
- 'm-0',
- {
- 'px-4 py-4': props.size == 'large',
- 'px-2 py-2': props.size == 'small',
- 'p-3': props.size == null
- },
-
- // Shape
- { 'rounded-md': parent.instance.$name !== 'InputGroup' },
- { 'first:rounded-l-md rounded-none last:rounded-r-md': parent.instance.$name == 'InputGroup' },
- { 'border-0 border-y border-l last:border-r': parent.instance.$name == 'InputGroup' },
- { 'first:ml-0 -ml-px': parent.instance.$name == 'InputGroup' && !props.showButtons },
-
- // Colors
- 'text-surface-600 dark:text-surface-200',
- 'placeholder:text-surface-400 dark:placeholder:text-surface-500',
- 'bg-surface-0 dark:bg-surface-900',
- 'border',
- { 'border-surface-300 dark:border-surface-600': !props.invalid },
-
- // Invalid State
- { 'border-red-500 dark:border-red-400': props.invalid },
-
- // States
- {
- 'hover:border-primary-500 dark:hover:border-primary-400': !context.disabled && !props.invalid,
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-500/50 dark:focus:ring-primary-400/50 focus:z-10': !context.disabled,
- 'opacity-60 select-none pointer-events-none cursor-default': context.disabled
- },
-
- // Filled State *for FloatLabel
- { filled: parent.instance?.$name == 'FloatLabel' && context.filled },
-
- // Misc
- 'appearance-none',
- 'transition-colors duration-200'
- ]
- })
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/knob/index.js b/frontend/packages/kwai-ui/src/presets/kwai/knob/index.js
deleted file mode 100644
index dc11d37f5..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/knob/index.js
+++ /dev/null
@@ -1,44 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- // Misc
- { 'opacity-60 select-none pointer-events-none cursor-default': props.disabled }
- ]
- }),
- range: {
- class: [
- // Stroke
- 'stroke-current',
-
- // Color
- 'stroke-surface-200 dark:stroke-surface-700',
-
- // Fill
- 'fill-none',
-
- // Transition
- 'transition duration-100 ease-in'
- ]
- },
- value: {
- class: [
- // Animation
- 'animate-dash-frame',
-
- // Color
- 'stroke-primary-500 dark:stroke-primary-400',
-
- // Fill
- 'fill-none'
- ]
- },
- label: {
- class: [
- // Text Style
- 'text-center text-xl',
-
- // Color
- 'fill-surface-600 dark:fill-surface-200'
- ]
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/listbox/index.js b/frontend/packages/kwai-ui/src/presets/kwai/listbox/index.js
deleted file mode 100644
index 02bf2b8da..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/listbox/index.js
+++ /dev/null
@@ -1,152 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- // Sizing and Shape
- 'min-w-[12rem]',
- 'rounded-md',
-
- // Colors
- 'bg-surface-0 dark:bg-surface-800',
- 'text-surface-700 dark:text-white/80',
- 'border',
- { 'border-surface-300 dark:border-surface-600': !props.invalid },
-
- // Invalid State
- { 'border-red-500 dark:border-red-400': props.invalid }
- ]
- }),
- wrapper: {
- class: [
- // Overflow
- 'overflow-auto'
- ]
- },
- list: {
- class: 'py-3 list-none m-0'
- },
- item: ({ context }) => ({
- class: [
- // Font
- 'font-normal',
- 'leading-none',
-
- // Position
- 'relative',
-
- // Shape
- 'border-0',
- 'rounded-none',
-
- // Spacing
- 'm-0',
- 'py-3 px-5',
-
- // Color
- { 'text-surface-700 dark:text-white/80': !context.focused && !context.selected },
- { 'bg-surface-200 dark:bg-surface-600/60 text-surface-700 dark:text-white/80': context.focused && !context.selected },
- { 'bg-primary-100 dark:bg-primary-400/40 text-primary-700 dark:text-white/80': context.focused && context.selected },
- { 'bg-primary-50 dark:bg-primary-400/40 text-primary-700 dark:text-white/80': !context.focused && context.selected },
-
- //States
- { 'hover:bg-surface-100 dark:hover:bg-surface-600/80': !context.focused && !context.selected },
- { 'hover:text-surface-700 hover:bg-surface-100 dark:hover:text-white dark:hover:bg-surface-600/80': context.focused && !context.selected },
- 'focus-visible:outline-none focus-visible:outline-offset-0 focus-visible:ring focus-visible:ring-inset focus-visible:ring-primary-400/50 dark:focus-visible:ring-primary-300/50',
-
- // Transitions
- 'transition-shadow',
- 'duration-200',
-
- // Misc
- 'cursor-pointer',
- 'overflow-hidden',
- 'whitespace-nowrap'
- ]
- }),
- itemgroup: {
- class: [
- //Font
- 'font-bold',
-
- // Spacing
- 'm-0',
- 'py-3 px-5',
-
- // Color
- 'text-surface-800 dark:text-white/80',
- 'bg-surface-0 dark:bg-surface-600/80',
-
- // Misc
- 'cursor-auto'
- ]
- },
- header: {
- class: [
- // Spacing
- 'py-3 px-5',
- 'm-0',
-
- //Shape
- 'border-b',
- 'rounded-tl-md',
- 'rounded-tr-md',
-
- // Color
- 'text-surface-700 dark:text-white/80',
- 'bg-surface-100 dark:bg-surface-800',
- 'border-surface-300 dark:border-surface-600'
- ]
- },
- filtercontainer: {
- class: 'relative'
- },
- filterinput: {
- class: [
- // Font
- 'font-sans',
- 'leading-none',
-
- // Sizing
- 'pr-7 py-3 px-3',
- '-mr-7',
- 'w-full',
-
- //Color
- 'text-surface-700 dark:text-white/80',
- 'bg-surface-0 dark:bg-surface-900',
- 'border-surface-200 dark:border-surface-700',
-
- // Shape
- 'border',
- 'rounded-lg',
- 'appearance-none',
-
- // Transitions
- 'transition',
- 'duration-200',
-
- // States
- 'hover:border-primary-500 dark:hover:border-primary-300',
- 'focus:ring focus:outline-none focus:outline-offset-0',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
-
- // Misc
- 'appearance-none'
- ]
- },
- filtericon: {
- class: ['absolute', 'top-1/2 right-3', '-mt-2']
- },
- emptymessage: {
- class: [
- // Font
- 'leading-none',
-
- // Spacing
- 'py-3 px-5',
-
- // Color
- 'text-surface-800 dark:text-white/80',
- 'bg-transparent'
- ]
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/megamenu/index.js b/frontend/packages/kwai-ui/src/presets/kwai/megamenu/index.js
deleted file mode 100644
index 45de85aca..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/megamenu/index.js
+++ /dev/null
@@ -1,199 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- 'relative',
-
- // Flexbox
- 'flex',
-
- // Shape & Size
- 'rounded-md',
-
- // Color
- 'bg-surface-50 dark:bg-surface-700',
- 'border border-surface-200 dark:border-surface-700',
- { 'p-2 items-center': props.orientation == 'horizontal', 'flex-col sm:w-48 p-0 py-1': props.orientation !== 'horizontal' }
- ]
- }),
- menu: ({ props }) => ({
- class: [
- // Flexbox
- 'sm:flex',
- 'items-center',
- 'flex-wrap',
- 'flex-col sm:flex-row',
- { hidden: !props?.mobileActive, flex: props?.mobileActive },
-
- // Position
- 'absolute sm:relative',
- 'top-full left-0',
- 'sm:top-auto sm:left-auto',
-
- // Size
- 'w-full sm:w-auto',
-
- // Spacing
- 'm-0',
- 'py-1 sm:py-0 sm:p-0',
- 'list-none',
-
- // Shape
- 'shadow-md sm:shadow-none',
- 'border-0',
-
- // Color
- 'bg-surface-0 dark:bg-surface-700 sm:bg-transparent dark:sm:bg-transparent',
-
- // Misc
- 'outline-none'
- ]
- }),
- menuitem: ({ props }) => ({
- class: [
- 'sm:relative static',
- {
- 'sm:w-auto w-full': props.horizontal,
- 'w-full': !props.horizontal
- }
- ]
- }),
- content: ({ props, context }) => ({
- class: [
- // Shape
- { 'rounded-md': props.level < 1 && props.horizontal },
-
- // Colors
- {
- 'text-surface-500 dark:text-white/70': !context.focused && !context.active,
- 'text-surface-500 dark:text-white/70 bg-surface-200 dark:bg-surface-600/90': context.focused && !context.active,
- 'text-primary-700 dark:text-surface-0/80 bg-primary-50 dark:bg-primary-400/30': context.focused && context.active,
- 'text-primary-700 dark:text-surface-0/80 bg-primary-50 dark:bg-primary-400/30': !context.focused && context.active
- },
-
- // Hover States
- {
- 'hover:bg-surface-100 dark:hover:bg-surface-600/80': !context.active,
- 'hover:bg-primary-500/50 dark:hover:bg-primary-300/30 text-primary-700 dark:text-surface-0/80': context.active
- },
-
- // Transitions
- 'transition-all',
- 'duration-200'
- ]
- }),
- action: {
- class: [
- 'relative',
-
- // Flexbox
- 'flex',
- 'items-center',
-
- // Spacing
- 'py-3',
- 'px-5',
-
- // Size
- 'py-3 pr-5 pl-9 sm:pl-5',
- 'leading-none',
-
- // Misc
- 'select-none',
- 'cursor-pointer',
- 'no-underline ',
- 'overflow-hidden'
- ]
- },
- icon: {
- class: 'mr-2'
- },
- submenuicon: ({ props }) => ({
- class: [
- {
- 'ml-auto sm:ml-2': props.horizontal,
- 'ml-auto': !props.horizontal
- }
- ]
- }),
- panel: ({ props }) => ({
- class: [
- // Size
- 'w-auto',
-
- // Spacing
- 'py-1',
- 'm-0',
-
- // Shape
- 'shadow-none sm:shadow-md',
- 'border-0',
-
- // Color
- 'bg-surface-0 dark:bg-surface-700',
-
- // Position
- 'static sm:absolute',
- 'z-10',
- {
- 'sm:left-full top-0': !props.horizontal
- }
- ]
- }),
- grid: {
- class: 'flex flex-wrap sm:flex-nowrap'
- },
- column: {
- class: 'w-full sm:w-1/2'
- },
- submenu: {
- class: ['m-0 list-none', 'py-1 px-2 w-full sm:min-w-[14rem]']
- },
- submenuheader: {
- class: [
- 'font-semibold',
-
- // Spacing
- 'py-3 px-5',
- 'm-0',
-
- // Color
- 'text-surface-700 dark:text-white/80',
- 'bg-surface-0 dark:bg-surface-700'
- ]
- },
- separator: {
- class: 'border-t border-surface-200 dark:border-surface-600 my-1'
- },
- menubutton: {
- class: [
- // Flexbox
- 'flex sm:hidden',
- 'items-center justify-center',
-
- // Size
- 'w-8',
- 'h-8',
-
- // Shape
- 'rounded-full',
- // Color
- 'text-surface-500 dark:text-white/80',
-
- // States
- 'hover:text-surface-600 dark:hover:text-white/60',
- 'hover:bg-surface-100 dark:hover:bg-surface-600/80',
- 'focus:outline-none focus:outline-offset-0',
- 'focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // Misc
- 'cursor-pointer',
- 'no-underline'
- ]
- },
- end: {
- class: 'ml-auto self-center'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/menu/index.js b/frontend/packages/kwai-ui/src/presets/kwai/menu/index.js
deleted file mode 100644
index fc971da9d..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/menu/index.js
+++ /dev/null
@@ -1,96 +0,0 @@
-export default {
- root: {
- class: [
- // Sizing and Shape
- 'min-w-[12rem]',
- 'rounded-md',
- // Spacing
- 'py-2',
- // Colors
- 'bg-surface-0 dark:bg-surface-700',
- 'text-surface-700 dark:text-white/80',
- 'border border-surface-200 dark:border-surface-700'
- ]
- },
- menu: {
- class: [
- // Spacings and Shape
- 'list-none',
- 'm-0',
- 'p-0',
- 'outline-none'
- ]
- },
- content: ({ context }) => ({
- class: [
- //Shape
- 'rounded-none',
- // Colors
- 'text-surface-700 dark:text-white/80',
- {
- 'bg-surface-200 text-surface-700 dark:bg-surface-300/10 dark:text-white': context.focused
- },
- // Transitions
- 'transition-shadow',
- 'duration-200',
- // States
- 'hover:text-surface-700 dark:hover:text-white/80',
- 'hover:bg-surface-100 dark:bg-surface-700 dark:hover:bg-surface-400/10'
- ]
- }),
- action: {
- class: [
- 'relative',
- // Flexbox
-
- 'flex',
- 'items-center',
-
- // Spacing
- 'py-3',
- 'px-5',
-
- // Color
- 'text-surface-700 dark:text-white/80',
-
- // Misc
- 'no-underline',
- 'overflow-hidden',
- 'cursor-pointer',
- 'select-none'
- ]
- },
- icon: {
- class: [
- // Spacing
- 'mr-2',
-
- // Color
- 'text-surface-600 dark:text-white/70'
- ]
- },
- label: {
- class: ['leading-none']
- },
- submenuheader: {
- class: [
- // Font
- 'font-bold',
- // Spacing
- 'm-0',
- 'py-3 px-5',
- // Shape
- 'rounded-tl-none',
- 'rounded-tr-none',
- // Colors
- 'bg-surface-0 dark:bg-surface-700',
- 'text-surface-700 dark:text-white'
- ]
- },
- transition: {
- enterFromClass: 'opacity-0 scale-y-[0.8]',
- enterActiveClass: 'transition-[transform,opacity] duration-[120ms] ease-[cubic-bezier(0,0,0.2,1)]',
- leaveActiveClass: 'transition-opacity duration-100 ease-linear',
- leaveToClass: 'opacity-0'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/menubar/index.js b/frontend/packages/kwai-ui/src/presets/kwai/menubar/index.js
deleted file mode 100644
index 8c3fec0ad..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/menubar/index.js
+++ /dev/null
@@ -1,176 +0,0 @@
-export default {
- root: {
- class: [
- 'relative',
-
- // Flexbox
- 'flex',
- 'items-center',
-
- // Spacing
- 'p-2',
-
- // Shape
- 'rounded-md',
-
- // Color
- 'bg-surface-50 dark:bg-surface-700',
- 'border border-surface-200 dark:border-surface-700'
- ]
- },
- menu: ({ props }) => ({
- class: [
- // Flexbox
- 'sm:flex',
- 'items-center',
- 'flex-wrap',
- 'flex-col sm:flex-row',
- { hidden: !props?.mobileActive, flex: props?.mobileActive },
-
- // Position
- 'absolute sm:relative',
- 'top-full left-0',
- 'sm:top-auto sm:left-auto',
-
- // Size
- 'w-full sm:w-auto',
-
- // Spacing
- 'm-0',
- 'py-1 sm:py-0 sm:p-0',
- 'list-none',
-
- // Shape
- 'shadow-md sm:shadow-none',
- 'border-0',
-
- // Color
- 'bg-surface-0 dark:bg-surface-700 sm:bg-transparent',
-
- // Misc
- 'outline-none'
- ]
- }),
- menuitem: {
- class: 'sm:relative sm:w-auto w-full static'
- },
- content: ({ props, context }) => ({
- class: [
- // Shape
- { 'rounded-md': props.root },
-
- // Colors
- {
- 'text-surface-500 dark:text-white/70': !context.focused && !context.active,
- 'text-surface-500 dark:text-white/70 bg-surface-200 dark:bg-surface-600/90': context.focused && !context.active,
- 'text-primary-700 dark:text-surface-0/80 bg-primary-50 dark:bg-primary-400/30': context.focused && context.active,
- 'text-primary-700 dark:text-surface-0/80 bg-primary-50 dark:bg-primary-400/30': !context.focused && context.active
- },
-
- // Hover States
- {
- 'hover:bg-surface-100 dark:hover:bg-surface-600/80': !context.active,
- 'hover:bg-primary-500/50 dark:hover:bg-primary-300/30 text-primary-700 dark:text-surface-0/80': context.active
- },
-
- // Transitions
- 'transition-all',
- 'duration-200'
- ]
- }),
- action: ({ context }) => ({
- class: [
- 'relative',
-
- // Flexbox
- 'flex',
- 'items-center',
-
- // Spacing
- 'py-3',
- 'px-5',
-
- // Size
- {
- 'pl-9 sm:pl-5': context.level === 1,
- 'pl-14 sm:pl-5': context.level === 2
- },
- 'leading-none',
-
- // Misc
- 'select-none',
- 'cursor-pointer',
- 'no-underline ',
- 'overflow-hidden'
- ]
- }),
- icon: {
- class: 'mr-2'
- },
- submenuicon: ({ props }) => ({
- class: [
- {
- 'ml-auto sm:ml-2': props.root,
- 'ml-auto': !props.root
- }
- ]
- }),
- submenu: ({ props }) => ({
- class: [
- // Size
- 'w-full sm:w-48',
-
- // Spacing
- 'py-1',
- 'm-0',
- 'list-none',
-
- // Shape
- 'shadow-none sm:shadow-md',
- 'border-0',
-
- // Position
- 'static sm:absolute',
- 'z-10',
- { 'sm:absolute sm:left-full sm:top-0': props.level > 1 },
-
- // Color
- 'bg-surface-0 dark:bg-surface-700'
- ]
- }),
- separator: {
- class: 'border-t border-surface-200 dark:border-surface-600 my-1'
- },
- button: {
- class: [
- // Flexbox
- 'flex sm:hidden',
- 'items-center justify-center',
-
- // Size
- 'w-8',
- 'h-8',
-
- // Shape
- 'rounded-full',
- // Color
- 'text-surface-500 dark:text-white/80',
-
- // States
- 'hover:text-surface-600 dark:hover:text-white/60',
- 'hover:bg-surface-100 dark:hover:bg-surface-600/80',
- 'focus:outline-none focus:outline-offset-0',
- 'focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // Misc
- 'cursor-pointer',
- 'no-underline'
- ]
- },
- end: {
- class: 'ml-auto self-center'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/message/index.js b/frontend/packages/kwai-ui/src/presets/kwai/message/index.js
deleted file mode 100644
index 18bef54b5..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/message/index.js
+++ /dev/null
@@ -1,87 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- // Spacing and Shape
- 'my-4 mx-0',
- 'rounded-md',
- 'border-solid border-0 border-l-[6px]',
-
- // Colors
- {
- 'bg-blue-100/70 dark:bg-blue-500/20': props.severity == 'info',
- 'bg-green-100/70 dark:bg-green-500/20': props.severity == 'success',
- 'bg-orange-100/70 dark:bg-orange-500/20': props.severity == 'warn',
- 'bg-red-100/70 dark:bg-red-500/20': props.severity == 'error'
- },
- {
- 'border-blue-500 dark:border-blue-400': props.severity == 'info',
- 'border-green-500 dark:border-green-400': props.severity == 'success',
- 'border-orange-500 dark:border-orange-400': props.severity == 'warn',
- 'border-red-500 dark:border-red-400': props.severity == 'error'
- },
- {
- 'text-blue-700 dark:text-blue-300': props.severity == 'info',
- 'text-green-700 dark:text-green-300': props.severity == 'success',
- 'text-orange-700 dark:text-orange-300': props.severity == 'warn',
- 'text-red-700 dark:text-red-300': props.severity == 'error'
- }
- ]
- }),
- wrapper: {
- class: [
- // Flexbox
- 'flex items-center',
-
- // Spacing
- 'py-5 px-7'
- ]
- },
- icon: {
- class: [
- // Sizing and Spacing
- 'w-6 h-6',
- 'text-lg leading-none mr-2 shrink-0'
- ]
- },
- text: {
- class: [
- // Font and Text
- 'text-base leading-none',
- 'font-medium'
- ]
- },
- button: {
- class: [
- // Flexbox
- 'flex items-center justify-center',
-
- // Size
- 'w-8 h-8',
-
- // Spacing and Misc
- 'ml-auto relative',
-
- // Shape
- 'rounded-full',
-
- // Colors
- 'bg-transparent',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // States
- 'hover:bg-surface-0/50 dark:hover:bg-surface-0/10',
-
- // Misc
- 'overflow-hidden'
- ]
- },
- transition: {
- enterFromClass: 'opacity-0',
- enterActiveClass: 'transition-opacity duration-300',
- leaveFromClass: 'max-h-40',
- leaveActiveClass: 'overflow-hidden transition-all duration-300 ease-in',
- leaveToClass: 'max-h-0 opacity-0 !m-0'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/metergroup/index.js b/frontend/packages/kwai-ui/src/presets/kwai/metergroup/index.js
deleted file mode 100644
index a820d8fe2..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/metergroup/index.js
+++ /dev/null
@@ -1,97 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- // Flexbox
- 'flex gap-4',
-
- { 'flex-col': props.orientation == 'horizontal', 'flex-row': props.orientation == 'vertical' }
- ]
- }),
- metercontainer: ({ props }) => ({
- class: [
- // Flexbox
- 'flex',
-
- { 'flex-col': props.orientation === 'vertical' },
-
- // Sizing
- { 'w-2 h-full': props.orientation === 'vertical' },
- { 'h-2': props.orientation === 'horizontal' },
-
- // Colors
- 'bg-gray-200 dark:bg-gray-700',
-
- // Border Radius
- 'rounded-lg'
- ]
- }),
- meter: ({ props }) => ({
- class: [
- // Shape
- 'border-0',
-
- // Rounded Corners - Horizontal
- {
- 'first:rounded-l-lg last:rounded-r-lg': props.orientation === 'horizontal'
- },
-
- // Rounded Corners - Vertical
- {
- 'first:rounded-t-lg last:rounded-b-lg': props.orientation === 'vertical'
- },
-
- // Colors
- 'bg-primary-500 dark:bg-primary-400'
- ]
- }),
- labellist: ({ props }) => ({
- class: [
- // Display & Flexbox
- 'flex flex-wrap',
-
- { 'gap-4': props.labelOrientation === 'horizontal' },
-
- { 'gap-2': props.labelOrientation === 'vertical' },
-
- { 'flex-col': props.labelOrientation === 'vertical' },
-
- // Conditional Alignment - Horizontal
- {
- 'align-end': props.labelOrientation === 'horizontal' && props.labelPosition === 'end',
- 'align-start': props.labelOrientation === 'horizontal' && props.labelPosition === 'start'
- },
-
- // Conditional Alignment - Vertical
- {
- 'justify-end': props.labelOrientation === 'vertical' && props.labelPosition === 'end',
- 'justify-start': props.labelOrientation === 'vertical' && props.labelPosition === 'start'
- },
-
- // List Styling
- 'm-0 p-0 list-none'
- ]
- }),
- labellistitem: {
- class: [
- // Flexbox
- 'inline-flex',
- 'items-center',
- 'gap-2'
- ]
- },
- labellisttype: {
- class: [
- // Display
- 'inline-flex',
-
- // Background Color
- 'bg-primary-500 dark:bg-primary-400',
-
- // Size
- 'w-2 h-2',
-
- // Rounded Shape
- 'rounded-full'
- ]
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/multiselect/index.js b/frontend/packages/kwai-ui/src/presets/kwai/multiselect/index.js
deleted file mode 100644
index b2cc23583..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/multiselect/index.js
+++ /dev/null
@@ -1,546 +0,0 @@
-export default {
- root: ({ props, state }) => ({
- class: [
- // Display and Position
- 'inline-flex',
- 'relative',
-
- // Shape
- 'rounded-md',
-
- // Color and Background
- 'bg-surface-0 dark:bg-surface-900',
- 'border',
- { 'border-surface-300 dark:border-surface-600': !props.invalid },
-
- // Invalid State
- { 'border-red-500 dark:border-red-400': props.invalid },
-
- // Transitions
- 'transition-all',
- 'duration-200',
-
- // States
- { 'hover:border-primary-500 dark:hover:border-primary-300': !props.invalid },
- { 'outline-none outline-offset-0 ring ring-primary-400/50 dark:ring-primary-300/50': state.focused },
-
- // Misc
- 'cursor-pointer',
- 'select-none',
- { 'opacity-60': props.disabled, 'pointer-events-none': props.disabled, 'cursor-default': props.disabled }
- ]
- }),
- labelContainer: {
- class: 'overflow-hidden flex flex-auto cursor-pointer '
- },
- label: ({ props }) => ({
- class: [
- 'leading-none',
- 'block ',
-
- // Spacing
- {
- 'p-3': props.display !== 'chip',
- 'py-3 px-3': props.display === 'chip' && !props?.modelValue?.length,
- 'py-1.5 px-3': props.display === 'chip' && props?.modelValue?.length > 0
- },
-
- // Color
- { 'text-surface-800 dark:text-white/80': props.modelValue?.length, 'text-surface-400 dark:text-surface-500': !props.modelValue?.length },
- 'placeholder:text-surface-400 dark:placeholder:text-surface-500',
-
- // Transitions
- 'transition duration-200',
-
- // Misc
- 'overflow-hidden whitespace-nowrap cursor-pointer overflow-ellipsis'
- ]
- }),
- token: {
- class: [
- // Flex
- 'inline-flex items-center',
-
- // Spacings
- 'py-1.5 px-3 mr-2',
-
- // Shape
- 'rounded-[1.14rem]',
-
- // Colors
- 'bg-surface-200 dark:bg-surface-700',
- 'text-surface-700 dark:text-white/70',
-
- // Misc
- 'cursor-default'
- ]
- },
- removeTokenIcon: {
- class: [
- // Shape
- 'rounded-md leading-6',
-
- // Spacing
- 'ml-2',
-
- // Size
- 'w-4 h-4',
-
- // Transition
- 'transition duration-200 ease-in-out',
-
- // Misc
- 'cursor-pointer'
- ]
- },
- trigger: {
- class: [
- // Flexbox
- 'flex items-center justify-center',
- 'shrink-0',
-
- // Color and Background
- 'bg-transparent',
- 'text-surface-500',
-
- // Size
- 'w-12',
-
- // Shape
- 'rounded-tr-md',
- 'rounded-br-md'
- ]
- },
- panel: {
- class: [
- // Position
- 'absolute top-0 left-0',
-
- // Shape
- 'border-0 dark:border',
- 'rounded-md',
- 'shadow-md',
-
- // Color
- 'bg-surface-0 dark:bg-surface-800',
- 'text-surface-800 dark:text-white/80',
- 'dark:border-surface-700'
- ]
- },
- header: {
- class: [
- 'flex items-center justify-between',
- // Spacing
- 'py-3 px-5',
- 'm-0',
-
- //Shape
- 'border-b',
- 'rounded-tl-md',
- 'rounded-tr-md',
-
- // Color
- 'text-surface-700 dark:text-white/80',
- 'bg-surface-100 dark:bg-surface-800',
- 'border-surface-300 dark:border-surface-700'
- ]
- },
- headerCheckboxContainer: {
- class: [
- 'relative',
-
- // Alignment
- 'inline-flex',
- 'align-bottom',
-
- // Size
- 'w-6',
- 'h-6',
-
- // Misc
- 'cursor-pointer',
- 'select-none'
- ]
- },
- headerCheckbox: {
- root: {
- class: [
- 'relative',
-
- // Alignment
- 'inline-flex',
- 'align-bottom',
-
- // Size
- 'w-6',
- 'h-6',
-
- // Spacing
- 'mr-2',
-
- // Misc
- 'cursor-pointer',
- 'select-none'
- ]
- },
- box: ({ props, context }) => ({
- class: [
- // Alignment
- 'flex',
- 'items-center',
- 'justify-center',
-
- // Size
- 'w-6',
- 'h-6',
-
- // Shape
- 'rounded-md',
- 'border-2',
-
- // Colors
- {
- 'border-surface-200 bg-surface-0 dark:border-surface-700 dark:bg-surface-900': !context.checked,
- 'border-primary-500 bg-primary-500 dark:border-primary-400 dark:bg-primary-400': context.checked
- },
-
- // States
- {
- 'peer-hover:border-primary-500 dark:peer-hover:border-primary-400': !props.disabled && !context.checked,
- 'peer-hover:bg-primary-600 dark:peer-hover:bg-primary-300 peer-hover:border-primary-700 dark:peer-hover:border-primary-300': !props.disabled && context.checked,
- 'peer-focus-visible:border-primary-500 dark:peer-focus-visible:border-primary-400 peer-focus-visible:ring-2 peer-focus-visible:ring-primary-400/20 dark:peer-focus-visible:ring-primary-300/20': !props.disabled,
- 'cursor-default opacity-60': props.disabled
- },
-
- // Transitions
- 'transition-colors',
- 'duration-200'
- ]
- }),
- input: {
- class: [
- 'peer',
-
- // Size
- 'w-full ',
- 'h-full',
-
- // Position
- 'absolute',
- 'top-0 left-0',
- 'z-10',
-
- // Spacing
- 'p-0',
- 'm-0',
-
- // Shape
- 'opacity-0',
- 'rounded-md',
- 'outline-none',
- 'border-2 border-surface-200 dark:border-surface-700',
-
- // Misc
- 'appearance-none',
- 'cursor-pointer'
- ]
- },
- icon: {
- class: [
- // Font
- 'text-base leading-none',
-
- // Size
- 'w-4',
- 'h-4',
-
- // Colors
- 'text-white dark:text-surface-900',
-
- // Transitions
- 'transition-all',
- 'duration-200'
- ]
- }
- },
- itemCheckbox: {
- root: {
- class: [
- 'relative',
-
- // Alignment
- 'inline-flex',
- 'align-bottom',
-
- // Size
- 'w-6',
- 'h-6',
-
- // Spacing
- 'mr-2',
-
- // Misc
- 'cursor-pointer',
- 'select-none'
- ]
- },
- box: ({ props, context }) => ({
- class: [
- // Alignment
- 'flex',
- 'items-center',
- 'justify-center',
-
- // Size
- 'w-6',
- 'h-6',
-
- // Shape
- 'rounded-md',
- 'border-2',
-
- // Colors
- {
- 'border-surface-200 bg-surface-0 dark:border-surface-700 dark:bg-surface-900': !context.checked,
- 'border-primary-500 bg-primary-500 dark:border-primary-400 dark:bg-primary-400': context.checked
- },
-
- // States
- {
- 'peer-hover:border-primary-500 dark:peer-hover:border-primary-400': !props.disabled && !context.checked,
- 'peer-hover:bg-primary-600 dark:peer-hover:bg-primary-300 peer-hover:border-primary-700 dark:peer-hover:border-primary-300': !props.disabled && context.checked,
- 'peer-focus-visible:border-primary-500 dark:peer-focus-visible:border-primary-400 peer-focus-visible:ring-2 peer-focus-visible:ring-primary-400/20 dark:peer-focus-visible:ring-primary-300/20': !props.disabled,
- 'cursor-default opacity-60': props.disabled
- },
-
- // Transitions
- 'transition-colors',
- 'duration-200'
- ]
- }),
- input: {
- class: [
- 'peer',
-
- // Size
- 'w-full ',
- 'h-full',
-
- // Position
- 'absolute',
- 'top-0 left-0',
- 'z-10',
-
- // Spacing
- 'p-0',
- 'm-0',
-
- // Shape
- 'opacity-0',
- 'rounded-md',
- 'outline-none',
- 'border-2 border-surface-200 dark:border-surface-700',
-
- // Misc
- 'appearance-none',
- 'cursor-pointer'
- ]
- },
- icon: {
- class: [
- // Font
- 'text-base leading-none',
-
- // Size
- 'w-4',
- 'h-4',
-
- // Colors
- 'text-white dark:text-surface-900',
-
- // Transitions
- 'transition-all',
- 'duration-200'
- ]
- }
- },
- closeButton: {
- class: [
- 'relative',
-
- // Flexbox and Alignment
- 'flex items-center justify-center',
-
- // Size and Spacing
- 'mr-2',
- 'last:mr-0',
- 'w-8 h-8',
-
- // Shape
- 'border-0',
- 'rounded-full',
-
- // Colors
- 'text-surface-500',
- 'bg-transparent',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // States
- 'hover:text-surface-700 dark:hover:text-white/80',
- 'hover:bg-surface-100 dark:hover:bg-surface-800/80',
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-inset',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
-
- // Misc
- 'overflow-hidden'
- ]
- },
- closeButtonIcon: {
- class: 'w-4 h-4 inline-block'
- },
- wrapper: {
- class: [
- // Sizing
- 'max-h-[200px]',
-
- // Misc
- 'overflow-auto'
- ]
- },
- list: {
- class: 'py-3 list-none m-0'
- },
- item: ({ context }) => ({
- class: [
- // Font
- 'font-normal',
- 'leading-none',
-
- // Flexbox
- 'flex items-center',
-
- // Position
- 'relative',
-
- // Shape
- 'border-0',
- 'rounded-none',
-
- // Spacing
- 'm-0',
- 'py-3 px-5',
-
- // Color
- { 'text-surface-700 dark:text-white/80': !context.focused && !context.selected },
- { 'bg-surface-200 dark:bg-surface-600/60 text-surface-700 dark:text-white/80': context.focused && !context.selected },
- { 'bg-primary-100 dark:bg-primary-400/40 text-primary-700 dark:text-white/80': context.focused && context.selected },
- { 'bg-primary-50 dark:bg-primary-400/40 text-primary-700 dark:text-white/80': !context.focused && context.selected },
-
- //States
- { 'hover:bg-surface-100 dark:hover:bg-surface-600/80': !context.focused && !context.selected },
- { 'hover:text-surface-700 hover:bg-surface-100 dark:hover:text-white dark:hover:bg-surface-600/80': context.focused && !context.selected },
-
- // Transitions
- 'transition-shadow',
- 'duration-200',
-
- // Misc
- 'cursor-pointer',
- 'overflow-hidden',
- 'whitespace-nowrap'
- ]
- }),
- itemgroup: {
- class: [
- //Font
- 'font-bold',
-
- // Spacing
- 'm-0',
- 'p-3 px-5',
-
- // Color
- 'text-surface-800 dark:text-white/80',
- 'bg-surface-0 dark:bg-surface-600/80',
-
- // Misc
- 'cursor-auto'
- ]
- },
- filtercontainer: {
- class: 'relative w-full mx-2'
- },
- filterinput: {
- class: [
- // Font
- 'font-sans',
- 'leading-none',
-
- // Sizing
- 'pr-7 py-3 px-3',
- '-mr-7',
- 'w-full',
-
- //Color
- 'text-surface-700 dark:text-white/80',
- 'bg-surface-0 dark:bg-surface-900',
- 'border-surface-200 dark:border-surface-700',
- 'placeholder:text-surface-400 dark:placeholder:text-surface-500',
-
- // Shape
- 'border',
- 'rounded-lg',
- 'appearance-none',
-
- // Transitions
- 'transition',
- 'duration-200',
-
- // States
- 'hover:border-primary-500 dark:hover:border-primary-300',
- 'focus:ring focus:outline-none focus:outline-offset-0',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
-
- // Misc
- 'appearance-none'
- ]
- },
- filtericon: {
- class: ['absolute', 'top-1/2 right-3', '-mt-2']
- },
- clearicon: {
- class: [
- // Color
- 'text-surface-500',
-
- // Position
- 'absolute',
- 'top-1/2',
- 'right-12',
-
- // Spacing
- '-mt-2'
- ]
- },
- emptymessage: {
- class: [
- // Font
- 'leading-none',
-
- // Spacing
- 'py-3 px-5',
-
- // Color
- 'text-surface-800 dark:text-white/80',
- 'bg-transparent'
- ]
- },
- transition: {
- enterFromClass: 'opacity-0 scale-y-[0.8]',
- enterActiveClass: 'transition-[transform,opacity] duration-[120ms] ease-[cubic-bezier(0,0,0.2,1)]',
- leaveActiveClass: 'transition-opacity duration-100 ease-linear',
- leaveToClass: 'opacity-0'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/orderlist/index.js b/frontend/packages/kwai-ui/src/presets/kwai/orderlist/index.js
deleted file mode 100644
index c05d631f4..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/orderlist/index.js
+++ /dev/null
@@ -1,257 +0,0 @@
-export default {
- root: {
- class: [
- // Flexbox
- 'flex'
- ]
- },
- controls: {
- class: [
- // Flexbox & Alignment
- 'flex flex-col justify-center gap-2',
-
- // Spacing
- 'p-5'
- ]
- },
- moveupbutton: {
- root: ({ context }) => ({
- class: [
- // Flexbox & Alignment
- 'relative inline-flex items-center justify-center',
-
- // Shape
- 'rounded-md',
-
- // Color
- 'text-white dark:text-surface-900',
- 'bg-primary-500 dark:bg-primary-400',
- 'border border-primary-500 dark:border-primary-400',
-
- // Spacing & Size
- 'w-12',
- 'm-0',
- 'px-0 py-3',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // State
- 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300',
- 'focus:outline-none focus:outline-offset-0 focus:ring',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
- { 'cursor-default pointer-events-none opacity-60': context.disabled },
-
- // Interactivity
- 'cursor-pointer user-select-none'
- ]
- }),
- label: {
- class: [
- // Flexbox
- 'flex-initial',
-
- // Size
- 'w-0'
- ]
- }
- },
- movedownbutton: {
- root: ({ context }) => ({
- class: [
- // Flexbox & Alignment
- 'relative inline-flex items-center justify-center',
-
- // Shape
- 'rounded-md',
-
- // Color
- 'text-white dark:text-surface-900',
- 'bg-primary-500 dark:bg-primary-400',
- 'border border-primary-500 dark:border-primary-400',
-
- // Spacing & Size
- 'w-12',
- 'm-0',
- 'px-0 py-3',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // State
- 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300',
- 'focus:outline-none focus:outline-offset-0 focus:ring',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
- { 'cursor-default pointer-events-none opacity-60': context.disabled },
-
- // Interactivity
- 'cursor-pointer user-select-none'
- ]
- }),
- label: {
- class: [
- // Flexbox
- 'flex-initial',
-
- // Size
- 'w-0'
- ]
- }
- },
- movetopbutton: {
- root: ({ context }) => ({
- class: [
- // Flexbox & Alignment
- 'relative inline-flex items-center justify-center',
-
- // Shape
- 'rounded-md',
-
- // Color
- 'text-white dark:text-surface-900',
- 'bg-primary-500 dark:bg-primary-400',
- 'border border-primary-500 dark:border-primary-400',
-
- // Spacing & Size
- 'w-12',
- 'm-0',
- 'px-0 py-3',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // State
- 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300',
- 'focus:outline-none focus:outline-offset-0 focus:ring',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
- { 'cursor-default pointer-events-none opacity-60': context.disabled },
-
- // Interactivity
- 'cursor-pointer user-select-none'
- ]
- }),
- label: {
- class: [
- // Flexbox
- 'flex-initial',
-
- // Size
- 'w-0'
- ]
- }
- },
- movebottombutton: {
- root: ({ context }) => ({
- class: [
- // Flexbox & Alignment
- 'relative inline-flex items-center justify-center',
-
- // Shape
- 'rounded-md',
-
- // Color
- 'text-white dark:text-surface-900',
- 'bg-primary-500 dark:bg-primary-400',
- 'border border-primary-500 dark:border-primary-400',
-
- // Spacing & Size
- 'w-12',
- 'm-0',
- 'px-0 py-3',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // State
- 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300',
- 'focus:outline-none focus:outline-offset-0 focus:ring',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
- { 'cursor-default pointer-events-none opacity-60': context.disabled },
-
- // Interactivity
- 'cursor-pointer user-select-none'
- ]
- }),
- label: {
- class: [
- // Flexbox
- 'flex-initial',
-
- // Size
- 'w-0'
- ]
- }
- },
- container: {
- class: ['flex-auto']
- },
- header: {
- class: [
- 'font-bold',
-
- // Shape
- 'border-b-0 rounded-t-md',
-
- // Spacing
- 'p-5',
-
- // Color
- 'text-surface-700 dark:text-white/80',
- 'bg-surface-50 dark:bg-surface-800',
- 'border border-surface-200 dark:border-surface-700'
- ]
- },
- list: {
- class: [
- // Spacing
- 'list-none m-0 p-0',
-
- // Size
- 'min-h-[12rem] max-h-[24rem]',
-
- // Shape
- 'rounded-b-md',
-
- // Color
- 'text-surface-600 dark:text-white/80',
- 'bg-surface-0 dark:bg-surface-800',
- 'border border-surface-200 dark:border-surface-700',
-
- // Spacing
- 'py-3 px-0',
-
- // Focus & Outline
- 'outline-none',
-
- // Misc
- 'overflow-auto'
- ]
- },
- item: ({ context }) => ({
- class: [
- // Position
- 'relative',
-
- // Spacing
- 'py-3 px-5 m-0',
-
- // Shape
- 'border-none',
-
- // Transition
- 'transition duration-200',
-
- // Color
- 'text-surface-700 dark:text-white/80',
- { 'bg-primary-500/20 dark:bg-primary-300/20': context.active && !context.focused },
- { 'bg-primary-500/30 dark:bg-primary-400/30': context.active && context.focused },
- { 'bg-surface-100 dark:bg-surface-700/70': !context.active && context.focused },
-
- // State
- 'hover:bg-surface-100 dark:hover:bg-surface-700',
-
- // Misc
- 'cursor-pointer overflow-hidden'
- ]
- })
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/organizationchart/index.js b/frontend/packages/kwai-ui/src/presets/kwai/organizationchart/index.js
deleted file mode 100644
index e0cc87a8b..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/organizationchart/index.js
+++ /dev/null
@@ -1,138 +0,0 @@
-export default {
- table: {
- class: [
- // Spacing & Position
- 'mx-auto my-0',
-
- // Table Style
- 'border-spacing-0 border-separate'
- ]
- },
- cell: {
- class: [
- // Alignment
- 'text-center align-top',
-
- // Spacing
- 'py-0 px-3'
- ]
- },
- node: ({ props, context }) => ({
- class: [
- 'relative inline-block',
-
- // Spacing
- 'p-5',
-
- // Shape
- 'border',
-
- // Color
- {
- 'text-surface-600 dark:text-white/80': !context?.selected,
- 'bg-surface-0 dark:bg-surface-800': !context?.selected,
- 'border-surface-200 dark:border-surface-700': !context?.selected,
- 'text-primary-700 dark:text-surface-0': context?.selected,
- 'bg-primary-50 dark:bg-primary-400/30': context?.selected,
- 'border-primary-200 dark:border-primary-600': context?.selected
- },
-
- // States
- {
- 'hover:bg-surface-100 dark:hover:bg-surface-700': context?.selectable && !context?.selected,
- 'hover:bg-primary-100 dark:hover:bg-primary-300/30': context?.selectable && context?.selected
- },
-
- { 'cursor-pointer': context?.selectable }
- ]
- }),
- linecell: {
- class: [
- // Alignment
- 'text-center align-top',
-
- // Spacing
- 'py-0 px-3'
- ]
- },
- linedown: {
- class: [
- // Spacing
- 'mx-auto my-0',
-
- // Size
- 'w-px h-[20px]',
-
- // Color
- 'bg-surface-200 dark:bg-surface-700'
- ]
- },
- lineleft: ({ context }) => ({
- class: [
- // Alignment
- 'text-center align-top',
-
- // Spacing
- 'py-0 px-3',
-
- // Shape
- 'rounded-none border-r',
- { 'border-t': context.lineTop },
-
- // Color
- 'border-surface-200 dark:border-surface-700'
- ]
- }),
- lineright: ({ context }) => ({
- class: [
- // Alignment
- 'text-center align-top',
-
- // Spacing
- 'py-0 px-3',
-
- // Shape
- 'rounded-none',
-
- // Color
- { 'border-t border-surface-200 dark:border-surface-700': context.lineTop }
- ]
- }),
- nodecell: {
- class: 'text-center align-top py-0 px-3'
- },
- nodetoggler: {
- class: [
- // Position
- 'absolute bottom-[-0.75rem] left-2/4 -ml-3',
- 'z-20',
-
- // Flexbox
- 'flex items-center justify-center',
-
- // Size
- 'w-6 h-6',
-
- // Shape
- 'rounded-full',
-
- // Color
- 'bg-inherit text-inherit',
-
- // Focus
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
-
- // Misc
- 'cursor-pointer no-underline select-none'
- ]
- },
- nodetogglericon: {
- class: [
- // Position
- 'relative inline-block',
-
- // Size
- 'w-4 h-4'
- ]
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/overlaypanel/index.js b/frontend/packages/kwai-ui/src/presets/kwai/overlaypanel/index.js
deleted file mode 100644
index f67d2ffe3..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/overlaypanel/index.js
+++ /dev/null
@@ -1,40 +0,0 @@
-export default {
- root: {
- class: [
- // Shape
- 'rounded-md shadow-lg',
- 'border-0 dark:border',
-
- // Position
- 'absolute left-0 top-0 mt-2',
- 'z-40 transform origin-center',
-
- // Color
- 'bg-surface-0 dark:bg-surface-800',
- 'text-surface-700 dark:text-surface-0/80',
- 'dark:border-surface-700',
-
- // Before: Triangle
- 'before:absolute before:-top-[9px] before:-ml-[9px] before:left-[calc(var(--overlayArrowLeft,0)+1.25rem)] z-0',
- 'before:w-0 before:h-0',
- 'before:border-transparent before:border-solid',
- 'before:border-x-[8px] before:border-[8px]',
- 'before:border-t-0 before:border-b-surface-300/10 dark:before:border-b-surface-700',
-
- 'after:absolute after:-top-2 after:-ml-[8px] after:left-[calc(var(--overlayArrowLeft,0)+1.25rem)]',
- 'after:w-0 after:h-0',
- 'after:border-transparent after:border-solid',
- 'after:border-x-[0.5rem] after:border-[0.5rem]',
- 'after:border-t-0 after:border-b-surface-0 dark:after:border-b-surface-800'
- ]
- },
- content: {
- class: 'p-5 items-center flex'
- },
- transition: {
- enterFromClass: 'opacity-0 scale-y-[0.8]',
- enterActiveClass: 'transition-[transform,opacity] duration-[120ms] ease-[cubic-bezier(0,0,0.2,1)]',
- leaveActiveClass: 'transition-opacity duration-100 ease-linear',
- leaveToClass: 'opacity-0'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/paginator/index.js b/frontend/packages/kwai-ui/src/presets/kwai/paginator/index.js
deleted file mode 100644
index 035907bf0..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/paginator/index.js
+++ /dev/null
@@ -1,533 +0,0 @@
-export default {
- root: {
- class: [
- // Flex & Alignment
- 'flex items-center justify-center flex-wrap',
-
- // Spacing
- 'px-4 py-2',
-
- // Shape
- 'border-0',
-
- // Color
- 'bg-surface-0 dark:bg-surface-800',
- 'text-surface-500 dark:text-white/60'
- ]
- },
- firstpagebutton: ({ context }) => ({
- class: [
- 'relative',
-
- // Flex & Alignment
- 'inline-flex items-center justify-center',
-
- // Shape
- 'border-0 rounded-full dark:rounded-md',
-
- // Size
- 'min-w-[3rem] h-12 m-[0.143rem]',
- 'leading-none',
-
- // Color
- 'text-surface-500 dark:text-white/60',
-
- // State
- {
- 'hover:bg-surface-50 dark:hover:bg-surface-700/70': !context.disabled,
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50': !context.disabled
- },
-
- // Transition
- 'transition duration-200',
-
- // Misc
- 'user-none overflow-hidden',
- { 'cursor-default pointer-events-none opacity-60': context.disabled }
- ]
- }),
- previouspagebutton: ({ context }) => ({
- class: [
- 'relative',
-
- // Flex & Alignment
- 'inline-flex items-center justify-center',
-
- // Shape
- 'border-0 rounded-full dark:rounded-md',
-
- // Size
- 'min-w-[3rem] h-12 m-[0.143rem]',
- 'leading-none',
-
- // Color
- 'text-surface-500 dark:text-white/60',
-
- // State
- {
- 'hover:bg-surface-50 dark:hover:bg-surface-700/70': !context.disabled,
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50': !context.disabled
- },
-
- // Transition
- 'transition duration-200',
-
- // Misc
- 'user-none overflow-hidden',
- { 'cursor-default pointer-events-none opacity-60': context.disabled }
- ]
- }),
- nextpagebutton: ({ context }) => ({
- class: [
- 'relative',
-
- // Flex & Alignment
- 'inline-flex items-center justify-center',
-
- // Shape
- 'border-0 rounded-full dark:rounded-md',
-
- // Size
- 'min-w-[3rem] h-12 m-[0.143rem]',
- 'leading-none',
-
- // Color
- 'text-surface-500 dark:text-white/60',
-
- // State
- {
- 'hover:bg-surface-50 dark:hover:bg-surface-700/70': !context.disabled,
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50': !context.disabled
- },
-
- // Transition
- 'transition duration-200',
-
- // Misc
- 'user-none overflow-hidden',
- { 'cursor-default pointer-events-none opacity-60': context.disabled }
- ]
- }),
- lastpagebutton: ({ context }) => ({
- class: [
- 'relative',
-
- // Flex & Alignment
- 'inline-flex items-center justify-center',
-
- // Shape
- 'border-0 rounded-full dark:rounded-md',
-
- // Size
- 'min-w-[3rem] h-12 m-[0.143rem]',
- 'leading-none',
-
- // Color
- 'text-surface-500 dark:text-white/60',
-
- // State
- {
- 'hover:bg-surface-50 dark:hover:bg-surface-700/70': !context.disabled,
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50': !context.disabled
- },
-
- // Transition
- 'transition duration-200',
-
- // Misc
- 'user-none overflow-hidden',
- { 'cursor-default pointer-events-none opacity-60': context.disabled }
- ]
- }),
- pagebutton: ({ context }) => ({
- class: [
- 'relative',
-
- // Flex & Alignment
- 'inline-flex items-center justify-center',
-
- // Shape
- 'border-0 rounded-full dark:rounded-md',
-
- // Size
- 'min-w-[3rem] h-12 m-[0.143rem]',
- 'leading-none',
-
- // Color
- 'text-surface-500 dark:text-white/80',
- {
- 'bg-primary-50 border-primary-50 dark:border-transparent text-primary-700 dark:text-surface-0 dark:bg-primary-400/30': context.active
- },
-
- // State
- {
- 'hover:bg-surface-50 dark:hover:bg-surface-700/70': !context.disabled && !context.active,
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50': !context.disabled
- },
-
- // Transition
- 'transition duration-200',
-
- // Misc
- 'user-none overflow-hidden',
- { 'cursor-default pointer-events-none opacity-60': context.disabled }
- ]
- }),
- rowperpagedropdown: {
- root: ({ props, state }) => ({
- class: [
- // Display and Position
- 'inline-flex',
- 'relative',
-
- // Shape
- 'h-12',
- 'rounded-md',
-
- // Spacing
- 'mx-2',
-
- // Color and Background
- 'bg-surface-0 dark:bg-surface-900',
- 'border border-surface-300 dark:border-surface-700',
-
- // Transitions
- 'transition-all',
- 'duration-200',
-
- // States
- 'hover:border-primary-500 dark:hover:border-primary-300',
- { 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50': !state.focused },
-
- // Misc
- 'cursor-pointer',
- 'select-none',
- { 'opacity-60': props.disabled, 'pointer-events-none': props.disabled, 'cursor-default': props.disabled }
- ]
- }),
- input: {
- class: [
- //Font
- 'font-sans',
- 'leading-5',
-
- // Display
- 'block',
- 'flex-auto',
-
- // Color and Background
- 'bg-transparent',
- 'border-0',
- 'text-surface-800 dark:text-white/80',
-
- // Sizing and Spacing
- 'w-[1%]',
- 'p-3 pr-0',
-
- //Shape
- 'rounded-none',
-
- // Transitions
- 'transition',
- 'duration-200',
-
- // States
- 'focus:outline-none focus:shadow-none',
-
- // Misc
- 'relative',
- 'cursor-pointer',
- 'overflow-hidden overflow-ellipsis',
- 'whitespace-nowrap',
- 'appearance-none'
- ]
- },
- trigger: {
- class: [
- // Flexbox
- 'flex items-center justify-center',
- 'shrink-0',
-
- // Color and Background
- 'bg-transparent',
- 'text-surface-500',
-
- // Size
- 'w-12',
-
- // Shape
- 'rounded-tr-md',
- 'rounded-br-md'
- ]
- },
- panel: {
- class: [
- // Position
- 'absolute top-0 left-0',
-
- // Shape
- 'border-0 dark:border',
- 'rounded-md',
- 'shadow-md',
-
- // Color
- 'bg-surface-0 dark:bg-surface-800',
- 'text-surface-800 dark:text-white/80',
- 'dark:border-surface-700'
- ]
- },
- wrapper: {
- class: [
- // Sizing
- 'max-h-[200px]',
-
- // Misc
- 'overflow-auto'
- ]
- },
- list: {
- class: 'py-3 list-none m-0'
- },
- item: ({ context }) => ({
- class: [
- // Font
- 'font-normal',
- 'leading-none',
-
- // Position
- 'relative',
-
- // Shape
- 'border-0',
- 'rounded-none',
-
- // Spacing
- 'm-0',
- 'py-3 px-5',
-
- // Color
- { 'text-surface-700 dark:text-white/80': !context.focused && !context.selected },
- { 'bg-surface-50 dark:bg-surface-600/60 text-surface-700 dark:text-white/80': context.focused && !context.selected },
- { 'bg-primary-100 dark:bg-primary-400/40 text-primary-700 dark:text-white/80': context.focused && context.selected },
- { 'bg-primary-50 dark:bg-primary-400/40 text-primary-700 dark:text-white/80': !context.focused && context.selected },
-
- //States
- { 'hover:bg-surface-100 dark:hover:bg-surface-600/80': !context.focused && !context.selected },
- { 'hover:text-surface-700 hover:bg-surface-100 dark:hover:text-white dark:hover:bg-surface-600/80': context.focused && !context.selected },
-
- // Transitions
- 'transition-shadow',
- 'duration-200',
-
- // Misc
- 'cursor-pointer',
- 'overflow-hidden',
- 'whitespace-nowrap'
- ]
- })
- },
- jumptopageinput: {
- root: {
- class: 'inline-flex mx-2'
- },
- input: {
- root: {
- class: [
- 'relative',
-
- //Font
- 'font-sans',
- 'leading-none',
-
- // Display
- 'block',
- 'flex-auto',
-
- // Colors
- 'text-surface-600 dark:text-surface-200',
- 'placeholder:text-surface-400 dark:placeholder:text-surface-500',
- 'bg-surface-0 dark:bg-surface-900',
- 'border border-surface-300 dark:border-surface-600',
-
- // Sizing and Spacing
- 'w-[1%] max-w-[3rem]',
- 'p-3 m-0',
-
- //Shape
- 'rounded-md',
-
- // Transitions
- 'transition',
- 'duration-200',
-
- // States
- 'hover:border-primary-500 dark:hover:border-primary-400',
- 'focus:outline-none focus:shadow-none',
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-500/50 dark:focus:ring-primary-400/50',
-
- // Misc
- 'cursor-pointer',
- 'overflow-hidden overflow-ellipsis',
- 'whitespace-nowrap',
- 'appearance-none'
- ]
- }
- }
- },
- jumptopagedropdown: {
- root: ({ props, state }) => ({
- class: [
- // Display and Position
- 'inline-flex',
- 'relative',
-
- // Shape
- 'h-12',
- 'rounded-md',
-
- // Color and Background
- 'bg-surface-0 dark:bg-surface-900',
- 'border border-surface-300 dark:border-surface-700',
-
- // Transitions
- 'transition-all',
- 'duration-200',
-
- // States
- 'hover:border-primary-500 dark:hover:border-primary-300',
- { 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50': !state.focused },
-
- // Misc
- 'cursor-pointer',
- 'select-none',
- { 'opacity-60': props.disabled, 'pointer-events-none': props.disabled, 'cursor-default': props.disabled }
- ]
- }),
- input: {
- class: [
- //Font
- 'font-sans',
- 'leading-none',
-
- // Display
- 'block',
- 'flex-auto',
-
- // Color and Background
- 'bg-transparent',
- 'border-0',
- 'text-surface-800 dark:text-white/80',
-
- // Sizing and Spacing
- 'w-[1%]',
- 'p-3',
-
- //Shape
- 'rounded-none',
-
- // Transitions
- 'transition',
- 'duration-200',
-
- // States
- 'focus:outline-none focus:shadow-none',
-
- // Misc
- 'relative',
- 'cursor-pointer',
- 'overflow-hidden overflow-ellipsis',
- 'whitespace-nowrap',
- 'appearance-none'
- ]
- },
- trigger: {
- class: [
- // Flexbox
- 'flex items-center justify-center',
- 'shrink-0',
-
- // Color and Background
- 'bg-transparent',
- 'text-surface-500',
-
- // Size
- 'w-12',
-
- // Shape
- 'rounded-tr-md',
- 'rounded-br-md'
- ]
- },
- panel: {
- class: [
- // Position
- 'absolute top-0 left-0',
-
- // Shape
- 'border-0 dark:border',
- 'rounded-md',
- 'shadow-md',
-
- // Color
- 'bg-surface-0 dark:bg-surface-800',
- 'text-surface-800 dark:text-white/80',
- 'dark:border-surface-700'
- ]
- },
- wrapper: {
- class: [
- // Sizing
- 'max-h-[200px]',
-
- // Misc
- 'overflow-auto'
- ]
- },
- list: {
- class: 'py-3 list-none m-0'
- },
- item: ({ context }) => ({
- class: [
- // Font
- 'font-normal',
- 'leading-none',
-
- // Position
- 'relative',
-
- // Shape
- 'border-0',
- 'rounded-none',
-
- // Spacing
- 'm-0',
- 'py-3 px-5',
-
- // Color
- { 'text-surface-700 dark:text-white/80': !context.focused && !context.selected },
- { 'bg-surface-50 dark:bg-surface-600/60 text-surface-700 dark:text-white/80': context.focused && !context.selected },
- { 'bg-primary-100 dark:bg-primary-400/40 text-primary-700 dark:text-white/80': context.focused && context.selected },
- { 'bg-primary-50 dark:bg-primary-400/40 text-primary-700 dark:text-white/80': !context.focused && context.selected },
-
- //States
- { 'hover:bg-surface-100 dark:hover:bg-surface-600/80': !context.focused && !context.selected },
- { 'hover:text-surface-700 hover:bg-surface-100 dark:hover:text-white dark:hover:bg-surface-600/80': context.focused && !context.selected },
-
- // Transitions
- 'transition-shadow',
- 'duration-200',
-
- // Misc
- 'cursor-pointer',
- 'overflow-hidden',
- 'whitespace-nowrap'
- ]
- })
- },
- start: {
- class: 'mr-auto'
- },
- end: {
- class: 'ml-auto'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/panel/index.js b/frontend/packages/kwai-ui/src/presets/kwai/panel/index.js
deleted file mode 100644
index d42820bd9..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/panel/index.js
+++ /dev/null
@@ -1,91 +0,0 @@
-export default {
- header: ({ props }) => ({
- class: [
- // Flex
- 'flex items-center justify-between',
-
- // Colors
- 'text-surface-700 dark:text-surface-0/80',
- 'bg-surface-50 dark:bg-surface-900',
- 'border border-surface-200 dark:border-surface-700',
-
- //Shape
- 'rounded-tl-lg rounded-tr-lg',
-
- // Conditional Spacing
- { 'p-5': !props.toggleable, 'py-3 px-5': props.toggleable }
- ]
- }),
- title: {
- class: 'leading-none font-bold'
- },
- toggler: {
- class: [
- // Alignments
- 'inline-flex items-center justify-center',
- 'relative',
-
- // Sized
- 'w-8 h-8',
- 'm-0 p-0',
-
- //Shape
- 'border-0 rounded-full',
-
- //Color
- 'bg-transparent',
- 'text-surface-600 dark:text-surface-0/80',
-
- // States
- 'hover:text-surface-800 dark:hover:text-surface-0/80',
- 'hover:bg-surface-100 dark:hover:bg-surface-800/80',
- 'focus:outline-none focus:outline-offset-0 focus-visible:ring focus-visible:ring-primary-400/50 focus-visible:ring-inset dark:focus-visible:ring-primary-300/50',
-
- // Transitions
- 'transition-all duration-200 ease-in-out',
-
- // Misc
- 'overflow-hidden no-underline',
- 'cursor-pointer'
- ]
- },
- togglerIcon: {
- class: 'inline-block'
- },
- content: {
- class: [
- // Spacing
- 'p-5',
-
- // Shape
- 'border border-t-0 last:rounded-br-lg last:rounded-bl-lg',
-
- //Color
- 'border-surface-200 dark:border-surface-700',
- 'bg-surface-0 dark:bg-surface-900',
- 'text-surface-700 dark:text-surface-0/80'
- ]
- },
- footer: {
- class: [
- // Spacing
- 'py-3 p-5',
-
- // Shape
- 'border border-t-0 rounded-br-lg rounded-bl-lg',
-
- //Color
- 'border-surface-200 dark:border-surface-700',
- 'bg-surface-0 dark:bg-surface-900',
- 'text-surface-700 dark:text-surface-0/80'
- ]
- },
- transition: {
- enterFromClass: 'max-h-0',
- enterActiveClass: 'overflow-hidden transition-[max-height] duration-1000 ease-[cubic-bezier(0.42,0,0.58,1)]',
- enterToClass: 'max-h-[1000px]',
- leaveFromClass: 'max-h-[1000px]',
- leaveActiveClass: 'overflow-hidden transition-[max-height] duration-[450ms] ease-[cubic-bezier(0,1,0,1)]',
- leaveToClass: 'max-h-0'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/panelmenu/index.js b/frontend/packages/kwai-ui/src/presets/kwai/panelmenu/index.js
deleted file mode 100644
index e6072e899..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/panelmenu/index.js
+++ /dev/null
@@ -1,127 +0,0 @@
-export default {
- panel: {
- class: 'mb-1'
- },
- header: {
- class: ['rounded-md', 'outline-none', 'focus-visible:outline-none focus-visible:outline-offset-0 focus-visible:ring focus-visible:ring-primary-400/50 dark:focus-visible:ring-primary-300/50']
- },
- headercontent: ({ context, instance }) => ({
- class: [
- // Shape
- 'rounded-t-md',
- { 'rounded-br-md rounded-bl-md': !context.active || instance.activeItem?.items === undefined, 'rounded-br-0 rounded-bl-0': context.active && instance.activeItem?.items !== undefined },
-
- // Color
- 'border border-surface-200 dark:border-surface-700',
- 'bg-surface-50 dark:bg-surface-800',
- 'text-surface-600 dark:text-surface-0/80',
- { 'text-surface-900': context.active },
-
- // States
- 'hover:bg-surface-100 dark:hover:bg-surface-700/80',
- 'hover:text-surface-900',
-
- // Transition
- 'transition duration-200 ease-in-out',
- 'transition-shadow duration-200'
- ]
- }),
- headeraction: {
- class: [
- 'relative',
-
- // Font
- 'font-bold',
- 'leading-none',
-
- // Flex & Alignments
- 'flex items-center',
-
- // Spacing
- 'p-5',
-
- // Misc
- 'select-none cursor-pointer no-underline'
- ]
- },
- headerlabel: {
- class: 'leading-none'
- },
- headerIcon: {
- class: 'mr-2'
- },
- submenuicon: {
- class: 'mr-2'
- },
- menucontent: {
- class: [
- // Spacing
- 'py-2',
-
- // Shape
- 'border border-t-0',
- 'rounded-t-none rounded-br-md rounded-bl-md',
-
- // Color
- 'text-surface-700 dark:text-white/80',
- 'bg-surface-0 dark:bg-surface-800',
- 'border-surface-200 dark:border-surface-700'
- ]
- },
- menu: {
- class: ['outline-none', 'm-0 p-0 list-none']
- },
- content: {
- class: [
- // Shape
- 'border-none rounded-none',
-
- // Color
- 'text-surface-700 dark:text-white/80',
-
- // Transition
- 'transition-shadow duration-200'
- ]
- },
- action: ({ context }) => ({
- class: [
- 'relative',
-
- // Font
- 'leading-none',
-
- // Flex & Alignments
- 'flex items-center',
-
- // Spacing
- 'py-3 px-5',
-
- // Color
- 'text-surface-700 dark:text-white/80',
-
- // States
- 'hover:bg-surface-100 dark:hover:bg-surface-700/80 hover:text-surface-700 dark:hover:text-white/80',
- {
- 'bg-surface-200 text-surface-700 dark:text-white/80 dark:bg-surface-600/90': context.focused
- },
-
- // Misc
- 'cursor-pointer no-underline',
- 'select-none overflow-hidden'
- ]
- }),
- icon: {
- class: 'mr-2'
- },
- submenu: {
- class: 'p-0 pl-4 m-0 list-none'
- },
- transition: {
- enterFromClass: 'max-h-0',
- enterActiveClass: 'overflow-hidden transition-[max-height] duration-1000 ease-[cubic-bezier(0.42,0,0.58,1)]',
- enterToClass: 'max-h-[1000px]',
- leaveFromClass: 'max-h-[1000px]',
- leaveActiveClass: 'overflow-hidden transition-[max-height] duration-[450ms] ease-[cubic-bezier(0,1,0,1)]',
- leaveToClass: 'max-h-0'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/password/index.js b/frontend/packages/kwai-ui/src/presets/kwai/password/index.js
deleted file mode 100644
index 9d4606b88..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/password/index.js
+++ /dev/null
@@ -1,118 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- 'inline-flex relative',
- {
- 'opacity-60 select-none pointer-events-none cursor-default': props.disabled
- },
- { '[&>input]:pr-10': props.toggleMask }
- ]
- }),
- panel: {
- class: [
- // Spacing
- 'p-5',
-
- // Shape
- 'border-0 dark:border',
- 'shadow-md rounded-md',
-
- // Colors
- 'bg-surface-0 dark:bg-surface-900',
- 'text-surface-700 dark:text-white/80',
- 'dark:border-surface-700'
- ]
- },
- meter: {
- class: [
- // Position and Overflow
- 'overflow-hidden',
- 'relative',
-
- // Shape and Size
- 'border-0',
- 'h-3',
-
- // Spacing
- 'mb-2',
-
- // Colors
- 'bg-surface-100 dark:bg-surface-700'
- ]
- },
- meterlabel: ({ instance }) => ({
- class: [
- // Size
- 'h-full',
-
- // Colors
- {
- 'bg-red-500 dark:bg-red-400/50': instance?.meter?.strength == 'weak',
- 'bg-orange-500 dark:bg-orange-400/50': instance?.meter?.strength == 'medium',
- 'bg-green-500 dark:bg-green-400/50': instance?.meter?.strength == 'strong'
- },
-
- // Transitions
- 'transition-all duration-1000 ease-in-out'
- ]
- }),
- showicon: {
- class: ['absolute top-1/2 right-3 -mt-2 z-10', 'text-surface-600 dark:text-white/70']
- },
- hideicon: {
- class: ['absolute top-1/2 right-3 -mt-2 z-10', 'text-surface-600 dark:text-white/70']
- },
- input: {
- root: ({ props, context, parent }) => ({
- class: [
- // Font
- 'font-sans leading-none',
-
- // Flex
- { 'flex-1 w-[1%]': parent.instance.$name == 'InputGroup' },
-
- // Spacing
- 'm-0',
- {
- 'px-4 py-4': props.size == 'large',
- 'px-2 py-2': props.size == 'small',
- 'p-3': props.size == null
- },
- 'w-full',
-
- // Shape
- { 'rounded-md': parent.instance.$name !== 'InputGroup' },
- { 'first:rounded-l-md rounded-none last:rounded-r-md': parent.instance.$name == 'InputGroup' },
- { 'border-0 border-y border-l last:border-r': parent.instance.$name == 'InputGroup' },
- { 'first:ml-0 -ml-px': parent.instance.$name == 'InputGroup' && !props.showButtons },
-
- // Colors
- 'text-surface-600 dark:text-surface-200',
- 'placeholder:text-surface-400 dark:placeholder:text-surface-500',
- 'bg-surface-0 dark:bg-surface-900',
- 'border',
- { 'border-surface-300 dark:border-surface-600': !parent.props.invalid },
-
- // Invalid State
- { 'border-red-500 dark:border-red-400': parent.props.invalid },
-
- // States
- {
- 'hover:border-primary-500 dark:hover:border-primary-400': !context.disabled && !parent.props.invalid,
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-500/50 dark:focus:ring-primary-400/50 focus:z-10': !context.disabled,
- 'opacity-60 select-none pointer-events-none cursor-default': context.disabled
- },
-
- // Misc
- 'appearance-none',
- 'transition-colors duration-200'
- ]
- })
- },
- transition: {
- enterFromClass: 'opacity-0 scale-y-[0.8]',
- enterActiveClass: 'transition-[transform,opacity] duration-[120ms] ease-[cubic-bezier(0,0,0.2,1)]',
- leaveActiveClass: 'transition-opacity duration-100 ease-linear',
- leaveToClass: 'opacity-0'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/picklist/index.js b/frontend/packages/kwai-ui/src/presets/kwai/picklist/index.js
deleted file mode 100644
index dedbeb75d..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/picklist/index.js
+++ /dev/null
@@ -1,650 +0,0 @@
-export default {
- root: {
- class: [
- // Flexbox
- 'flex lg:flex-row flex-col'
- ]
- },
- sourcecontrols: {
- class: [
- // Flexbox & Alignment
- 'flex lg:flex-col justify-center gap-2',
-
- // Spacing
- 'p-5'
- ]
- },
- sourcemoveupbutton: {
- root: ({ context }) => ({
- class: [
- // Flexbox & Alignment
- 'relative inline-flex items-center justify-center',
-
- // Shape
- 'rounded-md',
-
- // Color
- 'text-white dark:text-surface-900',
- 'bg-primary-500 dark:bg-primary-400',
- 'border border-primary-500 dark:border-primary-400',
-
- // Spacing & Size
- 'w-12',
- 'm-0',
- 'px-0 py-3',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // State
- 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300',
- 'focus:outline-none focus:outline-offset-0 focus:ring',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
- { 'cursor-default pointer-events-none opacity-60': context.disabled },
-
- // Interactivity
- 'cursor-pointer user-select-none'
- ]
- }),
- label: {
- class: [
- // Flexbox
- 'flex-initial',
-
- // Size
- 'w-0'
- ]
- }
- },
- sourcemovetopbutton: {
- root: ({ context }) => ({
- class: [
- // Flexbox & Alignment
- 'relative inline-flex items-center justify-center',
-
- // Shape
- 'rounded-md',
-
- // Color
- 'text-white dark:text-surface-900',
- 'bg-primary-500 dark:bg-primary-400',
- 'border border-primary-500 dark:border-primary-400',
-
- // Spacing & Size
- 'w-12',
- 'm-0',
- 'px-0 py-3',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // State
- 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300',
- 'focus:outline-none focus:outline-offset-0 focus:ring',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
- { 'cursor-default pointer-events-none opacity-60': context.disabled },
-
- // Interactivity
- 'cursor-pointer user-select-none'
- ]
- }),
- label: {
- class: [
- // Flexbox
- 'flex-initial',
-
- // Size
- 'w-0'
- ]
- }
- },
- sourcemovedownbutton: {
- root: ({ context }) => ({
- class: [
- // Flexbox & Alignment
- 'relative inline-flex items-center justify-center',
-
- // Shape
- 'rounded-md',
-
- // Color
- 'text-white dark:text-surface-900',
- 'bg-primary-500 dark:bg-primary-400',
- 'border border-primary-500 dark:border-primary-400',
-
- // Spacing & Size
- 'w-12',
- 'm-0',
- 'px-0 py-3',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // State
- 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300',
- 'focus:outline-none focus:outline-offset-0 focus:ring',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
- { 'cursor-default pointer-events-none opacity-60': context.disabled },
-
- // Interactivity
- 'cursor-pointer user-select-none'
- ]
- }),
- label: {
- class: [
- // Flexbox
- 'flex-initial',
-
- // Size
- 'w-0'
- ]
- }
- },
- sourcemovebottombutton: {
- root: ({ context }) => ({
- class: [
- // Flexbox & Alignment
- 'relative inline-flex items-center justify-center',
-
- // Shape
- 'rounded-md',
-
- // Color
- 'text-white dark:text-surface-900',
- 'bg-primary-500 dark:bg-primary-400',
- 'border border-primary-500 dark:border-primary-400',
-
- // Spacing & Size
- 'w-12',
- 'm-0',
- 'px-0 py-3',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // State
- 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300',
- 'focus:outline-none focus:outline-offset-0 focus:ring',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
- { 'cursor-default pointer-events-none opacity-60': context.disabled },
-
- // Interactivity
- 'cursor-pointer user-select-none'
- ]
- }),
- label: {
- class: [
- // Flexbox
- 'flex-initial',
-
- // Size
- 'w-0'
- ]
- }
- },
- sourcewrapper: {
- class: 'grow shrink basis-2/4'
- },
- sourceheader: {
- class: [
- 'font-bold',
-
- // Shape
- 'border-b-0 rounded-t-md',
-
- // Spacing
- 'p-5',
-
- // Color
- 'text-surface-700 dark:text-white/80',
- 'bg-surface-50 dark:bg-surface-800',
- 'border border-surface-200 dark:border-surface-700'
- ]
- },
- sourcelist: {
- class: [
- // Spacing
- 'list-none m-0 p-0',
-
- // Size
- 'min-h-[12rem] max-h-[24rem]',
-
- // Shape
- 'rounded-b-md',
-
- // Color
- 'text-surface-600 dark:text-white/80',
- 'bg-surface-0 dark:bg-surface-800',
- 'border border-surface-200 dark:border-surface-700',
-
- // Spacing
- 'py-3 px-0',
-
- // Focus & Outline
- 'outline-none',
-
- // Misc
- 'overflow-auto'
- ]
- },
- item: ({ context }) => ({
- class: [
- // Position
- 'relative',
-
- // Spacing
- 'py-3 px-5 m-0',
-
- // Shape
- 'border-none',
-
- // Transition
- 'transition duration-200',
-
- // Color
- 'text-surface-700 dark:text-white/80',
- { 'bg-primary-500/20 dark:bg-primary-300/20': context.active && !context.focused },
- { 'bg-primary-500/30 dark:bg-primary-400/30': context.active && context.focused },
- { 'bg-surface-100 dark:bg-surface-700/70': !context.active && context.focused },
-
- // State
- 'hover:bg-surface-100 dark:hover:bg-surface-700',
-
- // Misc
- 'cursor-pointer overflow-hidden'
- ]
- }),
- buttons: {
- class: 'flex lg:flex-col justify-center gap-2 p-5'
- },
- movetotargetbutton: {
- root: ({ context }) => ({
- class: [
- // Flexbox & Alignment
- 'relative inline-flex items-center justify-center',
-
- // Shape
- 'rounded-md',
-
- // Color
- 'text-white dark:text-surface-900',
- 'bg-primary-500 dark:bg-primary-400',
- 'border border-primary-500 dark:border-primary-400',
-
- // Spacing & Size
- 'w-12',
- 'm-0',
- 'px-0 py-3',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // State
- 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300',
- 'focus:outline-none focus:outline-offset-0 focus:ring',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
- { 'cursor-default pointer-events-none opacity-60': context.disabled },
-
- // Interactivity
- 'cursor-pointer user-select-none'
- ]
- }),
- label: {
- class: [
- // Flexbox
- 'flex-initial',
-
- // Size
- 'w-0'
- ]
- }
- },
- movealltotargetbutton: {
- root: ({ context }) => ({
- class: [
- // Flexbox & Alignment
- 'relative inline-flex items-center justify-center',
-
- // Shape
- 'rounded-md',
-
- // Color
- 'text-white dark:text-surface-900',
- 'bg-primary-500 dark:bg-primary-400',
- 'border border-primary-500 dark:border-primary-400',
-
- // Spacing & Size
- 'w-12',
- 'm-0',
- 'px-0 py-3',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // State
- 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300',
- 'focus:outline-none focus:outline-offset-0 focus:ring',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
- { 'cursor-default pointer-events-none opacity-60': context.disabled },
-
- // Interactivity
- 'cursor-pointer user-select-none'
- ]
- }),
- label: {
- class: [
- // Flexbox
- 'flex-initial',
-
- // Size
- 'w-0'
- ]
- }
- },
- movetosourcebutton: {
- root: ({ context }) => ({
- class: [
- // Flexbox & Alignment
- 'relative inline-flex items-center justify-center',
-
- // Shape
- 'rounded-md',
-
- // Color
- 'text-white dark:text-surface-900',
- 'bg-primary-500 dark:bg-primary-400',
- 'border border-primary-500 dark:border-primary-400',
-
- // Spacing & Size
- 'w-12',
- 'm-0',
- 'px-0 py-3',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // State
- 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300',
- 'focus:outline-none focus:outline-offset-0 focus:ring',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
- { 'cursor-default pointer-events-none opacity-60': context.disabled },
-
- // Interactivity
- 'cursor-pointer user-select-none'
- ]
- }),
- label: {
- class: [
- // Flexbox
- 'flex-initial',
-
- // Size
- 'w-0'
- ]
- }
- },
- movealltosourcebutton: {
- root: ({ context }) => ({
- class: [
- // Flexbox & Alignment
- 'relative inline-flex items-center justify-center',
-
- // Shape
- 'rounded-md',
-
- // Color
- 'text-white dark:text-surface-900',
- 'bg-primary-500 dark:bg-primary-400',
- 'border border-primary-500 dark:border-primary-400',
-
- // Spacing & Size
- 'w-12',
- 'm-0',
- 'px-0 py-3',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // State
- 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300',
- 'focus:outline-none focus:outline-offset-0 focus:ring',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
- { 'cursor-default pointer-events-none opacity-60': context.disabled },
-
- // Interactivity
- 'cursor-pointer user-select-none'
- ]
- }),
- label: {
- class: [
- // Flexbox
- 'flex-initial',
-
- // Size
- 'w-0'
- ]
- }
- },
- targetcontrols: {
- class: 'flex lg:flex-col justify-center gap-2 p-5'
- },
- targetmoveupbutton: {
- root: ({ context }) => ({
- class: [
- // Flexbox & Alignment
- 'relative inline-flex items-center justify-center',
-
- // Shape
- 'rounded-md',
-
- // Color
- 'text-white dark:text-surface-900',
- 'bg-primary-500 dark:bg-primary-400',
- 'border border-primary-500 dark:border-primary-400',
-
- // Spacing & Size
- 'w-12',
- 'm-0',
- 'px-0 py-3',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // State
- 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300',
- 'focus:outline-none focus:outline-offset-0 focus:ring',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
- { 'cursor-default pointer-events-none opacity-60': context.disabled },
-
- // Interactivity
- 'cursor-pointer user-select-none'
- ]
- }),
- label: {
- class: [
- // Flexbox
- 'flex-initial',
-
- // Size
- 'w-0'
- ]
- }
- },
- targetmovetopbutton: {
- root: ({ context }) => ({
- class: [
- // Flexbox & Alignment
- 'relative inline-flex items-center justify-center',
-
- // Shape
- 'rounded-md',
-
- // Color
- 'text-white dark:text-surface-900',
- 'bg-primary-500 dark:bg-primary-400',
- 'border border-primary-500 dark:border-primary-400',
-
- // Spacing & Size
- 'w-12',
- 'm-0',
- 'px-0 py-3',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // State
- 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300',
- 'focus:outline-none focus:outline-offset-0 focus:ring',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
- { 'cursor-default pointer-events-none opacity-60': context.disabled },
-
- // Interactivity
- 'cursor-pointer user-select-none'
- ]
- }),
- label: {
- class: [
- // Flexbox
- 'flex-initial',
-
- // Size
- 'w-0'
- ]
- }
- },
- targetmovedownbutton: {
- root: ({ context }) => ({
- class: [
- // Flexbox & Alignment
- 'relative inline-flex items-center justify-center',
-
- // Shape
- 'rounded-md',
-
- // Color
- 'text-white dark:text-surface-900',
- 'bg-primary-500 dark:bg-primary-400',
- 'border border-primary-500 dark:border-primary-400',
-
- // Spacing & Size
- 'w-12',
- 'm-0',
- 'px-0 py-3',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // State
- 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300',
- 'focus:outline-none focus:outline-offset-0 focus:ring',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
- { 'cursor-default pointer-events-none opacity-60': context.disabled },
-
- // Interactivity
- 'cursor-pointer user-select-none'
- ]
- }),
- label: {
- class: [
- // Flexbox
- 'flex-initial',
-
- // Size
- 'w-0'
- ]
- }
- },
- targetmovebottombutton: {
- root: ({ context }) => ({
- class: [
- // Flexbox & Alignment
- 'relative inline-flex items-center justify-center',
-
- // Shape
- 'rounded-md',
-
- // Color
- 'text-white dark:text-surface-900',
- 'bg-primary-500 dark:bg-primary-400',
- 'border border-primary-500 dark:border-primary-400',
-
- // Spacing & Size
- 'w-12',
- 'm-0',
- 'px-0 py-3',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // State
- 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300',
- 'focus:outline-none focus:outline-offset-0 focus:ring',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
- { 'cursor-default pointer-events-none opacity-60': context.disabled },
-
- // Interactivity
- 'cursor-pointer user-select-none'
- ]
- }),
- label: {
- class: [
- // Flexbox
- 'flex-initial',
-
- // Size
- 'w-0'
- ]
- }
- },
- targetwrapper: {
- class: 'grow shrink basis-2/4'
- },
- targetheader: {
- class: [
- 'font-bold',
-
- // Shape
- 'border-b-0 rounded-t-md',
-
- // Spacing
- 'p-5',
-
- // Color
- 'text-surface-700 dark:text-white/80',
- 'bg-surface-50 dark:bg-surface-800',
- 'border border-surface-200 dark:border-surface-700'
- ]
- },
- targetlist: {
- class: [
- // Spacing
- 'list-none m-0 p-0',
-
- // Size
- 'min-h-[12rem] max-h-[24rem]',
-
- // Shape
- 'rounded-b-md',
-
- // Color
- 'text-surface-600 dark:text-white/80',
- 'bg-surface-0 dark:bg-surface-800',
- 'border border-surface-200 dark:border-surface-700',
-
- // Spacing
- 'py-3 px-0',
-
- // Focus & Outline
- 'outline-none',
-
- // Misc
- 'overflow-auto'
- ]
- },
- transition: {
- enterFromClass: '!transition-none',
- enterActiveClass: '!transition-none',
- leaveActiveClass: '!transition-none',
- leaveToClass: '!transition-none'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/progressbar/index.js b/frontend/packages/kwai-ui/src/presets/kwai/progressbar/index.js
deleted file mode 100644
index 0ca7b9ffe..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/progressbar/index.js
+++ /dev/null
@@ -1,55 +0,0 @@
-export default {
- root: {
- class: [
- // Position and Overflow
- 'overflow-hidden',
- 'relative',
-
- // Shape and Size
- 'border-0',
- 'h-6',
- 'rounded-md',
-
- // Colors
- 'bg-surface-100 dark:bg-surface-700'
- ]
- },
- value: ({ props }) => ({
- class: [
- // Flexbox & Overflow & Position
- { 'absolute flex items-center justify-center overflow-hidden': props.mode !== 'indeterminate' },
-
- // Colors
- 'bg-primary-500 dark:bg-primary-400',
-
- // Spacing & Sizing
- 'm-0',
- { 'h-full w-0': props.mode !== 'indeterminate' },
-
- // Shape
- 'border-0',
-
- // Transitions
- {
- 'transition-width duration-1000 ease-in-out': props.mode !== 'indeterminate',
- 'progressbar-value-animate': props.mode == 'indeterminate'
- },
-
- // Before & After (indeterminate)
- {
- 'before:absolute before:top-0 before:left-0 before:bottom-0 before:bg-inherit ': props.mode == 'indeterminate',
- 'after:absolute after:top-0 after:left-0 after:bottom-0 after:bg-inherit after:delay-1000': props.mode == 'indeterminate'
- }
- ]
- }),
- label: {
- class: [
- // Flexbox
- 'inline-flex',
-
- // Font and Text
- 'text-white dark:text-surface-900',
- 'leading-6'
- ]
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/progressspinner/index.js b/frontend/packages/kwai-ui/src/presets/kwai/progressspinner/index.js
deleted file mode 100644
index 4e1faec86..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/progressspinner/index.js
+++ /dev/null
@@ -1,51 +0,0 @@
-export default {
- root: {
- class: [
- // Position
- 'relative',
- 'mx-auto',
-
- // Sizing
- 'w-28',
- 'h-28',
-
- // Flexbox
- 'inline-block',
-
- // Pseudo-Elements
- 'before:block',
- 'before:pt-full'
- ]
- },
- spinner: {
- class: [
- // Position
- 'absolute',
- 'top-0',
- 'bottom-0',
- 'left-0',
- 'right-0',
- 'm-auto',
-
- // Sizing
- 'w-full',
- 'h-full',
-
- // Transformations
- 'transform',
- 'origin-center',
-
- // Animations
- 'animate-spin'
- ]
- },
- circle: {
- class: [
- // Colors
- 'text-red-500',
-
- // Misc
- 'progress-spinner-circle'
- ]
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/radiobutton/index.js b/frontend/packages/kwai-ui/src/presets/kwai/radiobutton/index.js
deleted file mode 100644
index c80dbb2c5..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/radiobutton/index.js
+++ /dev/null
@@ -1,104 +0,0 @@
-export default {
- root: {
- class: [
- 'relative',
-
- // Flexbox & Alignment
- 'inline-flex',
- 'align-bottom',
-
- // Size
- 'w-[1.571rem] h-[1.571rem]',
-
- // Misc
- 'cursor-pointer',
- 'select-none'
- ]
- },
- box: ({ props }) => ({
- class: [
- // Flexbox
- 'flex justify-center items-center',
-
- // Size
- 'w-[1.571rem] h-[1.571rem]',
-
- // Shape
- 'border-2',
- 'rounded-full',
-
- // Transition
- 'transition duration-200 ease-in-out',
-
- // Colors
- {
- 'text-surface-700 dark:text-white/80': props.value !== props.modelValue && props.value !== undefined,
- 'bg-surface-0 dark:bg-surface-900': props.value !== props.modelValue && props.value !== undefined,
- 'border-surface-300 dark:border-surface-700': props.value !== props.modelValue && props.value !== undefined && !props.invalid,
- 'border-primary-500 dark:border-primary-400': props.value == props.modelValue && props.value !== undefined,
- 'bg-primary-500 dark:bg-primary-400': props.value == props.modelValue && props.value !== undefined
- },
- // Invalid State
- { 'border-red-500 dark:border-red-400': props.invalid },
-
- // States
- {
- 'peer-hover:border-primary-500 dark:peer-hover:border-primary-400': !props.disabled && !props.invalid,
- 'peer-hover:border-primary-600 dark:peer-hover:border-primary-300 peer-hover:bg-primary-600 dark:peer-hover:bg-primary-300': !props.disabled && props.value == props.modelValue && props.value !== undefined,
- 'peer-focus-visible:border-primary-500 dark:peer-focus-visible:border-primary-400 peer-focus-visible:ring-2 peer-focus-visible:ring-primary-400/20 dark:peer-focus-visible:ring-primary-300/20': !props.disabled,
- 'opacity-60 cursor-default': props.disabled
- }
- ]
- }),
- input: {
- class: [
- 'peer',
-
- // Size
- 'w-full ',
- 'h-full',
-
- // Position
- 'absolute',
- 'top-0 left-0',
- 'z-10',
-
- // Spacing
- 'p-0',
- 'm-0',
-
- // Shape
- 'opacity-0',
- 'rounded-md',
- 'outline-none',
- 'border-2 border-surface-200 dark:border-surface-700',
-
- // Misc
- 'appearance-none',
- 'cursor-pointer'
- ]
- },
- icon: ({ props }) => ({
- class: [
- 'block',
-
- // Shape
- 'rounded-full',
-
- // Size
- 'w-[0.857rem] h-[0.857rem]',
-
- // Colors
- 'bg-surface-0 dark:bg-surface-900',
-
- // Conditions
- {
- 'backface-hidden scale-10 invisible': props.value !== props.modelValue,
- 'transform visible scale-[1.1]': props.value == props.modelValue
- },
-
- // Transition
- 'transition duration-200'
- ]
- })
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/rating/index.js b/frontend/packages/kwai-ui/src/presets/kwai/rating/index.js
deleted file mode 100644
index db097f346..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/rating/index.js
+++ /dev/null
@@ -1,92 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- 'relative',
-
- // Flex & Alignment
- 'flex items-center',
- 'gap-2',
-
- // Misc
- {
- 'opacity-60 select-none pointer-events-none cursor-default': props.disabled
- }
- ]
- }),
- cancelitem: ({ context }) => ({
- class: [
- // Flex & Alignment
- 'inline-flex items-center',
-
- //State
- {
- 'outline-none ring ring-primary-500/50 dark:ring-primary-400/50': context.focused
- },
-
- // Misc
- 'cursor-pointer'
- ]
- }),
- cancelicon: {
- class: [
- // Size
- 'w-5 h-5',
-
- // Color
- 'text-red-500 dark:text-red-400',
-
- // State
- 'hover:text-red-600 dark:hover:text-red-300',
-
- // Transition
- 'transition duration-200 ease-in'
- ]
- },
- item: ({ props, context }) => ({
- class: [
- // Flex & Alignment
- 'inline-flex items-center',
-
- // State
- {
- 'outline-none ring ring-primary-500/50 dark:ring-primary-400/50': context.focused
- },
-
- // Misc
- {
- 'cursor-pointer': !props.readonly,
- 'cursor-default': props.readonly
- }
- ]
- }),
- officon: ({ props }) => ({
- class: [
- // Size
- 'w-5 h-5',
-
- // Color
- 'text-surface-700 dark:text-surface-0/80',
-
- // State
- { 'hover:text-primary-500 dark:hover:text-primary-400': !props.readonly },
-
- // Transition
- 'transition duration-200 ease-in'
- ]
- }),
- onicon: ({ props }) => ({
- class: [
- // Size
- 'w-5 h-5',
-
- // Color
- 'text-primary-500 dark:text-primary-400',
-
- // State
- { 'hover:text-primary-600 dark:hover:text-primary-300': !props.readonly },
-
- // Transition
- 'transition duration-200 ease-in'
- ]
- })
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/ripple/index.js b/frontend/packages/kwai-ui/src/presets/kwai/ripple/index.js
deleted file mode 100644
index 429c249e8..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/ripple/index.js
+++ /dev/null
@@ -1,6 +0,0 @@
-export default {
- root: {
- class: ['block absolute bg-surface-0/50 rounded-full pointer-events-none'],
- style: 'transform: scale(0)'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/scrollpanel/index.js b/frontend/packages/kwai-ui/src/presets/kwai/scrollpanel/index.js
deleted file mode 100644
index d41e690c3..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/scrollpanel/index.js
+++ /dev/null
@@ -1,77 +0,0 @@
-export default {
- wrapper: {
- class: [
- // Size & Position
- 'h-full w-full',
-
- // Layering
- 'z-[1]',
-
- // Spacing
- 'overflow-hidden',
-
- // Misc
- 'relative float-left'
- ]
- },
- content: {
- class: [
- // Size & Spacing
- 'h-[calc(100%+18px)] w-[calc(100%+18px)] pr-[18px] pb-[18px] pl-0 pt-0',
-
- // Overflow & Scrollbar
- 'overflow-scroll scrollbar-none',
-
- // Box Model
- 'box-border',
-
- // Position
- 'relative',
-
- // Webkit Specific
- '[&::-webkit-scrollbar]:hidden'
- ]
- },
- barX: {
- class: [
- // Size & Position
- 'h-[9px] bottom-0',
-
- // Appearance
- 'bg-surface-50 dark:bg-surface-700 rounded',
-
- // Interactivity
- 'cursor-pointer',
-
- // Visibility & Layering
- 'invisible z-20',
-
- // Transition
- 'transition duration-[250ms] ease-linear',
-
- // Misc
- 'relative'
- ]
- },
- barY: {
- class: [
- // Size & Position
- 'w-[9px] top-0',
-
- // Appearance
- 'bg-surface-50 dark:bg-surface-700 rounded',
-
- // Interactivity
- 'cursor-pointer',
-
- // Visibility & Layering
- 'z-20',
-
- // Transition
- 'transition duration-[250ms] ease-linear',
-
- // Misc
- 'relative'
- ]
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/scrolltop/index.js b/frontend/packages/kwai-ui/src/presets/kwai/scrolltop/index.js
deleted file mode 100644
index 04f6324c6..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/scrolltop/index.js
+++ /dev/null
@@ -1,41 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- // Flex & Alignment
- 'flex items-center justify-center',
-
- // Positioning
- {
- sticky: props.target === 'parent',
- fixed: props.target === 'window'
- },
- 'bottom-[20px] right-[20px]',
- 'ml-auto',
-
- // Shape & Size
- {
- 'rounded-md h-8 w-8': props.target === 'parent',
- 'h-12 w-12 rounded-full shadow-md': props.target === 'window'
- },
-
- // Color
- 'text-white dark:text-surface-900',
- {
- 'bg-primary-500 dark:bg-primary-400 hover:bg-primary-600 dark:hover:bg-primary-300': props.target === 'parent',
- 'bg-surface-500 dark:bg-surface-400 hover:bg-surface-600 dark:hover:bg-surface-300': props.target === 'window'
- },
-
- // States
- {
- 'hover:bg-primary-600 dark:hover:bg-primary-300': props.target === 'parent',
- 'hover:bg-surface-600 dark:hover:bg-surface-300': props.target === 'window'
- }
- ]
- }),
- transition: {
- enterFromClass: 'opacity-0',
- enterActiveClass: 'transition-opacity duration-150',
- leaveActiveClass: 'transition-opacity duration-150',
- leaveToClass: 'opacity-0'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/selectbutton/index.js b/frontend/packages/kwai-ui/src/presets/kwai/selectbutton/index.js
deleted file mode 100644
index b6fa797c2..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/selectbutton/index.js
+++ /dev/null
@@ -1,49 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [{ 'opacity-60 select-none pointer-events-none cursor-default': props.disabled }]
- }),
- button: ({ context, props }) => ({
- class: [
- 'relative',
- // Font
- 'leading-none',
-
- // Flex Alignment
- 'inline-flex items-center align-bottom text-center',
-
- // Spacing
- 'px-4 py-3',
-
- // Shape
- 'border border-r-0',
- 'first:rounded-l-md first:rounded-tr-none first:rounded-br-none',
- 'last:border-r last:rounded-tl-none last:rounded-bl-none last:rounded-r-md',
-
- // Color
- {
- 'bg-surface-0 dark:bg-surface-900': !context.active,
- 'text-surface-700 dark:text-white/80': !context.active,
- 'border-surface-200 dark:border-surface-700': !context.active && !props.invalid,
- 'bg-primary-500 dark:bg-primary-400 border-primary-500 dark:border-primary-400 text-white dark:text-surface-900': context.active
- },
- // Invalid State
- { 'border-red-500 dark:border-red-400': props.invalid },
-
- // States
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50 focus:z-10',
- {
- 'hover:bg-surface-50 dark:hover:bg-surface-800/80': !context.active && !props.invalid,
- 'hover:bg-primary-600 dark:hover:bg-primary-300': context.active
- },
- { 'opacity-60 select-none pointer-events-none cursor-default': context.disabled },
- // Transition
- 'transition duration-200',
-
- // Misc
- 'cursor-pointer select-none overflow-hidden'
- ]
- }),
- label: {
- class: 'font-bold'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/sidebar/index.js b/frontend/packages/kwai-ui/src/presets/kwai/sidebar/index.js
deleted file mode 100644
index 27b4160d2..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/sidebar/index.js
+++ /dev/null
@@ -1,149 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- // Flexbox
- 'flex flex-col',
-
- // Position
- 'relative',
- { '!transition-none !transform-none !w-screen !h-screen !max-h-full !top-0 !left-0': props.position == 'full' },
-
- // Size
- {
- 'h-full w-80': props.position == 'left' || props.position == 'right',
- 'h-auto w-full': props.position == 'top' || props.position == 'bottom'
- },
-
- // Shape
- 'border-0 dark:border',
- 'shadow-lg',
-
- // Colors
- 'bg-surface-0 dark:bg-surface-800',
- 'text-surface-700 dark:text-white/80',
- 'dark:border-surface-700',
-
- // Transitions
- 'transition-transform',
- 'duration-300',
-
- // Misc
- 'pointer-events-auto'
- ]
- }),
- header: {
- class: [
- // Flexbox and Alignment
- 'flex items-center justify-between',
- 'shrink-0',
-
- // Spacing
- 'p-5',
-
- // Colors
- 'bg-surface-0 dark:bg-surface-800',
- 'text-surface-700 dark:text-surface-0/80'
- ]
- },
- title: {
- class: ['font-bold text-lg']
- },
- icons: {
- class: ['flex items-center']
- },
- closeButton: {
- class: [
- 'relative',
-
- // Flexbox and Alignment
- 'flex items-center justify-center',
-
- // Size and Spacing
- 'mr-2',
- 'last:mr-0',
- 'w-8 h-8',
-
- // Shape
- 'border-0',
- 'rounded-full',
-
- // Colors
- 'text-surface-500',
- 'bg-transparent',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // States
- 'hover:text-surface-700 dark:hover:text-white/80',
- 'hover:bg-surface-100 dark:hover:bg-surface-800/80',
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-inset',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
-
- // Misc
- 'overflow-hidden'
- ]
- },
- closeButtonIcon: {
- class: [
- // Display
- 'inline-block',
-
- // Size
- 'w-4',
- 'h-4'
- ]
- },
- content: {
- class: [
- // Spacing and Size
- 'p-5',
- 'pt-0',
- 'h-full',
- 'w-full',
-
- // Growth and Overflow
- 'grow',
- 'overflow-y-auto'
- ]
- },
- mask: ({ props }) => ({
- class: [
- // Transitions
- 'transition-all',
- 'duration-300',
- { 'p-5': !props.position == 'full' },
-
- // Background and Effects
- { 'has-[.mask-active]:bg-transparent bg-black/40': props.modal, 'has-[.mask-active]:backdrop-blur-none backdrop-blur-sm': props.modal }
- ]
- }),
- transition: ({ props }) => {
- return props.position === 'top'
- ? {
- enterFromClass: 'translate-x-0 -translate-y-full translate-z-0 mask-active',
- leaveToClass: 'translate-x-0 -translate-y-full translate-z-0 mask-active'
- }
- : props.position === 'bottom'
- ? {
- enterFromClass: 'translate-x-0 translate-y-full translate-z-0 mask-active',
- leaveToClass: 'translate-x-0 translate-y-full translate-z-0 mask-active'
- }
- : props.position === 'left'
- ? {
- enterFromClass: '-translate-x-full translate-y-0 translate-z-0 mask-active',
- leaveToClass: '-translate-x-full translate-y-0 translate-z-0 mask-active'
- }
- : props.position === 'right'
- ? {
- enterFromClass: 'translate-x-full translate-y-0 translate-z-0 mask-active',
- leaveToClass: 'translate-x-full translate-y-0 translate-z-0 mask-active'
- }
- : {
- enterFromClass: 'opacity-0 mask-active',
- enterActiveClass: 'transition-opacity duration-400 ease-in',
- leaveActiveClass: 'transition-opacity duration-400 ease-in',
- leaveToClass: 'opacity-0 mask-active'
- };
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/skeleton/index.js b/frontend/packages/kwai-ui/src/presets/kwai/skeleton/index.js
deleted file mode 100644
index d459aaac9..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/skeleton/index.js
+++ /dev/null
@@ -1,16 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- 'overflow-hidden',
- {
- 'animate-pulse': props.animation !== 'none'
- },
-
- // Round
- { 'rounded-full': props.shape === 'circle', 'rounded-md': props.shape !== 'circle' },
-
- // Colors
- 'bg-surface-200 dark:bg-surface-700'
- ]
- })
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/slider/index.js b/frontend/packages/kwai-ui/src/presets/kwai/slider/index.js
deleted file mode 100644
index 18e3bbb09..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/slider/index.js
+++ /dev/null
@@ -1,137 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- 'relative',
-
- // Size
- { 'h-1 w-60': props.orientation == 'horizontal', 'w-1 h-56': props.orientation == 'vertical' },
-
- // Shape
- 'border-0',
-
- // Colors
- 'bg-surface-100 dark:bg-surface-700',
-
- // States
- { 'opacity-60 select-none pointer-events-none cursor-default': props.disabled }
- ]
- }),
- range: ({ props }) => ({
- class: [
- // Position
- 'block absolute',
- {
- 'top-0 left-0': props.orientation == 'horizontal',
- 'bottom-0 left-0': props.orientation == 'vertical'
- },
-
- //Size
- {
- 'h-full': props.orientation == 'horizontal',
- 'w-full': props.orientation == 'vertical'
- },
-
- // Colors
- 'bg-primary-500 dark:bg-primary-400'
- ]
- }),
- handle: ({ props }) => ({
- class: [
- 'block',
-
- // Size
- 'h-[1.143rem]',
- 'w-[1.143rem]',
- {
- 'top-[50%] mt-[-0.5715rem] ml-[-0.5715rem]': props.orientation == 'horizontal',
- 'left-[50%] mb-[-0.5715rem] ml-[-0.5715rem]': props.orientation == 'vertical'
- },
-
- // Shape
- 'rounded-full',
- 'border-2',
-
- // Colors
- 'bg-surface-0 dark:bg-surface-600',
- 'border-primary-500 dark:border-primary-400',
-
- // States
- 'hover:bg-primary-500 hover:border-primary-500',
- 'focus-visible:outline-none focus-visible:outline-offset-0 focus-visible:ring',
- 'ring-primary-400/50 dark:ring-primary-300/50',
-
- // Transitions
- 'transition duration-200',
-
- // Misc
- 'cursor-grab',
- 'touch-action-none'
- ]
- }),
- starthandler: ({ props }) => ({
- class: [
- 'block',
-
- // Size
- 'h-[1.143rem]',
- 'w-[1.143rem]',
- {
- 'top-[50%] mt-[-0.5715rem] ml-[-0.5715rem]': props.orientation == 'horizontal',
- 'left-[50%] mb-[-0.5715rem] ml-[-0.4715rem]': props.orientation == 'vertical'
- },
-
- // Shape
- 'rounded-full',
- 'border-2',
-
- // Colors
- 'bg-surface-0 dark:bg-surface-600',
- 'border-primary-500 dark:border-primary-400',
-
- // States
- 'hover:bg-primary-500 hover:border-primary-500',
- 'focus-visible:outline-none focus-visible:outline-offset-0 focus-visible:ring',
- 'focus-visible:ring-primary-400/50 dark:focus-visible:ring-primary-300/50',
-
- // Transitions
- 'transition duration-200',
-
- // Misc
- 'cursor-grab',
- 'touch-action-none'
- ]
- }),
- endhandler: ({ props }) => ({
- class: [
- 'block',
-
- // Size
- 'h-[1.143rem]',
- 'w-[1.143rem]',
- {
- 'top-[50%] mt-[-0.5715rem] ml-[-0.5715rem]': props.orientation == 'horizontal',
- 'left-[50%] mb-[-0.5715rem] ml-[-0.4715rem]': props.orientation == 'vertical'
- },
-
- // Shape
- 'rounded-full',
- 'border-2',
-
- // Colors
- 'bg-surface-0 dark:bg-surface-600',
- 'border-primary-500 dark:border-primary-400',
-
- // States
- 'hover:bg-primary-500 hover:border-primary-500',
- 'focus-visible:outline-none focus-visible:outline-offset-0 focus-visible:ring',
- 'focus-visible:ring-primary-400/50 dark:focus-visible:ring-primary-300/50',
-
- // Transitions
- 'transition duration-200',
-
- // Misc
- 'cursor-grab',
- 'touch-action-none'
- ]
- })
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/speeddial/index.js b/frontend/packages/kwai-ui/src/presets/kwai/speeddial/index.js
deleted file mode 100644
index 7ecbbcf23..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/speeddial/index.js
+++ /dev/null
@@ -1,283 +0,0 @@
-export default {
- root: {
- class: 'absolute flex'
- },
- button: {
- root: ({ props, context, parent }) => ({
- class: [
- 'relative',
- 'z-20',
-
- // Alignments
- 'items-center inline-flex text-center align-bottom justify-center',
-
- // Sizes & Spacing
- 'leading-[normal]',
- 'w-16 h-16 p-0 py-3',
-
- // Shapes
- 'rounded-full',
- 'shadow-md',
-
- // Link Button
- { 'text-primary-600 bg-transparent border-transparent': props.link },
-
- // Plain Button
- { 'text-white bg-gray-500 border border-gray-500': props.plain && !props.outlined && !props.text },
- // Plain Text Button
- { 'text-surface-500': props.plain && props.text },
- // Plain Outlined Button
- { 'text-surface-500 border border-gray-500': props.plain && props.outlined },
-
- // Text Button
- { 'bg-transparent border-transparent': props.text && !props.plain },
-
- // Outlined Button
- { 'bg-transparent border': props.outlined && !props.plain },
-
- // --- Severity Buttons ---
-
- // Primary Button
- {
- 'text-white dark:text-surface-900': !props.link && props.severity === null && !props.text && !props.outlined && !props.plain,
- 'bg-primary-500 dark:bg-primary-400': !props.link && props.severity === null && !props.text && !props.outlined && !props.plain,
- 'border border-primary-500 dark:border-primary-400': !props.link && props.severity === null && !props.text && !props.outlined && !props.plain
- },
- // Primary Text Button
- { 'text-primary-500 dark:text-primary-400': props.text && props.severity === null && !props.plain },
- // Primary Outlined Button
- { 'text-primary-500 border border-primary-500 hover:bg-primary-300/20': props.outlined && props.severity === null && !props.plain },
-
- // Secondary Button
- {
- 'text-white dark:text-surface-900': props.severity === 'secondary' && !props.text && !props.outlined && !props.plain,
- 'bg-surface-500 dark:bg-surface-400': props.severity === 'secondary' && !props.text && !props.outlined && !props.plain,
- 'border border-surface-500 dark:border-surface-400': props.severity === 'secondary' && !props.text && !props.outlined && !props.plain
- },
- // Secondary Text Button
- { 'text-surface-500 dark:text-surface-300': props.text && props.severity === 'secondary' && !props.plain },
- // Secondary Outlined Button
- { 'text-surface-500 dark:text-surface-300 border border-surface-500 hover:bg-surface-300/20': props.outlined && props.severity === 'secondary' && !props.plain },
-
- // Success Button
- {
- 'text-white dark:text-green-900': props.severity === 'success' && !props.text && !props.outlined && !props.plain,
- 'bg-green-500 dark:bg-green-400': props.severity === 'success' && !props.text && !props.outlined && !props.plain,
- 'border border-green-500 dark:border-green-400': props.severity === 'success' && !props.text && !props.outlined && !props.plain
- },
- // Success Text Button
- { 'text-green-500 dark:text-green-400': props.text && props.severity === 'success' && !props.plain },
- // Success Outlined Button
- { 'text-green-500 border border-green-500 hover:bg-green-300/20': props.outlined && props.severity === 'success' && !props.plain },
-
- // Info Button
- {
- 'text-white dark:text-surface-900': props.severity === 'info' && !props.text && !props.outlined && !props.plain,
- 'bg-blue-500 dark:bg-blue-400': props.severity === 'info' && !props.text && !props.outlined && !props.plain,
- 'border border-blue-500 dark:border-blue-400': props.severity === 'info' && !props.text && !props.outlined && !props.plain
- },
- // Info Text Button
- { 'text-blue-500 dark:text-blue-400': props.text && props.severity === 'info' && !props.plain },
- // Info Outlined Button
- { 'text-blue-500 border border-blue-500 hover:bg-blue-300/20 ': props.outlined && props.severity === 'info' && !props.plain },
-
- // Warning Button
- {
- 'text-white dark:text-surface-900': props.severity === 'warning' && !props.text && !props.outlined && !props.plain,
- 'bg-orange-500 dark:bg-orange-400': props.severity === 'warning' && !props.text && !props.outlined && !props.plain,
- 'border border-orange-500 dark:border-orange-400': props.severity === 'warning' && !props.text && !props.outlined && !props.plain
- },
- // Warning Text Button
- { 'text-orange-500 dark:text-orange-400': props.text && props.severity === 'warning' && !props.plain },
- // Warning Outlined Button
- { 'text-orange-500 border border-orange-500 hover:bg-orange-300/20': props.outlined && props.severity === 'warning' && !props.plain },
-
- // Help Button
- {
- 'text-white dark:text-surface-900': props.severity === 'help' && !props.text && !props.outlined && !props.plain,
- 'bg-purple-500 dark:bg-purple-400': props.severity === 'help' && !props.text && !props.outlined && !props.plain,
- 'border border-purple-500 dark:border-purple-400': props.severity === 'help' && !props.text && !props.outlined && !props.plain
- },
- // Help Text Button
- { 'text-purple-500 dark:text-purple-400': props.text && props.severity === 'help' && !props.plain },
- // Help Outlined Button
- { 'text-purple-500 border border-purple-500 hover:bg-purple-300/20': props.outlined && props.severity === 'help' && !props.plain },
-
- // Danger Button
- {
- 'text-white dark:text-surface-900': props.severity === 'danger' && !props.text && !props.outlined && !props.plain,
- 'bg-red-500 dark:bg-red-400': props.severity === 'danger' && !props.text && !props.outlined && !props.plain,
- 'border border-red-500 dark:border-red-400': props.severity === 'danger' && !props.text && !props.outlined && !props.plain
- },
- // Danger Text Button
- { 'text-red-500 dark:text-red-400': props.text && props.severity === 'danger' && !props.plain },
- // Danger Outlined Button
- { 'text-red-500 border border-red-500 hover:bg-red-300/20': props.outlined && props.severity === 'danger' && !props.plain },
-
- // --- Severity Button States ---
- 'focus:outline-none focus:outline-offset-0 focus:ring',
-
- // Link
- { 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50': props.link },
-
- // Plain
- { 'hover:bg-gray-600 hover:border-gray-600': props.plain && !props.outlined && !props.text },
- // Text & Outlined Button
- { 'hover:bg-surface-300/20': props.plain && (props.text || props.outlined) },
-
- // Primary
- { 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300': !props.link && props.severity === null && !props.text && !props.outlined && !props.plain },
- { 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50': props.severity === null },
- // Text & Outlined Button
- { 'hover:bg-primary-300/20': (props.text || props.outlined) && props.severity === null && !props.plain },
-
- // Secondary
- { 'hover:bg-surface-600 dark:hover:bg-surface-300 hover:border-surface-600 dark:hover:border-surface-300': props.severity === 'secondary' && !props.text && !props.outlined && !props.plain },
- { 'focus:ring-surface-400/50 dark:focus:ring-surface-300/50': props.severity === 'secondary' },
- // Text & Outlined Button
- { 'hover:bg-surface-300/20': (props.text || props.outlined) && props.severity === 'secondary' && !props.plain },
-
- // Success
- { 'hover:bg-green-600 dark:hover:bg-green-300 hover:border-green-600 dark:hover:border-green-300': props.severity === 'success' && !props.text && !props.outlined && !props.plain },
- { 'focus:ring-green-400/50 dark:focus:ring-green-300/50': props.severity === 'success' },
- // Text & Outlined Button
- { 'hover:bg-green-300/20': (props.text || props.outlined) && props.severity === 'success' && !props.plain },
-
- // Info
- { 'hover:bg-blue-600 dark:hover:bg-blue-300 hover:border-blue-600 dark:hover:border-blue-300': props.severity === 'info' && !props.text && !props.outlined && !props.plain },
- { 'focus:ring-blue-400/50 dark:focus:ring-blue-300/50': props.severity === 'info' },
- // Text & Outlined Button
- { 'hover:bg-blue-300/20': (props.text || props.outlined) && props.severity === 'info' && !props.plain },
-
- // Warning
- { 'hover:bg-orange-600 dark:hover:bg-orange-300 hover:border-orange-600 dark:hover:border-orange-300': props.severity === 'warning' && !props.text && !props.outlined && !props.plain },
- { 'focus:ring-orange-400/50 dark:focus:ring-orange-300/50': props.severity === 'warning' },
- // Text & Outlined Button
- { 'hover:bg-orange-300/20': (props.text || props.outlined) && props.severity === 'warning' && !props.plain },
-
- // Help
- { 'hover:bg-purple-600 dark:hover:bg-purple-300 hover:border-purple-600 dark:hover:border-purple-300': props.severity === 'help' && !props.text && !props.outlined && !props.plain },
- { 'focus:ring-purple-400/50 dark:focus:ring-purple-300/50': props.severity === 'help' },
- // Text & Outlined Button
- { 'hover:bg-purple-300/20': (props.text || props.outlined) && props.severity === 'help' && !props.plain },
-
- // Danger
- { 'hover:bg-red-600 dark:hover:bg-red-300 hover:border-red-600 dark:hover:border-red-300': props.severity === 'danger' && !props.text && !props.outlined && !props.plain },
- { 'focus:ring-red-400/50 dark:focus:ring-red-300/50': props.severity === 'danger' },
- // Text & Outlined Button
- { 'hover:bg-red-300/20': (props.text || props.outlined) && props.severity === 'danger' && !props.plain },
-
- // Disabled
- { 'opacity-60 pointer-events-none cursor-default': context.disabled },
-
- // Transitions
- 'transition duration-200 ease-in-out',
- parent.state.d_visible ? 'rotate-45' : 'rotate-0',
-
- // Misc
- 'cursor-pointer overflow-hidden select-none'
- ]
- }),
- label: ({ props }) => ({
- class: [
- 'duration-200',
- 'font-bold',
- {
- 'hover:underline': props.link
- },
- { 'flex-1': props.label !== null, 'invisible w-0': props.label == null }
- ]
- }),
- icon: ({ props }) => ({
- class: [
- 'mx-0',
- {
- 'mr-2': props.iconPos == 'left' && props.label != null,
- 'ml-2 order-1': props.iconPos == 'right' && props.label != null,
- 'mb-2': props.iconPos == 'top' && props.label != null,
- 'mt-2': props.iconPos == 'bottom' && props.label != null
- }
- ]
- }),
- loadingicon: ({ props }) => ({
- class: [
- 'h-4 w-4',
- 'mx-0',
- {
- 'mr-2': props.iconPos == 'left' && props.label != null,
- 'ml-2 order-1': props.iconPos == 'right' && props.label != null,
- 'mb-2': props.iconPos == 'top' && props.label != null,
- 'mt-2': props.iconPos == 'bottom' && props.label != null
- },
- 'animate-spin'
- ]
- }),
- badge: ({ props }) => ({
- class: [{ 'ml-2 w-4 h-4 leading-none flex items-center justify-center': props.badge }]
- })
- },
- menu: {
- class: [
- // Spacing
- 'm-0 p-0',
-
- // Layout & Flexbox
- 'list-none flex items-center justify-center',
-
- // Transitions
- 'transition delay-200',
-
- // Z-Index (Positioning)
- 'z-20'
- ]
- },
- menuitem: ({ props, context }) => ({
- class: [
- 'transform transition-transform duration-200 ease-out transition-opacity duration-800',
-
- // Conditional Appearance
- context.hidden ? 'opacity-0 scale-0' : 'opacity-100 scale-100',
-
- // Conditional Spacing
- {
- 'my-1 first:mb-2': props.direction == 'up' && props.type == 'linear',
- 'my-1 first:mt-2': props.direction == 'down' && props.type == 'linear',
- 'mx-1 first:mr-2': props.direction == 'left' && props.type == 'linear',
- 'mx-1 first:ml-2': props.direction == 'right' && props.type == 'linear'
- },
-
- // Conditional Positioning
- { absolute: props.type !== 'linear' }
- ]
- }),
- action: {
- class: [
- // Flexbox & Alignment
- 'flex items-center justify-center',
-
- // Size
- 'w-12 h-12',
-
- // Shape
- 'rounded-full relative overflow-hidden',
-
- // Appearance
- 'bg-surface-600 dark:bg-surface-0/80 text-white dark:text-surface-900/80',
-
- // Hover Effects
- 'hover:bg-surface-700 dark:hover:bg-surface-200/80'
- ]
- },
- mask: ({ state }) => ({
- class: [
- // Base Styles
- 'absolute left-0 top-0 w-full h-full transition-opacity duration-250 ease-in-out bg-black/40 z-0',
-
- // Conditional Appearance
- {
- 'opacity-0 pointer-events-none': !state.d_visible,
- 'opacity-100 transition-opacity duration-400 ease-in-out': state.d_visible
- }
- ]
- })
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/splitbutton/index.js b/frontend/packages/kwai-ui/src/presets/kwai/splitbutton/index.js
deleted file mode 100644
index 61a42f571..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/splitbutton/index.js
+++ /dev/null
@@ -1,502 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- // Flexbox and Position
- 'inline-flex',
- 'relative',
-
- // Shape
- 'rounded-md',
- { 'shadow-lg': props.raised }
- ]
- }),
- button: {
- root: ({ parent }) => ({
- class: [
- 'relative',
-
- // Alignments
- 'items-center inline-flex text-center align-bottom justify-center',
-
- // Sizes & Spacing
- 'leading-[normal]',
- {
- 'px-4 py-3': parent.props.size === null,
- 'text-sm py-2 px-3': parent.props.size === 'small',
- 'text-xl py-3 px-4': parent.props.size === 'large'
- },
- {
- 'min-w-12 p-0 py-3': parent.props.label == null && parent.props.icon !== null
- },
-
- // Shape
- 'rounded-r-none',
- 'border-r-0',
- { 'rounded-l-full': parent.props.rounded },
- { 'rounded-md': !parent.props.rounded, 'rounded-full': parent.props.rounded },
-
- // Link Button
- { 'text-primary-600 bg-transparent border-transparent': parent.props.link },
-
- // Plain Button
- { 'text-white bg-gray-500 border border-gray-500': parent.props.plain && !parent.props.outlined && !parent.props.text },
- // Plain Text Button
- { 'text-surface-500': parent.props.plain && parent.props.text },
- // Plain Outlined Button
- { 'text-surface-500 border border-gray-500': parent.props.plain && parent.props.outlined },
-
- // Text Button
- { 'bg-transparent border-transparent': parent.props.text && !parent.props.plain },
-
- // Outlined Button
- { 'bg-transparent border': parent.props.outlined && !parent.props.plain },
-
- // --- Severity Buttons ---
-
- // Primary Button
- {
- 'text-white dark:text-surface-900': !parent.props.link && parent.props.severity === null && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'bg-primary-500 dark:bg-primary-400': !parent.props.link && parent.props.severity === null && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'border border-primary-500 dark:border-primary-400': !parent.props.link && parent.props.severity === null && !parent.props.text && !parent.props.outlined && !parent.props.plain
- },
- // Primary Text Button
- { 'text-primary-500 dark:text-primary-400': parent.props.text && parent.props.severity === null && !parent.props.plain },
- // Primary Outlined Button
- { 'text-primary-500 border border-primary-500 hover:bg-primary-300/20': parent.props.outlined && parent.props.severity === null && !parent.props.plain },
-
- // Secondary Button
- {
- 'text-white dark:text-surface-900': parent.props.severity === 'secondary' && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'bg-surface-500 dark:bg-surface-400': parent.props.severity === 'secondary' && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'border border-surface-500 dark:border-surface-400': parent.props.severity === 'secondary' && !parent.props.text && !parent.props.outlined && !parent.props.plain
- },
- // Secondary Text Button
- { 'text-surface-500 dark:text-surface-400': parent.props.text && parent.props.severity === 'secondary' && !parent.props.plain },
- // Secondary Outlined Button
- { 'text-surface-500 border border-surface-500 hover:bg-surface-300/20': parent.props.outlined && parent.props.severity === 'secondary' && !parent.props.plain },
-
- // Success Button
- {
- 'text-white dark:text-surface-900': parent.props.severity === 'success' && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'bg-green-500 dark:bg-green-400': parent.props.severity === 'success' && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'border border-green-500 dark:border-green-400': parent.props.severity === 'success' && !parent.props.text && !parent.props.outlined && !parent.props.plain
- },
- // Success Text Button
- { 'text-surface-500 dark:text-surface-400': parent.props.text && parent.props.severity === 'secondary' && !parent.props.plain },
- // Success Outlined Button
- { 'text-green-500 border border-green-500 hover:bg-green-300/20': parent.props.outlined && parent.props.severity === 'success' && !parent.props.plain },
-
- // Info Button
- {
- 'text-white dark:text-surface-900': parent.props.severity === 'info' && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'bg-blue-500 dark:bg-blue-400': parent.props.severity === 'info' && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'border border-blue-500 dark:border-blue-400': parent.props.severity === 'info' && !parent.props.text && !parent.props.outlined && !parent.props.plain
- },
- // Info Text Button
- { 'text-blue-500 dark:text-blue-400': parent.props.text && parent.props.severity === 'info' && !parent.props.plain },
- // Info Outlined Button
- { 'text-blue-500 border border-blue-500 hover:bg-blue-300/20 ': parent.props.outlined && parent.props.severity === 'info' && !parent.props.plain },
-
- // Warning Button
- {
- 'text-white dark:text-surface-900': parent.props.severity === 'warning' && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'bg-orange-500 dark:bg-orange-400': parent.props.severity === 'warning' && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'border border-orange-500 dark:border-orange-400': parent.props.severity === 'warning' && !parent.props.text && !parent.props.outlined && !parent.props.plain
- },
- // Warning Text Button
- { 'text-orange-500 dark:text-orange-400': parent.props.text && parent.props.severity === 'warning' && !parent.props.plain },
- // Warning Outlined Button
- { 'text-orange-500 border border-orange-500 hover:bg-orange-300/20': parent.props.outlined && parent.props.severity === 'warning' && !parent.props.plain },
-
- // Help Button
- {
- 'text-white dark:text-surface-900': parent.props.severity === 'help' && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'bg-purple-500 dark:bg-purple-400': parent.props.severity === 'help' && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'border border-purple-500 dark:border-purple-400': parent.props.severity === 'help' && !parent.props.text && !parent.props.outlined && !parent.props.plain
- },
- // Help Text Button
- { 'text-purple-500 dark:text-purple-400': parent.props.text && parent.props.severity === 'help' && !parent.props.plain },
- // Help Outlined Button
- { 'text-purple-500 border border-purple-500 hover:bg-purple-300/20': parent.props.outlined && parent.props.severity === 'help' && !parent.props.plain },
-
- // Danger Button
- {
- 'text-white dark:text-surface-900': parent.props.severity === 'danger' && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'bg-red-500 dark:bg-red-400': parent.props.severity === 'danger' && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'border border-red-500 dark:border-red-400': parent.props.severity === 'danger' && !parent.props.text && !parent.props.outlined && !parent.props.plain
- },
- // Danger Text Button
- { 'text-red-500 dark:text-red-400': parent.props.text && parent.props.severity === 'danger' && !parent.props.plain },
- // Danger Outlined Button
- { 'text-red-500 border border-red-500 hover:bg-red-300/20': parent.props.outlined && parent.props.severity === 'danger' && !parent.props.plain },
-
- // --- Severity Button States ---
- 'focus:outline-none focus:outline-offset-0 focus:ring',
-
- // Link
- { 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50': parent.props.link },
-
- // Plain
- { 'hover:bg-gray-600 hover:border-gray-600': parent.props.plain && !parent.props.outlined && !parent.props.text },
- // Text & Outlined Button
- { 'hover:bg-surface-300/20': parent.props.plain && (parent.props.text || parent.props.outlined) },
-
- // Primary
- { 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300': !parent.props.link && parent.props.severity === null && !parent.props.text && !parent.props.outlined && !parent.props.plain },
- { 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50': !parent.props.link && parent.props.severity === null && !parent.props.text && !parent.props.outlined && !parent.props.plain },
- // Text & Outlined Button
- { 'hover:bg-primary-300/20': (parent.props.text || parent.props.outlined) && parent.props.severity === null && !parent.props.plain },
-
- // Secondary
- { 'hover:bg-surface-600 dark:hover:bg-surface-300 hover:border-surface-600 dark:hover:border-surface-300': parent.props.severity === 'secondary' && !parent.props.text && !parent.props.outlined && !parent.props.plain },
- { 'focus:ring-surface-400/50 dark:focus:ring-surface-300/50': parent.props.severity === 'secondary' },
- // Text & Outlined Button
- { 'hover:bg-surface-300/20': (parent.props.text || parent.props.outlined) && parent.props.severity === 'secondary' && !parent.props.plain },
-
- // Success
- { 'hover:bg-green-600 dark:hover:bg-green-300 hover:border-green-600 dark:hover:border-green-300': parent.props.severity === 'success' && !parent.props.text && !parent.props.outlined && !parent.props.plain },
- { 'focus:ring-green-400/50 dark:focus:ring-green-300/50': parent.props.severity === 'success' },
- // Text & Outlined Button
- { 'hover:bg-green-300/20': (parent.props.text || parent.props.outlined) && parent.props.severity === 'success' && !parent.props.plain },
-
- // Info
- { 'hover:bg-blue-600 dark:hover:bg-blue-300 hover:border-blue-600 dark:hover:border-blue-300': parent.props.severity === 'info' && !parent.props.text && !parent.props.outlined && !parent.props.plain },
- { 'focus:ring-blue-400/50 dark:focus:ring-blue-300/50': parent.props.severity === 'info' },
- // Text & Outlined Button
- { 'hover:bg-blue-300/20': (parent.props.text || parent.props.outlined) && parent.props.severity === 'info' && !parent.props.plain },
-
- // Warning
- { 'hover:bg-orange-600 dark:hover:bg-orange-300 hover:border-orange-600 dark:hover:border-orange-300': parent.props.severity === 'warning' && !parent.props.text && !parent.props.outlined && !parent.props.plain },
- { 'focus:ring-orange-400/50 dark:focus:ring-orange-300/50': parent.props.severity === 'warning' },
- // Text & Outlined Button
- { 'hover:bg-orange-300/20': (parent.props.text || parent.props.outlined) && parent.props.severity === 'warning' && !parent.props.plain },
-
- // Help
- { 'hover:bg-purple-600 dark:hover:bg-purple-300 hover:border-purple-600 dark:hover:border-purple-300': parent.props.severity === 'help' && !parent.props.text && !parent.props.outlined && !parent.props.plain },
- { 'focus:ring-purple-400/50 dark:focus:ring-purple-300/50': parent.props.severity === 'help' },
- // Text & Outlined Button
- { 'hover:bg-purple-300/20': (parent.props.text || parent.props.outlined) && parent.props.severity === 'help' && !parent.props.plain },
-
- // Warning
- { 'hover:bg-red-600 dark:hover:bg-red-300 hover:border-red-600 dark:hover:border-red-300': parent.props.severity === 'danger' && !parent.props.text && !parent.props.outlined && !parent.props.plain },
- { 'focus:ring-red-400/50 dark:focus:ring-red-300/50': parent.props.severity === 'danger' },
- // Text & Outlined Button
- { 'hover:bg-red-300/20': (parent.props.text || parent.props.outlined) && parent.props.severity === 'danger' && !parent.props.plain },
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // Misc
- 'cursor-pointer overflow-hidden select-none'
- ]
- }),
- icon: {
- class: [
- // Margins
- 'mr-2'
- ]
- }
- },
- menubutton: {
- root: ({ parent }) => ({
- class: [
- 'relative',
- // Alignments
- 'items-center inline-flex text-center align-bottom justify-center',
-
- // Sizes & Spacing
- 'leading-[normal]',
- {
- 'px-4 py-3': parent.props.size === null,
- 'text-sm py-2 px-3': parent.props.size === 'small',
- 'text-xl py-3 px-4': parent.props.size === 'large'
- },
- {
- 'min-w-12 p-0 py-3': parent.props.label == null && parent.props.icon !== null
- },
-
- // Shape
- 'rounded-l-none',
- { 'rounded-l-full': parent.props.rounded },
- { 'rounded-md': !parent.props.rounded, 'rounded-full': parent.props.rounded },
-
- // Link Button
- { 'text-primary-600 bg-transparent border-transparent': parent.props.link },
-
- // Plain Button
- { 'text-white bg-gray-500 border border-gray-500': parent.props.plain && !parent.props.outlined && !parent.props.text },
- // Plain Text Button
- { 'text-surface-500': parent.props.plain && parent.props.text },
- // Plain Outlined Button
- { 'text-surface-500 border border-gray-500': parent.props.plain && parent.props.outlined },
-
- // Text Button
- { 'bg-transparent border-transparent': parent.props.text && !parent.props.plain },
-
- // Outlined Button
- { 'bg-transparent border': parent.props.outlined && !parent.props.plain },
-
- // --- Severity Buttons ---
-
- // Primary Button
- {
- 'text-white dark:text-surface-900': !parent.props.link && parent.props.severity === null && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'bg-primary-500 dark:bg-primary-400': !parent.props.link && parent.props.severity === null && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'border border-primary-500 dark:border-primary-400': !parent.props.link && parent.props.severity === null && !parent.props.text && !parent.props.outlined && !parent.props.plain
- },
- // Primary Text Button
- { 'text-primary-500 dark:text-primary-400': parent.props.text && parent.props.severity === null && !parent.props.plain },
- // Primary Outlined Button
- { 'text-primary-500 border border-primary-500 hover:bg-primary-300/20': parent.props.outlined && parent.props.severity === null && !parent.props.plain },
-
- // Secondary Button
- {
- 'text-white dark:text-surface-900': parent.props.severity === 'secondary' && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'bg-surface-500 dark:bg-surface-400': parent.props.severity === 'secondary' && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'border border-surface-500 dark:border-surface-400': parent.props.severity === 'secondary' && !parent.props.text && !parent.props.outlined && !parent.props.plain
- },
- // Secondary Text Button
- { 'text-surface-500 dark:text-surface-400': parent.props.text && parent.props.severity === 'secondary' && !parent.props.plain },
- // Secondary Outlined Button
- { 'text-surface-500 border border-surface-500 hover:bg-surface-300/20': parent.props.outlined && parent.props.severity === 'secondary' && !parent.props.plain },
-
- // Success Button
- {
- 'text-white dark:text-surface-900': parent.props.severity === 'success' && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'bg-green-500 dark:bg-green-400': parent.props.severity === 'success' && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'border border-green-500 dark:border-green-400': parent.props.severity === 'success' && !parent.props.text && !parent.props.outlined && !parent.props.plain
- },
- // Success Text Button
- { 'text-surface-500 dark:text-surface-400': parent.props.text && parent.props.severity === 'secondary' && !parent.props.plain },
- // Success Outlined Button
- { 'text-green-500 border border-green-500 hover:bg-green-300/20': parent.props.outlined && parent.props.severity === 'success' && !parent.props.plain },
-
- // Info Button
- {
- 'text-white dark:text-surface-900': parent.props.severity === 'info' && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'bg-blue-500 dark:bg-blue-400': parent.props.severity === 'info' && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'border border-blue-500 dark:border-blue-400': parent.props.severity === 'info' && !parent.props.text && !parent.props.outlined && !parent.props.plain
- },
- // Info Text Button
- { 'text-blue-500 dark:text-blue-400': parent.props.text && parent.props.severity === 'info' && !parent.props.plain },
- // Info Outlined Button
- { 'text-blue-500 border border-blue-500 hover:bg-blue-300/20 ': parent.props.outlined && parent.props.severity === 'info' && !parent.props.plain },
-
- // Warning Button
- {
- 'text-white dark:text-surface-900': parent.props.severity === 'warning' && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'bg-orange-500 dark:bg-orange-400': parent.props.severity === 'warning' && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'border border-orange-500 dark:border-orange-400': parent.props.severity === 'warning' && !parent.props.text && !parent.props.outlined && !parent.props.plain
- },
- // Warning Text Button
- { 'text-orange-500 dark:text-orange-400': parent.props.text && parent.props.severity === 'warning' && !parent.props.plain },
- // Warning Outlined Button
- { 'text-orange-500 border border-orange-500 hover:bg-orange-300/20': parent.props.outlined && parent.props.severity === 'warning' && !parent.props.plain },
-
- // Help Button
- {
- 'text-white dark:text-surface-900': parent.props.severity === 'help' && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'bg-purple-500 dark:bg-purple-400': parent.props.severity === 'help' && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'border border-purple-500 dark:border-purple-400': parent.props.severity === 'help' && !parent.props.text && !parent.props.outlined && !parent.props.plain
- },
- // Help Text Button
- { 'text-purple-500 dark:text-purple-400': parent.props.text && parent.props.severity === 'help' && !parent.props.plain },
- // Help Outlined Button
- { 'text-purple-500 border border-purple-500 hover:bg-purple-300/20': parent.props.outlined && parent.props.severity === 'help' && !parent.props.plain },
-
- // Danger Button
- {
- 'text-white dark:text-surface-900': parent.props.severity === 'danger' && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'bg-red-500 dark:bg-red-400': parent.props.severity === 'danger' && !parent.props.text && !parent.props.outlined && !parent.props.plain,
- 'border border-red-500 dark:border-red-400': parent.props.severity === 'danger' && !parent.props.text && !parent.props.outlined && !parent.props.plain
- },
- // Danger Text Button
- { 'text-red-500 dark:text-red-400': parent.props.text && parent.props.severity === 'danger' && !parent.props.plain },
- // Danger Outlined Button
- { 'text-red-500 border border-red-500 hover:bg-red-300/20': parent.props.outlined && parent.props.severity === 'danger' && !parent.props.plain },
-
- // --- Severity Button States ---
- 'focus:outline-none focus:outline-offset-0 focus:ring',
-
- // Link
- { 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50': parent.props.link },
-
- // Plain
- { 'hover:bg-gray-600 hover:border-gray-600': parent.props.plain && !parent.props.outlined && !parent.props.text },
- // Text & Outlined Button
- { 'hover:bg-surface-300/20': parent.props.plain && (parent.props.text || parent.props.outlined) },
-
- // Primary
- { 'hover:bg-primary-600 dark:hover:bg-primary-300 hover:border-primary-600 dark:hover:border-primary-300': !parent.props.link && parent.props.severity === null && !parent.props.text && !parent.props.outlined && !parent.props.plain },
- { 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50': !parent.props.link && parent.props.severity === null && !parent.props.text && !parent.props.outlined && !parent.props.plain },
- // Text & Outlined Button
- { 'hover:bg-primary-300/20': (parent.props.text || parent.props.outlined) && parent.props.severity === null && !parent.props.plain },
-
- // Secondary
- { 'hover:bg-surface-600 dark:hover:bg-surface-300 hover:border-surface-600 dark:hover:border-surface-300': parent.props.severity === 'secondary' && !parent.props.text && !parent.props.outlined && !parent.props.plain },
- { 'focus:ring-surface-400/50 dark:focus:ring-surface-300/50': parent.props.severity === 'secondary' },
- // Text & Outlined Button
- { 'hover:bg-surface-300/20': (parent.props.text || parent.props.outlined) && parent.props.severity === 'secondary' && !parent.props.plain },
-
- // Success
- { 'hover:bg-green-600 dark:hover:bg-green-300 hover:border-green-600 dark:hover:border-green-300': parent.props.severity === 'success' && !parent.props.text && !parent.props.outlined && !parent.props.plain },
- { 'focus:ring-green-400/50 dark:focus:ring-green-300/50': parent.props.severity === 'success' },
- // Text & Outlined Button
- { 'hover:bg-green-300/20': (parent.props.text || parent.props.outlined) && parent.props.severity === 'success' && !parent.props.plain },
-
- // Info
- { 'hover:bg-blue-600 dark:hover:bg-blue-300 hover:border-blue-600 dark:hover:border-blue-300': parent.props.severity === 'info' && !parent.props.text && !parent.props.outlined && !parent.props.plain },
- { 'focus:ring-blue-400/50 dark:focus:ring-blue-300/50': parent.props.severity === 'info' },
- // Text & Outlined Button
- { 'hover:bg-blue-300/20': (parent.props.text || parent.props.outlined) && parent.props.severity === 'info' && !parent.props.plain },
-
- // Warning
- { 'hover:bg-orange-600 dark:hover:bg-orange-300 hover:border-orange-600 dark:hover:border-orange-300': parent.props.severity === 'warning' && !parent.props.text && !parent.props.outlined && !parent.props.plain },
- { 'focus:ring-orange-400/50 dark:focus:ring-orange-300/50': parent.props.severity === 'warning' },
- // Text & Outlined Button
- { 'hover:bg-orange-300/20': (parent.props.text || parent.props.outlined) && parent.props.severity === 'warning' && !parent.props.plain },
-
- // Help
- { 'hover:bg-purple-600 dark:hover:bg-purple-300 hover:border-purple-600 dark:hover:border-purple-300': parent.props.severity === 'help' && !parent.props.text && !parent.props.outlined && !parent.props.plain },
- { 'focus:ring-purple-400/50 dark:focus:ring-purple-300/50': parent.props.severity === 'help' },
- // Text & Outlined Button
- { 'hover:bg-purple-300/20': (parent.props.text || parent.props.outlined) && parent.props.severity === 'help' && !parent.props.plain },
-
- // Warning
- { 'hover:bg-red-600 dark:hover:bg-red-300 hover:border-red-600 dark:hover:border-red-300': parent.props.severity === 'danger' && !parent.props.text && !parent.props.outlined && !parent.props.plain },
- { 'focus:ring-red-400/50 dark:focus:ring-red-300/50': parent.props.severity === 'danger' },
- // Text & Outlined Button
- { 'hover:bg-red-300/20': (parent.props.text || parent.props.outlined) && parent.props.severity === 'danger' && !parent.props.plain },
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // Misc
- 'cursor-pointer overflow-hidden select-none'
- ]
- }),
- label: {
- class: ['hidden']
- }
- },
- menu: {
- root: {
- class: [
- // Shape
- 'rounded-md',
-
- // Size
- 'min-w-[12rem]',
- 'py-1',
-
- // Colors
- 'bg-surface-0 dark:bg-surface-700',
- 'border border-surface-200 dark:border-surface-700'
- ]
- },
- menu: {
- class: [
- // Spacings and Shape
- 'list-none',
- 'm-0',
- 'p-0',
- 'outline-none'
- ]
- },
- menuitem: {
- class: [
- // Position
- 'relative'
- ]
- },
- content: ({ context }) => ({
- class: [
- //Shape
- 'rounded-none',
-
- // Colors
- {
- 'text-surface-500 dark:text-white/70': !context.focused && !context.active,
- 'text-surface-500 dark:text-white/70 bg-surface-200 dark:bg-surface-600/90': context.focused && !context.active,
- 'text-primary-700 dark:text-surface-0/80 bg-primary-50 dark:bg-primary-400/30': context.focused && context.active,
- 'text-primary-700 dark:text-surface-0/80 bg-primary-50 dark:bg-primary-400/30': !context.focused && context.active
- },
-
- // Hover States
- {
- 'hover:bg-surface-100 dark:hover:bg-surface-600/80': !context.active,
- 'hover:bg-primary-500/50 dark:hover:bg-primary-300/30 text-primary-700 dark:text-surface-0/80': context.active
- },
-
- // Transitions
- 'transition-shadow',
- 'duration-200'
- ]
- }),
- action: {
- class: [
- 'relative',
- // Flexbox
-
- 'flex',
- 'items-center',
-
- // Spacing
- 'py-3',
- 'px-5',
-
- // Color
- 'text-surface-700 dark:text-white/80',
-
- // Misc
- 'no-underline',
- 'overflow-hidden',
- 'cursor-pointer',
- 'select-none'
- ]
- },
- icon: {
- class: [
- // Spacing
- 'mr-2',
-
- // Color
- 'text-surface-600 dark:text-white/70'
- ]
- },
- label: {
- class: ['leading-none']
- },
- submenuicon: {
- class: [
- // Position
- 'ml-auto'
- ]
- },
- submenu: {
- class: [
- // Size
- 'w-full sm:w-48',
-
- // Spacing
- 'py-1',
- 'm-0',
- 'list-none',
-
- // Shape
- 'shadow-none sm:shadow-md',
- 'border-0',
-
- // Position
- 'static sm:absolute',
- 'z-10',
-
- // Color
- 'bg-surface-0 dark:bg-surface-700'
- ]
- },
- separator: {
- class: 'border-t border-surface-200 dark:border-surface-600 my-1'
- }
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/splitter/index.js b/frontend/packages/kwai-ui/src/presets/kwai/splitter/index.js
deleted file mode 100644
index 877c80555..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/splitter/index.js
+++ /dev/null
@@ -1,61 +0,0 @@
-export default {
- root: ({ context }) => ({
- class: [
- // Colors
- 'bg-surface-0',
- 'dark:bg-surface-900',
- 'text-surface-700',
- 'dark:text-surface-0/80',
-
- // Shape
- 'rounded-lg',
-
- // Borders (Conditional)
- { 'border border-solid border-surface-50 dark:border-surface-700': !context.nested },
-
- // Nested
- { 'flex grow border-0': context.nested }
- ]
- }),
-
- gutter: ({ props }) => ({
- class: [
- // Flexbox
- 'flex',
- 'items-center',
- 'justify-center',
- 'shrink-0',
-
- // Colors
- 'bg-surface-50',
- 'dark:bg-surface-800',
-
- // Transitions
- 'transition-all',
- 'duration-200',
-
- // Misc
- {
- 'cursor-col-resize': props.layout == 'horizontal',
- 'cursor-row-resize': props.layout !== 'horizontal'
- }
- ]
- }),
- gutterhandler: ({ props }) => ({
- class: [
- // Colors
- 'bg-surface-100',
- 'dark:bg-surface-600',
-
- // Transitions
- 'transition-all',
- 'duration-200',
-
- // Sizing (Conditional)
- {
- 'h-7': props.layout == 'horizontal',
- 'w-7 h-2': props.layout !== 'horizontal'
- }
- ]
- })
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/stepper/index.js b/frontend/packages/kwai-ui/src/presets/kwai/stepper/index.js
deleted file mode 100644
index f49ae8920..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/stepper/index.js
+++ /dev/null
@@ -1,161 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: ['flex-1', props.orientation === 'vertical' ? 'flex-col' : 'flex-row']
- }),
- nav: {
- class: [
- // Flexbox
- 'flex',
- 'justify-between',
- 'items-center',
-
- // Spacing
- 'm-0',
- 'p-0',
-
- // Positioning
- 'relative',
-
- // Lists
- 'list-none',
-
- // Overflow
- 'overflow-x-auto'
- ]
- },
- stepperpanel: {
- panel: ({ context, parent }) => ({
- class: [context.active ? 'flex-1' : '', parent.props.orientation === 'vertical' ? 'flex flex-col flex-initial' : '']
- }),
- header: ({ parent, context }) => ({
- class: [
- // Position
- 'relative',
-
- // Flexbox
- 'flex',
- 'items-center',
- context.last ? 'flex-initial' : 'flex-1',
- parent.props.orientation === 'vertical' ? 'flex-initial' : '',
-
- // Spacing
- 'p-2'
- ]
- }),
- action: {
- class: [
- // Borders
- 'border-0',
- 'border-none',
-
- // Flexbox
- 'inline-flex',
- 'items-center',
-
- // Text
- 'text-decoration-none',
-
- // Transitions
- 'transition',
- 'transition-shadow',
- 'duration-200',
-
- // Shape
- 'rounded-md',
-
- // Backgrounds
- 'bg-transparent',
-
- // Focus
- 'outline-none'
- ]
- },
- number: ({ context }) => ({
- class: [
- // Flexbox
- 'flex',
- 'items-center',
- 'justify-center',
-
- // Colors (Conditional)
- context.active ? 'bg-primary-500 dark:bg-primary-400 text-surface-0 dark:text-surface-900' : 'border border-surface-200 dark:border-surface-700 text-surface-900 dark:text-surface-0', // Adjust colors as needed
-
- // Size and Shape
- 'min-w-[2rem]',
- 'h-[2rem]',
- 'line-height-[2rem]',
- 'rounded-full',
-
- // Text
- 'text-lg',
-
- // Borders
- context.active ? 'border-0 border-none' : 'border-solid border-2',
-
- // Transitions
- 'transition',
- 'transition-colors',
- 'transition-shadow',
- 'duration-200'
- ]
- }),
- title: ({ context }) => ({
- class: [
- // Layout
- 'block',
- 'whitespace-nowrap',
- 'overflow-hidden',
- 'text-ellipsis',
- 'max-w-full',
-
- // Spacing
- 'ml-2',
-
- // Text
- context.active ? 'text-surface-900 dark:text-surface-0' : 'text-surface-700 dark:text-surface-0/80',
- 'font-bold',
-
- // Transitions
- 'transition',
- 'transition-colors',
- 'transition-shadow',
- 'duration-200'
- ]
- }),
- separator: ({ context, state, parent }) => ({
- class: [
- // Colors (Conditional for active step)
- state.d_activeStep <= context.index ? 'bg-surface-200 dark:bg-surface-700' : 'bg-primary-500 dark:bg-primary-400',
-
- // Conditional for Vertical Orientation
- parent.props.orientation === 'vertical' ? ['flex-none', 'w-[2px]', 'h-auto', 'ml-[calc(1.29rem+2px)]'] : ['flex-1', 'w-full', 'h-[2px]', 'ml-4'],
-
- // Transitions
- 'transition-shadow',
- 'duration-200'
- ]
- }),
- transition: {
- class: ['flex flex-1', 'bg-surface-0 dark:bg-surface-800', 'text-surface-900 dark:text-surface-0'],
- enterFromClass: 'max-h-0',
- enterActiveClass: 'overflow-hidden transition-[max-height] duration-1000 ease-[cubic-bezier(0.42,0,0.58,1)]',
- enterToClass: 'max-h-[1000px]',
- leaveFromClass: 'max-h-[1000px]',
- leaveActiveClass: 'overflow-hidden transition-[max-height] duration-[450ms] ease-[cubic-bezier(0,1,0,1)]',
- leaveToClass: 'max-h-0'
- },
- content: ({ parent }) => ({
- class: [parent.props.orientation === 'vertical' ? 'w-full pl-4' : '']
- })
- },
- panelcontainer: {
- class: [
- // Colors
- 'bg-surface-0 dark:bg-surface-800',
- 'text-surface-900 dark:text-surface-0',
-
- // Spacing
- 'p-4'
- ]
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/steps/index.js b/frontend/packages/kwai-ui/src/presets/kwai/steps/index.js
deleted file mode 100644
index b9272691e..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/steps/index.js
+++ /dev/null
@@ -1,111 +0,0 @@
-export default {
- root: {
- class: 'relative'
- },
- menu: {
- class: 'p-0 m-0 list-none flex'
- },
- menuitem: {
- class: [
- // Flexbox and Position
- 'relative',
- 'flex',
- 'justify-center',
- 'flex-1',
- 'overflow-hidden',
-
- // Before
- 'before:border-t',
- 'before:border-surface-200',
- 'before:dark:border-surface-700',
- 'before:w-full',
- 'before:absolute',
- 'before:top-1/2',
- 'before:left-0',
- 'before:transform',
- 'before:-mt-4'
- ]
- },
- action: ({ props }) => ({
- class: [
- // Flexbox
- 'inline-flex items-center',
- 'flex-col',
-
- // Transitions and Shape
- 'transition-shadow',
- 'rounded-md',
-
- // Colors
- 'bg-surface-0',
- 'dark:bg-transparent',
-
- // States
- 'focus:outline-none focus:outline-offset-0 focus:ring',
- 'focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
-
- // Misc
- 'overflow-hidden',
- { 'cursor-pointer': !props.readonly }
- ]
- }),
- step: ({ context, props }) => ({
- class: [
- // Flexbox
- 'flex items-center justify-center',
-
- // Position
- 'z-20',
-
- // Shape
- 'rounded-full',
- 'border',
-
- // Size
- 'w-[2rem]',
- 'h-[2rem]',
- 'text-sm',
- 'leading-[2rem]',
-
- // Colors
- {
- 'text-surface-400 dark:text-white/60': !context.active,
- 'border-surface-100 dark:border-surface-700': !context.active,
- 'bg-surface-0 dark:bg-surface-800': !context.active,
- 'bg-primary-500 dark:bg-primary-400': context.active,
- 'border-primary-500 dark:border-primary-400': context.active,
- 'text-surface-0 dark:text-surface-900': context.active
- },
-
- // States
- {
- 'hover:border-surface-300 dark:hover:border-surface-500': !context.active && !props.readonly
- },
-
- // Transition
- 'transition-colors duration-200 ease-in-out'
- ]
- }),
- label: ({ context }) => ({
- class: [
- // Font
- 'leading-5',
- { 'font-bold': context.active },
-
- // Display
- 'block',
-
- // Spacing
- 'mt-2',
-
- // Colors
- { 'text-surface-400 dark:text-white/60': !context.active, 'text-surface-800 dark:text-white/80': context.active },
-
- // Text and Overflow
- 'whitespace-nowrap',
- 'overflow-hidden',
- 'overflow-ellipsis',
- 'max-w-full'
- ]
- })
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/tabmenu/index.js b/frontend/packages/kwai-ui/src/presets/kwai/tabmenu/index.js
deleted file mode 100644
index 2522382e9..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/tabmenu/index.js
+++ /dev/null
@@ -1,73 +0,0 @@
-export default {
- root: {
- class: 'overflow-x-auto'
- },
- menu: {
- class: [
- // Flexbox
- 'flex flex-1',
-
- // Spacing
- 'list-none',
- 'p-0 m-0',
-
- // Colors
- 'bg-surface-0 dark:bg-surface-800',
- 'border-b-2 border-surface-200 dark:border-surface-700',
- 'text-surface-900 dark:text-surface-0/80'
- ]
- },
- menuitem: {
- class: 'mr-0'
- },
- action: ({ context, state }) => ({
- class: [
- 'relative',
-
- // Font
- 'font-bold',
-
- // Flexbox and Alignment
- 'flex items-center',
-
- // Spacing
- 'p-5',
- '-mb-[2px]',
-
- // Shape
- 'border-b-2',
- 'rounded-t-md',
-
- // Colors and Conditions
- {
- 'border-surface-200 dark:border-surface-700': state.d_activeIndex !== context.index,
- 'bg-surface-0 dark:bg-surface-800': state.d_activeIndex !== context.index,
- 'text-surface-700 dark:text-surface-0/80': state.d_activeIndex !== context.index,
-
- 'bg-surface-0 dark:bg-surface-800': state.d_activeIndex === context.index,
- 'border-primary-500 dark:border-primary-400': state.d_activeIndex === context.index,
- 'text-primary-500 dark:text-primary-400': state.d_activeIndex === context.index
- },
-
- // States
- 'focus-visible:outline-none focus-visible:outline-offset-0 focus-visible:ring focus-visible:ring-inset',
- 'focus-visible:ring-primary-400/50 dark:focus-visible:ring-primary-300/50',
- {
- 'hover:bg-surface-0 dark:hover:bg-surface-800/80': state.d_activeIndex !== context.index,
- 'hover:border-surface-400 dark:hover:border-primary-400': state.d_activeIndex !== context.index,
- 'hover:text-surface-900 dark:hover:text-surface-0': state.d_activeIndex !== context.index
- },
-
- // Transitions
- 'transition-all duration-200',
-
- // Misc
- 'cursor-pointer select-none text-decoration-none',
- 'overflow-hidden',
- 'user-select-none'
- ]
- }),
- icon: {
- class: 'mr-2'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/tabview/index.js b/frontend/packages/kwai-ui/src/presets/kwai/tabview/index.js
deleted file mode 100644
index 20b19b083..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/tabview/index.js
+++ /dev/null
@@ -1,156 +0,0 @@
-export default {
- navContainer: ({ props }) => ({
- class: [
- // Position
- 'relative',
-
- // Misc
- { 'overflow-hidden': props.scrollable }
- ]
- }),
- navContent: {
- class: [
- // Overflow and Scrolling
- 'overflow-y-hidden overscroll-contain',
- 'overscroll-auto',
- 'scroll-smooth',
- '[&::-webkit-scrollbar]:hidden'
- ]
- },
- previousButton: {
- class: [
- // Flexbox and Alignment
- 'flex items-center justify-center',
-
- // Position
- '!absolute',
- 'top-0 left-0',
- 'z-20',
-
- // Size and Shape
- 'h-full w-12',
- 'rounded-none',
-
- // Colors
- 'bg-surface-0 dark:bg-surface-800',
- 'text-primary-500 dark:text-primary-400',
- 'shadow-md'
- ]
- },
- nextButton: {
- class: [
- // Flexbox and Alignment
- 'flex items-center justify-center',
-
- // Position
- '!absolute',
- 'top-0 right-0',
- 'z-20',
-
- // Size and Shape
- 'h-full w-12',
- 'rounded-none',
-
- // Colors
- 'bg-surface-0 dark:bg-surface-800',
- 'text-primary-500 dark:text-primary-400',
- 'shadow-md'
- ]
- },
- nav: {
- class: [
- // Flexbox
- 'flex flex-1',
-
- // Spacing
- 'list-none',
- 'p-0 m-0',
-
- // Colors
- 'bg-surface-0 dark:bg-surface-800',
- 'border-b-2 border-surface-200 dark:border-surface-700',
- 'text-surface-900 dark:text-surface-0/80'
- ]
- },
- tabpanel: {
- header: ({ props }) => ({
- class: [
- // Spacing
- 'mr-0',
-
- // Misc
- {
- 'opacity-60 cursor-default user-select-none select-none pointer-events-none': props?.disabled
- }
- ]
- }),
- headerAction: ({ parent, context }) => ({
- class: [
- 'relative',
-
- // Font
- 'font-bold',
-
- // Flexbox and Alignment
- 'flex items-center',
-
- // Spacing
- 'p-5',
- '-mb-[2px]',
-
- // Shape
- 'border-b-2',
- 'rounded-t-md',
-
- // Colors and Conditions
- {
- 'border-surface-200 dark:border-surface-700': parent.state.d_activeIndex !== context.index,
- 'bg-surface-0 dark:bg-surface-800': parent.state.d_activeIndex !== context.index,
- 'text-surface-700 dark:text-surface-0/80': parent.state.d_activeIndex !== context.index,
-
- 'bg-surface-0 dark:bg-surface-800': parent.state.d_activeIndex === context.index,
- 'border-primary-500 dark:border-primary-400': parent.state.d_activeIndex === context.index,
- 'text-primary-500 dark:text-primary-400': parent.state.d_activeIndex === context.index
- },
-
- // States
- 'focus-visible:outline-none focus-visible:outline-offset-0 focus-visible:ring focus-visible:ring-inset',
- 'focus-visible:ring-primary-400/50 dark:focus-visible:ring-primary-300/50',
- {
- 'hover:bg-surface-0 dark:hover:bg-surface-800/80': parent.state.d_activeIndex !== context.index,
- 'hover:border-surface-400 dark:hover:border-primary-400': parent.state.d_activeIndex !== context.index,
- 'hover:text-surface-900 dark:hover:text-surface-0': parent.state.d_activeIndex !== context.index
- },
-
- // Transitions
- 'transition-all duration-200',
-
- // Misc
- 'cursor-pointer select-none text-decoration-none',
- 'overflow-hidden',
- 'user-select-none'
- ]
- }),
- headerTitle: {
- class: [
- // Text
- 'leading-none',
- 'whitespace-nowrap'
- ]
- },
- content: {
- class: [
- // Spacing
- 'p-5',
-
- // Shape
- 'rounded-b-md',
-
- // Colors
- 'bg-surface-0 dark:bg-surface-800',
- 'text-surface-700 dark:text-surface-0/80',
- 'border-0'
- ]
- }
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/tag/index.js b/frontend/packages/kwai-ui/src/presets/kwai/tag/index.js
deleted file mode 100644
index 4c7a73962..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/tag/index.js
+++ /dev/null
@@ -1,36 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- //Font
- 'text-xs font-bold',
-
- //Alignments
- 'inline-flex items-center justify-center',
-
- //Spacing
- 'px-2 py-1',
-
- //Shape
- {
- 'rounded-md': !props.rounded,
- 'rounded-full': props.rounded
- },
-
- //Colors
- 'text-white dark:text-surface-900',
- {
- 'bg-primary-500 dark:bg-primary-400': props.severity == null || props.severity == 'primary',
- 'bg-green-500 dark:bg-green-400': props.severity == 'success',
- 'bg-blue-500 dark:bg-blue-400': props.severity == 'info',
- 'bg-orange-500 dark:bg-orange-400': props.severity == 'warning',
- 'bg-red-500 dark:bg-red-400': props.severity == 'danger'
- }
- ]
- }),
- value: {
- class: 'leading-normal'
- },
- icon: {
- class: 'mr-1 text-sm'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/terminal/index.js b/frontend/packages/kwai-ui/src/presets/kwai/terminal/index.js
deleted file mode 100644
index 3fbd652b5..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/terminal/index.js
+++ /dev/null
@@ -1,60 +0,0 @@
-export default {
- root: {
- class: [
- // Spacing
- 'p-5',
-
- // Shape
- 'rounded-md',
-
- // Color
- 'bg-surface-900 text-white',
- 'border border-surface-700',
-
- // Sizing & Overflow
- 'h-72 overflow-auto'
- ]
- },
- container: {
- class: [
- // Flexbox
- 'flex items-center'
- ]
- },
- prompt: {
- class: [
- // Color
- 'text-surface-400'
- ]
- },
- response: {
- class: [
- // Color
- 'text-primary-400'
- ]
- },
- command: {
- class: [
- // Color
- 'text-primary-400'
- ]
- },
- commandtext: {
- class: [
- // Flexbox
- 'flex-1 shrink grow-0',
-
- // Shape
- 'border-0',
-
- // Spacing
- 'p-0',
-
- // Color
- 'bg-transparent text-inherit',
-
- // Outline
- 'outline-none'
- ]
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/textarea/index.js b/frontend/packages/kwai-ui/src/presets/kwai/textarea/index.js
deleted file mode 100644
index 9b08011cf..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/textarea/index.js
+++ /dev/null
@@ -1,36 +0,0 @@
-export default {
- root: ({ context, props }) => ({
- class: [
- // Font
- 'font-sans leading-none',
-
- // Spacing
- 'm-0',
- 'p-3',
-
- // Shape
- 'rounded-md',
-
- // Colors
- 'text-surface-600 dark:text-surface-200',
- 'placeholder:text-surface-400 dark:placeholder:text-surface-500',
- 'bg-surface-0 dark:bg-surface-900',
- 'border',
- { 'border-surface-300 dark:border-surface-600': !props.invalid },
-
- // Invalid State
- { 'border-red-500 dark:border-red-400': props.invalid },
-
- // States
- {
- 'hover:border-primary-500 dark:hover:border-primary-400': !context.disabled && !props.invalid,
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-500/50 dark:focus:ring-primary-400/50': !context.disabled,
- 'opacity-60 select-none pointer-events-none cursor-default': context.disabled
- },
-
- // Misc
- 'appearance-none',
- 'transition-colors duration-200'
- ]
- })
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/tieredmenu/index.js b/frontend/packages/kwai-ui/src/presets/kwai/tieredmenu/index.js
deleted file mode 100644
index d16e1594b..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/tieredmenu/index.js
+++ /dev/null
@@ -1,120 +0,0 @@
-export default {
- root: {
- class: [
- // Shape
- 'rounded-md',
-
- // Size
- 'min-w-[12rem]',
- 'py-1',
-
- // Colors
- 'bg-surface-0 dark:bg-surface-700',
- 'border border-surface-200 dark:border-surface-700'
- ]
- },
- menu: {
- class: [
- // Spacings and Shape
- 'list-none',
- 'm-0',
- 'p-0',
- 'outline-none'
- ]
- },
- menuitem: {
- class: [
- // Position
- 'relative'
- ]
- },
- content: ({ context }) => ({
- class: [
- //Shape
- 'rounded-none',
-
- // Colors
- {
- 'text-surface-500 dark:text-white/70': !context.focused && !context.active,
- 'text-surface-500 dark:text-white/70 bg-surface-200 dark:bg-surface-600/90': context.focused && !context.active,
- 'text-primary-700 dark:text-surface-0/80 bg-primary-50 dark:bg-primary-400/30': context.focused && context.active,
- 'text-primary-700 dark:text-surface-0/80 bg-primary-50 dark:bg-primary-400/30': !context.focused && context.active
- },
-
- // Hover States
- {
- 'hover:bg-surface-100 dark:hover:bg-surface-600/80': !context.active,
- 'hover:bg-primary-500/50 dark:hover:bg-primary-300/30 text-primary-700 dark:text-surface-0/80': context.active
- },
-
- // Transitions
- 'transition-shadow',
- 'duration-200'
- ]
- }),
- action: {
- class: [
- 'relative',
- // Flexbox
-
- 'flex',
- 'items-center',
-
- // Spacing
- 'py-3',
- 'px-5',
-
- // Color
- 'text-surface-700 dark:text-white/80',
-
- // Misc
- 'no-underline',
- 'overflow-hidden',
- 'cursor-pointer',
- 'select-none'
- ]
- },
- icon: {
- class: [
- // Spacing
- 'mr-2',
-
- // Color
- 'text-surface-600 dark:text-white/70'
- ]
- },
- label: {
- class: ['leading-none']
- },
- submenuicon: {
- class: [
- // Position
- 'ml-auto'
- ]
- },
- submenu: {
- class: [
- // Size
- 'w-full sm:w-48',
-
- // Spacing
- 'py-1',
- 'm-0',
- 'list-none',
-
- // Shape
- 'shadow-none sm:shadow-md',
- 'border-0',
-
- // Position
- 'static sm:absolute',
- 'z-10',
-
- // Color
- 'bg-surface-0 dark:bg-surface-700'
- ]
- },
- separator: {
- class: 'border-t border-surface-200 dark:border-surface-600 my-1'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/timeline/index.js b/frontend/packages/kwai-ui/src/presets/kwai/timeline/index.js
deleted file mode 100644
index b037b738a..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/timeline/index.js
+++ /dev/null
@@ -1,81 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- 'flex grow',
- {
- 'flex-col': props.layout === 'vertical',
- 'flex-row flex-1': props.layout === 'horizontal'
- }
- ]
- }),
- event: ({ props, context }) => ({
- class: [
- 'flex relative min-h-[70px]',
- {
- 'flex-row-reverse': props.align === 'right' || (props.layout === 'vertical' && props.align === 'alternate' && context.index % 2 === 1),
- 'flex-col flex-1': props.layout === 'horizontal',
- 'flex-col-reverse ': props.align === 'bottom' || (props.layout === 'horizontal' && props.align === 'alternate' && context.index % 2 === 1)
- }
- ]
- }),
- opposite: ({ props, context }) => ({
- class: [
- 'flex-1',
- {
- 'px-4': props.layout === 'vertical',
- 'py-4': props.layout === 'horizontal'
- },
- {
- 'text-right': props.align === 'left' || (props.layout === 'vertical' && props.align === 'alternate' && context.index % 2 === 0),
- 'text-left': props.align === 'right' || (props.layout === 'vertical' && props.align === 'alternate' && context.index % 2 === 1)
- }
- ]
- }),
- separator: ({ props }) => ({
- class: [
- 'flex items-center flex-initial',
- {
- 'flex-col': props.layout === 'vertical',
- 'flex-row': props.layout === 'horizontal'
- }
- ]
- }),
- marker: {
- class: [
- // Display & Flexbox
- 'flex self-baseline',
-
- // Size
- 'w-4 h-4',
-
- // Appearance
- 'rounded-full border-2 border-primary-500 bg-surface-0 dark:border-primary-300 dark:bg-surface-900/40'
- ]
- },
- connector: ({ props }) => ({
- class: [
- 'grow bg-surface-300 dark:bg-surface-700',
- {
- 'w-[2px]': props.layout === 'vertical',
- 'w-full h-[2px]': props.layout === 'horizontal'
- }
- ]
- }),
- content: ({ props, context }) => ({
- class: [
- 'flex-1',
- {
- 'px-4': props.layout === 'vertical',
- 'py-4': props.layout === 'horizontal'
- },
- {
- 'text-left': props.align === 'left' || (props.layout === 'vertical' && props.align === 'alternate' && context.index % 2 === 0),
- 'text-right': props.align === 'right' || (props.layout === 'vertical' && props.align === 'alternate' && context.index % 2 === 1)
- },
- {
- 'min-h-0': props.layout === 'vertical' && context.index === context.count,
- 'grow-0': props.layout === 'horizontal' && context.index === context.count
- }
- ]
- })
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/toast/index.js b/frontend/packages/kwai-ui/src/presets/kwai/toast/index.js
deleted file mode 100644
index 01a4e07b4..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/toast/index.js
+++ /dev/null
@@ -1,102 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- //Size and Shape
- 'w-96 rounded-md',
-
- // Positioning
- { '-translate-x-2/4': props.position == 'top-center' || props.position == 'bottom-center' }
- ]
- }),
- container: ({ props }) => ({
- class: [
- 'my-4 rounded-md w-full',
- 'border-solid border-0 border-l-[6px]',
- 'backdrop-blur-[10px] shadow-md',
-
- // Colors
- {
- 'bg-blue-100/70 dark:bg-blue-500/20': props.message.severity == 'info',
- 'bg-green-100/70 dark:bg-green-500/20': props.message.severity == 'success',
- 'bg-orange-100/70 dark:bg-orange-500/20': props.message.severity == 'warn',
- 'bg-red-100/70 dark:bg-red-500/20': props.message.severity == 'error'
- },
- {
- 'border-blue-500 dark:border-blue-400': props.message.severity == 'info',
- 'border-green-500 dark:border-green-400': props.message.severity == 'success',
- 'border-orange-500 dark:border-orange-400': props.message.severity == 'warn',
- 'border-red-500 dark:border-red-400': props.message.severity == 'error'
- },
- {
- 'text-blue-700 dark:text-blue-300': props.message.severity == 'info',
- 'text-green-700 dark:text-green-300': props.message.severity == 'success',
- 'text-orange-700 dark:text-orange-300': props.message.severity == 'warn',
- 'text-red-700 dark:text-red-300': props.message.severity == 'error'
- }
- ]
- }),
- content: ({ props }) => ({
- class: [
- 'flex p-4',
- {
- 'items-start': props.message.summary,
- 'items-center': !props.message.summary,
- },
- ],
- }),
- icon: {
- class: [
- // Sizing and Spacing
- 'w-6 h-6',
- 'text-lg leading-none mr-2 shrink-0'
- ]
- },
- text: {
- class: [
- // Font and Text
- 'text-base leading-none',
- 'ml-2',
- 'flex-1'
- ]
- },
- summary: {
- class: 'font-bold block'
- },
- detail: ({ props }) => ({
- class: ['block', { 'mt-2': props.message.summary }],
- }),
- closebutton: {
- class: [
- // Flexbox
- 'flex items-center justify-center',
-
- // Size
- 'w-8 h-8',
-
- // Spacing and Misc
- 'ml-auto relative',
-
- // Shape
- 'rounded-full',
-
- // Colors
- 'bg-transparent',
-
- // Transitions
- 'transition duration-200 ease-in-out',
-
- // States
- 'hover:bg-surface-0/50 dark:hover:bg-surface-0/10',
-
- // Misc
- 'overflow-hidden'
- ]
- },
- transition: {
- enterFromClass: 'opacity-0 translate-y-2/4',
- enterActiveClass: 'transition-[transform,opacity] duration-300',
- leaveFromClass: 'max-h-[1000px]',
- leaveActiveClass: '!transition-[max-height_.45s_cubic-bezier(0,1,0,1),opacity_.3s,margin-bottom_.3s] overflow-hidden',
- leaveToClass: 'max-h-0 opacity-0 mb-0'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/togglebutton/index.js b/frontend/packages/kwai-ui/src/presets/kwai/togglebutton/index.js
deleted file mode 100644
index 592c3638f..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/togglebutton/index.js
+++ /dev/null
@@ -1,91 +0,0 @@
-export default {
- root: {
- class: [
- 'relative',
-
- // Alignment
- 'inline-flex',
- 'align-bottom',
-
- // Misc
- 'cursor-pointer',
- 'select-none'
- ]
- },
- box: ({ props }) => ({
- class: [
- // Alignments
- 'items-center inline-flex flex-1 text-center align-bottom justify-center',
-
- // Sizes & Spacing
- 'px-4 py-3 leading-none',
-
- // Shapes
- 'rounded-md border',
-
- // Colors
- {
- 'bg-surface-0 dark:bg-surface-900 ': !props.modelValue,
- 'border-surface-200 dark:border-surface-700 ': !props.modelValue && !props.invalid,
- 'text-surface-700 dark:text-white/80': !props.modelValue,
- 'bg-primary-500 dark:bg-primary-400 border-primary-500 dark:border-primary-400 text-white dark:text-surface-900': props.modelValue
- },
-
- // Invalid State
- { 'border-red-500 dark:border-red-400': props.invalid },
-
- // States
- {
- 'peer-hover:bg-surface-50 dark:peer-hover:bg-surface-800/80 peer-hover:border-surface-200 dark:peer-hover:bg-surface-700 peer-hover:text-surface-700 dark:peer-hover:text-white/80': !props.modelValue && !props.invalid,
- 'peer-hover:bg-primary-600 peer-hover:border-primary-600 dark:peer-hover:bg-primary-300 dark:peer-hover:border-primary-300': props.modelValue,
- 'peer-focus-visible:ring peer-focus-visible:ring-primary-400/50 dark:peer-focus-visible:ring-primary-300/50': !props.disabled
- },
-
- // Transitions
- 'transition-all duration-200',
-
- // Misc
- { 'cursor-pointer': !props.disabled, 'opacity-60 select-none pointer-events-none cursor-default': props.disabled }
- ]
- }),
- label: {
- class: 'font-bold text-center w-full'
- },
- input: {
- class: [
- 'peer',
-
- // Size
- 'w-full ',
- 'h-full',
-
- // Position
- 'absolute',
- 'top-0 left-0',
- 'z-10',
-
- // Spacing
- 'p-0',
- 'm-0',
-
- // Shape
- 'opacity-0',
- 'rounded-md',
- 'outline-none',
- 'border border-surface-200 dark:border-surface-700',
-
- // Misc
- 'appearance-none',
- 'cursor-pointer'
- ]
- },
- icon: ({ props }) => ({
- class: [
- ' mr-2',
- {
- 'text-surface-600 dark:text-white/70': !props.modelValue,
- 'text-white dark:text-surface-900': props.modelValue
- }
- ]
- })
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/toolbar/index.js b/frontend/packages/kwai-ui/src/presets/kwai/toolbar/index.js
deleted file mode 100644
index 4232baad4..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/toolbar/index.js
+++ /dev/null
@@ -1,28 +0,0 @@
-export default {
- root: {
- class: [
- // Flex & Alignment
- 'flex items-center justify-between flex-wrap',
- 'gap-2',
-
- // Spacing
- 'p-5',
-
- // Shape
- 'rounded-md',
-
- // Color
- 'bg-surface-50 dark:bg-surface-800',
- 'border border-surface-200 dark:border-surface-700'
- ]
- },
- start: {
- class: 'flex items-center'
- },
- center: {
- class: 'flex items-center'
- },
- end: {
- class: 'flex items-center'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/tooltip/index.js b/frontend/packages/kwai-ui/src/presets/kwai/tooltip/index.js
deleted file mode 100644
index 2856bf3b6..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/tooltip/index.js
+++ /dev/null
@@ -1,46 +0,0 @@
-export default {
- root: ({ context, props }) => ({
- class: [
- // Position and Shadows
- 'absolute',
- 'shadow-md',
- 'p-fadein',
- // Spacing
- {
- 'py-0 px-1': context?.right || context?.left || (!context?.right && !context?.left && !context?.top && !context?.bottom),
- 'py-1 px-0': context?.top || context?.bottom
- }
- ]
- }),
- arrow: ({ context, props }) => ({
- class: [
- // Position
-
- 'absolute',
-
- // Size
- 'w-0',
- 'h-0',
-
- // Shape
- 'border-transparent',
- 'border-solid',
- {
- 'border-y-[0.25rem] border-r-[0.25rem] border-l-0 border-r-surface-600': context?.right || (!context?.right && !context?.left && !context?.top && !context?.bottom),
- 'border-y-[0.25rem] border-l-[0.25rem] border-r-0 border-l-surface-600': context?.left,
- 'border-x-[0.25rem] border-t-[0.25rem] border-b-0 border-t-surface-600': context?.top,
- 'border-x-[0.25rem] border-b-[0.25rem] border-t-0 border-b-surface-600': context?.bottom
- },
-
- // Spacing
- {
- '-mt-1 ': context?.right || (!context?.right && !context?.left && !context?.top && !context?.bottom),
- '-mt-1': context?.left,
- '-ml-1': context?.top || context?.bottom
- }
- ]
- }),
- text: {
- class: ['p-3', 'bg-surface-600 dark:bg-surface-700', 'text-white', 'leading-none', 'rounded-md', 'whitespace-pre-line', 'break-words']
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/tree/index.js b/frontend/packages/kwai-ui/src/presets/kwai/tree/index.js
deleted file mode 100644
index 28eb56b8d..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/tree/index.js
+++ /dev/null
@@ -1,258 +0,0 @@
-export default {
- root: {
- class: [
- // Space
- 'p-5',
-
- // Shape
- 'rounded-md',
-
- // Color
- 'bg-surface-0 dark:bg-surface-800',
- 'text-surface-700 dark:text-white/80',
- 'border border-solid border-surface-200 dark:border-surface-700'
- ]
- },
- wrapper: {
- class: ['overflow-auto']
- },
- container: {
- class: [
- // Spacing
- 'm-0 p-0',
-
- // Misc
- 'list-none overflow-auto'
- ]
- },
- node: {
- class: ['p-1', 'rounded-md', 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-inset focus:ring-primary-400/50 dark:focus:ring-primary-300/50']
- },
- content: ({ context, props }) => ({
- class: [
- // Flex and Alignment
- 'flex items-center',
-
- // Shape
- 'rounded-md',
-
- // Spacing
- 'p-2',
-
- // Colors
- 'text-surface-600 dark:text-white/70',
- { 'bg-primary-50 dark:bg-primary-400/30 text-primary-600 dark:text-surface-0': context.selected },
-
- // States
- { 'hover:bg-surface-50 dark:hover:bg-surface-700/40': (props.selectionMode == 'single' || props.selectionMode == 'multiple') && !context.selected },
-
- // Transition
- 'transition-shadow duration-200',
-
- { 'cursor-pointer select-none': props.selectionMode == 'single' || props.selectionMode == 'multiple' }
- ]
- }),
- toggler: ({ context }) => ({
- class: [
- // Flex and Alignment
- 'inline-flex items-center justify-center',
-
- // Shape
- 'border-0 rounded-full',
-
- // Size
- 'w-8 h-8',
-
- // Spacing
- 'mr-2',
-
- // Colors
- 'bg-transparent',
- {
- 'text-surface-500 dark:text-white': !context.selected,
- 'text-primary-600 dark:text-white': context.selected,
- invisible: context.leaf
- },
-
- // States
- 'hover:bg-surface-200/20 dark:hover:bg-surface-500/20',
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
-
- // Transition
- 'transition duration-200',
-
- // Misc
- 'cursor-pointer select-none'
- ]
- }),
- nodeCheckbox: ({ props, context, instance }) => ({
- root: {
- class: [
- 'relative',
-
- // Alignment
- 'inline-flex',
- 'align-bottom',
-
- // Size
- 'w-6',
- 'h-6',
-
- // Spacing
- 'mr-2',
-
- // Misc
- 'cursor-pointer',
- 'select-none'
- ]
- },
- box: {
- class: [
- // Alignment
- 'flex',
- 'items-center',
- 'justify-center',
-
- // Size
- 'w-6',
- 'h-6',
-
- // Shape
- 'rounded-md',
- 'border-2',
-
- // Colors
- {
- 'border-surface-200 bg-surface-0 dark:border-surface-700 dark:bg-surface-900': !context.checked,
- 'border-primary-500 bg-primary-500 dark:border-primary-400 dark:bg-primary-400': context.checked
- },
-
- // States
- {
- 'peer-hover:border-primary-500 dark:peer-hover:border-primary-400': !props.disabled && !context.checked,
- 'peer-hover:bg-primary-600 dark:peer-hover:bg-primary-300 peer-hover:border-primary-700 dark:peer-hover:border-primary-300': !props.disabled && context.checked,
- 'peer-focus-visible:border-primary-500 dark:peer-focus-visible:border-primary-400 peer-focus-visible:ring-2 peer-focus-visible:ring-primary-400/20 dark:peer-focus-visible:ring-primary-300/20': !props.disabled,
- 'cursor-default opacity-60': props.disabled
- },
-
- // Transitions
- 'transition-colors',
- 'duration-200'
- ]
- },
- input: {
- class: [
- 'peer',
-
- // Size
- 'w-full ',
- 'h-full',
-
- // Position
- 'absolute',
- 'top-0 left-0',
- 'z-10',
-
- // Spacing
- 'p-0',
- 'm-0',
-
- // Shape
- 'opacity-0',
- 'rounded-md',
- 'outline-none',
- 'border-2 border-surface-200 dark:border-surface-700',
-
- // Misc
- 'appearance-none',
- 'cursor-pointer'
- ]
- },
- icon: {
- class: [
- // Font
- 'text-base leading-none',
-
- // Size
- 'w-4',
- 'h-4',
-
- // Colors
- {
- 'text-white dark:text-surface-900': !instance.partialChecked,
- 'text-gray dark:text-white': instance.partialChecked
- },
-
- // Transitions
- 'transition-all',
- 'duration-200'
- ]
- }
- }),
- nodeicon: {
- class: [
- // Space
- 'mr-2',
-
- // Color
- 'text-surface-600 dark:text-white/70'
- ]
- },
- subgroup: {
- class: ['m-0 list-none p-0 pl-2 mt-1']
- },
- filtercontainer: {
- class: [
- 'relative block',
-
- // Space
- 'mb-2',
-
- // Size
- 'w-full'
- ]
- },
- input: {
- class: [
- 'relative',
- // Font
- 'font-sans leading-none',
-
- // Spacing
- 'm-0',
- 'p-3 pr-10',
-
- // Size
- 'w-full',
-
- // Shape
- 'rounded-md',
-
- // Colors
- 'text-surface-600 dark:text-surface-200',
- 'placeholder:text-surface-400 dark:placeholder:text-surface-500',
- 'bg-surface-0 dark:bg-surface-900',
- 'border border-surface-300 dark:border-surface-600',
-
- // States
- 'hover:border-primary-500 dark:hover:border-primary-400',
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-500/50 dark:focus:ring-primary-400/50',
-
- // Transition & Misc
- 'appearance-none',
- 'transition-colors duration-200'
- ]
- },
- loadingicon: {
- class: ['text-surface-500 dark:text-surface-0/70', 'absolute top-[50%] right-[50%] -mt-2 -mr-2 animate-spin']
- },
- searchicon: {
- class: [
- // Position
- 'absolute top-1/2 -mt-2 right-3',
-
- // Color
- 'text-surface-600 dark:hover:text-white/70'
- ]
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/treeselect/index.js b/frontend/packages/kwai-ui/src/presets/kwai/treeselect/index.js
deleted file mode 100644
index d1e9628c2..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/treeselect/index.js
+++ /dev/null
@@ -1,352 +0,0 @@
-export default {
- root: ({ props, state }) => ({
- class: [
- // Display and Position
- 'inline-flex',
- 'relative',
-
- // Shape
- 'rounded-md',
-
- // Color and Background
- 'bg-surface-0 dark:bg-surface-900',
- 'border',
- { 'border-surface-300 dark:border-surface-600': !props.invalid },
-
- // Invalid State
- { 'border-red-500 dark:border-red-400': props.invalid },
-
- // Transitions
- 'transition-all',
- 'duration-200',
-
- // States
- { 'hover:border-primary-500 dark:hover:border-primary-300': !props.invalid },
- { 'outline-none outline-offset-0 ring ring-primary-400/50 dark:ring-primary-300/50': state.focused },
-
- // Misc
- 'cursor-pointer',
- 'select-none',
- { 'opacity-60': props.disabled, 'pointer-events-none': props.disabled, 'cursor-default': props.disabled }
- ]
- }),
- labelContainer: {
- class: ['overflow-hidden flex flex-auto cursor-pointer']
- },
- label: {
- class: [
- 'block leading-5',
-
- // Space
- 'p-3',
-
- // Color
- 'text-surface-800 dark:text-white/80',
-
- // Transition
- 'transition duration-200',
-
- // Misc
- 'overflow-hidden whitespace-nowrap cursor-pointer overflow-ellipsis'
- ]
- },
- trigger: {
- class: [
- // Flexbox
- 'flex items-center justify-center',
- 'shrink-0',
-
- // Color and Background
- 'bg-transparent',
- 'text-surface-500',
-
- // Size
- 'w-12',
-
- // Shape
- 'rounded-tr-md',
- 'rounded-br-md'
- ]
- },
- panel: {
- class: [
- // Position
- 'absolute top-0 left-0',
-
- // Shape
- 'border-0 dark:border',
- 'rounded-md',
- 'shadow-md',
-
- // Color
- 'bg-surface-0 dark:bg-surface-800',
- 'text-surface-800 dark:text-white/80',
- 'dark:border-surface-700'
- ]
- },
- wrapper: {
- class: [
- // Sizing
- 'max-h-[200px]',
-
- // Misc
- 'overflow-auto'
- ]
- },
- tree: {
- root: {
- class: [
- // Space
- 'p-5'
- ]
- },
- wrapper: {
- class: ['overflow-auto']
- },
- container: {
- class: [
- // Spacing
- 'm-0 p-0',
-
- // Misc
- 'list-none overflow-auto'
- ]
- },
- node: {
- class: ['p-1', 'rounded-md', 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-inset focus:ring-primary-400/50 dark:focus:ring-primary-300/50']
- },
- content: ({ context, props }) => ({
- class: [
- // Flex and Alignment
- 'flex items-center',
-
- // Shape
- 'rounded-md',
-
- // Spacing
- 'p-2',
-
- // Colors
- 'text-surface-600 dark:text-white/70',
- { 'bg-primary-50 dark:bg-primary-400/30 text-primary-600 dark:text-surface-0': context.selected },
-
- // States
- { 'hover:bg-surface-50 dark:hover:bg-surface-700/40': (props.selectionMode == 'single' || props.selectionMode == 'multiple') && !context.selected },
-
- // Transition
- 'transition-shadow duration-200',
-
- { 'cursor-pointer select-none': props.selectionMode == 'single' || props.selectionMode == 'multiple' }
- ]
- }),
- toggler: ({ context }) => ({
- class: [
- // Flex and Alignment
- 'inline-flex items-center justify-center',
-
- // Shape
- 'border-0 rounded-full',
-
- // Size
- 'w-8 h-8',
-
- // Spacing
- 'mr-2',
-
- // Colors
- 'bg-transparent',
- {
- 'text-surface-500 dark:text-white': !context.selected,
- 'text-primary-600 dark:text-white': context.selected,
- invisible: context.leaf
- },
-
- // States
- 'hover:bg-surface-200/20 dark:hover:bg-surface-500/20',
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 dark:focus:ring-primary-300/50',
-
- // Transition
- 'transition duration-200',
-
- // Misc
- 'cursor-pointer select-none'
- ]
- }),
- nodeCheckbox: ({ props, context, instance }) => ({
- root: {
- class: [
- 'relative',
-
- // Alignment
- 'inline-flex',
- 'align-bottom',
-
- // Size
- 'w-6',
- 'h-6',
-
- // Spacing
- 'mr-2',
-
- // Misc
- 'cursor-pointer',
- 'select-none'
- ]
- },
- box: {
- class: [
- // Alignment
- 'flex',
- 'items-center',
- 'justify-center',
-
- // Size
- 'w-6',
- 'h-6',
-
- // Shape
- 'rounded-md',
- 'border-2',
-
- // Colors
- {
- 'border-surface-200 bg-surface-0 dark:border-surface-700 dark:bg-surface-900': !context.checked,
- 'border-primary-500 bg-primary-500 dark:border-primary-400 dark:bg-primary-400': context.checked
- },
-
- // States
- {
- 'peer-hover:border-primary-500 dark:peer-hover:border-primary-400': !props.disabled && !context.checked,
- 'peer-hover:bg-primary-600 dark:peer-hover:bg-primary-300 peer-hover:border-primary-700 dark:peer-hover:border-primary-300': !props.disabled && context.checked,
- 'peer-focus-visible:border-primary-500 dark:peer-focus-visible:border-primary-400 peer-focus-visible:ring-2 peer-focus-visible:ring-primary-400/20 dark:peer-focus-visible:ring-primary-300/20': !props.disabled,
- 'cursor-default opacity-60': props.disabled
- },
-
- // Transitions
- 'transition-colors',
- 'duration-200'
- ]
- },
- input: {
- class: [
- 'peer',
-
- // Size
- 'w-full ',
- 'h-full',
-
- // Position
- 'absolute',
- 'top-0 left-0',
- 'z-10',
-
- // Spacing
- 'p-0',
- 'm-0',
-
- // Shape
- 'opacity-0',
- 'rounded-md',
- 'outline-none',
- 'border-2 border-surface-200 dark:border-surface-700',
-
- // Misc
- 'appearance-none',
- 'cursor-pointer'
- ]
- },
- icon: {
- class: [
- // Font
- 'text-base leading-none',
-
- // Size
- 'w-4',
- 'h-4',
-
- // Colors
- {
- 'text-white dark:text-surface-900': !instance.partialChecked,
- 'text-gray dark:text-white': instance.partialChecked
- },
-
- // Transitions
- 'transition-all',
- 'duration-200'
- ]
- }
- }),
- nodeicon: {
- class: [
- // Space
- 'mr-2',
-
- // Color
- 'text-surface-600 dark:text-white/70'
- ]
- },
- subgroup: {
- class: ['m-0 list-none p-0 pl-2 mt-1']
- },
- filtercontainer: {
- class: [
- 'relative block',
-
- // Space
- 'mb-2',
-
- // Size
- 'w-full'
- ]
- },
- input: {
- class: [
- 'relative',
- // Font
- 'font-sans leading-none',
-
- // Spacing
- 'm-0',
- 'p-3 pr-10',
-
- // Size
- 'w-full',
-
- // Shape
- 'rounded-md',
-
- // Colors
- 'text-surface-600 dark:text-surface-200',
- 'placeholder:text-surface-400 dark:placeholder:text-surface-500',
- 'bg-surface-0 dark:bg-surface-900',
- 'border border-surface-300 dark:border-surface-600',
-
- // States
- 'hover:border-primary-500 dark:hover:border-primary-400',
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-500/50 dark:focus:ring-primary-400/50',
-
- // Transition & Misc
- 'appearance-none',
- 'transition-colors duration-200'
- ]
- },
- loadingicon: {
- class: ['text-surface-500 dark:text-surface-0/70', 'absolute top-[50%] right-[50%] -mt-2 -mr-2 animate-spin']
- },
- searchicon: {
- class: [
- // Position
- 'absolute top-1/2 -mt-2 right-3',
-
- // Color
- 'text-surface-600 dark:hover:text-white/70'
- ]
- }
- },
- transition: {
- enterFromClass: 'opacity-0 scale-y-[0.8]',
- enterActiveClass: 'transition-[transform,opacity] duration-[120ms] ease-[cubic-bezier(0,0,0.2,1)]',
- leaveActiveClass: 'transition-opacity duration-100 ease-linear',
- leaveToClass: 'opacity-0'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/treetable/index.js b/frontend/packages/kwai-ui/src/presets/kwai/treetable/index.js
deleted file mode 100644
index 2a493c100..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/treetable/index.js
+++ /dev/null
@@ -1,434 +0,0 @@
-export default {
- root: ({ props }) => ({
- class: [
- 'relative',
- {
- 'flex flex-col h-full': props.scrollHeight === 'flex'
- }
- ]
- }),
- loadingoverlay: {
- class: [
- // Position
- 'absolute',
- 'top-0 left-0',
- 'z-20',
-
- // Flex & Alignment
- 'flex items-center justify-center',
-
- // Size
- 'w-full h-full',
-
- // Color
- 'bg-surface-100/40 dark:bg-surface-800/40',
-
- // Transition
- 'transition duration-200'
- ]
- },
- loadingicon: {
- class: 'w-8 h-8 animate-spin'
- },
- wrapper: ({ props }) => ({
- class: [
- // Overflow
- {
- 'relative overflow-auto': props.scrollable,
- 'overflow-x-auto': props.resizableColumns
- }
- ]
- }),
- header: ({ props }) => ({
- class: [
- 'font-bold',
-
- // Shape
- props.showGridlines ? 'border-x border-t border-b-0' : 'border-y border-x-0',
-
- // Spacing
- 'p-4',
-
- // Color
- 'bg-surface-50 dark:bg-surface-800',
- 'border-surface-200 dark:border-surface-700',
- 'text-surface-700 dark:text-white/80'
- ]
- }),
- footer: {
- class: [
- // Background, Border & Text
- 'bg-slate-50 text-slate-700',
- 'border border-x-0 border-t-0 border-surface-50',
- // Padding & Font
- 'p-4 font-bold',
- // Dark Mode
- 'dark:bg-surface-900 dark:text-white/70 dark:border-surface-700'
- ]
- },
- table: {
- class: [
- // Table & Width
- 'border-collapse table-fixed w-full '
- ]
- },
- thead: ({ props }) => ({
- class: [
- // Position & Z-index
- {
- 'top-0 z-40 sticky': props.scrollable
- }
- ]
- }),
- tbody: ({ props }) => ({
- class: [
- // Block Display
- {
- block: props.scrollable
- }
- ]
- }),
- tfoot: ({ props }) => ({
- class: [
- // Block Display
- {
- block: props.scrollable
- }
- ]
- }),
- headerrow: ({ props }) => ({
- class: [
- // Flexbox & Width
- {
- 'flex flex-nowrap w-full': props.scrollable
- }
- ]
- }),
- row: ({ context, props }) => ({
- class: [
- // Flex
- { 'flex flex-nowrap w-full': context.scrollable },
-
- // Color
- 'dark:text-white/80',
- { 'bg-primary-50 text-primary-700 dark:bg-primary-400/30': context.selected },
- { 'bg-surface-0 text-surface-600 dark:bg-surface-800': !context.selected },
-
- // Hover & Flexbox
- {
- 'hover:bg-surface-300/20 hover:text-surface-600': context.selectable && !context.selected
- },
- 'focus:outline-none focus:outline-offset-0 focus:ring focus:ring-primary-400/50 ring-inset dark:focus:ring-primary-300/50',
-
- // Transition
- { 'transition duration-200': (props.selectionMode && !context.selected) || props.rowHover }
- ]
- }),
- headercell: ({ context, props }) => ({
- class: [
- 'font-bold',
-
- // Position
- { 'sticky z-40': context.scrollable && context.scrollDirection === 'both' && context.frozen },
-
- // Flex & Alignment
- {
- 'flex flex-1 items-center': context.scrollable,
- 'flex-initial shrink-0': context.scrollable && context.scrollDirection === 'both' && !context.frozen
- },
- 'text-left',
-
- // Shape
- { 'first:border-l border-y border-r': context?.showGridlines },
- 'border-0 border-b border-solid',
-
- // Spacing
- context?.size === 'small' ? 'p-2' : context?.size === 'large' ? 'p-5' : 'p-4',
-
- // Color
- (props.sortable === '' || props.sortable) && context.sorted ? 'bg-primary-50 text-primary-700' : 'bg-surface-50 text-surface-700',
- (props.sortable === '' || props.sortable) && context.sorted ? 'dark:text-white dark:bg-primary-400/30' : 'dark:text-white/80 dark:bg-surface-800',
- 'border-surface-200 dark:border-surface-700',
-
- // States
- { 'hover:bg-surface-100 dark:hover:bg-surface-400/30': (props.sortable === '' || props.sortable) && !context?.sorted },
- 'focus-visible:outline-none focus-visible:outline-offset-0 focus-visible:ring focus-visible:ring-inset focus-visible:ring-primary-400/50 dark:focus-visible:ring-primary-300/50',
-
- // Transition
- { 'transition duration-200': props.sortable === '' || props.sortable },
-
- // Misc
- {
- 'overflow-hidden relative bg-clip-padding': context.resizable && !context.frozen
- }
- ]
- }),
- column: {
- headercell: ({ context, props }) => ({
- class: [
- 'font-bold',
-
- // Position
- { 'sticky z-40': context.scrollable && context.scrollDirection === 'both' && context.frozen },
-
- // Flex & Alignment
- {
- 'flex flex-1 items-center': context.scrollable,
- 'flex-initial shrink-0': context.scrollable && context.scrollDirection === 'both' && !context.frozen
- },
- 'text-left',
-
- // Shape
- { 'first:border-l border-y border-r': context?.showGridlines },
- 'border-0 border-b border-solid',
-
- // Spacing
- context?.size === 'small' ? 'p-2' : context?.size === 'large' ? 'p-5' : 'p-4',
-
- // Color
- (props.sortable === '' || props.sortable) && context.sorted ? 'bg-primary-50 text-primary-700' : 'bg-surface-50 text-surface-700',
- (props.sortable === '' || props.sortable) && context.sorted ? 'dark:text-white dark:bg-primary-400/30' : 'dark:text-white/80 dark:bg-surface-800',
- 'border-surface-200 dark:border-surface-700',
-
- // States
- { 'hover:bg-surface-100 dark:hover:bg-surface-400/30': (props.sortable === '' || props.sortable) && !context?.sorted },
- 'focus-visible:outline-none focus-visible:outline-offset-0 focus-visible:ring focus-visible:ring-inset focus-visible:ring-primary-400/50 dark:focus-visible:ring-primary-300/50',
-
- // Transition
- { 'transition duration-200': props.sortable === '' || props.sortable },
-
- // Misc
- {
- 'overflow-hidden relative bg-clip-padding': context.resizable && !context.frozen
- }
- ]
- }),
- bodycell: ({ context }) => ({
- class: [
- // Position
- {
- sticky: context.scrollable && context.scrollDirection === 'both' && context.frozen
- },
-
- // Flex & Alignment
- {
- 'flex flex-1 items-center': context.scrollable,
- 'flex-initial shrink-0': context.scrollable && context.scrollDirection === 'both' && !context.frozen
- },
- 'text-left',
-
- // Shape
- 'border-0 border-b border-solid',
- 'border-surface-200 dark:border-surface-700',
- {
- 'border-x-0 border-l-0': !context.showGridlines
- },
- { 'first:border-l border-r border-b': context?.showGridlines },
-
- // Color
- 'bg-surface-0 dark:bg-surface-800',
-
- // Spacing
- context?.size === 'small' ? 'p-2' : context?.size === 'large' ? 'p-5' : 'p-4',
-
- // Misc
- 'dark:border-surface-700',
- {
- 'cursor-pointer': context.selectable,
- sticky: context.scrollable && context.scrollDirection === 'both' && context.frozen,
- 'border-x-0 border-l-0': !context.showGridlines
- }
- ]
- }),
- rowtoggler: {
- class: [
- 'relative',
-
- // Flex & Alignment
- 'inline-flex items-center justify-center',
- 'text-left align-middle',
-
- // Spacing
- 'm-0 mr-2 p-0',
-
- // Size
- 'w-8 h-8',
-
- // Shape
- 'border-0 rounded-full',
-
- // Color
- 'text-surface-500 dark:text-white/70',
- 'bg-transparent',
-
- // States
- 'hover:bg-surface-50 dark:hover:bg-surface-700',
- 'focus-visible:outline-none focus-visible:outline-offset-0',
- 'focus-visible:ring focus-visible:ring-primary-400/50 dark:focus-visible:ring-primary-300/50',
-
- // Transition
- 'transition duration-200',
-
- // Misc
- 'overflow-hidden',
- 'cursor-pointer select-none'
- ]
- },
- sorticon: ({ context }) => ({
- class: ['ml-2 inline-block', context.sorted ? 'fill-primary-700 dark:fill-white/80' : 'fill-surface-700 dark:fill-white/70']
- }),
- sortbadge: {
- class: [
- // Flex & Alignment
- 'inline-flex items-center justify-center align-middle',
-
- // Shape
- 'rounded-full',
-
- // Size
- 'w-[1.143rem] leading-[1.143rem]',
-
- // Spacing
- 'ml-2',
-
- // Color
- 'text-primary-700 dark:text-white',
- 'bg-primary-50 dark:bg-primary-400/30'
- ]
- },
- columnresizer: {
- class: [
- 'block',
-
- // Position
- 'absolute top-0 right-0',
-
- // Sizing
- 'w-2 h-full',
-
- // Spacing
- 'm-0 p-0',
-
- // Color
- 'border border-transparent',
-
- // Misc
- 'cursor-col-resize'
- ]
- },
- rowCheckbox: ({ props, context, instance }) => ({
- root: {
- class: [
- 'relative',
-
- // Alignment
- 'inline-flex',
- 'align-middle',
-
- // Size
- 'w-6',
- 'h-6',
-
- // Spacing
- 'mr-2',
-
- // Misc
- 'cursor-pointer',
- 'select-none'
- ]
- },
- box: {
- class: [
- // Alignment
- 'flex',
- 'items-center',
- 'justify-center',
-
- // Size
- 'w-6',
- 'h-6',
-
- // Shape
- 'rounded-md',
- 'border-2',
-
- // Colors
- {
- 'border-surface-200 bg-surface-0 dark:border-surface-700 dark:bg-surface-900': !context.checked,
- 'border-primary-500 bg-primary-500 dark:border-primary-400 dark:bg-primary-400': context.checked
- },
-
- // States
- {
- 'peer-hover:border-primary-500 dark:peer-hover:border-primary-400': !props.disabled && !context.checked,
- 'peer-hover:bg-primary-700 dark:peer-hover:bg-primary-300 peer-hover:border-primary-700 dark:peer-hover:border-primary-300': !props.disabled && context.checked,
- 'peer-focus-visible:border-primary-500 dark:peer-focus-visible:border-primary-400 peer-focus-visible:ring-2 peer-focus-visible:ring-primary-400/20 dark:peer-focus-visible:ring-primary-300/20': !props.disabled,
- 'cursor-default opacity-60': props.disabled
- },
-
- // Transitions
- 'transition-colors',
- 'duration-200'
- ]
- },
- input: {
- class: [
- 'peer',
-
- // Size
- 'w-full ',
- 'h-full',
-
- // Position
- 'absolute',
- 'top-0 left-0',
- 'z-10',
-
- // Spacing
- 'p-0',
- 'm-0',
-
- // Shape
- 'opacity-0',
- 'rounded-md',
- 'outline-none',
- 'border-2 border-surface-200 dark:border-surface-700',
-
- // Misc
- 'appearance-none',
- 'cursor-pointer'
- ]
- },
- icon: {
- class: [
- // Font
- 'text-base leading-none',
-
- // Size
- 'w-4',
- 'h-4',
-
- // Colors
- {
- 'text-white dark:text-surface-900': !instance.partialChecked,
- 'text-gray dark:text-white': instance.partialChecked
- },
-
- // Transitions
- 'transition-all',
- 'duration-200'
- ]
- }
- }),
-
- transition: {
- enterFromClass: 'opacity-0 scale-y-[0.8]',
- enterActiveClass: 'transition-[transform,opacity] duration-[120ms] ease-[cubic-bezier(0,0,0.2,1)]',
- leaveActiveClass: 'transition-opacity duration-100 ease-linear',
- leaveToClass: 'opacity-0'
- }
- },
- resizehelper: {
- class: 'absolute hidden w-[2px] z-20 bg-primary-500 dark:bg-primary-400'
- }
-};
diff --git a/frontend/packages/kwai-ui/src/presets/kwai/tristatecheckbox/index.js b/frontend/packages/kwai-ui/src/presets/kwai/tristatecheckbox/index.js
deleted file mode 100644
index 177a2a845..000000000
--- a/frontend/packages/kwai-ui/src/presets/kwai/tristatecheckbox/index.js
+++ /dev/null
@@ -1,104 +0,0 @@
-export default {
- root: {
- class: ['cursor-pointer inline-flex relative select-none align-bottom', 'w-6 h-6']
- },
- input: {
- class: [
- 'peer',
-
- // Size
- 'w-full ',
- 'h-full',
-
- // Position
- 'absolute',
- 'top-0 left-0',
- 'z-10',
-
- // Spacing
- 'p-0',
- 'm-0',
-
- // Shape
- 'opacity-0',
- 'rounded-md',
- 'outline-none',
- 'border-2 border-surface-200 dark:border-surface-700',
-
- // Misc
- 'appearance-none',
- 'cursor-pointer'
- ]
- },
- box: ({ props, context }) => ({
- class: [
- // Alignment
- 'flex',
- 'items-center',
- 'justify-center',
-
- // Size
- 'w-6',
- 'h-6',
-
- // Shape
- 'rounded-md',
- 'border-2',
-
- // Colors
- {
- 'border-surface-200 bg-surface-0 dark:border-surface-700 dark:bg-surface-900': !context.active && !props.invalid,
- 'border-primary-500 bg-primary-500 dark:border-primary-400 dark:bg-primary-400': context.active
- },
-
- // Invalid State
- { 'border-red-500 dark:border-red-400': props.invalid },
-
- // States
- {
- 'peer-hover:border-primary-500 dark:peer-hover:border-primary-400': !props.disabled && !context.active && !props.invalid,
- 'peer-hover:bg-primary-600 dark:peer-hover:bg-primary-300 peer-hover:border-primary-700 dark:peer-hover:border-primary-300': !props.disabled && context.active,
- 'peer-focus-visible:border-primary-500 dark:peer-focus-visible:border-primary-400 peer-focus-visible:ring-2 peer-focus-visible:ring-primary-400/20 dark:peer-focus-visible:ring-primary-300/20': !props.disabled,
- 'cursor-default opacity-60': props.disabled
- },
-
- // Transitions
- 'transition-colors',
- 'duration-200'
- ]
- }),
- checkicon: {
- class: [
- // Font
- 'text-base leading-none',
-
- // Size
- 'w-4',
- 'h-4',
-
- // Colors
- 'text-white dark:text-surface-900',
-
- // Transitions
- 'transition-all',
- 'duration-200'
- ]
- },
- uncheckicon: {
- class: [
- // Font
- 'text-base leading-none',
-
- // Size
- 'w-4',
- 'h-4',
-
- // Colors
- 'text-white dark:text-surface-900',
-
- // Transitions
- 'transition-all',
- 'duration-200'
- ]
- }
-};
diff --git a/frontend/packages/kwai-ui/src/table/index.ts b/frontend/packages/kwai-ui/src/table/index.ts
new file mode 100644
index 000000000..10ecd20b2
--- /dev/null
+++ b/frontend/packages/kwai-ui/src/table/index.ts
@@ -0,0 +1,83 @@
+import { h, defineComponent, VNodeChild } from 'vue';
+
+export const KwaiTableColumn = defineComponent({
+ setup(props, { slots }) {
+ return () => h(
+ 'th',
+ {
+ class: 'px-6 py-3',
+ scope: 'col',
+ },
+ slots.default?.() ?? []
+ );
+ },
+});
+
+export const KwaiTableHead = defineComponent({
+ setup(props, { slots }) {
+ return () => h(
+ 'thead',
+ { class: 'text-xs text-gray-700 uppercase bg-primary-100' },
+ [h('tr', {}, slots.default?.() ?? [])]
+ );
+ },
+});
+
+export const KwaiTableBody = defineComponent({
+ setup(props, { slots }) {
+ return () => h(
+ 'tbody',
+ { class: 'divide-y divide-primary-100' },
+ slots.default?.() ?? []
+ );
+ },
+});
+
+export const KwaiTableCell = defineComponent({
+ setup(props, { slots }) {
+ return () => h(
+ 'td',
+ { class: 'px-6 py-3' },
+ slots.default?.() ?? []
+ );
+ },
+});
+
+export const KwaiTable = defineComponent({
+ setup(props, { slots }) {
+ const children: VNodeChild[] = [];
+
+ // When there is a header slot, we pass it as the default slot
+ // for the KwaiTableHead component.
+ if (slots.header) {
+ children.push(h(
+ KwaiTableHead,
+ {},
+ { default: () => slots.header!() }
+ ));
+ }
+
+ // When there is body slot, we pass it as the default slot
+ // for the KwaiTableBody component.
+ if (slots.body) {
+ children.push(h(
+ KwaiTableBody,
+ {},
+ { default: () => slots.body!() }
+ ));
+ }
+
+ // The default slot is part of our children.
+ if (slots.default) {
+ children.push(slots.default());
+ }
+
+ return () => {
+ return h(
+ 'table',
+ { class: 'w-full text-left' },
+ children
+ );
+ };
+ },
+});
diff --git a/frontend/packages/kwai-ui/src/types.ts b/frontend/packages/kwai-ui/src/types.ts
index 973c4b18e..0edf6f457 100644
--- a/frontend/packages/kwai-ui/src/types.ts
+++ b/frontend/packages/kwai-ui/src/types.ts
@@ -4,5 +4,6 @@ export interface MenuItem {
title: string,
route?: RouteRecord | LocationAsRelativeRaw,
url?: string,
- method?: () => void
+ method?: () => void,
+ disabled?: boolean,
}
diff --git a/frontend/packages/kwai-ui/tailwind.config.js b/frontend/packages/kwai-ui/tailwind.config.js
index 0186e8e86..74d89a351 100644
--- a/frontend/packages/kwai-ui/tailwind.config.js
+++ b/frontend/packages/kwai-ui/tailwind.config.js
@@ -1,15 +1,16 @@
/** @type {import('tailwindcss').Config} */
-import TailwindForms from "@tailwindcss/forms"
+import TailwindForms from '@tailwindcss/forms';
+import primeui from 'tailwindcss-primeui';
export default {
- content: [
- "./index.ts",
- "./src/**/*.{html,js,ts,vue,jsx,tsx}"
- ],
- theme: {
- extend: {},
- },
- plugins: [
- TailwindForms()
- ],
-}
+ content: [
+ './index.ts',
+ './src/**/*.{html,js,ts,vue,jsx,tsx}',
+ ],
+ theme: {
+ extend: {},
+ },
+ plugins: [
+ TailwindForms(), primeui,
+ ],
+};
diff --git a/frontend/turbo.json b/frontend/turbo.json
deleted file mode 100644
index c1543e3b1..000000000
--- a/frontend/turbo.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "pipeline": {
- "build": {
- "dependsOn": ["^build"],
- "outputs": ["dist/**"]
- },
- "lint": {
- "outputs": []
- },
- "dev": {
- "cache": false
- }
- }
-}
diff --git a/frontend/vitest.workspace.ts b/frontend/vitest.workspace.ts
new file mode 100644
index 000000000..4a3a88451
--- /dev/null
+++ b/frontend/vitest.workspace.ts
@@ -0,0 +1,3 @@
+export default [
+ 'apps/*/vitest.config.ts',
+];
diff --git a/mkdocs.yml b/mkdocs.yml
index 2fe8bc92b..c49c418af 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -23,8 +23,8 @@ theme:
icon: material/lightbulb-outline
name: Switch to dark mode
-repo_name: zumuta/kwai
-repo_url: https://codeberg.org/zumuta/kwai
+repo_name: fbraem/kwai
+repo_url: https://github.com/fbraem/kwai
extra_css:
- stylesheets/extra.css
@@ -34,10 +34,17 @@ markdown_extensions:
toc_depth: 4
- admonition
- codehilite
+ - attr_list
+ - pymdownx.superfences:
+ custom_fences:
+ - name: mermaid
+ class: mermaid
+ format: !!python/name:pymdownx.superfences.fence_code_format
plugins:
- monorepo
- - autorefs
+ - autorefs:
+ resolve_closest: true
- mkdocstrings:
handlers:
python:
@@ -47,5 +54,7 @@ plugins:
show_source: false
docstring_style: google
show_root_toc_entry: true
+ extensions:
+ - griffe_fastapi
watch:
- backend/src